@oneplatformdev/ui 0.1.99-beta.304 → 0.1.99-beta.306

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.
Files changed (221) hide show
  1. package/.storybook/Wrappers.js.map +1 -1
  2. package/Accordion/Accordion.js.map +1 -1
  3. package/Alert/Alert.js.map +1 -1
  4. package/Alert/alertVariants.js.map +1 -1
  5. package/AlertDialog/AlertDialog.js.map +1 -1
  6. package/AlertDialog/AlertDialog.stories.js +2 -4
  7. package/AlertDialog/AlertDialog.stories.js.map +1 -1
  8. package/AlertDialog/AlertDialogRoot.js +18 -20
  9. package/AlertDialog/AlertDialogRoot.js.map +1 -1
  10. package/AreaChart/AreaChart.js.map +1 -1
  11. package/Aside/Aside.js.map +1 -1
  12. package/Aside/AsideSidebar.js.map +1 -1
  13. package/AspectRatio/AspectRatio.js.map +1 -1
  14. package/Avatar/Avatar.js.map +1 -1
  15. package/Badge/Badge.js.map +1 -1
  16. package/Badge/badgeVariants.js.map +1 -1
  17. package/Breadcrumb/Breadcrumb.js.map +1 -1
  18. package/Button/Button.js +10 -11
  19. package/Button/Button.js.map +1 -1
  20. package/Button/Button.stories.js.map +1 -1
  21. package/Button/Button.utils.js.map +1 -1
  22. package/Button/ButtonCounterBadge.js.map +1 -1
  23. package/Button/buttonVariants.js.map +1 -1
  24. package/ButtonIcon/ButtonIcon.js +19 -22
  25. package/ButtonIcon/ButtonIcon.js.map +1 -1
  26. package/ButtonIcon/ButtonIcon.stories.js.map +1 -1
  27. package/ButtonIcon/buttonIconVariants.js.map +1 -1
  28. package/CHANGELOG.md +3487 -3487
  29. package/Calendar/Calendar.js +4 -6
  30. package/Calendar/Calendar.js.map +1 -1
  31. package/Card/Card.js.map +1 -1
  32. package/Carousel/Carousel.js +6 -7
  33. package/Carousel/Carousel.js.map +1 -1
  34. package/Chart/Chart.js.map +1 -1
  35. package/Checkbox/Checkbox.js +0 -1
  36. package/Checkbox/Checkbox.js.map +1 -1
  37. package/Checkbox/Checkbox.stories.js.map +1 -1
  38. package/Collapsible/Collapsible.js.map +1 -1
  39. package/ColorInput/ColorInput.d.ts +10 -0
  40. package/ColorInput/ColorInput.d.ts.map +1 -0
  41. package/ColorInput/ColorInput.js +103 -0
  42. package/ColorInput/ColorInput.js.map +1 -0
  43. package/ColorInput/ColorInput.stories.js +78 -0
  44. package/ColorInput/ColorInput.stories.js.map +1 -0
  45. package/ColorInput/ColorInput.types.d.ts +46 -0
  46. package/ColorInput/ColorInput.types.d.ts.map +1 -0
  47. package/ColorInput/ColorInput.types.js +2 -0
  48. package/ColorInput/ColorInput.types.js.map +1 -0
  49. package/ColorInput/ColorPicker.d.ts +28 -0
  50. package/ColorInput/ColorPicker.d.ts.map +1 -0
  51. package/ColorInput/ColorPicker.js +322 -0
  52. package/ColorInput/ColorPicker.js.map +1 -0
  53. package/ColorInput/color.utils.d.ts +42 -0
  54. package/ColorInput/color.utils.d.ts.map +1 -0
  55. package/ColorInput/color.utils.js +129 -0
  56. package/ColorInput/color.utils.js.map +1 -0
  57. package/ColorInput/index.d.ts +6 -0
  58. package/ColorInput/index.d.ts.map +1 -0
  59. package/ColorInput/index.js +25 -0
  60. package/ColorInput/index.js.map +1 -0
  61. package/ColorInput/useSavedColors.d.ts +13 -0
  62. package/ColorInput/useSavedColors.d.ts.map +1 -0
  63. package/ColorInput/useSavedColors.js +53 -0
  64. package/ColorInput/useSavedColors.js.map +1 -0
  65. package/Combobox/Combobox.js +10 -10
  66. package/Combobox/Combobox.js.map +1 -1
  67. package/Combobox/Combobox.stories.js.map +1 -1
  68. package/Combobox/Combobox.types.js.map +1 -1
  69. package/Combobox/ComboboxOptionItem.js +18 -19
  70. package/Combobox/ComboboxOptionItem.js.map +1 -1
  71. package/Combobox/ComboboxRenderContent.js +18 -19
  72. package/Combobox/ComboboxRenderContent.js.map +1 -1
  73. package/Combobox/ComboboxRenderOptions.js +5 -5
  74. package/Combobox/ComboboxRenderOptions.js.map +1 -1
  75. package/Combobox/ComboboxRenderTrigger.js +20 -22
  76. package/Combobox/ComboboxRenderTrigger.js.map +1 -1
  77. package/Command/Command.js +21 -22
  78. package/Command/Command.js.map +1 -1
  79. package/ContextPopover/ContextDropdownMenu.js.map +1 -1
  80. package/ContextPopover/ContextPopover.js.map +1 -1
  81. package/ContextPopover/useContextPopoverHandler.js.map +1 -1
  82. package/DataTable/DataTable.js +24 -26
  83. package/DataTable/DataTable.js.map +1 -1
  84. package/DataTable/DataTableColumnFilter.js +6 -7
  85. package/DataTable/DataTableColumnFilter.js.map +1 -1
  86. package/DataTable/useDataTable.js.map +1 -1
  87. package/DatePicker/DatePicker.js +1 -2
  88. package/DatePicker/DatePicker.js.map +1 -1
  89. package/Dialog/Dialog.js +20 -21
  90. package/Dialog/Dialog.js.map +1 -1
  91. package/Dialog/Dialog.stories.js +14 -15
  92. package/Dialog/Dialog.stories.js.map +1 -1
  93. package/Dialog/DialogOverlayScope.js.map +1 -1
  94. package/Dialog/useDialogClosePosition.js.map +1 -1
  95. package/Drawer/Drawer.js.map +1 -1
  96. package/DropdownMenu/DropdownMenu.js.map +1 -1
  97. package/Dropzone/Dropzone.d.ts.map +1 -1
  98. package/Dropzone/Dropzone.js +121 -122
  99. package/Dropzone/Dropzone.js.map +1 -1
  100. package/Dropzone/Dropzone.stories.js.map +1 -1
  101. package/Dropzone/Dropzone.types.js.map +1 -1
  102. package/Dropzone/DropzoneCoverPreview.js.map +1 -1
  103. package/Dropzone/DropzoneFilePreview.js.map +1 -1
  104. package/Dropzone/DropzoneSinglePickPreview.js +2 -3
  105. package/Dropzone/DropzoneSinglePickPreview.js.map +1 -1
  106. package/Dropzone/DropzoneUtils.js.map +1 -1
  107. package/Form/Form.js +14 -15
  108. package/Form/Form.js.map +1 -1
  109. package/Form/FormRenderControl.js +6 -7
  110. package/Form/FormRenderControl.js.map +1 -1
  111. package/Form/Form_old.js +4 -5
  112. package/Form/Form_old.js.map +1 -1
  113. package/FormCheckbox/FormCheckbox.js +4 -4
  114. package/FormCheckbox/FormCheckbox.js.map +1 -1
  115. package/FormColorInput/FormColorInput.d.ts +7 -0
  116. package/FormColorInput/FormColorInput.d.ts.map +1 -0
  117. package/FormColorInput/FormColorInput.js +38 -0
  118. package/FormColorInput/FormColorInput.js.map +1 -0
  119. package/FormColorInput/FormColorInput.stories.js +95 -0
  120. package/FormColorInput/FormColorInput.stories.js.map +1 -0
  121. package/FormColorInput/FormColorInput.types.d.ts +6 -0
  122. package/FormColorInput/FormColorInput.types.d.ts.map +1 -0
  123. package/FormColorInput/FormColorInput.types.js +2 -0
  124. package/FormColorInput/FormColorInput.types.js.map +1 -0
  125. package/FormColorInput/index.d.ts +3 -0
  126. package/FormColorInput/index.d.ts.map +1 -0
  127. package/FormColorInput/index.js +5 -0
  128. package/FormColorInput/index.js.map +1 -0
  129. package/FormCombobox/FormCombobox.js +4 -4
  130. package/FormCombobox/FormCombobox.js.map +1 -1
  131. package/FormCombobox/FormCombobox.stories.js +17 -19
  132. package/FormCombobox/FormCombobox.stories.js.map +1 -1
  133. package/FormDatePicker/FormDatePicker.js +4 -4
  134. package/FormDatePicker/FormDatePicker.js.map +1 -1
  135. package/FormDropzone/FormDropzone.js +3 -3
  136. package/FormDropzone/FormDropzone.js.map +1 -1
  137. package/FormInput/FormInput.js +6 -6
  138. package/FormInput/FormInput.js.map +1 -1
  139. package/FormInput/FormInput.stories.js +12 -13
  140. package/FormInput/FormInput.stories.js.map +1 -1
  141. package/FormRadio/FormRadio.js.map +1 -1
  142. package/FormSelect/FormSelect.js +12 -15
  143. package/FormSelect/FormSelect.js.map +1 -1
  144. package/FormTextarea/FormTextarea.js +4 -4
  145. package/FormTextarea/FormTextarea.js.map +1 -1
  146. package/Header/Header.js.map +1 -1
  147. package/HoverCard/HoverCard.js.map +1 -1
  148. package/InfoBlock/InfoBlock.js.map +1 -1
  149. package/InfoBlock/InfoBlock.stories.js.map +1 -1
  150. package/InfoBlock/infoBlockVariants.js.map +1 -1
  151. package/Input/Input.js.map +1 -1
  152. package/Input/Input.stories.js.map +1 -1
  153. package/Input/inputVariants.js.map +1 -1
  154. package/InputOTP/InputOTP.d.ts.map +1 -1
  155. package/InputOTP/InputOTP.js.map +1 -1
  156. package/LICENSE +21 -21
  157. package/Label/Label.js.map +1 -1
  158. package/Label/labelVariants.js.map +1 -1
  159. package/LazyLoader/LazyLoader.js +4 -5
  160. package/LazyLoader/LazyLoader.js.map +1 -1
  161. package/LoadedIcon/LoadedIcon.js.map +1 -1
  162. package/LoadingMask/LoadingMask.js.map +1 -1
  163. package/LoadingMask/RenderLoadingMask.js.map +1 -1
  164. package/LoadingProgress/LoadingProgress.js.map +1 -1
  165. package/LoadingProgress/loadingProgressVariants.js.map +1 -1
  166. package/Menubar/Menubar.js.map +1 -1
  167. package/NavigationMenu/NavigationMenu.js.map +1 -1
  168. package/NavigationMenu/navigationMenuVariants.js.map +1 -1
  169. package/Pagination/Pagination.js +0 -1
  170. package/Pagination/Pagination.js.map +1 -1
  171. package/Popover/Popover.js.map +1 -1
  172. package/Progress/Progress.js.map +1 -1
  173. package/README.md +7 -7
  174. package/Radio/Radio.js.map +1 -1
  175. package/RadioGroup/RadioGroup.js.map +1 -1
  176. package/Resizable/Resizable.js.map +1 -1
  177. package/Resizable/Resizable.stories.js.map +1 -1
  178. package/ScrollArea/ScrollArea.js.map +1 -1
  179. package/Search/Search.js +9 -9
  180. package/Search/Search.js.map +1 -1
  181. package/Search/Search.stories.js.map +1 -1
  182. package/Select/Select.js +6 -7
  183. package/Select/Select.js.map +1 -1
  184. package/Select/Select.stories.js.map +1 -1
  185. package/Select/SelectRoot.js.map +1 -1
  186. package/Separator/Separator.js.map +1 -1
  187. package/Sheet/Sheet.js.map +1 -1
  188. package/Sidebar/Sidebar.js +20 -21
  189. package/Sidebar/Sidebar.js.map +1 -1
  190. package/Skeleton/Skeleton.js.map +1 -1
  191. package/Slider/Slider.js.map +1 -1
  192. package/Sonner/Sonner.js.map +1 -1
  193. package/Switch/Switch.js.map +1 -1
  194. package/Switch/Switch.stories.js.map +1 -1
  195. package/Table/Table.js.map +1 -1
  196. package/TablePagination/TablePagination.js +21 -26
  197. package/TablePagination/TablePagination.js.map +1 -1
  198. package/Tabs/Tabs.js.map +1 -1
  199. package/Tabs/TabsRoot.js.map +1 -1
  200. package/Textarea/Textarea.js.map +1 -1
  201. package/Textarea/Textarea.stories.js.map +1 -1
  202. package/Textarea/useAutosizeTextArea.js.map +1 -1
  203. package/Theme/ThemeModeToggle.js +3 -4
  204. package/Theme/ThemeModeToggle.js.map +1 -1
  205. package/Theme/ThemeProvider.js.map +1 -1
  206. package/Toast/Toast.js.map +1 -1
  207. package/Toast/toast.constants.js.map +1 -1
  208. package/Toast/toastVariants.js.map +1 -1
  209. package/Toast/useToast.js.map +1 -1
  210. package/Toaster/Toaster.js.map +1 -1
  211. package/Toggle/Toggle.js.map +1 -1
  212. package/ToggleGroup/ToggleGroup.js.map +1 -1
  213. package/Tooltip/Tooltip.js.map +1 -1
  214. package/Tooltip/TooltipRoot.js.map +1 -1
  215. package/Tooltip/tooltipVariants.js.map +1 -1
  216. package/index.d.ts +2 -0
  217. package/index.d.ts.map +1 -1
  218. package/index.js +366 -342
  219. package/index.js.map +1 -1
  220. package/package.json +1 -1
  221. package/vite-env.d.ts +7 -7
