@oneplatformdev/ui 0.1.99-beta.302 → 0.1.99-beta.305
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/ColorInput/ColorInput.d.ts +10 -0
- package/ColorInput/ColorInput.d.ts.map +1 -0
- package/ColorInput/ColorInput.js +103 -0
- package/ColorInput/ColorInput.js.map +1 -0
- package/ColorInput/ColorInput.stories.js +78 -0
- package/ColorInput/ColorInput.stories.js.map +1 -0
- package/ColorInput/ColorInput.types.d.ts +46 -0
- package/ColorInput/ColorInput.types.d.ts.map +1 -0
- package/ColorInput/ColorInput.types.js +2 -0
- package/ColorInput/ColorInput.types.js.map +1 -0
- package/ColorInput/ColorPicker.d.ts +28 -0
- package/ColorInput/ColorPicker.d.ts.map +1 -0
- package/ColorInput/ColorPicker.js +322 -0
- package/ColorInput/ColorPicker.js.map +1 -0
- package/ColorInput/color.utils.d.ts +42 -0
- package/ColorInput/color.utils.d.ts.map +1 -0
- package/ColorInput/color.utils.js +129 -0
- package/ColorInput/color.utils.js.map +1 -0
- package/ColorInput/index.d.ts +6 -0
- package/ColorInput/index.d.ts.map +1 -0
- package/ColorInput/index.js +25 -0
- package/ColorInput/index.js.map +1 -0
- package/ColorInput/useSavedColors.d.ts +13 -0
- package/ColorInput/useSavedColors.d.ts.map +1 -0
- package/ColorInput/useSavedColors.js +53 -0
- package/ColorInput/useSavedColors.js.map +1 -0
- package/Combobox/ComboboxRenderContent.d.ts.map +1 -1
- package/Combobox/ComboboxRenderContent.js +38 -35
- package/Combobox/ComboboxRenderContent.js.map +1 -1
- package/Combobox/ComboboxRenderTrigger.js +8 -8
- package/FormColorInput/FormColorInput.d.ts +7 -0
- package/FormColorInput/FormColorInput.d.ts.map +1 -0
- package/FormColorInput/FormColorInput.js +38 -0
- package/FormColorInput/FormColorInput.js.map +1 -0
- package/FormColorInput/FormColorInput.stories.js +95 -0
- package/FormColorInput/FormColorInput.stories.js.map +1 -0
- package/FormColorInput/FormColorInput.types.d.ts +6 -0
- package/FormColorInput/FormColorInput.types.d.ts.map +1 -0
- package/FormColorInput/FormColorInput.types.js +2 -0
- package/FormColorInput/FormColorInput.types.js.map +1 -0
- package/FormColorInput/index.d.ts +3 -0
- package/FormColorInput/index.d.ts.map +1 -0
- package/FormColorInput/index.js +5 -0
- package/FormColorInput/index.js.map +1 -0
- package/FormCombobox/FormCombobox.stories.js.map +1 -1
- package/index.d.ts +2 -0
- package/index.d.ts.map +1 -1
- package/index.js +366 -342
- package/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ColorInputProps } from './ColorInput.types';
|
|
2
|
+
/**
|
|
3
|
+
* Color field: a text input showing the hex value with a color-indicator swatch
|
|
4
|
+
* that opens a full color picker popover. Mirrors the Figma branding design.
|
|
5
|
+
*
|
|
6
|
+
* Controlled via `value`/`onChange` (hex strings) — pair it with `FormColorInput`
|
|
7
|
+
* for react-hook-form usage, the same way `Input` pairs with `FormInput`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const ColorInput: import('react').ForwardRefExoticComponent<ColorInputProps & import('react').RefAttributes<HTMLInputElement>>;
|
|
10
|
+
//# sourceMappingURL=ColorInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorInput.d.ts","sourceRoot":"","sources":["../../src/ColorInput/ColorInput.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAKrD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,8GA6GtB,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { jsxs as v, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as L, useState as j } from "react";
|
|
3
|
+
import { cn as C } from "@oneplatformdev/utils";
|
|
4
|
+
import { ColorPicker as D } from "./ColorPicker.js";
|
|
5
|
+
import { parseColor as I, rgbaToHex as T, isValidColor as $ } from "./color.utils.js";
|
|
6
|
+
import { useSavedColors as z } from "./useSavedColors.js";
|
|
7
|
+
import { Popover as H, PopoverTrigger as K, PopoverContent as V } from "../Popover/Popover.js";
|
|
8
|
+
const W = L(
|
|
9
|
+
(u, f) => {
|
|
10
|
+
const {
|
|
11
|
+
value: s = "",
|
|
12
|
+
onChange: b,
|
|
13
|
+
withAlpha: g = !1,
|
|
14
|
+
error: h,
|
|
15
|
+
savedColors: d,
|
|
16
|
+
onAddSavedColor: i,
|
|
17
|
+
onRemoveSavedColor: m,
|
|
18
|
+
savedColorsLabel: x,
|
|
19
|
+
addLabel: S,
|
|
20
|
+
removeColorLabel: E,
|
|
21
|
+
storageKey: F,
|
|
22
|
+
formats: N,
|
|
23
|
+
className: k,
|
|
24
|
+
disabled: r,
|
|
25
|
+
onBlur: w,
|
|
26
|
+
...y
|
|
27
|
+
} = u, [c, A] = j(!1), a = z(F), l = d !== void 0 || i !== void 0 || m !== void 0, O = l ? d : a.savedColors, P = l ? i : a.addColor, B = l ? m : a.removeColor, p = I(s), R = p ? T(p, !0) : "#E8E9EB", n = (o) => b?.(o);
|
|
28
|
+
return /* @__PURE__ */ v(H, { open: c, onOpenChange: A, children: [
|
|
29
|
+
/* @__PURE__ */ v(
|
|
30
|
+
"div",
|
|
31
|
+
{
|
|
32
|
+
className: C(
|
|
33
|
+
"flex h-10 w-full items-center gap-2 rounded-lg border bg-[#FCFCFC] px-2",
|
|
34
|
+
c ? "border-[#9368FF]" : "border-[#E8E9EB]",
|
|
35
|
+
h && "border-red-500",
|
|
36
|
+
r && "opacity-60",
|
|
37
|
+
k
|
|
38
|
+
),
|
|
39
|
+
children: [
|
|
40
|
+
/* @__PURE__ */ e(
|
|
41
|
+
"input",
|
|
42
|
+
{
|
|
43
|
+
ref: f,
|
|
44
|
+
value: s,
|
|
45
|
+
disabled: r,
|
|
46
|
+
onChange: (o) => n(o.target.value),
|
|
47
|
+
onBlur: (o) => {
|
|
48
|
+
const t = o.target.value.trim();
|
|
49
|
+
t && !t.startsWith("#") && $(`#${t}`) && n(`#${t}`), w?.(o);
|
|
50
|
+
},
|
|
51
|
+
className: "h-full flex-1 bg-transparent text-base font-medium text-[#06080D] outline-none",
|
|
52
|
+
...y
|
|
53
|
+
}
|
|
54
|
+
),
|
|
55
|
+
/* @__PURE__ */ e(K, { asChild: !0, children: /* @__PURE__ */ e(
|
|
56
|
+
"button",
|
|
57
|
+
{
|
|
58
|
+
type: "button",
|
|
59
|
+
disabled: r,
|
|
60
|
+
"aria-label": "Open color picker",
|
|
61
|
+
className: C(
|
|
62
|
+
"size-6 shrink-0 rounded border border-black/5",
|
|
63
|
+
!r && "cursor-pointer"
|
|
64
|
+
),
|
|
65
|
+
style: { backgroundColor: R }
|
|
66
|
+
}
|
|
67
|
+
) })
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
),
|
|
71
|
+
/* @__PURE__ */ e(
|
|
72
|
+
V,
|
|
73
|
+
{
|
|
74
|
+
align: "end",
|
|
75
|
+
side: "right",
|
|
76
|
+
sideOffset: 8,
|
|
77
|
+
className: "w-auto",
|
|
78
|
+
onOpenAutoFocus: (o) => o.preventDefault(),
|
|
79
|
+
children: /* @__PURE__ */ e(
|
|
80
|
+
D,
|
|
81
|
+
{
|
|
82
|
+
value: s,
|
|
83
|
+
onChange: n,
|
|
84
|
+
withAlpha: g,
|
|
85
|
+
savedColors: O,
|
|
86
|
+
onAddSavedColor: P,
|
|
87
|
+
onRemoveSavedColor: B,
|
|
88
|
+
savedColorsLabel: x,
|
|
89
|
+
addLabel: S,
|
|
90
|
+
removeColorLabel: E,
|
|
91
|
+
formats: N
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
] });
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
W.displayName = "ColorInput";
|
|
100
|
+
export {
|
|
101
|
+
W as ColorInput
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=ColorInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorInput.js","sources":["../../src/ColorInput/ColorInput.tsx"],"sourcesContent":["import { forwardRef, useState } from 'react';\r\n\r\nimport { cn } from '@oneplatformdev/utils';\r\n\r\nimport { Popover, PopoverContent, PopoverTrigger } from '../Popover';\r\nimport { ColorInputProps } from './ColorInput.types';\r\nimport { ColorPicker } from './ColorPicker';\r\nimport { isValidColor, parseColor, rgbaToHex } from './color.utils';\r\nimport { useSavedColors } from './useSavedColors';\r\n\r\n/**\r\n * Color field: a text input showing the hex value with a color-indicator swatch\r\n * that opens a full color picker popover. Mirrors the Figma branding design.\r\n *\r\n * Controlled via `value`/`onChange` (hex strings) — pair it with `FormColorInput`\r\n * for react-hook-form usage, the same way `Input` pairs with `FormInput`.\r\n */\r\nexport const ColorInput = forwardRef<HTMLInputElement, ColorInputProps>(\r\n (props, ref) => {\r\n const {\r\n value = '',\r\n onChange,\r\n withAlpha = false,\r\n error,\r\n savedColors,\r\n onAddSavedColor,\r\n onRemoveSavedColor,\r\n savedColorsLabel,\r\n addLabel,\r\n removeColorLabel,\r\n storageKey,\r\n formats,\r\n className,\r\n disabled,\r\n onBlur,\r\n ...rest\r\n } = props;\r\n\r\n const [open, setOpen] = useState(false);\r\n\r\n // When the consumer doesn't control the palette, persist it to localStorage.\r\n const persisted = useSavedColors(storageKey);\r\n const isControlledPalette =\r\n savedColors !== undefined ||\r\n onAddSavedColor !== undefined ||\r\n onRemoveSavedColor !== undefined;\r\n const resolvedSavedColors = isControlledPalette\r\n ? savedColors\r\n : persisted.savedColors;\r\n const resolvedAddSavedColor = isControlledPalette\r\n ? onAddSavedColor\r\n : persisted.addColor;\r\n const resolvedRemoveSavedColor = isControlledPalette\r\n ? onRemoveSavedColor\r\n : persisted.removeColor;\r\n\r\n // The swatch reflects the last valid color; falls back to a neutral fill.\r\n const rgba = parseColor(value);\r\n const swatch = rgba ? rgbaToHex(rgba, true) : '#E8E9EB';\r\n\r\n const commit = (next: string) => onChange?.(next);\r\n\r\n return (\r\n <Popover open={open} onOpenChange={setOpen}>\r\n <div\r\n className={cn(\r\n 'flex h-10 w-full items-center gap-2 rounded-lg border bg-[#FCFCFC] px-2',\r\n open ? 'border-[#9368FF]' : 'border-[#E8E9EB]',\r\n error && 'border-red-500',\r\n disabled && 'opacity-60',\r\n className,\r\n )}\r\n >\r\n <input\r\n ref={ref}\r\n value={value}\r\n disabled={disabled}\r\n onChange={(e) => commit(e.target.value)}\r\n onBlur={(e) => {\r\n // Normalize on blur: prefix # and drop invalid input back to swatch.\r\n const trimmed = e.target.value.trim();\r\n if (trimmed && !trimmed.startsWith('#') && isValidColor(`#${trimmed}`)) {\r\n commit(`#${trimmed}`);\r\n }\r\n onBlur?.(e);\r\n }}\r\n className=\"h-full flex-1 bg-transparent text-base font-medium text-[#06080D] outline-none\"\r\n {...rest}\r\n />\r\n <PopoverTrigger asChild>\r\n <button\r\n type=\"button\"\r\n disabled={disabled}\r\n aria-label=\"Open color picker\"\r\n className={cn(\r\n 'size-6 shrink-0 rounded border border-black/5',\r\n !disabled && 'cursor-pointer',\r\n )}\r\n style={{ backgroundColor: swatch }}\r\n />\r\n </PopoverTrigger>\r\n </div>\r\n\r\n <PopoverContent\r\n align=\"end\"\r\n side=\"right\"\r\n sideOffset={8}\r\n className=\"w-auto\"\r\n onOpenAutoFocus={(e) => e.preventDefault()}\r\n >\r\n <ColorPicker\r\n value={value}\r\n onChange={commit}\r\n withAlpha={withAlpha}\r\n savedColors={resolvedSavedColors}\r\n onAddSavedColor={resolvedAddSavedColor}\r\n onRemoveSavedColor={resolvedRemoveSavedColor}\r\n savedColorsLabel={savedColorsLabel}\r\n addLabel={addLabel}\r\n removeColorLabel={removeColorLabel}\r\n formats={formats}\r\n />\r\n </PopoverContent>\r\n </Popover>\r\n );\r\n },\r\n);\r\n\r\nColorInput.displayName = 'ColorInput';\r\n"],"names":["ColorInput","forwardRef","props","ref","value","onChange","withAlpha","error","savedColors","onAddSavedColor","onRemoveSavedColor","savedColorsLabel","addLabel","removeColorLabel","storageKey","formats","className","disabled","onBlur","rest","open","setOpen","useState","persisted","useSavedColors","isControlledPalette","resolvedSavedColors","resolvedAddSavedColor","resolvedRemoveSavedColor","rgba","parseColor","swatch","rgbaToHex","commit","next","jsxs","Popover","cn","jsx","e","trimmed","isValidColor","PopoverTrigger","PopoverContent","ColorPicker"],"mappings":";;;;;;;AAiBO,MAAMA,IAAaC;AAAA,EACxB,CAACC,GAAOC,MAAQ;AACd,UAAM;AAAA,MACJ,OAAAC,IAAQ;AAAA,MACR,UAAAC;AAAA,MACA,WAAAC,IAAY;AAAA,MACZ,OAAAC;AAAA,MACA,aAAAC;AAAA,MACA,iBAAAC;AAAA,MACA,oBAAAC;AAAA,MACA,kBAAAC;AAAA,MACA,UAAAC;AAAA,MACA,kBAAAC;AAAA,MACA,YAAAC;AAAA,MACA,SAAAC;AAAA,MACA,WAAAC;AAAA,MACA,UAAAC;AAAA,MACA,QAAAC;AAAA,MACA,GAAGC;AAAA,IAAA,IACDjB,GAEE,CAACkB,GAAMC,CAAO,IAAIC,EAAS,EAAK,GAGhCC,IAAYC,EAAeV,CAAU,GACrCW,IACJjB,MAAgB,UAChBC,MAAoB,UACpBC,MAAuB,QACnBgB,IAAsBD,IACxBjB,IACAe,EAAU,aACRI,IAAwBF,IAC1BhB,IACAc,EAAU,UACRK,IAA2BH,IAC7Bf,IACAa,EAAU,aAGRM,IAAOC,EAAW1B,CAAK,GACvB2B,IAASF,IAAOG,EAAUH,GAAM,EAAI,IAAI,WAExCI,IAAS,CAACC,MAAiB7B,IAAW6B,CAAI;AAEhD,WACE,gBAAAC,EAACC,GAAA,EAAQ,MAAAhB,GAAY,cAAcC,GACjC,UAAA;AAAA,MAAA,gBAAAc;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWE;AAAA,YACT;AAAA,YACAjB,IAAO,qBAAqB;AAAA,YAC5Bb,KAAS;AAAA,YACTU,KAAY;AAAA,YACZD;AAAA,UAAA;AAAA,UAGF,UAAA;AAAA,YAAA,gBAAAsB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,KAAAnC;AAAA,gBACA,OAAAC;AAAA,gBACA,UAAAa;AAAA,gBACA,UAAU,CAACsB,MAAMN,EAAOM,EAAE,OAAO,KAAK;AAAA,gBACtC,QAAQ,CAACA,MAAM;AAEb,wBAAMC,IAAUD,EAAE,OAAO,MAAM,KAAA;AAC/B,kBAAIC,KAAW,CAACA,EAAQ,WAAW,GAAG,KAAKC,EAAa,IAAID,CAAO,EAAE,KACnEP,EAAO,IAAIO,CAAO,EAAE,GAEtBtB,IAASqB,CAAC;AAAA,gBACZ;AAAA,gBACA,WAAU;AAAA,gBACT,GAAGpB;AAAA,cAAA;AAAA,YAAA;AAAA,YAEN,gBAAAmB,EAACI,GAAA,EAAe,SAAO,IACrB,UAAA,gBAAAJ;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,UAAArB;AAAA,gBACA,cAAW;AAAA,gBACX,WAAWoB;AAAA,kBACT;AAAA,kBACA,CAACpB,KAAY;AAAA,gBAAA;AAAA,gBAEf,OAAO,EAAE,iBAAiBc,EAAA;AAAA,cAAO;AAAA,YAAA,EACnC,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAGF,gBAAAO;AAAA,QAACK;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,MAAK;AAAA,UACL,YAAY;AAAA,UACZ,WAAU;AAAA,UACV,iBAAiB,CAACJ,MAAMA,EAAE,eAAA;AAAA,UAE1B,UAAA,gBAAAD;AAAA,YAACM;AAAA,YAAA;AAAA,cACC,OAAAxC;AAAA,cACA,UAAU6B;AAAA,cACV,WAAA3B;AAAA,cACA,aAAaoB;AAAA,cACb,iBAAiBC;AAAA,cACjB,oBAAoBC;AAAA,cACpB,kBAAAjB;AAAA,cACA,UAAAC;AAAA,cACA,kBAAAC;AAAA,cACA,SAAAE;AAAA,YAAA;AAAA,UAAA;AAAA,QACF;AAAA,MAAA;AAAA,IACF,GACF;AAAA,EAEJ;AACF;AAEAf,EAAW,cAAc;"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { jsx as r, jsxs as l } from "react/jsx-runtime";
|
|
2
|
+
import { useState as d } from "react";
|
|
3
|
+
import { ColorInput as n } from "./ColorInput.js";
|
|
4
|
+
import { DEFAULT_SAVED_COLORS as i } from "./color.utils.js";
|
|
5
|
+
function o({ initialValue: e = "#9368FF", ...s }) {
|
|
6
|
+
const [t, a] = d(e);
|
|
7
|
+
return /* @__PURE__ */ l("div", { className: "w-[341px] space-y-3", children: [
|
|
8
|
+
/* @__PURE__ */ r("span", { className: "text-sm font-medium text-[#06080D]", children: "Колір" }),
|
|
9
|
+
/* @__PURE__ */ r(n, { ...s, value: t, onChange: a }),
|
|
10
|
+
/* @__PURE__ */ l("div", { className: "text-xs text-muted-foreground", children: [
|
|
11
|
+
"value: ",
|
|
12
|
+
/* @__PURE__ */ r("span", { className: "font-mono", children: t })
|
|
13
|
+
] })
|
|
14
|
+
] });
|
|
15
|
+
}
|
|
16
|
+
const h = {
|
|
17
|
+
title: "ColorInput",
|
|
18
|
+
component: n,
|
|
19
|
+
parameters: { layout: "centered" },
|
|
20
|
+
args: {
|
|
21
|
+
withAlpha: !1,
|
|
22
|
+
error: !1,
|
|
23
|
+
disabled: !1
|
|
24
|
+
},
|
|
25
|
+
argTypes: {
|
|
26
|
+
value: { control: !1 },
|
|
27
|
+
onChange: { control: !1 },
|
|
28
|
+
onAddSavedColor: { control: !1 }
|
|
29
|
+
},
|
|
30
|
+
decorators: [
|
|
31
|
+
(e) => /* @__PURE__ */ r("div", { className: "p-6 w-[420px]", children: /* @__PURE__ */ r(e, {}) })
|
|
32
|
+
]
|
|
33
|
+
}, v = {
|
|
34
|
+
render: (e) => /* @__PURE__ */ r(o, { ...e })
|
|
35
|
+
}, x = {
|
|
36
|
+
args: { withAlpha: !0 },
|
|
37
|
+
render: (e) => /* @__PURE__ */ r(o, { ...e, initialValue: "#9368FFcc" })
|
|
38
|
+
}, C = {
|
|
39
|
+
args: { error: !0 },
|
|
40
|
+
render: (e) => /* @__PURE__ */ r(o, { ...e })
|
|
41
|
+
}, g = {
|
|
42
|
+
args: { disabled: !0 },
|
|
43
|
+
render: (e) => /* @__PURE__ */ r(o, { ...e })
|
|
44
|
+
}, A = {
|
|
45
|
+
render: (e) => /* @__PURE__ */ r(o, { ...e, formats: ["hex"] })
|
|
46
|
+
}, S = {
|
|
47
|
+
render: (e) => /* @__PURE__ */ r(o, { ...e, formats: ["rgb", "hsl"] })
|
|
48
|
+
}, y = {
|
|
49
|
+
// No savedColors / onAddSavedColor → palette auto-persists to localStorage.
|
|
50
|
+
render: (e) => /* @__PURE__ */ r(o, { ...e, storageKey: "storybook-color-input" })
|
|
51
|
+
}, b = {
|
|
52
|
+
render: (e) => {
|
|
53
|
+
const [s, t] = d(i);
|
|
54
|
+
return /* @__PURE__ */ r("div", { className: "w-[341px] space-y-3", children: /* @__PURE__ */ r(
|
|
55
|
+
n,
|
|
56
|
+
{
|
|
57
|
+
...e,
|
|
58
|
+
value: "#3B82F6",
|
|
59
|
+
onChange: () => {
|
|
60
|
+
},
|
|
61
|
+
savedColors: s,
|
|
62
|
+
onAddSavedColor: (a) => t((c) => [...c, a])
|
|
63
|
+
}
|
|
64
|
+
) });
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
export {
|
|
68
|
+
v as Default,
|
|
69
|
+
g as Disabled,
|
|
70
|
+
C as Error,
|
|
71
|
+
A as HexOnly,
|
|
72
|
+
y as PersistedSavedColors,
|
|
73
|
+
S as RgbAndHsl,
|
|
74
|
+
x as WithAlpha,
|
|
75
|
+
b as WithSavedColorAdd,
|
|
76
|
+
h as default
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=ColorInput.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorInput.stories.js","sources":["../../src/ColorInput/ColorInput.stories.tsx"],"sourcesContent":["import React, { useState } from 'react';\r\nimport type { Meta, StoryObj } from '@storybook/react';\r\n\r\nimport { ColorInput } from './ColorInput';\r\nimport { DEFAULT_SAVED_COLORS } from './color.utils';\r\n\r\ntype ControlledProps = Omit<\r\n React.ComponentProps<typeof ColorInput>,\r\n 'value' | 'onChange'\r\n> & {\r\n initialValue?: string;\r\n};\r\n\r\nfunction ControlledColorInput({ initialValue = '#9368FF', ...args }: ControlledProps) {\r\n const [value, setValue] = useState(initialValue);\r\n return (\r\n <div className=\"w-[341px] space-y-3\">\r\n <span className=\"text-sm font-medium text-[#06080D]\">Колір</span>\r\n <ColorInput {...args} value={value} onChange={setValue} />\r\n <div className=\"text-xs text-muted-foreground\">\r\n value: <span className=\"font-mono\">{value}</span>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nconst meta = {\r\n title: 'ColorInput',\r\n component: ColorInput,\r\n parameters: { layout: 'centered' },\r\n args: {\r\n withAlpha: false,\r\n error: false,\r\n disabled: false,\r\n },\r\n argTypes: {\r\n value: { control: false },\r\n onChange: { control: false },\r\n onAddSavedColor: { control: false },\r\n },\r\n decorators: [\r\n (Story) => (\r\n <div className=\"p-6 w-[420px]\">\r\n <Story />\r\n </div>\r\n ),\r\n ],\r\n} satisfies Meta<typeof ColorInput>;\r\n\r\nexport default meta;\r\n\r\ntype Story = StoryObj<typeof meta>;\r\n\r\nexport const Default: Story = {\r\n render: (args) => <ControlledColorInput {...args} />,\r\n};\r\n\r\nexport const WithAlpha: Story = {\r\n args: { withAlpha: true },\r\n render: (args) => <ControlledColorInput {...args} initialValue=\"#9368FFcc\" />,\r\n};\r\n\r\nexport const Error: Story = {\r\n args: { error: true },\r\n render: (args) => <ControlledColorInput {...args} />,\r\n};\r\n\r\nexport const Disabled: Story = {\r\n args: { disabled: true },\r\n render: (args) => <ControlledColorInput {...args} />,\r\n};\r\n\r\nexport const HexOnly: Story = {\r\n render: (args) => <ControlledColorInput {...args} formats={['hex']} />,\r\n};\r\n\r\nexport const RgbAndHsl: Story = {\r\n render: (args) => (\r\n <ControlledColorInput {...args} formats={['rgb', 'hsl']} />\r\n ),\r\n};\r\n\r\nexport const PersistedSavedColors: Story = {\r\n // No savedColors / onAddSavedColor → palette auto-persists to localStorage.\r\n render: (args) => (\r\n <ControlledColorInput {...args} storageKey=\"storybook-color-input\" />\r\n ),\r\n};\r\n\r\nexport const WithSavedColorAdd: Story = {\r\n render: (args) => {\r\n const [saved, setSaved] = useState<string[]>(DEFAULT_SAVED_COLORS);\r\n return (\r\n <div className=\"w-[341px] space-y-3\">\r\n <ColorInput\r\n {...args}\r\n value=\"#3B82F6\"\r\n onChange={() => {}}\r\n savedColors={saved}\r\n onAddSavedColor={(hex) => setSaved((prev) => [...prev, hex])}\r\n />\r\n </div>\r\n );\r\n },\r\n};\r\n"],"names":["ControlledColorInput","initialValue","args","value","setValue","useState","jsxs","jsx","ColorInput","meta","Story","Default","WithAlpha","Error","Disabled","HexOnly","RgbAndHsl","PersistedSavedColors","WithSavedColorAdd","saved","setSaved","DEFAULT_SAVED_COLORS","hex","prev"],"mappings":";;;;AAaA,SAASA,EAAqB,EAAE,cAAAC,IAAe,WAAW,GAAGC,KAAyB;AACpF,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAASJ,CAAY;AAC/C,SACE,gBAAAK,EAAC,OAAA,EAAI,WAAU,uBACb,UAAA;AAAA,IAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,sCAAqC,UAAA,SAAK;AAAA,sBACzDC,GAAA,EAAY,GAAGN,GAAM,OAAAC,GAAc,UAAUC,GAAU;AAAA,IACxD,gBAAAE,EAAC,OAAA,EAAI,WAAU,iCAAgC,UAAA;AAAA,MAAA;AAAA,MACtC,gBAAAC,EAAC,QAAA,EAAK,WAAU,aAAa,UAAAJ,EAAA,CAAM;AAAA,IAAA,EAAA,CAC5C;AAAA,EAAA,GACF;AAEJ;AAEA,MAAMM,IAAO;AAAA,EACX,OAAO;AAAA,EACP,WAAWD;AAAA,EACX,YAAY,EAAE,QAAQ,WAAA;AAAA,EACtB,MAAM;AAAA,IACJ,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,EAAA;AAAA,EAEZ,UAAU;AAAA,IACR,OAAO,EAAE,SAAS,GAAA;AAAA,IAClB,UAAU,EAAE,SAAS,GAAA;AAAA,IACrB,iBAAiB,EAAE,SAAS,GAAA;AAAA,EAAM;AAAA,EAEpC,YAAY;AAAA,IACV,CAACE,MACC,gBAAAH,EAAC,OAAA,EAAI,WAAU,iBACb,UAAA,gBAAAA,EAACG,KAAM,EAAA,CACT;AAAA,EAAA;AAGN,GAMaC,IAAiB;AAAA,EAC5B,QAAQ,CAACT,MAAS,gBAAAK,EAACP,GAAA,EAAsB,GAAGE,EAAA,CAAM;AACpD,GAEaU,IAAmB;AAAA,EAC9B,MAAM,EAAE,WAAW,GAAA;AAAA,EACnB,QAAQ,CAACV,MAAS,gBAAAK,EAACP,KAAsB,GAAGE,GAAM,cAAa,YAAA,CAAY;AAC7E,GAEaW,IAAe;AAAA,EAC1B,MAAM,EAAE,OAAO,GAAA;AAAA,EACf,QAAQ,CAACX,MAAS,gBAAAK,EAACP,GAAA,EAAsB,GAAGE,EAAA,CAAM;AACpD,GAEaY,IAAkB;AAAA,EAC7B,MAAM,EAAE,UAAU,GAAA;AAAA,EAClB,QAAQ,CAACZ,MAAS,gBAAAK,EAACP,GAAA,EAAsB,GAAGE,EAAA,CAAM;AACpD,GAEaa,IAAiB;AAAA,EAC5B,QAAQ,CAACb,MAAS,gBAAAK,EAACP,GAAA,EAAsB,GAAGE,GAAM,SAAS,CAAC,KAAK,EAAA,CAAG;AACtE,GAEac,IAAmB;AAAA,EAC9B,QAAQ,CAACd,MACP,gBAAAK,EAACP,GAAA,EAAsB,GAAGE,GAAM,SAAS,CAAC,OAAO,KAAK,EAAA,CAAG;AAE7D,GAEae,IAA8B;AAAA;AAAA,EAEzC,QAAQ,CAACf,MACP,gBAAAK,EAACP,KAAsB,GAAGE,GAAM,YAAW,wBAAA,CAAwB;AAEvE,GAEagB,IAA2B;AAAA,EACtC,QAAQ,CAAChB,MAAS;AAChB,UAAM,CAACiB,GAAOC,CAAQ,IAAIf,EAAmBgB,CAAoB;AACjE,WACE,gBAAAd,EAAC,OAAA,EAAI,WAAU,uBACb,UAAA,gBAAAA;AAAA,MAACC;AAAA,MAAA;AAAA,QACE,GAAGN;AAAA,QACJ,OAAM;AAAA,QACN,UAAU,MAAM;AAAA,QAAC;AAAA,QACjB,aAAaiB;AAAA,QACb,iBAAiB,CAACG,MAAQF,EAAS,CAACG,MAAS,CAAC,GAAGA,GAAMD,CAAG,CAAC;AAAA,MAAA;AAAA,IAAA,GAE/D;AAAA,EAEJ;AACF;"}
|
|
@@ -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 @@
|
|
|
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
|