Git Product home page Git Product logo

Comments (14)

KimPaow avatar KimPaow commented on August 14, 2024 7

Hey everyone! First of all, apologies for the lack of feedback on my part.

Secondly, to update you on the progress - there is a branch with the current state of the progress: feature/v3. There is an initial version there that works with v3 studios. Although I need to share a disclaimer that testing has been minimal at this point, which is also why I've not published an update yet.

As for when I'll have the time to actually finish it and publish it... I'm sorry to say that I'm not sure. I would love to publish it asap, but there are personal circumstances in the way.

I would really like to invite you all to contribute to this project since that would probably be the fastest way to move forward. The feature branch is mostly finished but it needs testing and some cleaning up.

Unless such a hero shows up to assist on this project all I can say is that I'm aware that there are a lot of people waiting for this and I'll do my best to finish it as soon as possible after circumstances are better. I ask for your understanding and offer my apologies for the delays πŸ™‡

from sanity-color-list.

timbeglinger avatar timbeglinger commented on August 14, 2024 4

I've created a custom input component to use in the meantime. Code is below.

color-selector

ColorSelector.tsx

import type { StringInputProps } from 'sanity';
import { set, unset } from 'sanity';
import { Stack, Flex, TextInput, Text, Avatar, Card, Grid } from '@sanity/ui';
import React, { useCallback } from 'react';

type ColorList = {
  title: string;
  value: string;
};

type SchemaTypeOption = { list: ColorList[] } | undefined;

const ColorSelector = ({
  schemaType,
  value = '',
  onChange,
}: StringInputProps) => {
  const schemeTypeOptions = schemaType.options as SchemaTypeOption;

  const handleChange = useCallback(
    (event: React.ChangeEvent<HTMLInputElement>) =>
      onChange(
        event.currentTarget.value ? set(event.currentTarget.value) : unset(),
      ),
    [onChange],
  );

  const handleSelect = useCallback(
    (hex: string) => onChange(hex ? set(hex) : unset()),
    [onChange],
  );

  return (
    <Stack space={3}>
      <Grid columns={2} gap={1}>
        <Avatar size={1} style={{ backgroundColor: value, width: '100%' }} />
        <TextInput
          fontSize={1}
          padding={3}
          placeholder='Enter hex (#ffffff) or select color below'
          onChange={handleChange}
          value={value}
        />
      </Grid>
      <Card borderTop paddingTop={3}>
        <Flex direction={'row'} wrap={'wrap'}>
          {schemeTypeOptions.list.map(({ title, value }) => {
            return (
              <ColorCircle
                key={value}
                colorName={title}
                hex={value}
                onClickHandler={handleSelect}
              />
            );
          })}
        </Flex>
      </Card>
    </Stack>
  );
};

export default ColorSelector;

type ColorCircle = {
  colorName: string;
  hex: string;
  onClickHandler: (hex: string) => void;
};

const ColorCircle = ({ colorName, hex, onClickHandler }: ColorCircle) => {
  return (
    <Card paddingRight={2} paddingBottom={4}>
      <Avatar
        size={2}
        style={{
          backgroundColor: hex,
          cursor: 'pointer',
        }}
        onClick={() => onClickHandler(hex)}
      />
      <Text size={1} align={'center'} style={{ marginTop: '1em' }}>
        {colorName}
      </Text>
    </Card>
  );
};

your-schema.ts
It's using the options list to pass down the options to the custom input component.

import { defineType } from 'sanity';
import ColorSelector from '../../../components/inputs/ColorSelector';

export default defineType({
  name: 'color',
  title: 'Color',
  description: 'Choose a color for the background',
  type: 'string',
  components: { input: ColorSelector },
  options: {
        list: [
          { title: 'Orange', value: '#F27021' },
          { title: 'Grey', value: '#091C21' },
        ],
      },
});

from sanity-color-list.

fvieira avatar fvieira commented on August 14, 2024 4

