@bioturing/components 0.17.1 → 0.18.0

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.
@@ -1,138 +1,227 @@
1
1
  "use client";
2
- import { jsx as a, jsxs as P } from "react/jsx-runtime";
3
- import { forwardRef as q, useState as V, useRef as U, useCallback as v, useMemo as b } from "react";
4
- import W from "antd/es/color-picker";
5
- import { Stack as z } from "../Stack/index.js";
2
+ import { jsx as f, jsxs as Q } from "react/jsx-runtime";
3
+ import { forwardRef as Z, useState as w, useRef as I, useCallback as c, useEffect as L, useMemo as j } from "react";
4
+ import _ from "antd/es/color-picker";
5
+ import { Stack as ee } from "../Stack/index.js";
6
+ import te from "merge-refs";
6
7
  import './style.css';/* empty css */
7
- import { isValidHexColor as F } from "../utils/colors.js";
8
- import { toast as G } from "../Toast/function.js";
9
- import { Tag as J } from "../Tag/component.js";
10
- import { useCls as L } from "../utils/antdUtils.js";
11
- import { useControlledState as I } from "../hooks/useControlledState.js";
12
- import { Tooltip as Q } from "../Tooltip/component.js";
13
- const X = ({
14
- className: Z,
15
- value: K,
16
- defaultValue: M,
17
- onChange: i,
18
- colorPickerProps: w,
19
- presetColors: m,
20
- open: R,
21
- onOpenChange: u,
22
- defaultOpen: T,
23
- ...j
24
- }, y) => {
25
- const l = L(), [s, n] = I(
26
- K,
27
- i,
28
- M
29
- ), [r, f] = V(""), [C, d] = V(""), [g, o] = I(
30
- R,
31
- u,
32
- T
33
- ), [B, h] = V(!1), k = U(null), x = v(() => {
34
- const t = r.trim().split(/[;,\s]+/).filter(Boolean).map(
35
- (p) => p.trim().toUpperCase()
36
- ), c = [], A = t.reduce((p, S) => (F(S, !0) ? p.push(S) : c.push(S), p), []);
37
- c.length && G(`Invalid colors: ${c.join(", ")}`);
38
- const E = /* @__PURE__ */ new Set([...s, ...A]);
39
- i && i([...E]), u && u(!1), f(""), d(""), o(!1), requestAnimationFrame(() => {
40
- o(!0);
8
+ import { moveTypingCursorToEnd as oe } from "../utils/selectionRange.js";
9
+ import { isValidHexColor as R } from "../utils/colors.js";
10
+ import { toast as ne } from "../Toast/function.js";
11
+ import { useCls as re } from "../utils/antdUtils.js";
12
+ import { useControlledState as $ } from "../hooks/useControlledState.js";
13
+ import { Tooltip as se } from "../Tooltip/component.js";
14
+ import { Tag as le } from "../Tag/component.js";
15
+ const ce = ({
16
+ className: ue,
17
+ value: q,
18
+ defaultValue: O,
19
+ onChange: g,
20
+ colorPickerProps: F,
21
+ presetColors: P,
22
+ open: U,
23
+ onOpenChange: h,
24
+ defaultOpen: W,
25
+ ...X
26
+ }, N) => {
27
+ const a = re(), [s, u] = $(
28
+ q,
29
+ g,
30
+ O
31
+ ), [C, S] = w(null), [i, D] = w(""), [E, M] = w(""), [k, r] = $(
32
+ U,
33
+ h,
34
+ W
35
+ ), [Y, T] = w(!1), y = I(null), d = I(null), z = I(!1), x = I({
36
+ x: 0,
37
+ y: 0
38
+ }), v = c(() => {
39
+ var e;
40
+ z.current = !0, (e = d.current) == null || e.focus(), oe(d.current);
41
+ }, []), b = c(() => {
42
+ r(!1), v();
43
+ }, [r, v]);
44
+ L(() => {
45
+ if (!k) return;
46
+ const e = (t) => {
47
+ var o;
48
+ (o = y.current) != null && o.contains(t.target) || d.current && !d.current.isEqualNode(t.target) && b();
49
+ };
50
+ return document.addEventListener("click", e), () => document.removeEventListener("click", e);
51
+ }, [k, b]), L(() => {
52
+ const e = (t) => {
53
+ x.current = {
54
+ x: t.clientX,
55
+ y: t.clientY
56
+ };
57
+ };
58
+ return document.addEventListener("mousemove", e), () => {
59
+ document.removeEventListener("mousemove", e);
60
+ };
61
+ }, []);
62
+ const A = c(() => {
63
+ const t = i.trim().split(/[;,\s]+/).filter(Boolean).map(
64
+ (l) => l.trim().toUpperCase()
65
+ ), o = [], n = t.reduce((l, m) => (R(m, !0) ? l.push(m) : o.push(m), l), []);
66
+ o.length && ne(`Invalid colors: ${o.join(", ")}`);
67
+ const p = /* @__PURE__ */ new Set([...s, ...n]);
68
+ g && g([...p]), h && h(!1), D(""), M(""), r(!1), requestAnimationFrame(() => {
69
+ r(!0);
41
70
  });
42
- }, [r, s, i, u, o]), D = v(
71
+ }, [i, s, g, h, r]), B = c(
43
72
  (e) => {
44
- e.key === "Enter" && x(), e.key === "Backspace" && !r && (e.ctrlKey || e.metaKey ? n([]) : n(s.slice(0, -1)));
73
+ e.key === "Enter" && A(), e.key === "Backspace" && !i && (e.ctrlKey || e.metaKey ? u([]) : u(s.slice(0, -1)));
45
74
  },
46
- [x, r, s, n]
47
- ), H = b(
48
- () => s.map((e, t) => /* @__PURE__ */ a(Q, { title: e, children: /* @__PURE__ */ a(
49
- J,
50
- {
51
- className: l("color-select-tag"),
52
- closable: !0,
53
- onClose: () => n(s.filter((c) => c !== e)),
54
- icon: /* @__PURE__ */ a(
55
- "span",
56
- {
57
- className: l("color-select-swatch"),
58
- style: { backgroundColor: e }
59
- }
60
- )
61
- }
62
- ) }, `${e}-${t}`)),
63
- [s, l, n]
64
- ), N = v(
75
+ [A, i, s, u]
76
+ ), H = c(
77
+ (e) => {
78
+ e.preventDefault(), e.stopPropagation();
79
+ },
80
+ []
81
+ ), K = c(
65
82
  (e) => {
66
83
  e.preventDefault();
67
84
  },
68
85
  []
69
- ), $ = b(
70
- () => /* @__PURE__ */ a(
71
- W,
86
+ ), V = c(
87
+ ({
88
+ open: e,
89
+ child: t,
90
+ value: o,
91
+ onChange: n,
92
+ onOpenChange: p
93
+ }) => /* @__PURE__ */ f(
94
+ _,
72
95
  {
73
- value: C,
74
- onChange: (e) => {
75
- d(e.toHexString()), f(e.toHexString());
76
- },
77
- open: g,
96
+ value: o,
97
+ onChange: n,
98
+ open: e,
99
+ onOpenChange: p,
78
100
  arrow: !1,
79
- presets: m ? [{ label: "Preset Colors", colors: m }] : void 0,
80
- ...w,
81
- panelRender: (e) => /* @__PURE__ */ a("div", { ref: k, onMouseDown: N, children: e }),
82
- children: /* @__PURE__ */ a(
83
- "input",
101
+ presets: P ? [{ label: "Preset Colors", colors: P }] : void 0,
102
+ ...F,
103
+ panelRender: (l) => /* @__PURE__ */ f(
104
+ "div",
84
105
  {
85
- placeholder: "Select or enter a color list",
86
- className: l("color-select-input"),
87
- value: r,
88
- type: "text",
89
- ref: y,
90
- onChange: (e) => {
91
- const t = e.target.value;
92
- f(t), F(t, !0) && d(t), t.length > 7 || t.length == 7 && !t.startsWith("#") ? o(!1) : o(!0);
93
- },
94
- onKeyDown: D,
95
- onFocus: () => {
96
- h(!0), o(!0);
106
+ ref: (m) => {
107
+ m && (y.current = m);
97
108
  },
98
- onBlur: () => {
99
- h(!1), o(!1);
100
- }
109
+ onMouseDown: H,
110
+ onMouseDownCapture: K,
111
+ children: l
101
112
  }
102
- )
113
+ ),
114
+ children: t
103
115
  }
104
116
  ),
105
117
  [
118
+ P,
119
+ F,
120
+ H,
121
+ K
122
+ ]
123
+ ), G = j(
124
+ () => s.map((e, t) => {
125
+ const o = /* @__PURE__ */ f(se, { title: e, children: /* @__PURE__ */ f(
126
+ le,
127
+ {
128
+ className: a("color-select-tag"),
129
+ closable: !0,
130
+ onClose: () => u(s.filter((n) => n !== e)),
131
+ icon: /* @__PURE__ */ f(
132
+ "span",
133
+ {
134
+ className: a("color-select-swatch"),
135
+ style: { backgroundColor: e }
136
+ }
137
+ ),
138
+ onClick: () => S(C === t ? null : t)
139
+ }
140
+ ) }, `${e}-${t}`);
141
+ return V({
142
+ child: o,
143
+ open: C !== null && C === t,
144
+ value: s[t],
145
+ onChange: (n) => {
146
+ u(
147
+ s.map((p, l) => l === t ? n.toHexString() : p)
148
+ );
149
+ },
150
+ onOpenChange: (n) => {
151
+ S(n ? t : null);
152
+ }
153
+ });
154
+ }),
155
+ [
156
+ s,
157
+ a,
158
+ u,
106
159
  C,
107
- g,
108
- m,
109
- w,
110
- r,
111
- l,
112
- y,
113
- D,
114
- h,
115
- o,
116
- N,
117
- k
160
+ S,
161
+ V
118
162
  ]
119
- );
120
- return /* @__PURE__ */ P(
121
- z,
163
+ ), J = j(() => V({
164
+ child: /* @__PURE__ */ f(
165
+ "input",
166
+ {
167
+ placeholder: "Select or enter a color list",
168
+ className: a("color-select-input"),
169
+ value: i,
170
+ type: "text",
171
+ ref: te(N, d),
172
+ onChange: (e) => {
173
+ const t = e.target.value;
174
+ D(t), R(t, !0) && M(t), t.length > 7 || t.length == 7 && !t.startsWith("#") ? r(!1) : r(!0);
175
+ },
176
+ onKeyDown: B,
177
+ onFocus: (e) => {
178
+ T(!0), r(!0);
179
+ },
180
+ onBlur: (e) => {
181
+ if (y.current) {
182
+ const t = y.current.getBoundingClientRect(), { x: o, y: n } = x.current;
183
+ if (o >= t.left && o <= t.right && n >= t.top && n <= t.bottom) {
184
+ e.preventDefault(), e.stopPropagation(), R(E) && v();
185
+ return;
186
+ }
187
+ }
188
+ T(!1), r(!1);
189
+ }
190
+ }
191
+ ),
192
+ value: E,
193
+ onChange: (e) => {
194
+ M(e.toHexString()), D(e.toHexString()), v();
195
+ },
196
+ open: k
197
+ }), [
198
+ a,
199
+ E,
200
+ B,
201
+ N,
202
+ V,
203
+ i,
204
+ r,
205
+ k,
206
+ v,
207
+ x
208
+ ]);
209
+ return /* @__PURE__ */ Q(
210
+ ee,
122
211
  {
123
212
  wrap: !0,
124
213
  gap: 4,
125
- className: l("color-select"),
126
- "data-focus": B || void 0,
127
- ...j,
214
+ className: a("color-select"),
215
+ "data-focus": Y || void 0,
216
+ ...X,
128
217
  children: [
129
- H,
130
- $
218
+ G,
219
+ J
131
220
  ]
132
221
  }
133
222
  );
134
- }, Y = q(X), ie = Y;
223
+ }, ae = Z(ce), we = ae;
135
224
  export {
136
- ie as ColorSelect
225
+ we as ColorSelect
137
226
  };
138
227
  //# sourceMappingURL=component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"component.js","sources":["../../../src/components/ColorSelect/component.tsx"],"sourcesContent":["\"use client\";\nimport React, {\n ComponentPropsWithoutRef,\n forwardRef,\n useRef,\n useState,\n useCallback,\n useMemo,\n} from \"react\";\nimport ColorPicker from \"antd/es/color-picker\";\nimport { type ColorPickerProps } from \"antd/es/color-picker\";\nimport { useCls, isValidHexColor } from \"../utils\";\nimport { useControlledState } from \"../hooks\";\nimport { Tag } from \"../Tag\";\nimport { Stack } from \"../Stack\";\nimport { toast } from \"../Toast\";\n\n// Import component-specific styles\nimport \"./style.css\";\nimport { Tooltip } from \"../Tooltip\";\n\n/**\n * Props for the ColorSelect component.\n */\nexport interface ColorSelectProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n /** Controlled list of selected hex colors */\n value?: string[];\n /** Default list of selected hex colors for uncontrolled usage */\n defaultValue?: string[];\n /** Callback invoked when selected colors change */\n onChange?: (value: string[]) => void;\n /** Props to pass through to the Ant Design ColorPicker, excluding value/onChange/onChangeComplete */\n colorPickerProps?: Omit<\n ColorPickerProps,\n \"value\" | \"onChange\" | \"onChangeComplete\"\n >;\n /** Preset color swatches displayed in the picker */\n presetColors?: string[];\n /** Controlled open state of the ColorPicker dropdown */\n open?: boolean;\n /** Callback invoked when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Default open state for uncontrolled usage */\n defaultOpen?: boolean;\n}\n\n/**\n * ColorSelectInner - Combines an input and Ant Design ColorPicker for selecting multiple colors.\n * Supports preset color swatches and freeform hex entry, displaying selections as tags.\n * Controlled/uncontrolled APIs for `value` and `open`, emitting invalid input notifications via toast.\n * @param props - {@link ColorSelectProps}\n * @param ref - ref to the input element\n * @returns JSX.Element\n */\nconst ColorSelectInner = (\n {\n className,\n value: valueProp,\n defaultValue,\n onChange,\n colorPickerProps,\n presetColors,\n open: openProp,\n onOpenChange,\n defaultOpen,\n ...rest\n },\n ref: React.Ref<React.ComponentRef<\"input\">>\n) => {\n const cls = useCls();\n const [value, setValue] = useControlledState<string[]>(\n valueProp,\n onChange,\n defaultValue\n );\n const [searchValue, setSearchValue] = useState(\"\");\n const [tmpValue, setTmpValue] = useState(\"\");\n const [open, setOpen] = useControlledState<boolean>(\n openProp,\n onOpenChange,\n defaultOpen\n );\n\n const [isFocus, setIsFocus] = useState(false);\n\n const popupRef = useRef<HTMLDivElement>(null);\n\n const onEnter = useCallback(() => {\n const searchValueSplit = searchValue\n .trim()\n .split(/[;,\\s]+/)\n .filter(Boolean);\n const addedValues = searchValueSplit.map((gene) =>\n gene.trim().toUpperCase()\n );\n const inValidValues: string[] = [];\n const validAddedValues = addedValues.reduce((acc, curr) => {\n if (!isValidHexColor(curr, true)) {\n inValidValues.push(curr);\n } else {\n acc.push(curr);\n }\n return acc;\n }, [] as string[]);\n if (inValidValues.length) {\n toast(`Invalid colors: ${inValidValues.join(\", \")}`);\n }\n const newColors = new Set([...value, ...validAddedValues]);\n if (onChange) onChange([...newColors]);\n if (onOpenChange) onOpenChange(false);\n setSearchValue(\"\");\n setTmpValue(\"\");\n setOpen(false);\n requestAnimationFrame(() => {\n setOpen(true);\n });\n }, [searchValue, value, onChange, onOpenChange, setOpen]);\n\n const onInputKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\") onEnter();\n if (e.key === \"Backspace\" && !searchValue) {\n if (e.ctrlKey || e.metaKey) {\n setValue([]);\n } else {\n setValue(value.slice(0, -1));\n }\n }\n },\n [onEnter, searchValue, value, setValue]\n );\n\n const renderedTags = useMemo(\n () =>\n value.map((color, index) => (\n <Tooltip title={color} key={`${color}-${index}`}>\n <Tag\n className={cls(\"color-select-tag\")}\n closable\n onClose={() => setValue(value.filter((v) => v !== color))}\n icon={\n <span\n className={cls(\"color-select-swatch\")}\n style={{ backgroundColor: color }}\n />\n }\n />\n </Tooltip>\n )),\n [value, cls, setValue]\n );\n\n const handlePopupMouseDown = useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n // Prevent input blur when clicking popup\n e.preventDefault();\n },\n []\n );\n\n const renderedColorPicker = useMemo(\n () => (\n <ColorPicker\n value={tmpValue}\n onChange={(color) => {\n // setValue([...value, color]);\n setTmpValue(color.toHexString());\n setSearchValue(color.toHexString());\n }}\n open={open}\n arrow={false}\n presets={\n presetColors\n ? [{ label: \"Preset Colors\", colors: presetColors }]\n : undefined\n }\n {...colorPickerProps}\n panelRender={(panel) => (\n <div ref={popupRef} onMouseDown={handlePopupMouseDown}>\n {panel}\n </div>\n )}\n >\n <input\n placeholder=\"Select or enter a color list\"\n className={cls(\"color-select-input\")}\n value={searchValue}\n type=\"text\"\n ref={ref}\n onChange={(e) => {\n const currValue = e.target.value;\n setSearchValue(currValue);\n if (isValidHexColor(currValue, true)) setTmpValue(currValue);\n if (\n currValue.length > 7 ||\n (currValue.length == 7 && !currValue.startsWith(\"#\"))\n ) {\n setOpen(false);\n } else {\n setOpen(true);\n }\n }}\n onKeyDown={onInputKeyDown}\n onFocus={() => {\n setIsFocus(true);\n setOpen(true);\n }}\n onBlur={() => {\n // Check if the new focus target is inside the popup\n setIsFocus(false);\n setOpen(false);\n }}\n />\n </ColorPicker>\n ),\n [\n tmpValue,\n open,\n presetColors,\n colorPickerProps,\n searchValue,\n cls,\n ref,\n onInputKeyDown,\n setIsFocus,\n setOpen,\n handlePopupMouseDown,\n popupRef,\n ]\n );\n\n return (\n <Stack\n wrap\n gap={4}\n className={cls(\"color-select\")}\n data-focus={isFocus || undefined}\n {...rest}\n >\n {renderedTags}\n {renderedColorPicker}\n </Stack>\n );\n};\n\n// Use forwardRef with type assertion\nconst MainColorSelect = forwardRef(ColorSelectInner);\n\nexport const ColorSelect = MainColorSelect;\n"],"names":["ColorSelectInner","className","valueProp","defaultValue","onChange","colorPickerProps","presetColors","openProp","onOpenChange","defaultOpen","rest","ref","cls","useCls","value","setValue","useControlledState","searchValue","setSearchValue","useState","tmpValue","setTmpValue","open","setOpen","isFocus","setIsFocus","popupRef","useRef","onEnter","useCallback","addedValues","gene","inValidValues","validAddedValues","acc","curr","isValidHexColor","toast","newColors","onInputKeyDown","renderedTags","useMemo","color","index","jsx","Tooltip","Tag","v","handlePopupMouseDown","renderedColorPicker","ColorPicker","panel","currValue","jsxs","Stack","MainColorSelect","forwardRef","ColorSelect"],"mappings":"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"}
1
+ {"version":3,"file":"component.js","sources":["../../../src/components/ColorSelect/component.tsx"],"sourcesContent":["\"use client\";\nimport React, {\n ComponentPropsWithoutRef,\n forwardRef,\n useRef,\n useState,\n useCallback,\n useMemo,\n useEffect,\n} from \"react\";\nimport ColorPicker from \"antd/es/color-picker\";\nimport { type ColorPickerProps, type Color } from \"antd/es/color-picker\";\nimport { useCls, isValidHexColor } from \"../utils\";\nimport { useControlledState } from \"../hooks\";\nimport { Tag } from \"../Tag\";\nimport { Stack } from \"../Stack\";\nimport { toast } from \"../Toast\";\nimport mergeRefs from \"merge-refs\";\nimport { moveTypingCursorToEnd } from \"../utils/client\";\n\n// Import component-specific styles\nimport \"./style.css\";\nimport { Tooltip } from \"../Tooltip\";\n\n/**\n * Props for the ColorSelect component.\n */\nexport interface ColorSelectProps\n extends Omit<ComponentPropsWithoutRef<\"div\">, \"onChange\"> {\n /** Controlled list of selected hex colors */\n value?: string[];\n /** Default list of selected hex colors for uncontrolled usage */\n defaultValue?: string[];\n /** Callback invoked when selected colors change */\n onChange?: (value: string[]) => void;\n /** Props to pass through to the Ant Design ColorPicker, excluding value/onChange/onChangeComplete */\n colorPickerProps?: Omit<\n ColorPickerProps,\n \"value\" | \"onChange\" | \"onChangeComplete\"\n >;\n /** Preset color swatches displayed in the picker */\n presetColors?: string[];\n /** Controlled open state of the ColorPicker dropdown */\n open?: boolean;\n /** Callback invoked when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Default open state for uncontrolled usage */\n defaultOpen?: boolean;\n}\n\n/**\n * ColorSelectInner - Combines an input and Ant Design ColorPicker for selecting multiple colors.\n * Supports preset color swatches and freeform hex entry, displaying selections as tags.\n * Controlled/uncontrolled APIs for `value` and `open`, emitting invalid input notifications via toast.\n * @param props - {@link ColorSelectProps}\n * @param ref - ref to the input element\n * @returns JSX.Element\n */\nconst ColorSelectInner = (\n {\n className,\n value: valueProp,\n defaultValue,\n onChange,\n colorPickerProps,\n presetColors,\n open: openProp,\n onOpenChange,\n defaultOpen,\n ...rest\n },\n ref: React.Ref<React.ComponentRef<\"input\">>\n) => {\n const cls = useCls();\n const [value, setValue] = useControlledState<string[]>(\n valueProp,\n onChange,\n defaultValue\n );\n const [activeColorIndex, setActiveColorIndex] = useState<number | null>(null);\n const [searchValue, setSearchValue] = useState(\"\");\n const [tmpValue, setTmpValue] = useState(\"\");\n const [open, setOpen] = useControlledState<boolean>(\n openProp,\n onOpenChange,\n defaultOpen\n );\n\n const [isFocus, setIsFocus] = useState(false);\n\n const popupRef = useRef<HTMLDivElement>(null);\n\n const inputRef = useRef<HTMLInputElement>(null);\n\n const isFocusedProgramatically = useRef(false);\n\n const mousePosition = useRef({\n x: 0,\n y: 0,\n });\n\n const focusInput = useCallback(() => {\n isFocusedProgramatically.current = true;\n inputRef.current?.focus();\n moveTypingCursorToEnd(inputRef.current);\n }, []);\n\n const closeAndFocus = useCallback(() => {\n setOpen(false);\n focusInput();\n }, [setOpen, focusInput]);\n\n useEffect(() => {\n if (!open) return;\n const handler = (event: MouseEvent) => {\n if (!popupRef.current?.contains(event.target as Node)) {\n if (\n inputRef.current &&\n !inputRef.current.isEqualNode(event.target as Node)\n ) {\n closeAndFocus();\n }\n }\n };\n document.addEventListener(\"click\", handler);\n\n // Return cleanup function\n return () => document.removeEventListener(\"click\", handler);\n }, [open, closeAndFocus]);\n\n useEffect(() => {\n const handleMouseMove = (e: MouseEvent) => {\n mousePosition.current = {\n x: e.clientX,\n y: e.clientY,\n };\n };\n document.addEventListener(\"mousemove\", handleMouseMove);\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove);\n };\n }, []);\n\n const onEnter = useCallback(() => {\n const searchValueSplit = searchValue\n .trim()\n .split(/[;,\\s]+/)\n .filter(Boolean);\n const addedValues = searchValueSplit.map((gene) =>\n gene.trim().toUpperCase()\n );\n const inValidValues: string[] = [];\n const validAddedValues = addedValues.reduce((acc, curr) => {\n if (!isValidHexColor(curr, true)) {\n inValidValues.push(curr);\n } else {\n acc.push(curr);\n }\n return acc;\n }, [] as string[]);\n if (inValidValues.length) {\n toast(`Invalid colors: ${inValidValues.join(\", \")}`);\n }\n const newColors = new Set([...value, ...validAddedValues]);\n if (onChange) onChange([...newColors]);\n if (onOpenChange) onOpenChange(false);\n setSearchValue(\"\");\n setTmpValue(\"\");\n setOpen(false);\n requestAnimationFrame(() => {\n setOpen(true);\n });\n }, [searchValue, value, onChange, onOpenChange, setOpen]);\n\n const onInputKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\") onEnter();\n if (e.key === \"Backspace\" && !searchValue) {\n if (e.ctrlKey || e.metaKey) {\n setValue([]);\n } else {\n setValue(value.slice(0, -1));\n }\n }\n },\n [onEnter, searchValue, value, setValue]\n );\n\n const handlePopupMouseDown = useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n // Prevent input blur when clicking popup\n e.preventDefault();\n e.stopPropagation();\n },\n []\n );\n\n const handlePopupMouseDownCapture = useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n // Prevent input blur when clicking popup\n e.preventDefault();\n },\n []\n );\n\n const renderedColorPicker = useCallback(\n ({\n open,\n child,\n value,\n onChange,\n onOpenChange,\n }: {\n open: boolean;\n child: React.ReactNode;\n value: string;\n onChange: (value: Color) => void;\n onOpenChange?: (open: boolean) => void;\n }) => (\n <ColorPicker\n value={value}\n onChange={onChange}\n open={open}\n onOpenChange={onOpenChange}\n arrow={false}\n presets={\n presetColors\n ? [{ label: \"Preset Colors\", colors: presetColors }]\n : undefined\n }\n {...colorPickerProps}\n panelRender={(panel) => (\n <div\n ref={(el) => {\n if (el) {\n popupRef.current = el;\n }\n }}\n onMouseDown={handlePopupMouseDown}\n onMouseDownCapture={handlePopupMouseDownCapture}\n >\n {panel}\n </div>\n )}\n >\n {child}\n </ColorPicker>\n ),\n [\n presetColors,\n colorPickerProps,\n handlePopupMouseDown,\n handlePopupMouseDownCapture,\n ]\n );\n\n const renderedTags = useMemo(\n () =>\n value.map((color, index) => {\n const tag = (\n <Tooltip title={color} key={`${color}-${index}`}>\n <Tag\n className={cls(\"color-select-tag\")}\n closable\n onClose={() => setValue(value.filter((v) => v !== color))}\n icon={\n <span\n className={cls(\"color-select-swatch\")}\n style={{ backgroundColor: color }}\n />\n }\n onClick={() =>\n activeColorIndex === index\n ? setActiveColorIndex(null)\n : setActiveColorIndex(index)\n }\n />\n </Tooltip>\n );\n return renderedColorPicker({\n child: tag,\n open: activeColorIndex !== null && activeColorIndex === index,\n value: value[index],\n onChange: (color) => {\n setValue(\n value.map((v, i) => (i === index ? color.toHexString() : v))\n );\n },\n onOpenChange: (open) => {\n setActiveColorIndex(open ? index : null);\n },\n });\n }),\n [\n value,\n cls,\n setValue,\n activeColorIndex,\n setActiveColorIndex,\n renderedColorPicker,\n ]\n );\n\n const renderedColorPickerInput = useMemo(() => {\n return renderedColorPicker({\n child: (\n <input\n placeholder=\"Select or enter a color list\"\n className={cls(\"color-select-input\")}\n value={searchValue}\n type=\"text\"\n ref={mergeRefs(ref, inputRef)}\n onChange={(e) => {\n const currValue = e.target.value;\n setSearchValue(currValue);\n if (isValidHexColor(currValue, true)) setTmpValue(currValue);\n if (\n currValue.length > 7 ||\n (currValue.length == 7 && !currValue.startsWith(\"#\"))\n ) {\n // closeAndFocus();\n setOpen(false);\n } else {\n setOpen(true);\n }\n }}\n onKeyDown={onInputKeyDown}\n onFocus={(e) => {\n // if focus is triggered by programatically, do not open the popup\n // if (isFocusedProgramatically.current) {\n // isFocusedProgramatically.current = false;\n // return;\n // }\n setIsFocus(true);\n setOpen(true);\n }}\n onBlur={(e) => {\n // if (popupRef.current?.contains(e.relatedTarget)) return;\n // Check if click is inside popup using cursor position\n if (popupRef.current) {\n const rect = popupRef.current.getBoundingClientRect();\n const { x, y } = mousePosition.current;\n const isClickInsidePopup =\n x >= rect.left &&\n x <= rect.right &&\n y >= rect.top &&\n y <= rect.bottom;\n if (isClickInsidePopup) {\n e.preventDefault();\n e.stopPropagation();\n if (isValidHexColor(tmpValue)) {\n focusInput();\n }\n return;\n }\n }\n // Check if the new focus target is inside the popup\n setIsFocus(false);\n setOpen(false);\n }}\n />\n ),\n value: tmpValue,\n onChange: (color) => {\n // setValue([...value, color]);\n setTmpValue(color.toHexString());\n setSearchValue(color.toHexString());\n focusInput();\n },\n open,\n });\n }, [\n cls,\n tmpValue,\n onInputKeyDown,\n ref,\n renderedColorPicker,\n searchValue,\n setOpen,\n open,\n focusInput,\n mousePosition,\n ]);\n return (\n <Stack\n wrap\n gap={4}\n className={cls(\"color-select\")}\n data-focus={isFocus || undefined}\n {...rest}\n >\n {renderedTags}\n {renderedColorPickerInput}\n </Stack>\n );\n};\n\n// Use forwardRef with type assertion\nconst MainColorSelect = forwardRef(ColorSelectInner);\n\nexport const ColorSelect = MainColorSelect;\n"],"names":["ColorSelectInner","className","valueProp","defaultValue","onChange","colorPickerProps","presetColors","openProp","onOpenChange","defaultOpen","rest","ref","cls","useCls","value","setValue","useControlledState","activeColorIndex","setActiveColorIndex","useState","searchValue","setSearchValue","tmpValue","setTmpValue","open","setOpen","isFocus","setIsFocus","popupRef","useRef","inputRef","isFocusedProgramatically","mousePosition","focusInput","useCallback","_a","moveTypingCursorToEnd","closeAndFocus","useEffect","handler","event","handleMouseMove","e","onEnter","addedValues","gene","inValidValues","validAddedValues","acc","curr","isValidHexColor","toast","newColors","onInputKeyDown","handlePopupMouseDown","handlePopupMouseDownCapture","renderedColorPicker","child","jsx","ColorPicker","panel","el","renderedTags","useMemo","color","index","tag","Tooltip","Tag","v","i","renderedColorPickerInput","mergeRefs","currValue","rect","x","y","jsxs","Stack","MainColorSelect","forwardRef","ColorSelect"],"mappings":"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"}
@@ -1 +1 @@
1
- @layer components{.ds-color-select{border-color:var(--ds-color-border);border-radius:var(--ds-border-radius);padding:.25rem;background:var(--ds-color-bg-container);border-width:var(--ds-line-width);border-style:var(--ds-line-type);transition:all var(--ds-motion-duration-mid)}.ds-color-select[data-focus=true]{border-color:var(--ds-input-color-border-active);box-shadow:var(--ds-input-shadow-active);outline:0;background-color:var(--ds-input-active-bg)}.ds-color-select .ds-tag{margin-right:0}.ds-color-select-option,.ds-color-select-tag{display:flex;align-items:center;gap:.5rem}.ds-color-select-swatch{width:16px;height:16px;border-radius:9999px;border:1px solid var(--ds-color-border);flex-shrink:0}.ds-color-select-input{outline:none;border:none;background:transparent;color:var(--ds-color-text);font-size:var(--ds-font-size);font-family:var(--ds-font-family);line-height:var(--ds-line-height);flex:1;min-width:11rem;width:100%;margin-left:.25rem}.ds-color-select-input:first-child{margin-left:.7rem}}
1
+ @layer components{.ds-color-select{border-color:var(--ds-color-border);border-radius:var(--ds-border-radius);padding:.25rem;background:var(--ds-color-bg-container);border-width:var(--ds-line-width);border-style:var(--ds-line-type);transition:all var(--ds-motion-duration-mid)}.ds-color-select[data-focus=true]{border-color:var(--ds-input-color-border-active);box-shadow:var(--ds-input-shadow-active);outline:0;background-color:var(--ds-input-active-bg)}.ds-color-select .ds-tag{margin-right:0}.ds-color-select-option{display:flex;align-items:center;gap:.5rem}.ds-color-select-tag{display:flex;align-items:center}.ds-color-select-swatch{width:16px;height:16px;border-radius:9999px;border:1px solid var(--ds-color-border);flex-shrink:0}.ds-color-select-input{outline:none;border:none;background:transparent;color:var(--ds-color-text);font-size:var(--ds-font-size);font-family:var(--ds-font-family);line-height:var(--ds-line-height);flex:1;min-width:11rem;width:100%;margin-left:.25rem}.ds-color-select-input:first-child{margin-left:.7rem}}
@@ -7,34 +7,35 @@ import { isValidElement as N, cloneElement as R } from "react";
7
7
  import { useCls as V } from "../utils/antdUtils.js";
8
8
  import { clsx as h } from "../utils/cn.js";
9
9
  const F = ({
10
- id: t,
11
- children: e,
10
+ id: e,
11
+ children: r,
12
12
  className: o,
13
- disabled: s = !1,
14
- data: n,
13
+ disabled: n = !1,
14
+ data: s,
15
15
  style: d,
16
16
  render: i,
17
17
  onDragEnd: g,
18
18
  onDragStart: E,
19
- indicator: l = !0,
20
- onlyIndicatorDraggable: m = !1,
19
+ indicator: c = !0,
20
+ onlyIndicatorDraggable: l = !1,
21
21
  ...b
22
22
  }) => {
23
- const c = V(), { attributes: a, listeners: f, isDragging: u, setNodeRef: x } = A({
24
- id: t,
25
- data: n,
26
- disabled: s,
23
+ const m = V(), { attributes: a, listeners: f, isDragging: u, setNodeRef: x } = A({
24
+ id: e,
25
+ data: s,
26
+ disabled: n,
27
27
  onDragEnd: g,
28
28
  onDragStart: E
29
- }), r = l === !0 ? /* @__PURE__ */ p(C, { className: c("draggable-indicator") }) : l, y = [
30
- N(r) ? m ? R(r, {
29
+ }), t = c === !0 ? /* @__PURE__ */ p(C, { className: m("draggable-indicator") }) : c, y = [
30
+ N(t) ? l ? R(t, {
31
31
  ...a,
32
- ...f
33
- }) : r : null,
34
- ...Array.isArray(e) ? e : [e]
32
+ ...f,
33
+ key: "indicator" + e
34
+ }) : t : null,
35
+ ...Array.isArray(r) ? r : [r]
35
36
  ];
36
37
  return D({
37
- render: i || /* @__PURE__ */ p("div", { className: h(c("draggable"), o) }),
38
+ render: i || /* @__PURE__ */ p("div", { className: h(m("draggable"), o) }),
38
39
  ref: x,
39
40
  props: {
40
41
  children: y,
@@ -43,18 +44,18 @@ const F = ({
43
44
  ...d,
44
45
  touchAction: "none",
45
46
  // Prevents scrolling on touch devices while dragging
46
- cursor: s ? "default" : "grab",
47
+ cursor: n ? "default" : "grab",
47
48
  opacity: u ? 0.5 : 1
48
49
  // Visual feedback when dragging
49
50
  },
50
51
  ...b,
51
52
  ...a,
52
- ...m ? {} : f
53
+ ...l ? {} : f
53
54
  },
54
55
  state: {
55
56
  isDragging: u,
56
- id: t,
57
- data: n
57
+ id: e,
58
+ data: s
58
59
  }
59
60
  });
60
61
  };
@@ -1 +1 @@
1
- {"version":3,"file":"draggable.js","sources":["../../../src/components/DragDrop/draggable.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDraggable } from \"./hooks\";\nimport { clsx, useCls } from \"../utils\";\nimport { useRender } from \"@base-ui-components/react/use-render\";\nimport type { Data, DragDropDraggableProps } from \"./types\";\nimport { DotsSixVerticalIcon } from \"@bioturing/assets\";\nimport { cloneElement, isValidElement, HTMLProps } from \"react\";\n\n/**\n * A draggable item component that can be used within the Drag context\n */\nexport const Draggable = <T extends Data = Data>({\n id,\n children,\n className,\n disabled = false,\n data,\n style,\n render,\n onDragEnd,\n onDragStart,\n indicator = true,\n onlyIndicatorDraggable = false,\n ...rest\n}: DragDropDraggableProps<T>) => {\n const cls = useCls();\n\n const { attributes, listeners, isDragging, setNodeRef } = useDraggable({\n id,\n data,\n disabled,\n onDragEnd,\n onDragStart,\n });\n\n const indicatorIcon =\n indicator === true ? (\n <DotsSixVerticalIcon className={cls(\"draggable-indicator\")} />\n ) : (\n indicator\n );\n const indicatorElement = isValidElement(indicatorIcon)\n ? onlyIndicatorDraggable\n ? cloneElement(indicatorIcon, {\n ...attributes,\n ...listeners,\n })\n : indicatorIcon\n : null;\n\n const combinedChildren = [\n indicatorElement,\n ...(Array.isArray(children) ? children : [children]),\n ];\n\n const renderedElement = useRender({\n render: render ? (\n render\n ) : (\n <div className={clsx(cls(\"draggable\"), className)} />\n ),\n ref: setNodeRef,\n props: {\n children: combinedChildren,\n className,\n style: {\n ...style,\n touchAction: \"none\", // Prevents scrolling on touch devices while dragging\n cursor: disabled ? \"default\" : \"grab\",\n opacity: isDragging ? 0.5 : 1, // Visual feedback when dragging\n },\n ...rest,\n ...attributes,\n ...(!onlyIndicatorDraggable ? listeners : {}),\n },\n state: {\n isDragging,\n id,\n data,\n },\n });\n\n return renderedElement;\n};\n"],"names":["Draggable","id","children","className","disabled","data","style","render","onDragEnd","onDragStart","indicator","onlyIndicatorDraggable","rest","cls","useCls","attributes","listeners","isDragging","setNodeRef","useDraggable","indicatorIcon","jsx","DotsSixVerticalIcon","combinedChildren","isValidElement","cloneElement","useRender","clsx"],"mappings":";;;;;;;;AAYO,MAAMA,IAAY,CAAwB;AAAA,EAC/C,IAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,WAAAC;AAAA,EACA,aAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,wBAAAC,IAAyB;AAAA,EACzB,GAAGC;AACL,MAAiC;AAC/B,QAAMC,IAAMC,EAAO,GAEb,EAAE,YAAAC,GAAY,WAAAC,GAAW,YAAAC,GAAY,YAAAC,EAAA,IAAeC,EAAa;AAAA,IACrE,IAAAlB;AAAA,IACA,MAAAI;AAAA,IACA,UAAAD;AAAA,IACA,WAAAI;AAAA,IACA,aAAAC;AAAA,EAAA,CACD,GAEKW,IACJV,MAAc,KACZ,gBAAAW,EAACC,KAAoB,WAAWT,EAAI,qBAAqB,EAAA,CAAG,IAE5DH,GAWEa,IAAmB;AAAA,IATAC,EAAeJ,CAAa,IACjDT,IACEc,EAAaL,GAAe;AAAA,MAC1B,GAAGL;AAAA,MACH,GAAGC;AAAA,IAAA,CACJ,IACDI,IACF;AAAA,IAIF,GAAI,MAAM,QAAQlB,CAAQ,IAAIA,IAAW,CAACA,CAAQ;AAAA,EACpD;AA6BO,SA3BiBwB,EAAU;AAAA,IAChC,QAAQnB,KAGL,gBAAAc,EAAA,OAAA,EAAI,WAAWM,EAAKd,EAAI,WAAW,GAAGV,CAAS,EAAG,CAAA;AAAA,IAErD,KAAKe;AAAA,IACL,OAAO;AAAA,MACL,UAAUK;AAAA,MACV,WAAApB;AAAA,MACA,OAAO;AAAA,QACL,GAAGG;AAAA,QACH,aAAa;AAAA;AAAA,QACb,QAAQF,IAAW,YAAY;AAAA,QAC/B,SAASa,IAAa,MAAM;AAAA;AAAA,MAC9B;AAAA,MACA,GAAGL;AAAA,MACH,GAAGG;AAAA,MACH,GAAKJ,IAAqC,CAAA,IAAZK;AAAA,IAChC;AAAA,IACA,OAAO;AAAA,MACL,YAAAC;AAAA,MACA,IAAAhB;AAAA,MACA,MAAAI;AAAA,IAAA;AAAA,EACF,CACD;AAGH;"}
1
+ {"version":3,"file":"draggable.js","sources":["../../../src/components/DragDrop/draggable.tsx"],"sourcesContent":["\"use client\";\n\nimport { useDraggable } from \"./hooks\";\nimport { clsx, useCls } from \"../utils\";\nimport { useRender } from \"@base-ui-components/react/use-render\";\nimport type { Data, DragDropDraggableProps } from \"./types\";\nimport { DotsSixVerticalIcon } from \"@bioturing/assets\";\nimport { cloneElement, isValidElement, HTMLProps } from \"react\";\n\n/**\n * A draggable item component that can be used within the Drag context\n */\nexport const Draggable = <T extends Data = Data>({\n id,\n children,\n className,\n disabled = false,\n data,\n style,\n render,\n onDragEnd,\n onDragStart,\n indicator = true,\n onlyIndicatorDraggable = false,\n ...rest\n}: DragDropDraggableProps<T>) => {\n const cls = useCls();\n\n const { attributes, listeners, isDragging, setNodeRef } = useDraggable({\n id,\n data,\n disabled,\n onDragEnd,\n onDragStart,\n });\n\n const indicatorIcon =\n indicator === true ? (\n <DotsSixVerticalIcon className={cls(\"draggable-indicator\")} />\n ) : (\n indicator\n );\n const indicatorElement = isValidElement(indicatorIcon)\n ? onlyIndicatorDraggable\n ? cloneElement(indicatorIcon, {\n ...attributes,\n ...listeners,\n key: \"indicator\" + id,\n })\n : indicatorIcon\n : null;\n\n const combinedChildren = [\n indicatorElement,\n ...(Array.isArray(children) ? children : [children]),\n ];\n\n const renderedElement = useRender({\n render: render ? (\n render\n ) : (\n <div className={clsx(cls(\"draggable\"), className)} />\n ),\n ref: setNodeRef,\n props: {\n children: combinedChildren,\n className,\n style: {\n ...style,\n touchAction: \"none\", // Prevents scrolling on touch devices while dragging\n cursor: disabled ? \"default\" : \"grab\",\n opacity: isDragging ? 0.5 : 1, // Visual feedback when dragging\n },\n ...rest,\n ...attributes,\n ...(!onlyIndicatorDraggable ? listeners : {}),\n },\n state: {\n isDragging,\n id,\n data,\n },\n });\n\n return renderedElement;\n};\n"],"names":["Draggable","id","children","className","disabled","data","style","render","onDragEnd","onDragStart","indicator","onlyIndicatorDraggable","rest","cls","useCls","attributes","listeners","isDragging","setNodeRef","useDraggable","indicatorIcon","jsx","DotsSixVerticalIcon","combinedChildren","isValidElement","cloneElement","useRender","clsx"],"mappings":";;;;;;;;AAYO,MAAMA,IAAY,CAAwB;AAAA,EAC/C,IAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,MAAAC;AAAA,EACA,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,WAAAC;AAAA,EACA,aAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,wBAAAC,IAAyB;AAAA,EACzB,GAAGC;AACL,MAAiC;AAC/B,QAAMC,IAAMC,EAAO,GAEb,EAAE,YAAAC,GAAY,WAAAC,GAAW,YAAAC,GAAY,YAAAC,EAAA,IAAeC,EAAa;AAAA,IACrE,IAAAlB;AAAA,IACA,MAAAI;AAAA,IACA,UAAAD;AAAA,IACA,WAAAI;AAAA,IACA,aAAAC;AAAA,EAAA,CACD,GAEKW,IACJV,MAAc,KACZ,gBAAAW,EAACC,KAAoB,WAAWT,EAAI,qBAAqB,EAAA,CAAG,IAE5DH,GAYEa,IAAmB;AAAA,IAVAC,EAAeJ,CAAa,IACjDT,IACEc,EAAaL,GAAe;AAAA,MAC1B,GAAGL;AAAA,MACH,GAAGC;AAAA,MACH,KAAK,cAAcf;AAAA,IAAA,CACpB,IACDmB,IACF;AAAA,IAIF,GAAI,MAAM,QAAQlB,CAAQ,IAAIA,IAAW,CAACA,CAAQ;AAAA,EACpD;AA6BO,SA3BiBwB,EAAU;AAAA,IAChC,QAAQnB,KAGL,gBAAAc,EAAA,OAAA,EAAI,WAAWM,EAAKd,EAAI,WAAW,GAAGV,CAAS,EAAG,CAAA;AAAA,IAErD,KAAKe;AAAA,IACL,OAAO;AAAA,MACL,UAAUK;AAAA,MACV,WAAApB;AAAA,MACA,OAAO;AAAA,QACL,GAAGG;AAAA,QACH,aAAa;AAAA;AAAA,QACb,QAAQF,IAAW,YAAY;AAAA,QAC/B,SAASa,IAAa,MAAM;AAAA;AAAA,MAC9B;AAAA,MACA,GAAGL;AAAA,MACH,GAAGG;AAAA,MACH,GAAKJ,IAAqC,CAAA,IAAZK;AAAA,IAChC;AAAA,IACA,OAAO;AAAA,MACL,YAAAC;AAAA,MACA,IAAAhB;AAAA,MACA,MAAAI;AAAA,IAAA;AAAA,EACF,CACD;AAGH;"}
@@ -1,48 +1,80 @@
1
1
  "use client";
2
- import { jsxs as x, jsx as r } from "react/jsx-runtime";
3
- import { useDroppable as z } from "./hooks.js";
4
- import { ArrowsOutCardinalIcon as N } from "@bioturing/assets";
5
- import { useRender as b } from "@base-ui-components/react/use-render";
6
- import { useCls as C } from "../utils/antdUtils.js";
7
- import { clsx as D } from "../utils/cn.js";
8
- const g = ({
9
- id: o,
10
- children: n,
11
- className: s,
12
- disabled: i = !1,
13
- placeholder: d = "Drop items here",
14
- icon: l = /* @__PURE__ */ r(N, { size: 24 }),
15
- render: t,
2
+ import { jsxs as P, jsx as n } from "react/jsx-runtime";
3
+ import { memo as W, useCallback as x, useMemo as b } from "react";
4
+ import { useDroppable as h } from "./hooks.js";
5
+ import { ArrowsOutCardinalIcon as y } from "@bioturing/assets";
6
+ import { useRender as B } from "@base-ui-components/react/use-render";
7
+ import { Value as F } from "./value.js";
8
+ import { uniqWith as G, isEqual as H } from "es-toolkit";
9
+ import { useCls as J } from "../utils/antdUtils.js";
10
+ import { clsx as K } from "../utils/cn.js";
11
+ const Q = ({
12
+ id: d,
13
+ children: m,
14
+ className: D,
15
+ disabled: E = !1,
16
+ placeholder: i = "Drop items here",
17
+ icon: f = /* @__PURE__ */ n(y, { size: 24 }),
18
+ render: O,
16
19
  onDrop: c,
17
- validate: m,
18
- ...p
20
+ validate: R,
21
+ multiple: s,
22
+ value: r,
23
+ onChange: o,
24
+ renderValueLabel: p,
25
+ renderValueIcon: a,
26
+ ...j
19
27
  }) => {
20
- const e = C(), { isOver: a, setNodeRef: f, attributes: u, listeners: h } = z({
21
- id: o,
22
- disabled: i,
23
- onDrop: c,
24
- validate: m
25
- }), v = /* @__PURE__ */ x("div", { className: e("drop-zone-content"), children: [
26
- /* @__PURE__ */ r("div", { className: e("drop-zone-icon"), children: l }),
27
- /* @__PURE__ */ r("div", { className: e("drop-zone-text"), children: d })
28
- ] });
29
- return b({
30
- render: t || /* @__PURE__ */ r("div", { className: D(e("drop-zone"), s) }),
31
- ref: f,
28
+ const e = J(), q = x(
29
+ (t) => {
30
+ c && c(t), o && o(
31
+ s ? G([...r, t.data], H) : t.data
32
+ );
33
+ },
34
+ [c, o, s, r]
35
+ ), { isOver: k, setNodeRef: w, attributes: A, listeners: I } = h({
36
+ id: d,
37
+ disabled: E,
38
+ onDrop: q,
39
+ validate: R
40
+ }), z = b(
41
+ () => ({ value: r, onChange: o, multiple: s, renderValueLabel: p, renderValueIcon: a }),
42
+ [r, o, s, p, a]
43
+ ), N = b(
44
+ () => m || /* @__PURE__ */ P("div", { className: e("drop-zone-content"), children: [
45
+ /* @__PURE__ */ n("div", { className: e("drop-zone-icon"), children: f }),
46
+ /* @__PURE__ */ n("div", { className: e("drop-zone-text"), children: i })
47
+ ] }),
48
+ [m, e, f, i]
49
+ ), M = x(
50
+ ({ className: t, ...l }) => !s && r || s && r.length ? /* @__PURE__ */ n(
51
+ F,
52
+ {
53
+ ...z,
54
+ className: t,
55
+ ...l
56
+ }
57
+ ) : /* @__PURE__ */ n("div", { className: K(e("drop-zone"), t), ...l, children: N }),
58
+ [r, s, z, N, e]
59
+ );
60
+ return B({
61
+ render: O ?? M,
62
+ ref: w,
32
63
  props: {
33
- children: n || v,
34
- className: s,
35
- ...u,
36
- ...h,
37
- ...p
64
+ className: D,
65
+ ...A,
66
+ ...I,
67
+ ...j
38
68
  },
39
69
  state: {
40
- isOver: a,
41
- id: o
70
+ isOver: k,
71
+ value: r,
72
+ onChange: o,
73
+ id: d
42
74
  }
43
75
  });
44
- };
76
+ }, L = W(Q);
45
77
  export {
46
- g as Droppable
78
+ L as Droppable
47
79
  };
48
80
  //# sourceMappingURL=droppable.js.map