@madebywild/sanity-color-field 0.3.13 → 0.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -13,6 +13,22 @@ function safeGetLuminance(maybeColor) {
13
13
  return;
14
14
  }
15
15
  }
16
+ function defaultRenderSelected(value) {
17
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Avatar, { style: {
18
+ backgroundColor: value
19
+ } });
20
+ }
21
+ function defaultRenderOption({
22
+ label,
23
+ value
24
+ }) {
25
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { as: "button", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", padding: 2, children: [
26
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Avatar, { size: 1, style: {
27
+ backgroundColor: value
28
+ } }),
29
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { flex: 1, padding: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 2, children: label }) })
30
+ ] }) });
31
+ }
16
32
  function ColorInput(t0) {
17
33
  const $ = compilerRuntime.c(17);
18
34
  let pluginConfig, props;
@@ -20,7 +36,7 @@ function ColorInput(t0) {
20
36
  pluginConfig,
21
37
  ...props
22
38
  } = t0, $[0] = t0, $[1] = pluginConfig, $[2] = props) : (pluginConfig = $[1], props = $[2]);
23
- const options = props.schemaType.options, colorList = pluginConfig.colorList, renderOption = options?.renderOption ?? pluginConfig.renderOption, renderSelected = options?.renderSelected ?? pluginConfig.renderSelected, whitelist = options?.whitelist, blacklist = options?.blacklist, t1 = props.value?.value;
39
+ const options = props.schemaType.options, colorList = pluginConfig.colorList, renderOption = pluginConfig.renderOption ?? defaultRenderOption, renderSelected = pluginConfig.renderSelected ?? defaultRenderSelected, whitelist = options?.whitelist, blacklist = options?.blacklist, t1 = props.value?.value;
24
40
  let t2;
25
41
  $[3] !== props ? (t2 = (value_0) => {
26
42
  if (!value_0)
@@ -33,24 +49,17 @@ function ColorInput(t0) {
33
49
  }));
34
50
  }, $[3] = props, $[4] = t2) : t2 = $[4];
35
51
  let t3;
36
- $[5] !== renderSelected ? (t3 = (value_1) => renderSelected ? renderSelected(value_1) : /* @__PURE__ */ jsxRuntime.jsx(ui.Avatar, { style: {
37
- backgroundColor: value_1
38
- } }), $[5] = renderSelected, $[6] = t3) : t3 = $[6];
52
+ $[5] !== renderSelected ? (t3 = (value_1) => renderSelected(value_1), $[5] = renderSelected, $[6] = t3) : t3 = $[6];
39
53
  let t4;
40
54
  $[7] !== renderOption ? (t4 = (t52) => {
41
55
  const {
42
56
  label,
43
57
  value: value_2
44
58
  } = t52;
45
- return renderOption ? renderOption({
59
+ return renderOption({
46
60
  label,
47
61
  value: value_2
48
- }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { as: "button", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", padding: 2, children: [
49
- /* @__PURE__ */ jsxRuntime.jsx(ui.Avatar, { size: 1, style: {
50
- backgroundColor: value_2
51
- } }),
52
- /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { flex: 1, padding: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 2, children: label }) })
53
- ] }) });
62
+ });
54
63
  }, $[7] = renderOption, $[8] = t4) : t4 = $[8];
55
64
  let t5;