First of all, a huge thanks to @timbeglinger for the custom input component, I'm just starting to use Sanity v3 now and needed to migrate the color-list type, and it was awesome finding this component ready to use and adapt.

I've taken the liberty of adding a bunch of features to it and want to return the favor and share the code back.
You can see how this version looks (3 screenshots to show both themes and different configs):
2023-03-11_19-54
2023-03-11_19-55
2023-03-11_19-57

Here's some of the features I added:

  • Some changes to the layout (some are a matter of preference, not an obvious improvement)
  • Show active color from the list
  • Add light grey borders to color circles to allow white to be visible on light theme and black on dark theme
  • Pass configs as component props to have Typescript autocomplete/validations
  • Add prop withColorNames to allow having/not having color names under colors in list
  • Add prop withHexInput to allow having/not having the input (in which case the label of the list also disappears)
  • Prop list is optinal if using withHexInput to allow having just the hex input
  • Exported a colorHexValidator that can be used in a custom validation to ensure the value is a well formatted color
  • Preprocess the string in the input to only allow valid hex chars and to auto add the # in the beginning

Feel free to suggest improvements, I can't promise I'll add them as I spent too much time on this already, but I might, and they're welcome anyway. And here's the code.

ColorSelector.tsx

import { Avatar, Card, Flex, Grid, Stack, Text, TextInput } from '@sanity/ui';
import React, { useCallback } from 'react';
import { set, StringInputProps, unset } from 'sanity';