@@ -0,0 +1,46 @@
1
+ import { InputHTMLAttributes } from 'react';
2
+ import { ColorFormat } from './color.utils';
3
+ export interface ColorInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'color'> {
4
+ /** Current color as a hex string (#rrggbb or #rrggbbaa). */
5
+ value?: string;
6
+ /** Called with the next hex string whenever the color changes. */
7
+ onChange?: (hex: string) => void;
8
+ /** Show the alpha slider / percent field and emit 8-digit hex. Default false. */
9
+ withAlpha?: boolean;
10
+ /** Marks the field as invalid (red border). */
11
+ error?: boolean;
12
+ /**
13
+ * Saved-colors palette inside the picker. When omitted the input manages its
14
+ * own palette persisted to localStorage (see `storageKey`).
15
+ */
16
+ savedColors?: string[];
17
+ /**
18
+ * Called from the picker's "+ Add" action. When omitted (and `savedColors`
19
+ * is also omitted) the added color is persisted to localStorage instead.
20
+ */
21
+ onAddSavedColor?: (hex: string) => void;
22
+ /**
23
+ * Called when a saved swatch's hover "×" is clicked. When omitted (and the
24
+ * palette is auto-managed) removal is persisted to localStorage instead.
25
+ */
26
+ onRemoveSavedColor?: (hex: string) => void;
27
+ /** i18n: label before the palette. Default "Saved colors:". */
28
+ savedColorsLabel?: string;
29
+ /** i18n: label of the add action. Default "+ Add". */
30
+ addLabel?: string;
31
+ /** i18n: accessible label for a swatch's remove button. Default "Remove color". */
32
+ removeColorLabel?: string;
33
+ /**
34
+ * localStorage key for the auto-managed saved-colors palette. Only used when
35
+ * `savedColors`/`onAddSavedColor` are not provided.
36
+ */
37
+ storageKey?: string;
38
+ /**
39
+ * Color formats offered in the picker's format dropdown. Defaults to all
40
+ * (`['hex', 'rgb', 'rgba', 'hsl', 'hsb']`). Restrict with e.g.
41
+ * `formats={['hex']}`.
42
+ */
43
+ formats?: ColorFormat[];
44
+ className?: string;
45
+ }
46
+ //# sourceMappingURL=ColorInput.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorInput.types.d.ts","sourceRoot":"","sources":["../../src/ColorInput/ColorInput.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,eACf,SAAQ,IAAI,CACV,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,OAAO,GAAG,UAAU,GAAG,OAAO,CAC/B;IACD,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,2 @@
1
+
2
+ //# sourceMappingURL=ColorInput.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorInput.types.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import { ColorFormat } from './color.utils';
2
+ export interface ColorPickerProps {
3
+ value: string;
4
+ onChange: (hex: string) => void;
5
+ withAlpha?: boolean;
6
+ /** Saved-colors palette. Empty by default. */
7
+ savedColors?: string[];
8
+ /** Renders the "+ Add" action; called with the current color. */
9
+ onAddSavedColor?: (hex: string) => void;
10
+ /** When provided, each saved swatch gets a hover "×" to remove it. */
11
+ onRemoveSavedColor?: (hex: string) => void;
12
+ /** Label before the palette (i18n). Default "Saved colors:". */
13
+ savedColorsLabel?: string;
14
+ /** Label of the add action (i18n). Default "+ Add". */
15
+ addLabel?: string;
16
+ /** Accessible label for a swatch's remove button (i18n). Default "Remove color". */
17
+ removeColorLabel?: string;
18
+ /**
19
+ * Color formats offered in the format dropdown. Defaults to all of them
20
+ * (`['hex', 'rgb', 'rgba', 'hsl', 'hsb']`). Pass a subset to restrict input,
21
+ * e.g. `formats={['hex']}` to only allow hex. With a single format the
22
+ * dropdown is hidden.
23
+ */
24
+ formats?: ColorFormat[];
25
+ className?: string;
26
+ }
27
+ export declare const ColorPicker: ({ value, onChange, withAlpha, savedColors, onAddSavedColor, onRemoveSavedColor, savedColorsLabel, addLabel, removeColorLabel, formats, className, }: ColorPickerProps) => import("react/jsx-runtime").JSX.Element;
28
+ //# sourceMappingURL=ColorPicker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorPicker.d.ts","sourceRoot":"","sources":["../../src/ColorInput/ColorPicker.tsx"],"names":[],"mappings":"AAIA,OAAO,EAIL,WAAW,EAQZ,MAAM,eAAe,CAAC;AAyEvB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,iEAAiE;IACjE,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6CD,eAAO,MAAM,WAAW,GAAI,qJAYzB,gBAAgB,4CAmRlB,CAAC"}
@@ -0,0 +1,322 @@
1
+ import { jsxs as d, jsx as t, Fragment as K } from "react/jsx-runtime";
2
+ import { useState as k, useEffect as A, useCallback as V, useRef as W } from "react";
3
+ import { cn as N } from "@oneplatformdev/utils";
4
+ import { COLOR_FORMATS as H, parseColor as C, rgbaToHsva as _, formatColor as g, hsvaToRgba as w, COLOR_FORMAT_LABELS as B, parseColorInFormat as Q, clamp as z, FORMAT_HAS_ALPHA as Z } from "./color.utils.js";
5
+ const ee = ({
6
+ value: a,
7
+ options: p,
8
+ onChange: h
9
+ }) => {
10
+ const [r, o] = k(!1), c = W(null);
11
+ return A(() => {
12
+ if (!r) return;
13
+ const n = (m) => {
14
+ c.current && !c.current.contains(m.target) && o(!1);
15
+ };
16
+ return window.addEventListener("mousedown", n), () => window.removeEventListener("mousedown", n);
17
+ }, [r]), /* @__PURE__ */ d("div", { ref: c, className: "relative w-[74px] shrink-0", children: [
18
+ /* @__PURE__ */ d(
19
+ "button",
20
+ {
21
+ type: "button",
22
+ onClick: () => o((n) => !n),
23
+ "aria-haspopup": "listbox",
24
+ "aria-expanded": r,
25
+ className: N(
26
+ "flex h-7 w-full cursor-pointer items-center justify-between rounded border bg-white pl-2 pr-1.5 text-sm text-[#374151] shadow-[0px_1px_2px_rgba(31,41,55,0.08)] transition-colors",
27
+ r ? "border-[#9368FF]" : "border-[#E5E7EB] hover:border-[#D1D5DB]"
28
+ ),
29
+ children: [
30
+ /* @__PURE__ */ t("span", { children: B[a] }),
31
+ /* @__PURE__ */ d("svg", { className: "size-3 text-[#9CA3AF]", viewBox: "0 0 12 12", fill: "none", children: [
32
+ /* @__PURE__ */ t("path", { d: "M3.5 5 6 2.5 8.5 5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }),
33
+ /* @__PURE__ */ t("path", { d: "M3.5 7 6 9.5 8.5 7", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
34
+ ] })
35
+ ]
36
+ }
37
+ ),
38
+ r && /* @__PURE__ */ t(
39
+ "ul",
40
+ {
41
+ role: "listbox",
42
+ className: "absolute left-0 top-[calc(100%+4px)] z-20 w-full overflow-hidden rounded border border-[#E5E7EB] bg-white py-1 shadow-[0px_10px_15px_rgba(31,41,55,0.1),0px_4px_6px_rgba(31,41,55,0.05)]",
43
+ children: p.map((n) => /* @__PURE__ */ t("li", { children: /* @__PURE__ */ t(
44
+ "button",
45
+ {
46
+ type: "button",
47
+ role: "option",
48
+ "aria-selected": n === a,
49
+ onClick: () => {
50
+ h(n), o(!1);
51
+ },
52
+ className: N(
53
+ "flex w-full cursor-pointer items-center px-2 py-1 text-left text-sm hover:bg-[#F3F4F6]",
54
+ n === a ? "font-medium text-[#9368FF]" : "text-[#374151]"
55
+ ),
56
+ children: B[n]
57
+ }
58
+ ) }, n))
59
+ }
60
+ )
61
+ ] });
62
+ }, E = (a, p, h, r) => {
63
+ const o = a.getBoundingClientRect(), c = z((p - o.left) / o.width, 0, 1), n = z((h - o.top) / o.height, 0, 1);
64
+ return {
65
+ x: r === "y" ? 0 : c,
66
+ y: r === "x" ? 0 : n
67
+ };
68
+ }, L = (a) => {
69
+ const p = W(null), h = V(
70
+ (r) => {
71
+ const o = p.current;
72
+ if (!o) return;
73
+ r.preventDefault(), a(r.clientX, r.clientY, o);
74
+ const c = (m) => a(m.clientX, m.clientY, o), n = () => {
75
+ window.removeEventListener("pointermove", c), window.removeEventListener("pointerup", n);
76
+ };
77
+ window.addEventListener("pointermove", c), window.addEventListener("pointerup", n);
78
+ },
79
+ [a]
80
+ );
81
+ return { ref: p, start: h };
82
+ }, se = ({
83
+ value: a,
84
+ onChange: p,
85
+ withAlpha: h = !1,
86
+ savedColors: r = [],
87
+ onAddSavedColor: o,
88
+ onRemoveSavedColor: c,
89
+ savedColorsLabel: n = "Saved colors:",
90
+ addLabel: m = "+ Add",
91
+ removeColorLabel: D = "Remove color",
92
+ formats: M = H,
93
+ className: X
94
+ }) => {
95
+ const f = M.length ? M : H, [i, S] = k(f[0]);
96
+ A(() => {
97
+ f.includes(i) || S(f[0]);
98
+ }, [f, i]);
99
+ const [s, O] = k(() => {
100
+ const e = C(a);
101
+ return e ? _(e) : { h: 0, s: 0, v: 0, a: 1 };
102
+ }), [Y, y] = k(null), u = h || (i === "hex" || i === "rgba");
103
+ A(() => {
104
+ const e = C(a);
105
+ if (!e) return;
106
+ const l = _(e);
107
+ O(
108
+ (x) => g(w(x), "hex", u).toLowerCase() === a.trim().toLowerCase() ? x : l
109
+ );
110
+ }, [a, u]);
111
+ const b = V(
112
+ (e) => {
113
+ O(e), p(g(w(e), "hex", u));
114
+ },
115
+ [p, u]
116
+ ), R = L((e, l, x) => {
117
+ const { x: v, y: J } = E(x, e, l, "both");
118
+ b({ ...s, s: v, v: 1 - J });
119
+ }), $ = L((e, l, x) => {
120
+ const { x: v } = E(x, e, 0, "x");
121
+ b({ ...s, h: v * 360 });
122
+ }), j = L((e, l, x) => {
123
+ const { x: v } = E(x, e, 0, "x");
124
+ b({ ...s, a: v });
125
+ }), I = g(w({ h: s.h, s: 1, v: 1, a: 1 }), "hex"), T = g(w({ ...s, a: 1 }), "hex"), F = g(w(s), "hex", u), U = u ? s.a : 1, P = r.find(
126
+ (e) => e.toLowerCase() === F.toLowerCase()
127
+ ), q = Y ?? g(w(s), i, Z[i]).replace(
128
+ i === "hex" ? /^#/ : /^$/,
129
+ ""
130
+ ), G = f.length > 1;
131
+ return /* @__PURE__ */ d("div", { className: N("flex w-[232px] flex-col gap-4", X), children: [
132
+ /* @__PURE__ */ d(
133
+ "div",
134
+ {
135
+ ref: R.ref,
136
+ onPointerDown: R.start,
137
+ className: "relative h-[152px] w-full cursor-crosshair touch-none overflow-hidden rounded",
138
+ style: {
139
+ backgroundImage: "repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%)",
140
+ backgroundSize: "16px 16px"
141
+ },
142
+ children: [
143
+ /* @__PURE__ */ t(
144
+ "div",
145
+ {
146
+ className: "pointer-events-none absolute inset-0",
147
+ style: {
148
+ opacity: U,
149
+ backgroundColor: I,
150
+ backgroundImage: "linear-gradient(to top, #000 0%, transparent 100%), linear-gradient(to right, #fff 0%, transparent 100%)"
151
+ }
152
+ }
153
+ ),
154
+ /* @__PURE__ */ t(
155
+ "span",
156
+ {
157
+ className: "pointer-events-none absolute size-4 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-[0px_2px_4px_rgba(31,41,55,0.2)]",
158
+ style: {
159
+ left: `calc(8px + ${s.s} * (100% - 16px))`,
160
+ top: `calc(8px + ${1 - s.v} * (100% - 16px))`,
161
+ // actual color incl. alpha, so the dot matches the square
162
+ backgroundColor: F
163
+ }
164
+ }
165
+ )
166
+ ]
167
+ }
168
+ ),
169
+ /* @__PURE__ */ t(
170
+ "div",
171
+ {
172
+ ref: $.ref,
173
+ onPointerDown: $.start,
174
+ className: "relative h-2 w-full cursor-pointer touch-none rounded-full",
175
+ style: {
176
+ backgroundImage: "linear-gradient(90deg, #FF0000 0%, #FF8A00 12%, #FFE600 25%, #14FF00 39%, #00A3FF 50%, #0500FF 62%, #AD00FF 73%, #FF00C7 85%, #FF0000 100%)"
177
+ },
178
+ children: /* @__PURE__ */ t(
179
+ "span",
180
+ {
181
+ className: "pointer-events-none absolute top-1/2 size-4 -translate-y-1/2 rounded-full border-2 border-white shadow-[0px_2px_4px_rgba(31,41,55,0.2)]",
182
+ style: {
183
+ left: `calc(${s.h / 360} * (100% - 16px))`,
184
+ backgroundColor: I
185
+ }
186
+ }
187
+ )
188
+ }
189
+ ),
190
+ u && /* @__PURE__ */ t(
191
+ "div",
192
+ {
193
+ ref: j.ref,
194
+ onPointerDown: j.start,
195
+ className: "relative h-2 w-full cursor-pointer touch-none rounded-full",
196
+ style: {
197
+ backgroundImage: `linear-gradient(90deg, transparent 0%, ${T} 100%), repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%)`,
198
+ backgroundSize: "100% 100%, 6px 6px"
199
+ },
200
+ children: /* @__PURE__ */ t(
201
+ "span",
202
+ {
203
+ className: "pointer-events-none absolute top-1/2 size-4 -translate-y-1/2 rounded-full border-2 border-white shadow-[0px_2px_4px_rgba(31,41,55,0.2)]",
204
+ style: {
205
+ left: `calc(${s.a} * (100% - 16px))`,
206
+ backgroundColor: T
207
+ }
208
+ }
209
+ )
210
+ }
211
+ ),
212
+ /* @__PURE__ */ d("div", { className: "flex items-start gap-2", children: [
213
+ G && /* @__PURE__ */ t(
214
+ ee,
215
+ {
216
+ value: i,
217
+ options: f,
218
+ onChange: (e) => {
219
+ y(null), S(e);
220
+ }
221
+ }
222
+ ),
223
+ /* @__PURE__ */ d("div", { className: "flex h-7 flex-1 items-center gap-1 rounded border border-[#E5E7EB] bg-white px-1.5 shadow-[0px_1px_2px_rgba(31,41,55,0.08)]", children: [
224
+ i === "hex" && /* @__PURE__ */ t("span", { className: "text-sm text-[#9CA3AF]", children: "#" }),
225
+ /* @__PURE__ */ t(
226
+ "input",
227
+ {
228
+ value: q,
229
+ onChange: (e) => {
230
+ y(e.target.value);
231
+ const l = Q(e.target.value, i);
232
+ l && b(_(l));
233
+ },
234
+ onBlur: () => y(null),
235
+ className: "w-full min-w-0 bg-transparent text-sm text-[#374151] outline-none",
236
+ "aria-label": `${B[i]} value`
237
+ }
238
+ )
239
+ ] }),
240
+ u && i === "hex" && /* @__PURE__ */ t("div", { className: "flex h-7 w-[56px] shrink-0 items-center rounded border border-[#E5E7EB] bg-white px-1.5 shadow-[0px_1px_2px_rgba(31,41,55,0.08)]", children: /* @__PURE__ */ t(
241
+ "input",
242
+ {
243
+ value: `${Math.round(s.a * 100)}%`,
244
+ onChange: (e) => {
245
+ const l = parseInt(e.target.value.replace(/[^0-9]/g, ""), 10);
246
+ Number.isNaN(l) || b({ ...s, a: z(l, 0, 100) / 100 });
247
+ },
248
+ className: "w-full bg-transparent text-sm text-[#374151] outline-none",
249
+ "aria-label": "Alpha percent"
250
+ }
251
+ ) })
252
+ ] }),
253
+ (!!o || r.length > 0) && /* @__PURE__ */ d(K, { children: [
254
+ /* @__PURE__ */ d("div", { className: "flex items-center justify-between", children: [
255
+ /* @__PURE__ */ t("span", { className: "text-xs font-medium text-[#374151]", children: n }),
256
+ /* @__PURE__ */ d("div", { className: "flex items-center gap-2", children: [
257
+ !!c && P && /* @__PURE__ */ t(
258
+ "button",
259
+ {
260
+ type: "button",
261
+ "aria-label": D,
262
+ title: D,
263
+ className: "flex cursor-pointer items-center text-[#6B7280] hover:text-[#EF4444]",
264
+ onClick: () => c?.(P),
265
+ children: /* @__PURE__ */ t("svg", { viewBox: "0 0 16 16", className: "size-3.5", fill: "none", children: /* @__PURE__ */ t(
266
+ "path",
267
+ {
268
+ d: "M2.5 4h11M6.5 4V2.8c0-.4.3-.8.8-.8h1.4c.5 0 .8.4.8.8V4M4 4l.6 8.3c0 .6.5 1 1 1h4.8c.5 0 1-.4 1-1L12 4M6.5 6.8v4M9.5 6.8v4",
269
+ stroke: "currentColor",
270
+ strokeWidth: "1.1",
271
+ strokeLinecap: "round",
272
+ strokeLinejoin: "round"
273
+ }
274
+ ) })
275
+ }
276
+ ),
277
+ !!o && /* @__PURE__ */ t(
278
+ "button",
279
+ {
280
+ type: "button",
281
+ className: "text-xs font-medium text-[#6B7280] hover:text-[#374151]",
282
+ onClick: () => o?.(F),
283
+ children: m
284
+ }
285
+ )
286
+ ] })
287
+ ] }),
288
+ r.length > 0 && /* @__PURE__ */ t("div", { className: "grid grid-cols-7 gap-2", children: r.map((e) => /* @__PURE__ */ d("div", { className: "relative size-6", children: [
289
+ /* @__PURE__ */ t(
290
+ "span",
291
+ {
292
+ className: "absolute inset-0 rounded-full",
293
+ style: {
294
+ backgroundImage: "repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%)",
295
+ backgroundSize: "8px 8px"
296
+ }
297
+ }
298
+ ),
299
+ /* @__PURE__ */ t(
300
+ "button",
301
+ {
302
+ type: "button",
303
+ title: e,
304
+ onClick: () => {
305
+ const l = C(e);
306
+ l && b(_(l));
307
+ },
308
+ className: N(
309
+ "absolute inset-0 cursor-pointer rounded-full",
310
+ F.toLowerCase() === e.toLowerCase() && "border-2 border-white shadow-[0px_0px_0px_2px_rgba(0,0,0,0.25)]"
311
+ ),
312
+ style: { backgroundColor: e }
313
+ }
314
+ )
315
+ ] }, e)) })
316
+ ] })
317
+ ] });
318
+ };
319
+ export {
320
+ se as ColorPicker
321
+ };
322
+ //# sourceMappingURL=ColorPicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorPicker.js","sources":["../../src/ColorInput/ColorPicker.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\r\n\r\nimport { cn } from '@oneplatformdev/utils';\r\n\r\nimport {\r\n clamp,\r\n COLOR_FORMAT_LABELS,\r\n COLOR_FORMATS,\r\n ColorFormat,\r\n formatColor,\r\n FORMAT_HAS_ALPHA,\r\n HSVA,\r\n hsvaToRgba,\r\n parseColor,\r\n parseColorInFormat,\r\n rgbaToHsva,\r\n} from './color.utils';\r\n\r\n/** Compact, styled dropdown for the color format (Hex / RGB / RGBA / …). */\r\nconst FormatSelect = ({\r\n value,\r\n options,\r\n onChange,\r\n}: {\r\n value: ColorFormat;\r\n options: ColorFormat[];\r\n onChange: (next: ColorFormat) => void;\r\n}) => {\r\n const [open, setOpen] = useState(false);\r\n const ref = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n const onDown = (e: MouseEvent) => {\r\n if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);\r\n };\r\n window.addEventListener('mousedown', onDown);\r\n return () => window.removeEventListener('mousedown', onDown);\r\n }, [open]);\r\n\r\n return (\r\n <div ref={ref} className=\"relative w-[74px] shrink-0\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setOpen((o) => !o)}\r\n aria-haspopup=\"listbox\"\r\n aria-expanded={open}\r\n className={cn(\r\n 'flex h-7 w-full cursor-pointer items-center justify-between rounded border bg-white pl-2 pr-1.5 text-sm text-[#374151] shadow-[0px_1px_2px_rgba(31,41,55,0.08)] transition-colors',\r\n open ? 'border-[#9368FF]' : 'border-[#E5E7EB] hover:border-[#D1D5DB]',\r\n )}\r\n >\r\n <span>{COLOR_FORMAT_LABELS[value]}</span>\r\n <svg className=\"size-3 text-[#9CA3AF]\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M3.5 5 6 2.5 8.5 5\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n <path d=\"M3.5 7 6 9.5 8.5 7\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\r\n </svg>\r\n </button>\r\n\r\n {open && (\r\n <ul\r\n role=\"listbox\"\r\n className=\"absolute left-0 top-[calc(100%+4px)] z-20 w-full overflow-hidden rounded border border-[#E5E7EB] bg-white py-1 shadow-[0px_10px_15px_rgba(31,41,55,0.1),0px_4px_6px_rgba(31,41,55,0.05)]\"\r\n >\r\n {options.map((f) => (\r\n <li key={f}>\r\n <button\r\n type=\"button\"\r\n role=\"option\"\r\n aria-selected={f === value}\r\n onClick={() => {\r\n onChange(f);\r\n setOpen(false);\r\n }}\r\n className={cn(\r\n 'flex w-full cursor-pointer items-center px-2 py-1 text-left text-sm hover:bg-[#F3F4F6]',\r\n f === value ? 'font-medium text-[#9368FF]' : 'text-[#374151]',\r\n )}\r\n >\r\n {COLOR_FORMAT_LABELS[f]}\r\n </button>\r\n </li>\r\n ))}\r\n </ul>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport interface ColorPickerProps {\r\n value: string;\r\n onChange: (hex: string) => void;\r\n withAlpha?: boolean;\r\n /** Saved-colors palette. Empty by default. */\r\n savedColors?: string[];\r\n /** Renders the \"+ Add\" action; called with the current color. */\r\n onAddSavedColor?: (hex: string) => void;\r\n /** When provided, each saved swatch gets a hover \"×\" to remove it. */\r\n onRemoveSavedColor?: (hex: string) => void;\r\n /** Label before the palette (i18n). Default \"Saved colors:\". */\r\n savedColorsLabel?: string;\r\n /** Label of the add action (i18n). Default \"+ Add\". */\r\n addLabel?: string;\r\n /** Accessible label for a swatch's remove button (i18n). Default \"Remove color\". */\r\n removeColorLabel?: string;\r\n /**\r\n * Color formats offered in the format dropdown. Defaults to all of them\r\n * (`['hex', 'rgb', 'rgba', 'hsl', 'hsb']`). Pass a subset to restrict input,\r\n * e.g. `formats={['hex']}` to only allow hex. With a single format the\r\n * dropdown is hidden.\r\n */\r\n formats?: ColorFormat[];\r\n className?: string;\r\n}\r\n\r\n/** Returns a 0..1 ratio of pointer position inside an element along an axis. */\r\nconst ratioFromPointer = (\r\n el: HTMLElement,\r\n clientX: number,\r\n clientY: number,\r\n axis: 'x' | 'y' | 'both',\r\n): { x: number; y: number } => {\r\n const rect = el.getBoundingClientRect();\r\n const x = clamp((clientX - rect.left) / rect.width, 0, 1);\r\n const y = clamp((clientY - rect.top) / rect.height, 0, 1);\r\n return {\r\n x: axis === 'y' ? 0 : x,\r\n y: axis === 'x' ? 0 : y,\r\n };\r\n};\r\n\r\nconst useDrag = (\r\n onMove: (clientX: number, clientY: number, el: HTMLElement) => void,\r\n) => {\r\n const ref = useRef<HTMLDivElement>(null);\r\n\r\n const start = useCallback(\r\n (e: React.PointerEvent) => {\r\n const el = ref.current;\r\n if (!el) return;\r\n e.preventDefault();\r\n onMove(e.clientX, e.clientY, el);\r\n\r\n const handleMove = (ev: PointerEvent) =>\r\n onMove(ev.clientX, ev.clientY, el);\r\n const handleUp = () => {\r\n window.removeEventListener('pointermove', handleMove);\r\n window.removeEventListener('pointerup', handleUp);\r\n };\r\n window.addEventListener('pointermove', handleMove);\r\n window.addEventListener('pointerup', handleUp);\r\n },\r\n [onMove],\r\n );\r\n\r\n return { ref, start };\r\n};\r\n\r\nexport const ColorPicker = ({\r\n value,\r\n onChange,\r\n withAlpha = false,\r\n savedColors = [],\r\n onAddSavedColor,\r\n onRemoveSavedColor,\r\n savedColorsLabel = 'Saved colors:',\r\n addLabel = '+ Add',\r\n removeColorLabel = 'Remove color',\r\n formats = COLOR_FORMATS,\r\n className,\r\n}: ColorPickerProps) => {\r\n const availableFormats = formats.length ? formats : COLOR_FORMATS;\r\n const [format, setFormat] = useState<ColorFormat>(availableFormats[0]);\r\n\r\n // Keep the active format within the allowed set if `formats` changes.\r\n useEffect(() => {\r\n if (!availableFormats.includes(format)) setFormat(availableFormats[0]);\r\n }, [availableFormats, format]);\r\n\r\n const [hsva, setHsva] = useState<HSVA>(() => {\r\n const rgba = parseColor(value);\r\n return rgba ? rgbaToHsva(rgba) : { h: 0, s: 0, v: 0, a: 1 };\r\n });\r\n\r\n // Local text buffer so partially-typed values (e.g. \"255, 20\") don't get\r\n // snapped back by the controlled value while the user is mid-edit.\r\n const [fieldText, setFieldText] = useState<string | null>(null);\r\n\r\n // Alpha only makes sense for formats that can encode it: hex (#RRGGBBAA) and\r\n // rgba. rgb/hsl/hsb have no alpha channel, so the transparency slider is\r\n // hidden there. `withAlpha` can still force it on explicitly.\r\n const formatSupportsAlpha = format === 'hex' || format === 'rgba';\r\n const alphaEnabled = withAlpha || formatSupportsAlpha;\r\n\r\n // Sync from external value, but keep internal hue when only it differs\r\n // (prevents the hue jumping when saturation/value reach extremes).\r\n useEffect(() => {\r\n const rgba = parseColor(value);\r\n if (!rgba) return;\r\n const next = rgbaToHsva(rgba);\r\n setHsva((prev) =>\r\n formatColor(hsvaToRgba(prev), 'hex', alphaEnabled).toLowerCase() ===\r\n value.trim().toLowerCase()\r\n ? prev\r\n : next,\r\n );\r\n }, [value, alphaEnabled]);\r\n\r\n const emit = useCallback(\r\n (next: HSVA) => {\r\n setHsva(next);\r\n onChange(formatColor(hsvaToRgba(next), 'hex', alphaEnabled));\r\n },\r\n [onChange, alphaEnabled],\r\n );\r\n\r\n const saturation = useDrag((x, y, el) => {\r\n const { x: rx, y: ry } = ratioFromPointer(el, x, y, 'both');\r\n emit({ ...hsva, s: rx, v: 1 - ry });\r\n });\r\n const hue = useDrag((x, _y, el) => {\r\n const { x: rx } = ratioFromPointer(el, x, 0, 'x');\r\n emit({ ...hsva, h: rx * 360 });\r\n });\r\n const alpha = useDrag((x, _y, el) => {\r\n const { x: rx } = ratioFromPointer(el, x, 0, 'x');\r\n emit({ ...hsva, a: rx });\r\n });\r\n\r\n const hueColor = formatColor(hsvaToRgba({ h: hsva.h, s: 1, v: 1, a: 1 }), 'hex');\r\n const solidColor = formatColor(hsvaToRgba({ ...hsva, a: 1 }), 'hex');\r\n // The actual color with its alpha applied — used for the palette opacity and\r\n // for what \"+ Add\" saves (so a semi-transparent color is stored as #rrggbbaa).\r\n const currentColor = formatColor(hsvaToRgba(hsva), 'hex', alphaEnabled);\r\n const paletteOpacity = alphaEnabled ? hsva.a : 1;\r\n // The saved swatch matching the current color — the trash button targets it.\r\n const selectedSavedColor = savedColors.find(\r\n (c) => c.toLowerCase() === currentColor.toLowerCase(),\r\n );\r\n // The value field shows alpha inline only for formats that encode it (RGBA).\r\n // For hex/rgb/hsl/hsb the alpha lives in the separate `%` field instead.\r\n const fieldValue =\r\n fieldText ??\r\n formatColor(hsvaToRgba(hsva), format, FORMAT_HAS_ALPHA[format]).replace(\r\n format === 'hex' ? /^#/ : /^$/,\r\n '',\r\n );\r\n\r\n const showFormatSelect = availableFormats.length > 1;\r\n\r\n return (\r\n <div className={cn('flex w-[232px] flex-col gap-4', className)}>\r\n {/* Saturation / Value area — checker shows through as alpha drops. */}\r\n <div\r\n ref={saturation.ref}\r\n onPointerDown={saturation.start}\r\n className=\"relative h-[152px] w-full cursor-crosshair touch-none overflow-hidden rounded\"\r\n style={{\r\n backgroundImage:\r\n 'repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%)',\r\n backgroundSize: '16px 16px',\r\n }}\r\n >\r\n <div\r\n className=\"pointer-events-none absolute inset-0\"\r\n style={{\r\n opacity: paletteOpacity,\r\n backgroundColor: hueColor,\r\n backgroundImage:\r\n 'linear-gradient(to top, #000 0%, transparent 100%), linear-gradient(to right, #fff 0%, transparent 100%)',\r\n }}\r\n />\r\n <span\r\n className=\"pointer-events-none absolute size-4 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-[0px_2px_4px_rgba(31,41,55,0.2)]\"\r\n style={{\r\n left: `calc(8px + ${hsva.s} * (100% - 16px))`,\r\n top: `calc(8px + ${1 - hsva.v} * (100% - 16px))`,\r\n // actual color incl. alpha, so the dot matches the square\r\n backgroundColor: currentColor,\r\n }}\r\n />\r\n </div>\r\n\r\n {/* Hue slider */}\r\n <div\r\n ref={hue.ref}\r\n onPointerDown={hue.start}\r\n className=\"relative h-2 w-full cursor-pointer touch-none rounded-full\"\r\n style={{\r\n backgroundImage:\r\n 'linear-gradient(90deg, #FF0000 0%, #FF8A00 12%, #FFE600 25%, #14FF00 39%, #00A3FF 50%, #0500FF 62%, #AD00FF 73%, #FF00C7 85%, #FF0000 100%)',\r\n }}\r\n >\r\n <span\r\n className=\"pointer-events-none absolute top-1/2 size-4 -translate-y-1/2 rounded-full border-2 border-white shadow-[0px_2px_4px_rgba(31,41,55,0.2)]\"\r\n style={{\r\n left: `calc(${hsva.h / 360} * (100% - 16px))`,\r\n backgroundColor: hueColor,\r\n }}\r\n />\r\n </div>\r\n\r\n {/* Alpha (transparency) slider */}\r\n {alphaEnabled && (\r\n <div\r\n ref={alpha.ref}\r\n onPointerDown={alpha.start}\r\n className=\"relative h-2 w-full cursor-pointer touch-none rounded-full\"\r\n style={{\r\n backgroundImage: `linear-gradient(90deg, transparent 0%, ${solidColor} 100%), repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%)`,\r\n backgroundSize: '100% 100%, 6px 6px',\r\n }}\r\n >\r\n <span\r\n className=\"pointer-events-none absolute top-1/2 size-4 -translate-y-1/2 rounded-full border-2 border-white shadow-[0px_2px_4px_rgba(31,41,55,0.2)]\"\r\n style={{\r\n left: `calc(${hsva.a} * (100% - 16px))`,\r\n backgroundColor: solidColor,\r\n }}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* Fields: format select + value + optional alpha % */}\r\n <div className=\"flex items-start gap-2\">\r\n {showFormatSelect && (\r\n <FormatSelect\r\n value={format}\r\n options={availableFormats}\r\n onChange={(next) => {\r\n setFieldText(null);\r\n setFormat(next);\r\n }}\r\n />\r\n )}\r\n\r\n <div className=\"flex h-7 flex-1 items-center gap-1 rounded border border-[#E5E7EB] bg-white px-1.5 shadow-[0px_1px_2px_rgba(31,41,55,0.08)]\">\r\n {format === 'hex' && <span className=\"text-sm text-[#9CA3AF]\">#</span>}\r\n <input\r\n value={fieldValue}\r\n onChange={(e) => {\r\n setFieldText(e.target.value);\r\n const rgba = parseColorInFormat(e.target.value, format);\r\n if (rgba) emit(rgbaToHsva(rgba));\r\n }}\r\n onBlur={() => setFieldText(null)}\r\n className=\"w-full min-w-0 bg-transparent text-sm text-[#374151] outline-none\"\r\n aria-label={`${COLOR_FORMAT_LABELS[format]} value`}\r\n />\r\n </div>\r\n\r\n {/*\r\n The separate % field is only for hex (its value is short, so 3 boxes\r\n fit). RGBA carries alpha in its value field; rgb/hsl/hsb control alpha\r\n via the slider — keeping their (long) value field from being squeezed.\r\n */}\r\n {alphaEnabled && format === 'hex' && (\r\n <div className=\"flex h-7 w-[56px] shrink-0 items-center rounded border border-[#E5E7EB] bg-white px-1.5 shadow-[0px_1px_2px_rgba(31,41,55,0.08)]\">\r\n <input\r\n value={`${Math.round(hsva.a * 100)}%`}\r\n onChange={(e) => {\r\n const num = parseInt(e.target.value.replace(/[^0-9]/g, ''), 10);\r\n if (!Number.isNaN(num)) emit({ ...hsva, a: clamp(num, 0, 100) / 100 });\r\n }}\r\n className=\"w-full bg-transparent text-sm text-[#374151] outline-none\"\r\n aria-label=\"Alpha percent\"\r\n />\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Saved colors */}\r\n {(Boolean(onAddSavedColor) || savedColors.length > 0) && (\r\n <>\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"text-xs font-medium text-[#374151]\">\r\n {savedColorsLabel}\r\n </span>\r\n <div className=\"flex items-center gap-2\">\r\n {/* Remove the currently selected swatch (avoids per-dot crosses). */}\r\n {Boolean(onRemoveSavedColor) && selectedSavedColor && (\r\n <button\r\n type=\"button\"\r\n aria-label={removeColorLabel}\r\n title={removeColorLabel}\r\n className=\"flex cursor-pointer items-center text-[#6B7280] hover:text-[#EF4444]\"\r\n onClick={() => onRemoveSavedColor?.(selectedSavedColor)}\r\n >\r\n <svg viewBox=\"0 0 16 16\" className=\"size-3.5\" fill=\"none\">\r\n <path\r\n d=\"M2.5 4h11M6.5 4V2.8c0-.4.3-.8.8-.8h1.4c.5 0 .8.4.8.8V4M4 4l.6 8.3c0 .6.5 1 1 1h4.8c.5 0 1-.4 1-1L12 4M6.5 6.8v4M9.5 6.8v4\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.1\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n />\r\n </svg>\r\n </button>\r\n )}\r\n {Boolean(onAddSavedColor) && (\r\n <button\r\n type=\"button\"\r\n className=\"text-xs font-medium text-[#6B7280] hover:text-[#374151]\"\r\n onClick={() => onAddSavedColor?.(currentColor)}\r\n >\r\n {addLabel}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n {savedColors.length > 0 && (\r\n <div className=\"grid grid-cols-7 gap-2\">\r\n {savedColors.map((color) => (\r\n <div key={color} className=\"relative size-6\">\r\n {/* checker so semi-transparent swatches read correctly */}\r\n <span\r\n className=\"absolute inset-0 rounded-full\"\r\n style={{\r\n backgroundImage:\r\n 'repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%)',\r\n backgroundSize: '8px 8px',\r\n }}\r\n />\r\n <button\r\n type=\"button\"\r\n title={color}\r\n onClick={() => {\r\n const rgba = parseColor(color);\r\n if (rgba) emit(rgbaToHsva(rgba));\r\n }}\r\n className={cn(\r\n 'absolute inset-0 cursor-pointer rounded-full',\r\n currentColor.toLowerCase() === color.toLowerCase() &&\r\n 'border-2 border-white shadow-[0px_0px_0px_2px_rgba(0,0,0,0.25)]',\r\n )}\r\n style={{ backgroundColor: color }}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </>\r\n )}\r\n </div>\r\n );\r\n};\r\n"],"names":["FormatSelect","value","options","onChange","open","setOpen","useState","ref","useRef","useEffect","onDown","e","jsxs","o","cn","jsx","COLOR_FORMAT_LABELS","f","ratioFromPointer","el","clientX","clientY","axis","rect","x","clamp","y","useDrag","onMove","start","useCallback","handleMove","ev","handleUp","ColorPicker","withAlpha","savedColors","onAddSavedColor","onRemoveSavedColor","savedColorsLabel","addLabel","removeColorLabel","formats","COLOR_FORMATS","className","availableFormats","format","setFormat","hsva","setHsva","rgba","parseColor","rgbaToHsva","fieldText","setFieldText","alphaEnabled","next","prev","formatColor","hsvaToRgba","emit","saturation","rx","ry","hue","_y","alpha","hueColor","solidColor","currentColor","paletteOpacity","selectedSavedColor","c","fieldValue","FORMAT_HAS_ALPHA","showFormatSelect","parseColorInFormat","num","Fragment","color"],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ export interface RGBA {
2
+ r: number;
3
+ g: number;
4
+ b: number;
5
+ a: number;
6
+ }
7
+ export interface HSVA {
8
+ h: number;
9
+ s: number;
10
+ v: number;
11
+ a: number;
12
+ }
13
+ export declare const clamp: (value: number, min: number, max: number) => number;
14
+ /** Parses #rgb / #rrggbb / #rrggbbaa (with or without leading #) into RGBA. */
15
+ export declare const parseColor: (input: string) => RGBA | null;
16
+ export declare const isValidColor: (input: string) => boolean;
17
+ /** Formats RGBA to a hex string. Includes the alpha byte only when withAlpha and a<1. */
18
+ export declare const rgbaToHex: (rgba: RGBA, withAlpha?: boolean) => string;
19
+ export declare const rgbaToHsva: ({ r, g, b, a }: RGBA) => HSVA;
20
+ export declare const hsvaToRgba: ({ h, s, v, a }: HSVA) => RGBA;
21
+ /** Color string formats the picker can read/emit. */
22
+ export type ColorFormat = 'hex' | 'rgb' | 'rgba' | 'hsl' | 'hsb';
23
+ /** All formats, in the order they appear in the format dropdown. */
24
+ export declare const COLOR_FORMATS: ColorFormat[];
25
+ export declare const COLOR_FORMAT_LABELS: Record<ColorFormat, string>;
26
+ /** Formats that carry an alpha channel — these enable the transparency slider. */
27
+ export declare const FORMAT_HAS_ALPHA: Record<ColorFormat, boolean>;
28
+ export interface HSLA {
29
+ h: number;
30
+ s: number;
31
+ l: number;
32
+ a: number;
33
+ }
34
+ export declare const rgbaToHsla: ({ r, g, b, a }: RGBA) => HSLA;
35
+ export declare const hslaToRgba: ({ h, s, l, a }: HSLA) => RGBA;
36
+ /** Renders an RGBA value as a string in the requested format. */
37
+ export declare const formatColor: (rgba: RGBA, format: ColorFormat, withAlpha?: boolean) => string;
38
+ /** Parses a string written in the given format back into RGBA. */
39
+ export declare const parseColorInFormat: (input: string, format: ColorFormat) => RGBA | null;
40
+ /** Default saved-colors palette mirroring the Figma design. */
41
+ export declare const DEFAULT_SAVED_COLORS: string[];
42
+ //# sourceMappingURL=color.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color.utils.d.ts","sourceRoot":"","sources":["../../src/ColorInput/color.utils.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,IAAI;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,IAAI;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,MAC3B,CAAC;AAKtC,+EAA+E;AAC/E,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,KAAG,IAAI,GAAG,IA8BjD,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,OAAqC,CAAC;AAEnF,yFAAyF;AACzF,eAAO,MAAM,SAAS,GAAI,MAAM,IAAI,EAAE,mBAAiB,KAAG,MAIzD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,gBAAgB,IAAI,KAAG,IAmBjD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,gBAAgB,IAAI,KAAG,IAqBjD,CAAC;AAEF,qDAAqD;AACrD,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;AAEjE,oEAAoE;AACpE,eAAO,MAAM,aAAa,EAAE,WAAW,EAAyC,CAAC;AAEjF,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAM3D,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CAMzD,CAAC;AAEF,MAAM,WAAW,IAAI;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,eAAO,MAAM,UAAU,GAAI,gBAAgB,IAAI,KAAG,IAoBjD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,gBAAgB,IAAI,KAAG,IAqBjD,CAAC;AAKF,iEAAiE;AACjE,eAAO,MAAM,WAAW,GACtB,MAAM,IAAI,EACV,QAAQ,WAAW,EACnB,mBAAiB,KAChB,MAoBF,CAAC;AAKF,kEAAkE;AAClE,eAAO,MAAM,kBAAkB,GAC7B,OAAO,MAAM,EACb,QAAQ,WAAW,KAClB,IAAI,GAAG,IA8BT,CAAC;AAEF,+DAA+D;AAC/D,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAexC,CAAC"}
@@ -0,0 +1,129 @@
1
+ const u = (t, n, e) => Math.min(e, Math.max(n, t)), b = (t) => u(Math.round(t), 0, 255).toString(16).padStart(2, "0"), m = (t) => {
2
+ if (!t) return null;
3
+ let n = t.trim().replace(/^#/, "");
4
+ return /^[0-9a-f]{3}$/i.test(n) && (n = n.split("").map((e) => e + e).join("")), /^[0-9a-f]{6}$/i.test(n) ? {
5
+ r: parseInt(n.slice(0, 2), 16),
6
+ g: parseInt(n.slice(2, 4), 16),
7
+ b: parseInt(n.slice(4, 6), 16),
8
+ a: 1
9
+ } : /^[0-9a-f]{8}$/i.test(n) ? {
10
+ r: parseInt(n.slice(0, 2), 16),
11
+ g: parseInt(n.slice(2, 4), 16),
12
+ b: parseInt(n.slice(4, 6), 16),
13
+ a: parseInt(n.slice(6, 8), 16) / 255
14
+ } : null;
15
+ }, E = (t) => m(t) !== null, x = (t, n = !1) => {
16
+ const e = `#${b(t.r)}${b(t.g)}${b(t.b)}`;
17
+ return n && t.a < 1 ? `${e}${b(t.a * 255)}` : e;
18
+ }, g = ({ r: t, g: n, b: e, a: h }) => {
19
+ const s = t / 255, r = n / 255, c = e / 255, l = Math.max(s, r, c), a = Math.min(s, r, c), o = l - a;
20
+ let i = 0;
21
+ o !== 0 && (l === s ? i = (r - c) / o % 6 : l === r ? i = (c - s) / o + 2 : i = (s - r) / o + 4, i *= 60, i < 0 && (i += 360));
22
+ const $ = l === 0 ? 0 : o / l;
23
+ return { h: i, s: $, v: l, a: h };
24
+ }, F = ({ h: t, s: n, v: e, a: h }) => {
25
+ const s = e * n, r = s * (1 - Math.abs(t / 60 % 2 - 1)), c = e - s;
26
+ let l = 0, a = 0, o = 0;
27
+ return t < 60 ? [l, a, o] = [s, r, 0] : t < 120 ? [l, a, o] = [r, s, 0] : t < 180 ? [l, a, o] = [0, s, r] : t < 240 ? [l, a, o] = [0, r, s] : t < 300 ? [l, a, o] = [r, 0, s] : [l, a, o] = [s, 0, r], {
28
+ r: Math.round((l + c) * 255),
29
+ g: Math.round((a + c) * 255),
30
+ b: Math.round((o + c) * 255),
31
+ a: h
32
+ };
33
+ }, R = ["hex", "rgb", "rgba", "hsl", "hsb"], H = {
34
+ hex: "Hex",
35
+ rgb: "RGB",
36
+ rgba: "RGBA",
37
+ hsl: "HSL",
38
+ hsb: "HSB"
39
+ }, O = {
40
+ hex: !1,
41
+ rgb: !1,
42
+ rgba: !0,
43
+ hsl: !1,
44
+ hsb: !1
45
+ }, p = ({ r: t, g: n, b: e, a: h }) => {
46
+ const s = t / 255, r = n / 255, c = e / 255, l = Math.max(s, r, c), a = Math.min(s, r, c), o = l - a;
47
+ let i = 0;
48
+ o !== 0 && (l === s ? i = (r - c) / o % 6 : l === r ? i = (c - s) / o + 2 : i = (s - r) / o + 4, i *= 60, i < 0 && (i += 360));
49
+ const $ = (l + a) / 2, d = o === 0 ? 0 : o / (1 - Math.abs(2 * $ - 1));
50
+ return { h: i, s: d, l: $, a: h };
51
+ }, C = ({ h: t, s: n, l: e, a: h }) => {
52
+ const s = (1 - Math.abs(2 * e - 1)) * n, r = s * (1 - Math.abs(t / 60 % 2 - 1)), c = e - s / 2;
53
+ let l = 0, a = 0, o = 0;
54
+ return t < 60 ? [l, a, o] = [s, r, 0] : t < 120 ? [l, a, o] = [r, s, 0] : t < 180 ? [l, a, o] = [0, s, r] : t < 240 ? [l, a, o] = [0, r, s] : t < 300 ? [l, a, o] = [r, 0, s] : [l, a, o] = [s, 0, r], {
55
+ r: Math.round((l + c) * 255),
56
+ g: Math.round((a + c) * 255),
57
+ b: Math.round((o + c) * 255),
58
+ a: h
59
+ };
60
+ }, f = (t) => Math.round(t), M = (t) => `${Math.round(t * 100)}%`, S = (t, n, e = !1) => {
61
+ switch (n) {
62
+ case "rgba":
63
+ return `${f(t.r)}, ${f(t.g)}, ${f(t.b)}, ${Number(t.a.toFixed(2))}`;
64
+ case "rgb":
65
+ return e && t.a < 1 ? `${f(t.r)}, ${f(t.g)}, ${f(t.b)}, ${Number(t.a.toFixed(2))}` : `${f(t.r)}, ${f(t.g)}, ${f(t.b)}`;
66
+ case "hsl": {
67
+ const { h, s, l: r } = p(t);
68
+ return `${f(h)}, ${M(s)}, ${M(r)}`;
69
+ }
70
+ case "hsb": {
71
+ const { h, s, v: r } = g(t);
72
+ return `${f(h)}, ${M(s)}, ${M(r)}`;
73
+ }
74
+ case "hex":
75
+ default:
76
+ return x(t, e).toUpperCase();
77
+ }
78
+ }, A = (t) => (t.match(/-?\d*\.?\d+/g) || []).map(Number), T = (t, n) => {
79
+ if (n === "hex") return m(t);
80
+ const e = A(t);
81
+ return n === "rgb" || n === "rgba" ? e.length < 3 ? null : {
82
+ r: u(e[0], 0, 255),
83
+ g: u(e[1], 0, 255),
84
+ b: u(e[2], 0, 255),
85
+ a: e.length > 3 ? u(e[3], 0, 1) : 1
86
+ } : n === "hsl" ? e.length < 3 ? null : C({
87
+ h: u(e[0], 0, 360),
88
+ s: u(e[1], 0, 100) / 100,
89
+ l: u(e[2], 0, 100) / 100,
90
+ a: e.length > 3 ? u(e[3], 0, 1) : 1
91
+ }) : e.length < 3 ? null : F({
92
+ h: u(e[0], 0, 360),
93
+ s: u(e[1], 0, 100) / 100,
94
+ v: u(e[2], 0, 100) / 100,
95
+ a: e.length > 3 ? u(e[3], 0, 1) : 1
96
+ });
97
+ }, B = [
98
+ "#EF4444",
99
+ "#F97316",
100
+ "#FACC15",
101
+ "#4ADE80",
102
+ "#2DD4BF",
103
+ "#3B82F6",
104
+ "#6366F1",
105
+ "#EC4899",
106
+ "#F43F5E",
107
+ "#D946EF",
108
+ "#8B5CF6",
109
+ "#0EA5E9",
110
+ "#10B981",
111
+ "#84CC16"
112
+ ];
113
+ export {
114
+ R as COLOR_FORMATS,
115
+ H as COLOR_FORMAT_LABELS,
116
+ B as DEFAULT_SAVED_COLORS,
117
+ O as FORMAT_HAS_ALPHA,
118
+ u as clamp,
119
+ S as formatColor,
120
+ C as hslaToRgba,
121
+ F as hsvaToRgba,
122
+ E as isValidColor,
123
+ m as parseColor,
124
+ T as parseColorInFormat,
125
+ x as rgbaToHex,
126
+ p as rgbaToHsla,
127
+ g as rgbaToHsva
128
+ };
129
+ //# sourceMappingURL=color.utils.js.map