56
65
  return $[9] !== blacklist || $[10] !== colorList || $[11] !== t1 || $[12] !== t2 || $[13] !== t3 || $[14] !== t4 || $[15] !== whitelist ? (t5 = /* @__PURE__ */ jsxRuntime.jsx(asyncAutocomplete.AsyncAutocomplete, { placeholder: "Select color", noOptionsPlaceholder: "No colors found", listItems: colorList, whitelist, blacklist, value: t1, renderValue: _temp, onChange: t2, renderSelected: t3, renderOption: t4 }), $[9] = blacklist, $[10] = colorList, $[11] = t1, $[12] = t2, $[13] = t3, $[14] = t4, $[15] = whitelist, $[16] = t5) : t5 = $[16], t5;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/input.tsx","../src/types.tsx","../src/index.tsx"],"sourcesContent":["import { AsyncAutocomplete } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport { Avatar, Box, Card, Flex, Text } from \"@sanity/ui\";\nimport { getLuminance } from \"color2k\";\nimport { type ObjectInputProps, set, unset } from \"sanity\";\nimport type { FieldOptions, PluginConfig } from \"./types\";\n\ntype FieldValues = {\n // The selected value from the color list.\n value?: string;\n // The calculated luminance of the selected color (0 to 1).\n luminance?: number;\n};\n\n// Maybe parse CSS variable and return its computed value.\n// Handles var(--variable), --variable.\n// If the input is not a CSS variable, returns it as-is.\nfunction maybeGetColorValue(source: string) {\n const varMatch = source.match(/^var\\((.+)\\)$/);\n const inner = varMatch?.[1] ? varMatch[1].trim() : source.trim();\n\n // Only take the first part for var(--variable, fallback) and ignore the fallback.\n const cssVarName = inner.split(\",\")[0]?.trim();\n const resolved = cssVarName?.startsWith(\"--\")\n ? getComputedStyle(document.documentElement).getPropertyValue(cssVarName).trim()\n : null;\n\n const color = resolved || source;\n return color;\n}\n\n// The getLuminance function can throw for invalid colors.\nfunction safeGetLuminance(maybeColor: string) {\n try {\n return getLuminance(maybeColor);\n } catch (e) {\n console.warn(\"Failed to get luminance\", e);\n return undefined;\n }\n}\n\nfunction ColorInput({\n pluginConfig,\n ...props\n}: ObjectInputProps<FieldValues> & {\n pluginConfig: PluginConfig;\n}) {\n const options = props.schemaType.options as FieldOptions | undefined;\n const colorList = pluginConfig.colorList;\n const renderOption = options?.renderOption ?? pluginConfig.renderOption;\n const renderSelected = options?.renderSelected ?? pluginConfig.renderSelected;\n\n const whitelist = options?.whitelist;\n const blacklist = options?.blacklist;\n\n return (\n <AsyncAutocomplete\n placeholder=\"Select color\"\n noOptionsPlaceholder=\"No colors found\"\n listItems={colorList}\n whitelist={whitelist}\n blacklist={blacklist}\n value={props.value?.value}\n renderValue={(value, opt) => opt?.label ?? value}\n onChange={(value) => {\n if (!value) return props.onChange(unset());\n const color = maybeGetColorValue(value);\n const luminance = color ? safeGetLuminance(color) : undefined;\n return props.onChange(set({ ...props.value, value, luminance }));\n }}\n renderSelected={(value) => {\n if (renderSelected) return renderSelected(value);\n return <Avatar style={{ backgroundColor: value }} />;\n }}\n renderOption={({ label, value }) => {\n if (renderOption) return renderOption({ label, value });\n return (\n <Card as=\"button\">\n <Flex align=\"center\" padding={2}>\n <Avatar size={1} style={{ backgroundColor: value }} />\n <Box flex={1} padding={2}>\n <Text size={2}>{label}</Text>\n </Box>\n </Flex>\n </Card>\n );\n }}\n />\n );\n}\n\nexport { ColorInput };\n","import type { ListItems } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport type { ObjectOptions, StringDefinition } from \"sanity\";\n\n/** @public */\nexport const typeName = \"wild.color\" as const;\n\n/** @public */\nexport type PluginConfig = {\n colorList: ListItems;\n renderSelected?: (value: string) => React.JSX.Element;\n renderOption?: (item: { label?: string; value: string }) => React.JSX.Element;\n};\n\n/** @public */\nexport type FieldOptions = ObjectOptions & {\n whitelist?: string[];\n blacklist?: string[];\n renderSelected?: (value: string) => React.JSX.Element;\n renderOption?: (item: { label?: string; value: string }) => React.JSX.Element;\n};\n\n// Add the custom field definition to Sanity's intrinsic definitions\n// so that type checking works correctly when using this field type.\ndeclare module \"sanity\" {\n export interface IntrinsicDefinitions {\n [typeName]: Omit<StringDefinition, \"type\" | \"fields\" | \"options\"> & {\n type: typeof typeName;\n options?: FieldOptions;\n };\n }\n}\n","import { defineField, definePlugin, defineType } from \"sanity\";\nimport { ColorInput } from \"./input\";\nimport { type FieldOptions, type PluginConfig, typeName } from \"./types\";\n\n/** @public */\nconst wildSanityColorFieldPlugin = definePlugin<PluginConfig>((config) => {\n return {\n name: \"@madebywild/sanity-color-field\",\n schema: {\n types: [\n defineType({\n name: typeName,\n type: \"object\",\n title: \"Color\",\n description: \"Select a color.\",\n icon: () => <>🎨</>,\n components: {\n input: (props) => <ColorInput pluginConfig={config} {...props} />,\n },\n fields: [\n defineField({\n name: \"value\",\n type: \"string\",\n }),\n defineField({\n name: \"luminance\",\n type: \"number\",\n }),\n ],\n }),\n ],\n },\n };\n});\n\nexport { wildSanityColorFieldPlugin, typeName, type PluginConfig, type FieldOptions };\n"],"names":["maybeGetColorValue","source","varMatch","match","cssVarName","trim","split","startsWith","getComputedStyle","document","documentElement","getPropertyValue","safeGetLuminance","maybeColor","getLuminance","e","console","warn","ColorInput","t0","$","_c","pluginConfig","props","options","schemaType","colorList","renderOption","renderSelected","whitelist","blacklist","t1","value","t2","value_0","onChange","unset","color","luminance","undefined","set","t3","value_1","jsx","Avatar","backgroundColor","t4","t5","label","value_2","Card","jsxs","Flex","Box","Text","AsyncAutocomplete","_temp","opt","typeName","wildSanityColorFieldPlugin","definePlugin","config","name","schema","types","defineType","type","title","description","icon","Fragment","components","input","fields","defineField"],"mappings":";;;AAgBA,SAASA,mBAAmBC,QAAgB;AAC1C,QAAMC,WAAWD,OAAOE,MAAM,eAAe,GAIvCC,cAHQF,WAAW,CAAC,IAAIA,SAAS,CAAC,EAAEG,KAAAA,IAASJ,OAAOI,KAAAA,GAGjCC,MAAM,GAAG,EAAE,CAAC,GAAGD,KAAAA;AAMxC,UALiBD,YAAYG,WAAW,IAAI,IACxCC,iBAAiBC,SAASC,eAAe,EAAEC,iBAAiBP,UAAU,EAAEC,KAAAA,IACxE,SAEsBJ;AAE5B;AAGA,SAASW,iBAAiBC,YAAoB;AAC5C,MAAI;AACF,WAAOC,QAAAA,aAAaD,UAAU;AAAA,EAChC,SAASE,GAAG;AACVC,YAAQC,KAAK,2BAA2BF,CAAC;AACzC;AAAA,EACF;AACF;AAEA,SAAAG,WAAAC,IAAA;AAAA,QAAAC,IAAAC,gBAAAA,EAAA,EAAA;AAAA,MAAAC,cAAAC;AAAAH,WAAAD,MAAoB;AAAA,IAAAG;AAAAA,IAAA,GAAAC;AAAAA,EAAAA,IAAAJ,IAKnBC,OAAAD,IAAAC,OAAAE,cAAAF,OAAAG,UAAAD,eAAAF,EAAA,CAAA,GAAAG,QAAAH,EAAA,CAAA;AACC,QAAAI,UAAgBD,MAAKE,WAAWD,SAChCE,YAAkBJ,aAAYI,WAC9BC,eAAqBH,SAAOG,gBAAkBL,aAAYK,cAC1DC,iBAAuBJ,SAAOI,kBAAoBN,aAAYM,gBAE9DC,YAAkBL,SAAOK,WACzBC,YAAkBN,SAAOM,WASdC,KAAAR,MAAKS,OAAaA;AAAA,MAAAC;AAAAb,WAAAG,SAEfU,KAAAC,CAAAA,YAAA;AACR,QAAI,CAACF;AAAK,aAAST,MAAKY,SAAUC,OAAAA,OAAO;AACzC,UAAAC,QAAcrC,mBAAmBgC,OAAK,GACtCM,YAAkBD,QAAQzB,iBAAiByB,KAAiB,IAA1CE;AAA4C,WACvDhB,MAAKY,SAAUK,WAAI;AAAA,MAAA,GAAKjB,MAAKS;AAAAA,MAAMA,OAAEA;AAAAA,MAAKM;AAAAA,IAAAA,CAAa,CAAC;AAAA,EAAC,GACjElB,OAAAG,OAAAH,OAAAa,MAAAA,KAAAb,EAAA,CAAA;AAAA,MAAAqB;AAAArB,WAAAQ,kBACea,KAAAC,CAAAA,YACVd,iBAAuBA,eAAeI,OAAK,IACxCW,2BAAAA,IAACC,GAAAA,QAAA,EAAc,OAAA;AAAA,IAAAC,iBAAmBb;AAAAA,EAAAA,EAAM,CAAC,GACjDZ,OAAAQ,gBAAAR,OAAAqB,MAAAA,KAAArB,EAAA,CAAA;AAAA,MAAA0B;AAAA1B,WAAAO,gBACamB,KAAAC,CAAAA,QAAA;AAAC,UAAA;AAAA,MAAAC;AAAAA,MAAAhB,OAAAiB;AAAAA,IAAAA,IAAAF;AACb,WAAIpB,eAAqBA,aAAa;AAAA,MAAAqB;AAAAA,MAAAhB,OAASA;AAAAA,IAAAA,CAAO,IAEpDW,2BAAAA,IAACO,GAAAA,MAAA,EAAQ,IAAA,UACP,UAAAC,2BAAAA,KAACC,GAAAA,MAAA,EAAW,OAAA,UAAkB,SAAA,GAC5B,UAAA;AAAA,MAAAT,2BAAAA,IAACC,GAAAA,QAAA,EAAa,MAAA,GAAU,OAAA;AAAA,QAAAC,iBAAmBb;AAAAA,MAAAA,GAAO;AAAA,MAClDW,2BAAAA,IAACU,GAAAA,KAAA,EAAU,MAAA,GAAY,SAAA,GACrB,UAAAV,2BAAAA,IAACW,GAAAA,MAAA,EAAW,MAAA,GAAIN,UAAAA,MAAAA,CAAM,EAAA,CACxB;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,EAAO,GAEV5B,OAAAO,cAAAP,OAAA0B,MAAAA,KAAA1B,EAAA,CAAA;AAAA,MAAA2B;AAAA,SAAA3B,EAAA,CAAA,MAAAU,aAAAV,EAAA,EAAA,MAAAM,aAAAN,EAAA,EAAA,MAAAW,MAAAX,UAAAa,MAAAb,EAAA,EAAA,MAAAqB,MAAArB,EAAA,EAAA,MAAA0B,MAAA1B,EAAA,EAAA,MAAAS,aA9BHkB,KAAAJ,2BAAAA,IAACY,kBAAAA,mBAAA,EACa,aAAA,gBACS,sBAAA,mBACV7B,WAAAA,WACAG,WACAC,WACJ,OAAAC,IACM,aAAAyB,OACH,UAAAvB,IAMM,gBAAAQ,IAIF,cAAAK,GAAAA,CAYb,GACD1B,OAAAU,WAAAV,QAAAM,WAAAN,QAAAW,IAAAX,QAAAa,IAAAb,QAAAqB,IAAArB,QAAA0B,IAAA1B,QAAAS,WAAAT,QAAA2B,MAAAA,KAAA3B,EAAA,EAAA,GA/BF2B;AA+BE;AA9CN,SAAAS,MAAAxB,OAAAyB,KAAA;AAAA,SAsBmCA,KAAGT,SAAHhB;AAAmB;AC1D/C,MAAM0B,WAAW,cCClBC,6BAA6BC,OAAAA,aAA4BC,CAAAA,YACtD;AAAA,EACLC,MAAM;AAAA,EACNC,QAAQ;AAAA,IACNC,OAAO,CACLC,OAAAA,WAAW;AAAA,MACTH,MAAMJ;AAAAA,MACNQ,MAAM;AAAA,MACNC,OAAO;AAAA,MACPC,aAAa;AAAA,MACbC,MAAMA,MAAM1B,2BAAAA,IAAA2B,WAAAA,UAAA,EAAE,UAAA,YAAA,CAAE;AAAA,MAChBC,YAAY;AAAA,QACVC,OAAQjD,CAAAA,UAAUoB,+BAAC,cAAW,cAAckB,QAAQ,GAAItC,MAAAA,CAAM;AAAA,MAAA;AAAA,MAEhEkD,QAAQ,CACNC,OAAAA,YAAY;AAAA,QACVZ,MAAM;AAAA,QACNI,MAAM;AAAA,MAAA,CACP,GACDQ,OAAAA,YAAY;AAAA,QACVZ,MAAM;AAAA,QACNI,MAAM;AAAA,MAAA,CACP,CAAC;AAAA,IAAA,CAEL,CAAC;AAAA,EAAA;AAGR,EACD;;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/input.tsx","../src/types.tsx","../src/index.tsx"],"sourcesContent":["import { AsyncAutocomplete } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport { Avatar, Box, Card, Flex, Text } from \"@sanity/ui\";\nimport { getLuminance } from \"color2k\";\nimport { type ObjectInputProps, set, unset } from \"sanity\";\nimport type { FieldOptions, PluginConfig } from \"./types\";\n\ntype FieldValues = {\n // The selected value from the color list.\n value?: string;\n // The calculated luminance of the selected color (0 to 1).\n luminance?: number;\n};\n\n// Maybe parse CSS variable and return its computed value.\n// Handles var(--variable), --variable.\n// If the input is not a CSS variable, returns it as-is.\nfunction maybeGetColorValue(source: string) {\n const varMatch = source.match(/^var\\((.+)\\)$/);\n const inner = varMatch?.[1] ? varMatch[1].trim() : source.trim();\n\n // Only take the first part for var(--variable, fallback) and ignore the fallback.\n const cssVarName = inner.split(\",\")[0]?.trim();\n const resolved = cssVarName?.startsWith(\"--\")\n ? getComputedStyle(document.documentElement).getPropertyValue(cssVarName).trim()\n : null;\n\n // Fallback to the source if we couldn't resolve the CSS variable.\n return resolved || source;\n}\n\n// The getLuminance function can throw for invalid colors.\nfunction safeGetLuminance(maybeColor: string) {\n try {\n return getLuminance(maybeColor);\n } catch (e) {\n console.warn(\"Failed to get luminance\", e);\n return undefined;\n }\n}\n\nfunction defaultRenderSelected(value: string) {\n return <Avatar style={{ backgroundColor: value }} />;\n}\n\nfunction defaultRenderOption({ label, value }: { label?: string; value: string }) {\n return (\n <Card as=\"button\">\n <Flex align=\"center\" padding={2}>\n <Avatar size={1} style={{ backgroundColor: value }} />\n <Box flex={1} padding={2}>\n <Text size={2}>{label}</Text>\n </Box>\n </Flex>\n </Card>\n );\n}\n\nfunction ColorInput({\n pluginConfig,\n ...props\n}: ObjectInputProps<FieldValues> & {\n pluginConfig: PluginConfig;\n}) {\n const options = props.schemaType.options as FieldOptions | undefined;\n const colorList = pluginConfig.colorList;\n const renderOption = pluginConfig.renderOption ?? defaultRenderOption;\n const renderSelected = pluginConfig.renderSelected ?? defaultRenderSelected;\n\n const whitelist = options?.whitelist;\n const blacklist = options?.blacklist;\n\n return (\n <AsyncAutocomplete\n placeholder=\"Select color\"\n noOptionsPlaceholder=\"No colors found\"\n listItems={colorList}\n whitelist={whitelist}\n blacklist={blacklist}\n value={props.value?.value}\n renderValue={(value, opt) => opt?.label ?? value}\n onChange={(value) => {\n if (!value) return props.onChange(unset());\n const color = maybeGetColorValue(value);\n const luminance = color ? safeGetLuminance(color) : undefined;\n return props.onChange(set({ ...props.value, value, luminance }));\n }}\n renderSelected={(value) => {\n return renderSelected(value);\n }}\n renderOption={({ label, value }) => {\n return renderOption({ label, value });\n }}\n />\n );\n}\n\nexport { ColorInput };\n","import type { ListItems } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport type { ObjectOptions, StringDefinition } from \"sanity\";\n\n/** @public */\nexport const typeName = \"wild.color\" as const;\n\n/** @public */\nexport type PluginConfig = {\n /**\n * A list of colors to show in the color picker.\n * In addition to the value, the field will also calculate\n * and store the color's luminance in a separate field.\n * @example\n * ```ts\n * colorList: [\n * { label: \"Red\", value: \"#ff0000\" },\n * { label: \"Green\", value: \"#00ff00\" },\n * { label: \"Blue\", value: \"#0000ff\" },\n * ]\n * ```\n */\n colorList: ListItems;\n /**\n * A function to render the selected color value.\n * @example\n * ```ts\n * renderSelected: (value) => <div style={{ backgroundColor: value, width: 20, height: 20 }} />\n * ```\n */\n renderSelected?: (value: string) => React.JSX.Element;\n /** A function to render each color option in the dropdown.\n * @example\n * ```ts\n * renderOption: (item) => <div>{item.label}</div>\n * ```\n */\n renderOption?: (item: { label?: string; value: string }) => React.JSX.Element;\n};\n\n/** @public */\nexport type FieldOptions = ObjectOptions & {\n /**\n * Whitelist colors by their values.\n */\n whitelist?: string[];\n /**\n * Blacklist colors by their values.\n */\n blacklist?: string[];\n};\n\n// Add the custom field definition to Sanity's intrinsic definitions\n// so that type checking works correctly when using this field type.\ndeclare module \"sanity\" {\n export interface IntrinsicDefinitions {\n [typeName]: Omit<StringDefinition, \"type\" | \"fields\" | \"options\"> & {\n type: typeof typeName;\n options?: FieldOptions;\n };\n }\n}\n","import { defineField, definePlugin, defineType } from \"sanity\";\nimport { ColorInput } from \"./input\";\nimport { type FieldOptions, type PluginConfig, typeName } from \"./types\";\n\n/** @public */\nconst wildSanityColorFieldPlugin = definePlugin<PluginConfig>((config) => {\n return {\n name: \"@madebywild/sanity-color-field\",\n schema: {\n types: [\n defineType({\n name: typeName,\n type: \"object\",\n title: \"Color\",\n description: \"Select a color.\",\n icon: () => <>🎨</>,\n components: {\n input: (props) => <ColorInput pluginConfig={config} {...props} />,\n },\n fields: [\n defineField({\n name: \"value\",\n type: \"string\",\n }),\n defineField({\n name: \"luminance\",\n type: \"number\",\n }),\n ],\n }),\n ],\n },\n };\n});\n\nexport { wildSanityColorFieldPlugin, typeName, type PluginConfig, type FieldOptions };\n"],"names":["maybeGetColorValue","source","varMatch","match","cssVarName","trim","split","startsWith","getComputedStyle","document","documentElement","getPropertyValue","safeGetLuminance","maybeColor","getLuminance","e","console","warn","defaultRenderSelected","value","jsx","Avatar","backgroundColor","defaultRenderOption","label","Card","Flex","Box","Text","ColorInput","t0","$","_c","pluginConfig","props","options","schemaType","colorList","renderOption","renderSelected","whitelist","blacklist","t1","t2","value_0","onChange","unset","color","luminance","undefined","set","t3","value_1","t4","t5","value_2","AsyncAutocomplete","_temp","opt","typeName","wildSanityColorFieldPlugin","definePlugin","config","name","schema","types","defineType","type","title","description","icon","Fragment","components","input","fields","defineField"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -12,8 +12,34 @@ type ListItems<List extends ListItem[] = ListItem[]> = List | Promise<List> | ((
12
12
  declare const typeName: "wild.color";
13
13
  /** @public */
14
14
  type PluginConfig = {
15
+ /**
16
+ * A list of colors to show in the color picker.
17
+ * In addition to the value, the field will also calculate
18
+ * and store the color's luminance in a separate field.
19
+ * @example
20
+ * ```ts
21
+ * colorList: [
22
+ * { label: "Red", value: "#ff0000" },
23
+ * { label: "Green", value: "#00ff00" },
24
+ * { label: "Blue", value: "#0000ff" },
25
+ * ]
26
+ * ```
27
+ */
15
28
  colorList: ListItems;
29
+ /**
30
+ * A function to render the selected color value.
31
+ * @example
32
+ * ```ts
33
+ * renderSelected: (value) => <div style={{ backgroundColor: value, width: 20, height: 20 }} />
34
+ * ```
35
+ */
16
36
  renderSelected?: (value: string) => React.JSX.Element;
37
+ /** A function to render each color option in the dropdown.
38
+ * @example
39
+ * ```ts
40
+ * renderOption: (item) => <div>{item.label}</div>
41
+ * ```
42
+ */
17
43
  renderOption?: (item: {
18
44
  label?: string;
19
45
  value: string;
@@ -21,13 +47,14 @@ type PluginConfig = {
21
47
  };
22
48
  /** @public */
23
49
  type FieldOptions = ObjectOptions & {
50
+ /**
51
+ * Whitelist colors by their values.
52
+ */
24
53
  whitelist?: string[];
54
+ /**
55
+ * Blacklist colors by their values.
56
+ */
25
57
  blacklist?: string[];
26
- renderSelected?: (value: string) => React.JSX.Element;
27
- renderOption?: (item: {
28
- label?: string;
29
- value: string;
30
- }) => React.JSX.Element;
31
58
  };
32
59
  declare module "sanity" {
33
60
  interface IntrinsicDefinitions {
package/dist/index.d.ts CHANGED
@@ -12,8 +12,34 @@ type ListItems<List extends ListItem[] = ListItem[]> = List | Promise<List> | ((
12
12
  declare const typeName: "wild.color";
13
13
  /** @public */
14
14
  type PluginConfig = {
15
+ /**
16
+ * A list of colors to show in the color picker.
17
+ * In addition to the value, the field will also calculate
18
+ * and store the color's luminance in a separate field.
19
+ * @example
20
+ * ```ts
21
+ * colorList: [
22
+ * { label: "Red", value: "#ff0000" },
23
+ * { label: "Green", value: "#00ff00" },
24
+ * { label: "Blue", value: "#0000ff" },
25
+ * ]
26
+ * ```
27
+ */
15
28
  colorList: ListItems;
29
+ /**
30
+ * A function to render the selected color value.
31
+ * @example
32
+ * ```ts
33
+ * renderSelected: (value) => <div style={{ backgroundColor: value, width: 20, height: 20 }} />
34
+ * ```
35
+ */
16
36
  renderSelected?: (value: string) => React.JSX.Element;
37
+ /** A function to render each color option in the dropdown.
38
+ * @example
39
+ * ```ts
40
+ * renderOption: (item) => <div>{item.label}</div>
41
+ * ```
42
+ */
17
43
  renderOption?: (item: {
18
44
  label?: string;
19
45
  value: string;
@@ -21,13 +47,14 @@ type PluginConfig = {
21
47
  };
22
48
  /** @public */
23
49
  type FieldOptions = ObjectOptions & {
50
+ /**
51
+ * Whitelist colors by their values.
52
+ */
24
53
  whitelist?: string[];
54
+ /**
55
+ * Blacklist colors by their values.
56
+ */
25
57
  blacklist?: string[];
26
- renderSelected?: (value: string) => React.JSX.Element;
27
- renderOption?: (item: {
28
- label?: string;
29
- value: string;
30
- }) => React.JSX.Element;
31
58
  };
32
59
  declare module "sanity" {
33
60
  interface IntrinsicDefinitions {
package/dist/index.js CHANGED
@@ -16,6 +16,22 @@ function safeGetLuminance(maybeColor) {
16
16
  return;
17
17
  }
18
18
  }
19
+ function defaultRenderSelected(value) {
20
+ return /* @__PURE__ */ jsx(Avatar, { style: {
21
+ backgroundColor: value
22
+ } });
23
+ }
24
+ function defaultRenderOption({
25
+ label,
26
+ value
27
+ }) {
28
+ return /* @__PURE__ */ jsx(Card, { as: "button", children: /* @__PURE__ */ jsxs(Flex, { align: "center", padding: 2, children: [
29
+ /* @__PURE__ */ jsx(Avatar, { size: 1, style: {
30
+ backgroundColor: value
31
+ } }),
32
+ /* @__PURE__ */ jsx(Box, { flex: 1, padding: 2, children: /* @__PURE__ */ jsx(Text, { size: 2, children: label }) })
33
+ ] }) });
34
+ }
19
35
  function ColorInput(t0) {
20
36
  const $ = c(17);
21
37
  let pluginConfig, props;
@@ -23,7 +39,7 @@ function ColorInput(t0) {
23
39
  pluginConfig,
24
40
  ...props
25
41
  } = t0, $[0] = t0, $[1] = pluginConfig, $[2] = props) : (pluginConfig = $[1], props = $[2]);
26
- const options = props.schemaType.options, colorList = pluginConfig.colorList, renderOption = options?.renderOption ?? pluginConfig.renderOption, renderSelected = options?.renderSelected ?? pluginConfig.renderSelected, whitelist = options?.whitelist, blacklist = options?.blacklist, t1 = props.value?.value;
42
+ const options = props.schemaType.options, colorList = pluginConfig.colorList, renderOption = pluginConfig.renderOption ?? defaultRenderOption, renderSelected = pluginConfig.renderSelected ?? defaultRenderSelected, whitelist = options?.whitelist, blacklist = options?.blacklist, t1 = props.value?.value;
27
43
  let t2;
28
44
  $[3] !== props ? (t2 = (value_0) => {
29
45
  if (!value_0)
@@ -36,24 +52,17 @@ function ColorInput(t0) {
36
52
  }));
37
53
  }, $[3] = props, $[4] = t2) : t2 = $[4];
38
54
  let t3;
39
- $[5] !== renderSelected ? (t3 = (value_1) => renderSelected ? renderSelected(value_1) : /* @__PURE__ */ jsx(Avatar, { style: {
40
- backgroundColor: value_1
41
- } }), $[5] = renderSelected, $[6] = t3) : t3 = $[6];
55
+ $[5] !== renderSelected ? (t3 = (value_1) => renderSelected(value_1), $[5] = renderSelected, $[6] = t3) : t3 = $[6];
42
56
  let t4;
43
57
  $[7] !== renderOption ? (t4 = (t52) => {
44
58
  const {
45
59
  label,
46
60
  value: value_2
47
61
  } = t52;
48
- return renderOption ? renderOption({
62
+ return renderOption({
49
63
  label,
50
64
  value: value_2
51
- }) : /* @__PURE__ */ jsx(Card, { as: "button", children: /* @__PURE__ */ jsxs(Flex, { align: "center", padding: 2, children: [
52
- /* @__PURE__ */ jsx(Avatar, { size: 1, style: {
53
- backgroundColor: value_2
54
- } }),
55
- /* @__PURE__ */ jsx(Box, { flex: 1, padding: 2, children: /* @__PURE__ */ jsx(Text, { size: 2, children: label }) })
56
- ] }) });
65
+ });
57
66
  }, $[7] = renderOption, $[8] = t4) : t4 = $[8];
58
67
  let t5;
59
68
  return $[9] !== blacklist || $[10] !== colorList || $[11] !== t1 || $[12] !== t2 || $[13] !== t3 || $[14] !== t4 || $[15] !== whitelist ? (t5 = /* @__PURE__ */ jsx(AsyncAutocomplete, { placeholder: "Select color", noOptionsPlaceholder: "No colors found", listItems: colorList, whitelist, blacklist, value: t1, renderValue: _temp, onChange: t2, renderSelected: t3, renderOption: t4 }), $[9] = blacklist, $[10] = colorList, $[11] = t1, $[12] = t2, $[13] = t3, $[14] = t4, $[15] = whitelist, $[16] = t5) : t5 = $[16], t5;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/input.tsx","../src/types.tsx","../src/index.tsx"],"sourcesContent":["import { AsyncAutocomplete } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport { Avatar, Box, Card, Flex, Text } from \"@sanity/ui\";\nimport { getLuminance } from \"color2k\";\nimport { type ObjectInputProps, set, unset } from \"sanity\";\nimport type { FieldOptions, PluginConfig } from \"./types\";\n\ntype FieldValues = {\n // The selected value from the color list.\n value?: string;\n // The calculated luminance of the selected color (0 to 1).\n luminance?: number;\n};\n\n// Maybe parse CSS variable and return its computed value.\n// Handles var(--variable), --variable.\n// If the input is not a CSS variable, returns it as-is.\nfunction maybeGetColorValue(source: string) {\n const varMatch = source.match(/^var\\((.+)\\)$/);\n const inner = varMatch?.[1] ? varMatch[1].trim() : source.trim();\n\n // Only take the first part for var(--variable, fallback) and ignore the fallback.\n const cssVarName = inner.split(\",\")[0]?.trim();\n const resolved = cssVarName?.startsWith(\"--\")\n ? getComputedStyle(document.documentElement).getPropertyValue(cssVarName).trim()\n : null;\n\n const color = resolved || source;\n return color;\n}\n\n// The getLuminance function can throw for invalid colors.\nfunction safeGetLuminance(maybeColor: string) {\n try {\n return getLuminance(maybeColor);\n } catch (e) {\n console.warn(\"Failed to get luminance\", e);\n return undefined;\n }\n}\n\nfunction ColorInput({\n pluginConfig,\n ...props\n}: ObjectInputProps<FieldValues> & {\n pluginConfig: PluginConfig;\n}) {\n const options = props.schemaType.options as FieldOptions | undefined;\n const colorList = pluginConfig.colorList;\n const renderOption = options?.renderOption ?? pluginConfig.renderOption;\n const renderSelected = options?.renderSelected ?? pluginConfig.renderSelected;\n\n const whitelist = options?.whitelist;\n const blacklist = options?.blacklist;\n\n return (\n <AsyncAutocomplete\n placeholder=\"Select color\"\n noOptionsPlaceholder=\"No colors found\"\n listItems={colorList}\n whitelist={whitelist}\n blacklist={blacklist}\n value={props.value?.value}\n renderValue={(value, opt) => opt?.label ?? value}\n onChange={(value) => {\n if (!value) return props.onChange(unset());\n const color = maybeGetColorValue(value);\n const luminance = color ? safeGetLuminance(color) : undefined;\n return props.onChange(set({ ...props.value, value, luminance }));\n }}\n renderSelected={(value) => {\n if (renderSelected) return renderSelected(value);\n return <Avatar style={{ backgroundColor: value }} />;\n }}\n renderOption={({ label, value }) => {\n if (renderOption) return renderOption({ label, value });\n return (\n <Card as=\"button\">\n <Flex align=\"center\" padding={2}>\n <Avatar size={1} style={{ backgroundColor: value }} />\n <Box flex={1} padding={2}>\n <Text size={2}>{label}</Text>\n </Box>\n </Flex>\n </Card>\n );\n }}\n />\n );\n}\n\nexport { ColorInput };\n","import type { ListItems } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport type { ObjectOptions, StringDefinition } from \"sanity\";\n\n/** @public */\nexport const typeName = \"wild.color\" as const;\n\n/** @public */\nexport type PluginConfig = {\n colorList: ListItems;\n renderSelected?: (value: string) => React.JSX.Element;\n renderOption?: (item: { label?: string; value: string }) => React.JSX.Element;\n};\n\n/** @public */\nexport type FieldOptions = ObjectOptions & {\n whitelist?: string[];\n blacklist?: string[];\n renderSelected?: (value: string) => React.JSX.Element;\n renderOption?: (item: { label?: string; value: string }) => React.JSX.Element;\n};\n\n// Add the custom field definition to Sanity's intrinsic definitions\n// so that type checking works correctly when using this field type.\ndeclare module \"sanity\" {\n export interface IntrinsicDefinitions {\n [typeName]: Omit<StringDefinition, \"type\" | \"fields\" | \"options\"> & {\n type: typeof typeName;\n options?: FieldOptions;\n };\n }\n}\n","import { defineField, definePlugin, defineType } from \"sanity\";\nimport { ColorInput } from \"./input\";\nimport { type FieldOptions, type PluginConfig, typeName } from \"./types\";\n\n/** @public */\nconst wildSanityColorFieldPlugin = definePlugin<PluginConfig>((config) => {\n return {\n name: \"@madebywild/sanity-color-field\",\n schema: {\n types: [\n defineType({\n name: typeName,\n type: \"object\",\n title: \"Color\",\n description: \"Select a color.\",\n icon: () => <>🎨</>,\n components: {\n input: (props) => <ColorInput pluginConfig={config} {...props} />,\n },\n fields: [\n defineField({\n name: \"value\",\n type: \"string\",\n }),\n defineField({\n name: \"luminance\",\n type: \"number\",\n }),\n ],\n }),\n ],\n },\n };\n});\n\nexport { wildSanityColorFieldPlugin, typeName, type PluginConfig, type FieldOptions };\n"],"names":["maybeGetColorValue","source","varMatch","match","cssVarName","trim","split","startsWith","getComputedStyle","document","documentElement","getPropertyValue","safeGetLuminance","maybeColor","getLuminance","e","console","warn","ColorInput","t0","$","_c","pluginConfig","props","options","schemaType","colorList","renderOption","renderSelected","whitelist","blacklist","t1","value","t2","value_0","onChange","unset","color","luminance","undefined","set","t3","value_1","backgroundColor","t4","t5","label","value_2","_temp","opt","typeName","wildSanityColorFieldPlugin","definePlugin","config","name","schema","types","defineType","type","title","description","icon","components","input","fields","defineField"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/input.tsx","../src/types.tsx","../src/index.tsx"],"sourcesContent":["import { AsyncAutocomplete } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport { Avatar, Box, Card, Flex, Text } from \"@sanity/ui\";\nimport { getLuminance } from \"color2k\";\nimport { type ObjectInputProps, set, unset } from \"sanity\";\nimport type { FieldOptions, PluginConfig } from \"./types\";\n\ntype FieldValues = {\n // The selected value from the color list.\n value?: string;\n // The calculated luminance of the selected color (0 to 1).\n luminance?: number;\n};\n\n// Maybe parse CSS variable and return its computed value.\n// Handles var(--variable), --variable.\n// If the input is not a CSS variable, returns it as-is.\nfunction maybeGetColorValue(source: string) {\n const varMatch = source.match(/^var\\((.+)\\)$/);\n const inner = varMatch?.[1] ? varMatch[1].trim() : source.trim();\n\n // Only take the first part for var(--variable, fallback) and ignore the fallback.\n const cssVarName = inner.split(\",\")[0]?.trim();\n const resolved = cssVarName?.startsWith(\"--\")\n ? getComputedStyle(document.documentElement).getPropertyValue(cssVarName).trim()\n : null;\n\n // Fallback to the source if we couldn't resolve the CSS variable.\n return resolved || source;\n}\n\n// The getLuminance function can throw for invalid colors.\nfunction safeGetLuminance(maybeColor: string) {\n try {\n return getLuminance(maybeColor);\n } catch (e) {\n console.warn(\"Failed to get luminance\", e);\n return undefined;\n }\n}\n\nfunction defaultRenderSelected(value: string) {\n return <Avatar style={{ backgroundColor: value }} />;\n}\n\nfunction defaultRenderOption({ label, value }: { label?: string; value: string }) {\n return (\n <Card as=\"button\">\n <Flex align=\"center\" padding={2}>\n <Avatar size={1} style={{ backgroundColor: value }} />\n <Box flex={1} padding={2}>\n <Text size={2}>{label}</Text>\n </Box>\n </Flex>\n </Card>\n );\n}\n\nfunction ColorInput({\n pluginConfig,\n ...props\n}: ObjectInputProps<FieldValues> & {\n pluginConfig: PluginConfig;\n}) {\n const options = props.schemaType.options as FieldOptions | undefined;\n const colorList = pluginConfig.colorList;\n const renderOption = pluginConfig.renderOption ?? defaultRenderOption;\n const renderSelected = pluginConfig.renderSelected ?? defaultRenderSelected;\n\n const whitelist = options?.whitelist;\n const blacklist = options?.blacklist;\n\n return (\n <AsyncAutocomplete\n placeholder=\"Select color\"\n noOptionsPlaceholder=\"No colors found\"\n listItems={colorList}\n whitelist={whitelist}\n blacklist={blacklist}\n value={props.value?.value}\n renderValue={(value, opt) => opt?.label ?? value}\n onChange={(value) => {\n if (!value) return props.onChange(unset());\n const color = maybeGetColorValue(value);\n const luminance = color ? safeGetLuminance(color) : undefined;\n return props.onChange(set({ ...props.value, value, luminance }));\n }}\n renderSelected={(value) => {\n return renderSelected(value);\n }}\n renderOption={({ label, value }) => {\n return renderOption({ label, value });\n }}\n />\n );\n}\n\nexport { ColorInput };\n","import type { ListItems } from \"@madebywild/sanity-utils/async-autocomplete\";\nimport type { ObjectOptions, StringDefinition } from \"sanity\";\n\n/** @public */\nexport const typeName = \"wild.color\" as const;\n\n/** @public */\nexport type PluginConfig = {\n /**\n * A list of colors to show in the color picker.\n * In addition to the value, the field will also calculate\n * and store the color's luminance in a separate field.\n * @example\n * ```ts\n * colorList: [\n * { label: \"Red\", value: \"#ff0000\" },\n * { label: \"Green\", value: \"#00ff00\" },\n * { label: \"Blue\", value: \"#0000ff\" },\n * ]\n * ```\n */\n colorList: ListItems;\n /**\n * A function to render the selected color value.\n * @example\n * ```ts\n * renderSelected: (value) => <div style={{ backgroundColor: value, width: 20, height: 20 }} />\n * ```\n */\n renderSelected?: (value: string) => React.JSX.Element;\n /** A function to render each color option in the dropdown.\n * @example\n * ```ts\n * renderOption: (item) => <div>{item.label}</div>\n * ```\n */\n renderOption?: (item: { label?: string; value: string }) => React.JSX.Element;\n};\n\n/** @public */\nexport type FieldOptions = ObjectOptions & {\n /**\n * Whitelist colors by their values.\n */\n whitelist?: string[];\n /**\n * Blacklist colors by their values.\n */\n blacklist?: string[];\n};\n\n// Add the custom field definition to Sanity's intrinsic definitions\n// so that type checking works correctly when using this field type.\ndeclare module \"sanity\" {\n export interface IntrinsicDefinitions {\n [typeName]: Omit<StringDefinition, \"type\" | \"fields\" | \"options\"> & {\n type: typeof typeName;\n options?: FieldOptions;\n };\n }\n}\n","import { defineField, definePlugin, defineType } from \"sanity\";\nimport { ColorInput } from \"./input\";\nimport { type FieldOptions, type PluginConfig, typeName } from \"./types\";\n\n/** @public */\nconst wildSanityColorFieldPlugin = definePlugin<PluginConfig>((config) => {\n return {\n name: \"@madebywild/sanity-color-field\",\n schema: {\n types: [\n defineType({\n name: typeName,\n type: \"object\",\n title: \"Color\",\n description: \"Select a color.\",\n icon: () => <>🎨</>,\n components: {\n input: (props) => <ColorInput pluginConfig={config} {...props} />,\n },\n fields: [\n defineField({\n name: \"value\",\n type: \"string\",\n }),\n defineField({\n name: \"luminance\",\n type: \"number\",\n }),\n ],\n }),\n ],\n },\n };\n});\n\nexport { wildSanityColorFieldPlugin, typeName, type PluginConfig, type FieldOptions };\n"],"names":["maybeGetColorValue","source","varMatch","match","cssVarName","trim","split","startsWith","getComputedStyle","document","documentElement","getPropertyValue","safeGetLuminance","maybeColor","getLuminance","e","console","warn","defaultRenderSelected","value","backgroundColor","defaultRenderOption","label","ColorInput","t0","$","_c","pluginConfig","props","options","schemaType","colorList","renderOption","renderSelected","whitelist","blacklist","t1","t2","value_0","onChange","unset","color","luminance","undefined","set","t3","value_1","t4","t5","value_2","_temp","opt","typeName","wildSanityColorFieldPlugin","definePlugin","config","name","schema","types","defineType","type","title","description","icon","components","input","fields","defineField"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madebywild/sanity-color-field",
3
- "version": "0.3.13",
3
+ "version": "0.3.15",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "UNLICENSED",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "color2k": "2.0.3",
25
- "@madebywild/sanity-utils": "0.3.12"
25
+ "@madebywild/sanity-utils": "0.3.13"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "@sanity/ui": "^3.1",
package/src/input.tsx CHANGED
@@ -24,8 +24,8 @@ function maybeGetColorValue(source: string) {
24
24
  ? getComputedStyle(document.documentElement).getPropertyValue(cssVarName).trim()
25
25
  : null;
26
26
 
27
- const color = resolved || source;
28
- return color;
27
+ // Fallback to the source if we couldn't resolve the CSS variable.
28
+ return resolved || source;
29
29
  }
30
30
 
31
31
  // The getLuminance function can throw for invalid colors.
@@ -38,6 +38,23 @@ function safeGetLuminance(maybeColor: string) {
38
38
  }
39
39
  }
40
40
 
41
+ function defaultRenderSelected(value: string) {
42
+ return <Avatar style={{ backgroundColor: value }} />;
43
+ }
44
+
45
+ function defaultRenderOption({ label, value }: { label?: string; value: string }) {
46
+ return (
47
+ <Card as="button">
48
+ <Flex align="center" padding={2}>
49
+ <Avatar size={1} style={{ backgroundColor: value }} />
50
+ <Box flex={1} padding={2}>
51
+ <Text size={2}>{label}</Text>
52
+ </Box>
53
+ </Flex>
54
+ </Card>
55
+ );
56
+ }
57
+
41
58
  function ColorInput({
42
59
  pluginConfig,
43
60
  ...props
@@ -46,8 +63,8 @@ function ColorInput({
46
63
  }) {
47
64
  const options = props.schemaType.options as FieldOptions | undefined;
48
65
  const colorList = pluginConfig.colorList;
49
- const renderOption = options?.renderOption ?? pluginConfig.renderOption;
50
- const renderSelected = options?.renderSelected ?? pluginConfig.renderSelected;
66
+ const renderOption = pluginConfig.renderOption ?? defaultRenderOption;
67
+ const renderSelected = pluginConfig.renderSelected ?? defaultRenderSelected;
51
68
 
52
69
  const whitelist = options?.whitelist;
53
70
  const blacklist = options?.blacklist;
@@ -68,21 +85,10 @@ function ColorInput({
68
85
  return props.onChange(set({ ...props.value, value, luminance }));
69
86
  }}
70
87
  renderSelected={(value) => {
71
- if (renderSelected) return renderSelected(value);
72
- return <Avatar style={{ backgroundColor: value }} />;
88
+ return renderSelected(value);
73
89
  }}
74
90
  renderOption={({ label, value }) => {
75
- if (renderOption) return renderOption({ label, value });
76
- return (
77
- <Card as="button">
78
- <Flex align="center" padding={2}>
79
- <Avatar size={1} style={{ backgroundColor: value }} />
80
- <Box flex={1} padding={2}>
81
- <Text size={2}>{label}</Text>
82
- </Box>
83
- </Flex>
84
- </Card>
85
- );
91
+ return renderOption({ label, value });
86
92
  }}
87
93
  />
88
94
  );
package/src/types.tsx CHANGED
@@ -6,17 +6,47 @@ export const typeName = "wild.color" as const;
6
6
 
7
7
  /** @public */
8
8
  export type PluginConfig = {
9
+ /**
10
+ * A list of colors to show in the color picker.
11
+ * In addition to the value, the field will also calculate
12
+ * and store the color's luminance in a separate field.
13
+ * @example
14
+ * ```ts
15
+ * colorList: [
16
+ * { label: "Red", value: "#ff0000" },
17
+ * { label: "Green", value: "#00ff00" },
18
+ * { label: "Blue", value: "#0000ff" },
19
+ * ]
20
+ * ```
21
+ */
9
22
  colorList: ListItems;
23
+ /**
24
+ * A function to render the selected color value.
25
+ * @example
26
+ * ```ts
27
+ * renderSelected: (value) => <div style={{ backgroundColor: value, width: 20, height: 20 }} />
28
+ * ```
29
+ */
10
30
  renderSelected?: (value: string) => React.JSX.Element;
31
+ /** A function to render each color option in the dropdown.
32
+ * @example
33
+ * ```ts
34
+ * renderOption: (item) => <div>{item.label}</div>
35
+ * ```
36
+ */
11
37
  renderOption?: (item: { label?: string; value: string }) => React.JSX.Element;
12
38
  };
13
39
 
14
40
  /** @public */
15
41
  export type FieldOptions = ObjectOptions & {
42
+ /**
43
+ * Whitelist colors by their values.
44
+ */
16
45
  whitelist?: string[];
46
+ /**
47
+ * Blacklist colors by their values.
48
+ */
17
49
  blacklist?: string[];
18
- renderSelected?: (value: string) => React.JSX.Element;
19
- renderOption?: (item: { label?: string; value: string }) => React.JSX.Element;
20
50
  };
21
51
 
22
52
  // Add the custom field definition to Sanity's intrinsic definitions