export function colorHexValidator(value?: string) {
  if (value && !value.match(/^#[a-fA-f0-9]{6}$/)) {
    return 'Color must be a valid hex (e.g. #A4F23B)';
  }
  return true;
}

type ColorCircleProps = {
  colorName: string;
  hex: string;
  active: boolean;
  withColorName: boolean;
  onClickHandler: (hex: string) => void;
};

const ColorCircle = ({
  colorName,
  hex,
  active,
  withColorName,
  onClickHandler,
}: ColorCircleProps) => {
  return (
    <Card paddingRight={2} paddingBottom={4}>
      <div
        style={{
          padding: '4px',
          borderRadius: '50%',
          backgroundColor: active ? hex : 'transparent',
          border: active ? '1px solid var(--card-hairline-soft-color)' : '1px solid transparent',
          cursor: 'pointer',
        }}
        onClick={() => onClickHandler(hex)}
      >
        <Avatar
          size={1}
          style={{
            backgroundColor: hex,
            border: '1px solid var(--card-hairline-soft-color)',
          }}
        />
      </div>
      {withColorName && (
        <Text size={1} align={'center'} style={{ marginTop: '.5em' }}>
          {colorName}
        </Text>
      )}
    </Card>
  );
};

type ColorObject = {
  title: string;
  value: string;
};

type ColorSelectorProps = StringInputProps &
  (
    | {
        list: ColorObject[];
        withColorNames?: boolean;
        withHexInput?: boolean;
      }
    | {
        list?: never;
        withColorNames?: never;
        withHexInput: true;
      }
  );

const ColorSelector = ({
  value = '',
  onChange,
  list,
  withHexInput,
  withColorNames,
}: ColorSelectorProps) => {
  // Removes non-hex chars from the string, trims to 6 chars,
  // adds a # at the beginning and upper cases it
  const preprocessValue = (str: string) => {
    const validHexChars = /[0-9a-fA-F]/g;
    const hexChars = str.match(validHexChars)?.join('') || '';

    const hasHashSymbol = hexChars.startsWith('#');

    return (hasHashSymbol ? '' : '#') + hexChars.replace(/^#/, '').substring(0, 6).toUpperCase();
  };

  const handleChange = useCallback(
    (event: React.ChangeEvent<HTMLInputElement>) =>
      onChange(
        event.currentTarget.value ? set(preprocessValue(event.currentTarget.value)) : unset(),
      ),
    [onChange],
  );

  const handleSelect = useCallback(
    (hex: string) => onChange(hex && hex !== value ? set(preprocessValue(hex)) : unset()),
    [onChange, value],
  );

  return (
    <Stack space={3}>
      {withHexInput && (
        <>
          <Text size={1}>Enter hex</Text>
          <Grid
            columns={2}
            gap={1}
            style={{
              gridTemplateColumns: 'auto 1fr',
            }}
          >
            <Avatar
              size={1}
              style={{
                backgroundColor: value,
                border: '1px solid var(--card-hairline-soft-color)',
              }}
            />
            <TextInput
              style={{ flexGrow: 1 }}
              fontSize={1}
              padding={3}
              placeholder={'#FFFFFF'}
              onChange={handleChange}
              value={value}
            />
          </Grid>
        </>
      )}
      {list && (
        <Card
          borderTop={withHexInput}
          paddingTop={withHexInput ? 3 : 0}
          style={{
            transform: 'translateX(-4px)',
          }}
        >
          {withHexInput && (
            <Text size={1} style={{ marginBottom: '.5em' }}>
              or select color below
            </Text>
          )}
          <Flex direction={'row'} wrap={'wrap'}>
            {list.map(colorItem => {
              return (
                <ColorCircle
                  key={colorItem.value}
                  colorName={colorItem.title}
                  hex={colorItem.value}
                  active={colorItem.value === value}
                  withColorName={!!withColorNames}
                  onClickHandler={handleSelect}
                />
              );
            })}
          </Flex>
        </Card>
      )}
    </Stack>
  );
};

export default ColorSelector;

your-schema.tsx

import ColorSelector, { colorHexValidator } from '../../src/components/ColorSelector';

...

defineField({
  name: 'color',
  title: 'Color',
  type: 'string',
  components: {
    input: props => (
      <ColorSelector
        {...props}
        withHexInput
        withColorNames
        list={[
          { title: 'Orange', value: '#F27021' },
          { title: 'Grey', value: '#DDDDDD' },
          { title: 'White', value: '#FFFFFF' },
          { title: 'Dark', value: '#101112' },
        ]}
      />
    ),
  },
  validation: Rule => Rule.custom(colorHexValidator).required(),
})

from sanity-color-list.

KimPaow avatar KimPaow commented on August 14, 2024 2

Hi Fabien, I just opened up my editor for that purpose 5 min ago :) It will feature v3 compatibility and a complete rewrite in TS. The API will most likely not change however.

from sanity-color-list.

fabien avatar fabien commented on August 14, 2024

What a coincidence! Sounds good, thanks!

Any chance to include the async options (beta) functionality too?

from sanity-color-list.

KimPaow avatar KimPaow commented on August 14, 2024

I'll definitely take a look at that as well!

from sanity-color-list.

trebua avatar trebua commented on August 14, 2024

I would definitely appreciate v3 compatibility as well 🀞

from sanity-color-list.

1jmj avatar 1jmj commented on August 14, 2024

any update please?

from sanity-color-list.

hectorg2211 avatar hectorg2211 commented on August 14, 2024

Hey there, would be great to have an update on when this might be released πŸ˜€

from sanity-color-list.

Bobeta avatar Bobeta commented on August 14, 2024

@KimPaow Let us know how it goes πŸ™πŸ»

from sanity-color-list.

miguelpruivo avatar miguelpruivo commented on August 14, 2024

Hi, is the v3 version supposedly working in the v3 branch? I've tried adding it into the project without success. :(

[vite] Internal server error: Failed to resolve entry for package "sanity-plugin-color-list". The package may have incorrect main/module/exports specified in its package.json.

from sanity-color-list.

edolyne avatar edolyne commented on August 14, 2024

Has anyone been successful in getting this to work with v3?

from sanity-color-list.

jcontonio avatar jcontonio commented on August 14, 2024

Any update on merging the v3 feature branch?

from sanity-color-list.

Related Issues (14)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.