dishui 0.0.56 → 0.0.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Select/index.js +90 -72
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/pro/Flow/Flow.js +659 -552
- package/dist/components/pro/Flow/Flow.js.map +1 -1
- package/dist/components/pro/Flow/FlowCanvas.js +1041 -966
- package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
- package/dist/components/pro/Flow/canvas/ViewportContainer.d.ts +6 -0
- package/dist/components/pro/Flow/canvas/ViewportContainer.js +20 -15
- package/dist/components/pro/Flow/canvas/ViewportContainer.js.map +1 -1
- package/dist/components/pro/Flow/context/FlowUIContext.d.ts +6 -2
- package/dist/components/pro/Flow/context/FlowUIContext.js +51 -51
- package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useCompactMode.d.ts +13 -0
- package/dist/components/pro/Flow/hooks/useCompactMode.js +20 -0
- package/dist/components/pro/Flow/hooks/useCompactMode.js.map +1 -0
- package/dist/components/pro/Flow/hooks/useDraggablePanel.d.ts +19 -4
- package/dist/components/pro/Flow/hooks/useDraggablePanel.js +31 -24
- package/dist/components/pro/Flow/hooks/useDraggablePanel.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useMindMap.js +16 -22
- package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
- package/dist/components/pro/Flow/hooks/usePixiApp.js +16 -16
- package/dist/components/pro/Flow/hooks/usePixiApp.js.map +1 -1
- package/dist/components/pro/Flow/nodes/nodeUtils.d.ts +2 -2
- package/dist/components/pro/Flow/nodes/nodeUtils.js +12 -12
- package/dist/components/pro/Flow/nodes/nodeUtils.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowPanelGroup.d.ts +10 -5
- package/dist/components/pro/Flow/panels/FlowPanelGroup.js +95 -67
- package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/utils/i18n.js +10 -0
- package/dist/utils/i18n.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { useClickOutside as
|
|
2
|
-
import { useCallback as
|
|
3
|
-
import { jsx as o, jsxs as
|
|
4
|
-
import { createPortal as
|
|
5
|
-
var
|
|
1
|
+
import { useClickOutside as K } from "../../hooks/useClickOutside.js";
|
|
2
|
+
import { useCallback as L, useEffect as p, useRef as v, useState as w } from "react";
|
|
3
|
+
import { jsx as o, jsxs as P } from "react/jsx-runtime";
|
|
4
|
+
import { createPortal as U } from "react-dom";
|
|
5
|
+
var Y = ({ isOpen: r }) => /* @__PURE__ */ o("svg", {
|
|
6
6
|
xmlns: "http://www.w3.org/2000/svg",
|
|
7
7
|
fill: "none",
|
|
8
8
|
viewBox: "0 0 24 24",
|
|
@@ -20,7 +20,7 @@ var V = ({ isOpen: r }) => /* @__PURE__ */ o("svg", {
|
|
|
20
20
|
strokeLinejoin: "round",
|
|
21
21
|
d: "M19 9l-7 7-7-7"
|
|
22
22
|
})
|
|
23
|
-
}),
|
|
23
|
+
}), X = () => /* @__PURE__ */ o("svg", {
|
|
24
24
|
xmlns: "http://www.w3.org/2000/svg",
|
|
25
25
|
className: "h-3 w-3",
|
|
26
26
|
fill: "none",
|
|
@@ -32,10 +32,10 @@ var V = ({ isOpen: r }) => /* @__PURE__ */ o("svg", {
|
|
|
32
32
|
strokeLinejoin: "round",
|
|
33
33
|
d: "M6 18L18 6M6 6l12 12"
|
|
34
34
|
})
|
|
35
|
-
}),
|
|
36
|
-
const [
|
|
37
|
-
|
|
38
|
-
if (!
|
|
35
|
+
}), Z = ({ options: r, value: i, onChange: x, placeholder: R = "Select...", multiple: l = !1, fixedHeight: D = !1, style: O, className: $ }) => {
|
|
36
|
+
const [a, u] = w(!1), [c, b] = w(-1), [y, N] = w(""), [A, j] = w(!0), [M, S] = w({}), h = v(null), k = v(null), m = v(null), g = v(null);
|
|
37
|
+
p(() => {
|
|
38
|
+
if (!a) return;
|
|
39
39
|
const e = (n) => {
|
|
40
40
|
const t = n.target;
|
|
41
41
|
h.current?.contains(t) || m.current?.contains(t) || u(!1);
|
|
@@ -43,10 +43,10 @@ var V = ({ isOpen: r }) => /* @__PURE__ */ o("svg", {
|
|
|
43
43
|
return document.addEventListener("pointerdown", e), document.addEventListener("mousedown", e), () => {
|
|
44
44
|
document.removeEventListener("pointerdown", e), document.removeEventListener("mousedown", e);
|
|
45
45
|
};
|
|
46
|
-
}, [
|
|
47
|
-
const d = Array.isArray(
|
|
48
|
-
|
|
49
|
-
const f =
|
|
46
|
+
}, [a]);
|
|
47
|
+
const d = Array.isArray(i) ? i : i != null ? [i] : [];
|
|
48
|
+
K(h, L(() => u(!1), []));
|
|
49
|
+
const f = L(() => {
|
|
50
50
|
const e = h.current;
|
|
51
51
|
if (!e) return;
|
|
52
52
|
const n = e.getBoundingClientRect(), t = Math.min(r.length, 8) * 36 + 8, s = n.bottom + 4 + t <= window.innerHeight;
|
|
@@ -58,31 +58,31 @@ var V = ({ isOpen: r }) => /* @__PURE__ */ o("svg", {
|
|
|
58
58
|
zIndex: 1e4
|
|
59
59
|
});
|
|
60
60
|
}, [r.length]);
|
|
61
|
-
|
|
62
|
-
if (
|
|
61
|
+
p(() => {
|
|
62
|
+
if (a)
|
|
63
63
|
return f(), window.addEventListener("resize", f), window.addEventListener("scroll", f, !0), () => {
|
|
64
64
|
window.removeEventListener("resize", f), window.removeEventListener("scroll", f, !0);
|
|
65
65
|
};
|
|
66
|
-
}, [
|
|
66
|
+
}, [a, f]), p(() => {
|
|
67
67
|
const e = h.current;
|
|
68
68
|
if (!e) return;
|
|
69
|
-
const n = () =>
|
|
69
|
+
const n = () => j(e.clientWidth >= 88);
|
|
70
70
|
n();
|
|
71
71
|
const t = new ResizeObserver(n);
|
|
72
72
|
return t.observe(e), () => t.disconnect();
|
|
73
|
-
}, []),
|
|
74
|
-
if (!
|
|
73
|
+
}, []), p(() => {
|
|
74
|
+
if (!a) return;
|
|
75
75
|
const e = (n) => {
|
|
76
76
|
switch (n.key) {
|
|
77
77
|
case "ArrowDown":
|
|
78
|
-
n.preventDefault(), b((t) => t < r.length - 1 ? t + 1 : 0),
|
|
78
|
+
n.preventDefault(), b((t) => t < r.length - 1 ? t + 1 : 0), C();
|
|
79
79
|
break;
|
|
80
80
|
case "ArrowUp":
|
|
81
|
-
n.preventDefault(), b((t) => t > 0 ? t - 1 : r.length - 1),
|
|
81
|
+
n.preventDefault(), b((t) => t > 0 ? t - 1 : r.length - 1), C();
|
|
82
82
|
break;
|
|
83
83
|
case "Enter":
|
|
84
84
|
case " ":
|
|
85
|
-
n.preventDefault(), c >= 0 && c < r.length &&
|
|
85
|
+
n.preventDefault(), c >= 0 && c < r.length && E(r[c]), l || u(!1);
|
|
86
86
|
break;
|
|
87
87
|
case "Escape":
|
|
88
88
|
u(!1);
|
|
@@ -95,12 +95,12 @@ var V = ({ isOpen: r }) => /* @__PURE__ */ o("svg", {
|
|
|
95
95
|
document.removeEventListener("keydown", e);
|
|
96
96
|
};
|
|
97
97
|
}, [
|
|
98
|
-
|
|
98
|
+
a,
|
|
99
99
|
c,
|
|
100
100
|
r,
|
|
101
|
-
|
|
101
|
+
l
|
|
102
102
|
]);
|
|
103
|
-
const
|
|
103
|
+
const C = L(() => {
|
|
104
104
|
if (m.current && c >= 0) {
|
|
105
105
|
const e = m.current, n = e.children[c];
|
|
106
106
|
if (n) {
|
|
@@ -108,58 +108,73 @@ var V = ({ isOpen: r }) => /* @__PURE__ */ o("svg", {
|
|
|
108
108
|
s.bottom > t.bottom ? e.scrollTop += s.bottom - t.bottom : s.top < t.top && (e.scrollTop -= t.top - s.top);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
}, [c]),
|
|
112
|
-
const e = !
|
|
111
|
+
}, [c]), I = () => {
|
|
112
|
+
const e = !a;
|
|
113
113
|
u(e), b(e ? 0 : -1), e && f();
|
|
114
|
-
},
|
|
115
|
-
if (
|
|
116
|
-
const n = Array.isArray(
|
|
114
|
+
}, E = (e) => {
|
|
115
|
+
if (l) {
|
|
116
|
+
const n = Array.isArray(i) ? i : [];
|
|
117
117
|
let t;
|
|
118
|
-
n.includes(e.value) ? t = n.filter((s) => s !== e.value) : t = [...n, e.value],
|
|
118
|
+
n.includes(e.value) ? t = n.filter((s) => s !== e.value) : t = [...n, e.value], x(t);
|
|
119
119
|
} else
|
|
120
|
-
|
|
120
|
+
x(e.value), u(!1);
|
|
121
|
+
}, T = (e, n) => {
|
|
122
|
+
if (e.pointerType === "mouse") {
|
|
123
|
+
e.preventDefault(), e.stopPropagation(), E(n);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
e.stopPropagation(), g.current = {
|
|
127
|
+
pointerId: e.pointerId,
|
|
128
|
+
x: e.clientX,
|
|
129
|
+
y: e.clientY
|
|
130
|
+
};
|
|
121
131
|
}, B = (e, n) => {
|
|
122
|
-
|
|
132
|
+
const t = g.current;
|
|
133
|
+
g.current = null, !(!t || e.pointerId !== t.pointerId) && Math.hypot(e.clientX - t.x, e.clientY - t.y) < 10 && (e.stopPropagation(), E(n));
|
|
134
|
+
}, W = () => {
|
|
135
|
+
g.current = null;
|
|
136
|
+
}, z = (e, n) => {
|
|
137
|
+
e.stopPropagation(), x((Array.isArray(i) ? i : []).filter((t) => t !== n));
|
|
123
138
|
};
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
const e =
|
|
127
|
-
|
|
128
|
-
} else
|
|
139
|
+
p(() => {
|
|
140
|
+
if (l && k.current) {
|
|
141
|
+
const e = k.current, n = r.filter((s) => d.includes(s.value)).map((s) => s.label).join(", "), t = e.scrollWidth > e.clientWidth;
|
|
142
|
+
N(t ? n : "");
|
|
143
|
+
} else N("");
|
|
129
144
|
}, [
|
|
145
|
+
i,
|
|
130
146
|
l,
|
|
131
|
-
a,
|
|
132
147
|
r,
|
|
133
148
|
d
|
|
134
149
|
]);
|
|
135
|
-
const
|
|
150
|
+
const V = () => {
|
|
136
151
|
if (d.length === 0) return /* @__PURE__ */ o("span", {
|
|
137
152
|
className: "text-base-content/60 italic",
|
|
138
|
-
children:
|
|
153
|
+
children: R
|
|
139
154
|
});
|
|
140
155
|
const e = r.filter((n) => d.includes(n.value));
|
|
141
|
-
if (
|
|
142
|
-
const n =
|
|
156
|
+
if (l) {
|
|
157
|
+
const n = D;
|
|
143
158
|
return /* @__PURE__ */ o("div", {
|
|
144
|
-
ref:
|
|
159
|
+
ref: k,
|
|
145
160
|
className: `
|
|
146
161
|
flex gap-1
|
|
147
162
|
${n ? "flex-nowrap overflow-x-auto overflow-y-hidden" : "flex-wrap overflow-hidden"} // Enable horizontal scroll, hide vertical scrollbar if any
|
|
148
|
-
${
|
|
163
|
+
${y ? "tooltip tooltip-bottom" : ""} // Keep tooltip for overflow
|
|
149
164
|
`,
|
|
150
|
-
"data-tip":
|
|
165
|
+
"data-tip": y || void 0,
|
|
151
166
|
style: {
|
|
152
167
|
scrollbarWidth: "thin",
|
|
153
168
|
...n ? { paddingRight: "1.75rem" } : {}
|
|
154
169
|
},
|
|
155
|
-
children: e.map((t) => /* @__PURE__ */
|
|
170
|
+
children: e.map((t) => /* @__PURE__ */ P("span", {
|
|
156
171
|
className: "badge badge-ghost gap-1 text-xs items-center whitespace-nowrap flex-shrink-0",
|
|
157
172
|
children: [t.label, /* @__PURE__ */ o("button", {
|
|
158
173
|
type: "button",
|
|
159
|
-
onClick: (s) =>
|
|
174
|
+
onClick: (s) => z(s, t.value),
|
|
160
175
|
className: "btn btn-xs btn-ghost btn-circle p-0 m-0 hover:bg-error hover:text-error-content",
|
|
161
176
|
"aria-label": `Remove ${t.label}`,
|
|
162
|
-
children: /* @__PURE__ */ o(
|
|
177
|
+
children: /* @__PURE__ */ o(X, {})
|
|
163
178
|
})]
|
|
164
179
|
}, t.value))
|
|
165
180
|
});
|
|
@@ -170,35 +185,35 @@ var V = ({ isOpen: r }) => /* @__PURE__ */ o("svg", {
|
|
|
170
185
|
children: n.label
|
|
171
186
|
}) : /* @__PURE__ */ o("span", {
|
|
172
187
|
className: "text-base-content/60 italic",
|
|
173
|
-
children:
|
|
188
|
+
children: R
|
|
174
189
|
});
|
|
175
190
|
}
|
|
176
|
-
},
|
|
191
|
+
}, H = `
|
|
177
192
|
relative border border-base-300 rounded-lg bg-base-100 w-full
|
|
178
193
|
flex justify-between items-center cursor-pointer px-3 text-sm
|
|
179
194
|
focus:outline-none focus:ring-2 focus:ring-primary focus:ring-opacity-50
|
|
180
195
|
hover:border-base-content/30
|
|
181
|
-
${
|
|
196
|
+
${l ? D ? "h-8" : "min-h-8 h-auto py-1" : "h-8"}
|
|
182
197
|
`;
|
|
183
|
-
return /* @__PURE__ */
|
|
198
|
+
return /* @__PURE__ */ P("div", {
|
|
184
199
|
ref: h,
|
|
185
|
-
style:
|
|
186
|
-
className: `relative w-full font-sans select-none ${
|
|
187
|
-
children: [/* @__PURE__ */
|
|
200
|
+
style: O,
|
|
201
|
+
className: `relative w-full font-sans select-none ${$ || ""}`,
|
|
202
|
+
children: [/* @__PURE__ */ P("div", {
|
|
188
203
|
tabIndex: 0,
|
|
189
|
-
className:
|
|
190
|
-
onClick:
|
|
204
|
+
className: H,
|
|
205
|
+
onClick: I,
|
|
191
206
|
onKeyDown: (e) => {
|
|
192
|
-
(e.key === "Enter" || e.key === " ") &&
|
|
207
|
+
(e.key === "Enter" || e.key === " ") && I();
|
|
193
208
|
},
|
|
194
209
|
role: "combobox",
|
|
195
210
|
"aria-haspopup": "listbox",
|
|
196
|
-
"aria-expanded":
|
|
211
|
+
"aria-expanded": a,
|
|
197
212
|
children: [/* @__PURE__ */ o("div", {
|
|
198
213
|
className: "flex-1 min-w-0 overflow-hidden",
|
|
199
|
-
style: { paddingRight:
|
|
200
|
-
children:
|
|
201
|
-
}),
|
|
214
|
+
style: { paddingRight: A ? 28 : 0 },
|
|
215
|
+
children: V()
|
|
216
|
+
}), A && /* @__PURE__ */ o("div", {
|
|
202
217
|
"aria-hidden": "true",
|
|
203
218
|
style: {
|
|
204
219
|
position: "absolute",
|
|
@@ -212,22 +227,25 @@ var V = ({ isOpen: r }) => /* @__PURE__ */ o("svg", {
|
|
|
212
227
|
width: 16,
|
|
213
228
|
height: 16
|
|
214
229
|
},
|
|
215
|
-
children: /* @__PURE__ */ o(
|
|
230
|
+
children: /* @__PURE__ */ o(Y, { isOpen: a })
|
|
216
231
|
})]
|
|
217
|
-
}),
|
|
232
|
+
}), a && typeof document < "u" && U(/* @__PURE__ */ o("ul", {
|
|
218
233
|
ref: m,
|
|
219
234
|
className: "bg-base-100 border border-base-300 rounded-md shadow-lg list-none p-0 m-0 max-h-60 overflow-y-auto focus:outline-none",
|
|
220
|
-
style:
|
|
235
|
+
style: {
|
|
236
|
+
...M,
|
|
237
|
+
touchAction: "pan-y"
|
|
238
|
+
},
|
|
221
239
|
onPointerDown: (e) => e.stopPropagation(),
|
|
222
240
|
role: "listbox",
|
|
223
241
|
"aria-activedescendant": c >= 0 ? `option-${r[c]?.value}` : void 0,
|
|
224
242
|
tabIndex: -1,
|
|
225
243
|
children: r.length > 0 ? r.map((e, n) => /* @__PURE__ */ o("li", {
|
|
226
244
|
id: `option-${e.value}`,
|
|
227
|
-
className: `p-2 cursor-pointer whitespace-nowrap overflow-hidden text-ellipsis hover:bg-base-200 ${n === c ? "bg-base-300" : ""} ${d.includes(e.value) && !
|
|
228
|
-
onPointerDown: (t) =>
|
|
229
|
-
|
|
230
|
-
|
|
245
|
+
className: `p-2 cursor-pointer whitespace-nowrap overflow-hidden text-ellipsis hover:bg-base-200 ${n === c ? "bg-base-300" : ""} ${d.includes(e.value) && !l ? "font-semibold bg-base-200" : ""} ${d.includes(e.value) && l ? "font-semibold" : ""}`,
|
|
246
|
+
onPointerDown: (t) => T(t, e),
|
|
247
|
+
onPointerUp: (t) => B(t, e),
|
|
248
|
+
onPointerCancel: W,
|
|
231
249
|
onClick: (t) => {
|
|
232
250
|
t.preventDefault(), t.stopPropagation();
|
|
233
251
|
},
|
|
@@ -243,7 +261,7 @@ var V = ({ isOpen: r }) => /* @__PURE__ */ o("svg", {
|
|
|
243
261
|
});
|
|
244
262
|
};
|
|
245
263
|
export {
|
|
246
|
-
|
|
264
|
+
Z as default
|
|
247
265
|
};
|
|
248
266
|
|
|
249
267
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Select/index.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useClickOutside } from '../../hooks/useClickOutside';\n\nexport interface Option {\n value: string | number;\n label: string;\n}\n\nexport interface SelectProps {\n options: Option[];\n value?: string | number | (string | number)[];\n onChange: (value: string | number | (string | number)[]) => void;\n placeholder?: string;\n multiple?: boolean;\n fixedHeight?: boolean;\n style?: React.CSSProperties; // Allow passing inline styles\n className?: string; // Allow passing CSS classes for the wrapper\n}\n\n// SVG component for the dropdown arrow\nconst DropdownArrow: React.FC<{ isOpen: boolean }> = ({ isOpen }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n style={{\n display: 'block',\n width: 16,\n height: 16,\n transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',\n transition: 'transform 200ms ease-in-out',\n }}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n);\n\n// SVG component for the remove button 'x'\nconst RemoveIcon: React.FC = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n);\n\n// Select Component Implementation using daisyUI/Tailwind\nconst Select: React.FC<SelectProps> = ({\n options,\n value,\n onChange,\n placeholder = 'Select...',\n multiple = false,\n fixedHeight = false,\n style,\n className // This className applies to the wrapper\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n const [tooltipText, setTooltipText] = useState('');\n const [showArrow, setShowArrow] = useState(true);\n const [dropdownStyle, setDropdownStyle] = useState<React.CSSProperties>({});\n const wrapperRef = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null); // Ref for the header div\n const optionsListRef = useRef<HTMLUListElement>(null);\n\n useEffect(() => {\n if (!isOpen) return;\n const handlePointerDown = (event: MouseEvent) => {\n const target = event.target as Node;\n if (wrapperRef.current?.contains(target) || optionsListRef.current?.contains(target)) return;\n setIsOpen(false);\n };\n document.addEventListener('pointerdown', handlePointerDown);\n document.addEventListener('mousedown', handlePointerDown);\n return () => {\n document.removeEventListener('pointerdown', handlePointerDown);\n document.removeEventListener('mousedown', handlePointerDown);\n };\n }, [isOpen]);\n\n const selectedValuesArray = Array.isArray(value) ? value : (value !== undefined && value !== null ? [value] : []);\n\n // Close dropdown when clicking outside\n useClickOutside(wrapperRef, useCallback(() => setIsOpen(false), []));\n\n const updateDropdownPosition = useCallback(() => {\n const wrapper = wrapperRef.current;\n if (!wrapper) return;\n const rect = wrapper.getBoundingClientRect();\n const estimatedHeight = Math.min(options.length, 8) * 36 + 8;\n const fitsBelow = rect.bottom + 4 + estimatedHeight <= window.innerHeight;\n setDropdownStyle({\n position: 'fixed',\n left: rect.left,\n top: fitsBelow ? rect.bottom + 4 : Math.max(8, rect.top - estimatedHeight - 4),\n width: rect.width,\n zIndex: 10000,\n });\n }, [options.length]);\n\n useEffect(() => {\n if (!isOpen) return;\n updateDropdownPosition();\n window.addEventListener('resize', updateDropdownPosition);\n window.addEventListener('scroll', updateDropdownPosition, true);\n return () => {\n window.removeEventListener('resize', updateDropdownPosition);\n window.removeEventListener('scroll', updateDropdownPosition, true);\n };\n }, [isOpen, updateDropdownPosition]);\n\n // Hide the decorative arrow when the control becomes too narrow to reserve\n // space for both it and a useful amount of label text.\n useEffect(() => {\n const wrapper = wrapperRef.current;\n if (!wrapper) return;\n const update = () => setShowArrow(wrapper.clientWidth >= 88);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(wrapper);\n return () => observer.disconnect();\n }, []);\n\n // Keyboard navigation\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n setHighlightedIndex(prev => (prev < options.length - 1 ? prev + 1 : 0));\n scrollToHighlightedOption();\n break;\n case 'ArrowUp':\n event.preventDefault();\n setHighlightedIndex(prev => (prev > 0 ? prev - 1 : options.length - 1));\n scrollToHighlightedOption();\n break;\n case 'Enter':\n case ' ': // Space key\n event.preventDefault();\n if (highlightedIndex >= 0 && highlightedIndex < options.length) {\n handleOptionClick(options[highlightedIndex]);\n if (!multiple) setIsOpen(false); // Close dropdown on selection if single mode\n } else if (!multiple) {\n setIsOpen(false); // Close dropdown if Enter/Space is pressed without a highlighted option in single mode\n }\n break;\n case 'Escape':\n setIsOpen(false);\n break;\n default:\n // Optional: Implement type-ahead find\n break;\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen, highlightedIndex, options, multiple]); // Added multiple to dependencies\n\n const scrollToHighlightedOption = useCallback(() => {\n if (optionsListRef.current && highlightedIndex >= 0) {\n const list = optionsListRef.current;\n const optionElement = list.children[highlightedIndex] as HTMLLIElement;\n if (optionElement) {\n const listRect = list.getBoundingClientRect();\n const optionRect = optionElement.getBoundingClientRect();\n\n if (optionRect.bottom > listRect.bottom) {\n list.scrollTop += optionRect.bottom - listRect.bottom;\n } else if (optionRect.top < listRect.top) {\n list.scrollTop -= listRect.top - optionRect.top;\n }\n }\n }\n }, [highlightedIndex]);\n\n const toggleDropdown = () => {\n const next = !isOpen;\n setIsOpen(next);\n setHighlightedIndex(next ? 0 : -1); // Reset or set initial highlight\n if (next) updateDropdownPosition();\n };\n\n const handleOptionClick = (option: Option) => {\n if (multiple) {\n const currentValues = Array.isArray(value) ? value : [];\n let newValue;\n if (currentValues.includes(option.value)) {\n newValue = currentValues.filter(v => v !== option.value);\n } else {\n newValue = [...currentValues, option.value];\n }\n onChange(newValue);\n } else {\n onChange(option.value);\n setIsOpen(false); // Close dropdown on single select\n }\n // Keep highlight on the selected item in multi-select? Maybe not.\n // setHighlightedIndex(options.findIndex(o => o.value === option.value));\n };\n\n const handleRemoveItem = (e: React.MouseEvent, itemValue: string | number) => {\n e.stopPropagation(); // Prevent dropdown from opening/closing\n const currentValues = Array.isArray(value) ? value : [];\n onChange(currentValues.filter(v => v !== itemValue));\n };\n\n // Update tooltip text and check for overflow\n useEffect(() => {\n if (multiple && headerRef.current) {\n const header = headerRef.current;\n const selectedLabels = options\n .filter(opt => selectedValuesArray.includes(opt.value))\n .map(opt => opt.label)\n .join(', ');\n\n // Check if the content (scrollWidth) exceeds the visible area (clientWidth)\n const isOverflowing = header.scrollWidth > header.clientWidth;\n setTooltipText(isOverflowing ? selectedLabels : ''); // Only set text if overflowing\n } else {\n setTooltipText(''); // Clear tooltip for single select or empty multi-select\n }\n }, [value, multiple, options, selectedValuesArray]);\n\n\n const renderSelectedValue = () => {\n if (selectedValuesArray.length === 0) {\n return <span className=\"text-base-content/60 italic\">{placeholder}</span>;\n }\n\n const selectedOptions = options.filter(opt => selectedValuesArray.includes(opt.value));\n\n if (multiple) {\n const isFixed = fixedHeight;\n // Apply overflow-x-auto for horizontal scrolling in fixedHeight mode\n const containerClasses = `\n flex gap-1 \n ${isFixed ? 'flex-nowrap overflow-x-auto overflow-y-hidden' : 'flex-wrap overflow-hidden'} // Enable horizontal scroll, hide vertical scrollbar if any\n ${tooltipText ? 'tooltip tooltip-bottom' : ''} // Keep tooltip for overflow\n `;\n // Removed showEllipsisPrefix\n\n return (\n <div\n ref={headerRef}\n className={containerClasses}\n data-tip={tooltipText ? tooltipText : undefined} // Keep tooltip logic\n // Add scrollbar styling if desired (e.g., using ::-webkit-scrollbar pseudo-element via CSS or a utility)\n style={{\n scrollbarWidth: 'thin',\n // 为固定高度模式添加右侧内边距,避免与下拉图标重叠\n ...(isFixed ? { paddingRight: '1.75rem' } : {})\n }}\n >\n {/* Removed wrapper for ellipsis and its popup */}\n\n {/* Render the badges */}\n {selectedOptions.map(option => (\n <span key={option.value} className=\"badge badge-ghost gap-1 text-xs items-center whitespace-nowrap flex-shrink-0\">\n {option.label}\n <button\n type=\"button\"\n onClick={(e) => handleRemoveItem(e, option.value)}\n className=\"btn btn-xs btn-ghost btn-circle p-0 m-0 hover:bg-error hover:text-error-content\"\n aria-label={`Remove ${option.label}`}\n >\n <RemoveIcon />\n </button>\n </span>\n ))}\n </div>\n );\n } else {\n const selectedOption = options.find(opt => opt.value === selectedValuesArray[0]);\n return selectedOption ? <span className=\"truncate\">{selectedOption.label}</span> : <span className=\"text-base-content/60 italic\">{placeholder}</span>;\n }\n };\n\n // Match the default control height to a normal line of form text. Multi-select\n // may still grow when wrapping tags unless fixedHeight is requested.\n const selectClasses = `\n relative border border-base-300 rounded-lg bg-base-100 w-full\n flex justify-between items-center cursor-pointer px-3 text-sm\n focus:outline-none focus:ring-2 focus:ring-primary focus:ring-opacity-50\n hover:border-base-content/30\n ${multiple\n ? (fixedHeight ? 'h-8' : 'min-h-8 h-auto py-1')\n : 'h-8'}\n `;\n\n return (\n <div\n ref={wrapperRef}\n style={style}\n className={`relative w-full font-sans select-none ${className || ''}`}\n >\n {/* Header */}\n <div\n tabIndex={0}\n className={selectClasses}\n onClick={toggleDropdown}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') toggleDropdown(); }}\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n >\n <div\n className=\"flex-1 min-w-0 overflow-hidden\"\n style={{ paddingRight: showArrow ? 28 : 0 }}\n >\n {renderSelectedValue()}\n </div>\n {/* Inline positioning avoids utility CSS/theme overrides moving the icon. */}\n {showArrow && (\n <div\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n right: 10,\n top: '50%',\n transform: 'translateY(-50%)',\n pointerEvents: 'none',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 16,\n height: 16,\n }}\n >\n <DropdownArrow isOpen={isOpen} />\n </div>\n )}\n </div>\n\n {/* Dropdown Options */}\n {isOpen && typeof document !== 'undefined' && createPortal(\n <ul\n ref={optionsListRef}\n className=\"bg-base-100 border border-base-300 rounded-md shadow-lg list-none p-0 m-0 max-h-60 overflow-y-auto focus:outline-none\"\n style={dropdownStyle}\n onPointerDown={(event) => event.stopPropagation()}\n role=\"listbox\" // ARIA role\n aria-activedescendant={highlightedIndex >= 0 ? `option-${options[highlightedIndex]?.value}` : undefined} // For screen readers\n tabIndex={-1} // Allows focus programmatically but not via tab\n >\n {options.length > 0 ? (\n options.map((option, index) => (\n <li\n key={option.value}\n id={`option-${option.value}`} // ID for aria-activedescendant\n className={`p-2 cursor-pointer whitespace-nowrap overflow-hidden text-ellipsis hover:bg-base-200 ${index === highlightedIndex ? 'bg-base-300' : '' // Highlight style\n } ${selectedValuesArray.includes(option.value) && !multiple ? 'font-semibold bg-base-200' : '' // Style for selected single item\n } ${selectedValuesArray.includes(option.value) && multiple ? 'font-semibold' : '' // Style for selected multi items (less prominent background)\n }`}\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n handleOptionClick(option);\n }}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n onMouseEnter={() => setHighlightedIndex(index)} // Highlight on hover\n role=\"option\" // ARIA role\n aria-selected={selectedValuesArray.includes(option.value)}\n >\n {/* Optional: Add a checkmark or similar for selected items, especially in multi-select */}\n {option.label}\n </li>\n ))\n ) : (\n <li className=\"p-2 text-base-content/60 italic\">\n No options available\n </li>\n )}\n </ul>,\n document.body,\n )}\n </div>\n );\n};\n\nexport default Select; "],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Select/index.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useClickOutside } from '../../hooks/useClickOutside';\n\nexport interface Option {\n value: string | number;\n label: string;\n}\n\nexport interface SelectProps {\n options: Option[];\n value?: string | number | (string | number)[];\n onChange: (value: string | number | (string | number)[]) => void;\n placeholder?: string;\n multiple?: boolean;\n fixedHeight?: boolean;\n style?: React.CSSProperties; // Allow passing inline styles\n className?: string; // Allow passing CSS classes for the wrapper\n}\n\n// SVG component for the dropdown arrow\nconst DropdownArrow: React.FC<{ isOpen: boolean }> = ({ isOpen }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n style={{\n display: 'block',\n width: 16,\n height: 16,\n transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',\n transition: 'transform 200ms ease-in-out',\n }}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n);\n\n// SVG component for the remove button 'x'\nconst RemoveIcon: React.FC = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n);\n\n// Select Component Implementation using daisyUI/Tailwind\nconst Select: React.FC<SelectProps> = ({\n options,\n value,\n onChange,\n placeholder = 'Select...',\n multiple = false,\n fixedHeight = false,\n style,\n className // This className applies to the wrapper\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n const [tooltipText, setTooltipText] = useState('');\n const [showArrow, setShowArrow] = useState(true);\n const [dropdownStyle, setDropdownStyle] = useState<React.CSSProperties>({});\n const wrapperRef = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null); // Ref for the header div\n const optionsListRef = useRef<HTMLUListElement>(null);\n // Tracks a touch/pen press on an option so a tap selects while a drag scrolls.\n // (pointerdown on touch must NOT preventDefault — that blocks native scrolling.)\n const touchPressRef = useRef<{ pointerId: number; x: number; y: number } | null>(null);\n\n useEffect(() => {\n if (!isOpen) return;\n const handlePointerDown = (event: MouseEvent) => {\n const target = event.target as Node;\n if (wrapperRef.current?.contains(target) || optionsListRef.current?.contains(target)) return;\n setIsOpen(false);\n };\n document.addEventListener('pointerdown', handlePointerDown);\n document.addEventListener('mousedown', handlePointerDown);\n return () => {\n document.removeEventListener('pointerdown', handlePointerDown);\n document.removeEventListener('mousedown', handlePointerDown);\n };\n }, [isOpen]);\n\n const selectedValuesArray = Array.isArray(value) ? value : (value !== undefined && value !== null ? [value] : []);\n\n // Close dropdown when clicking outside\n useClickOutside(wrapperRef, useCallback(() => setIsOpen(false), []));\n\n const updateDropdownPosition = useCallback(() => {\n const wrapper = wrapperRef.current;\n if (!wrapper) return;\n const rect = wrapper.getBoundingClientRect();\n const estimatedHeight = Math.min(options.length, 8) * 36 + 8;\n const fitsBelow = rect.bottom + 4 + estimatedHeight <= window.innerHeight;\n setDropdownStyle({\n position: 'fixed',\n left: rect.left,\n top: fitsBelow ? rect.bottom + 4 : Math.max(8, rect.top - estimatedHeight - 4),\n width: rect.width,\n zIndex: 10000,\n });\n }, [options.length]);\n\n useEffect(() => {\n if (!isOpen) return;\n updateDropdownPosition();\n window.addEventListener('resize', updateDropdownPosition);\n window.addEventListener('scroll', updateDropdownPosition, true);\n return () => {\n window.removeEventListener('resize', updateDropdownPosition);\n window.removeEventListener('scroll', updateDropdownPosition, true);\n };\n }, [isOpen, updateDropdownPosition]);\n\n // Hide the decorative arrow when the control becomes too narrow to reserve\n // space for both it and a useful amount of label text.\n useEffect(() => {\n const wrapper = wrapperRef.current;\n if (!wrapper) return;\n const update = () => setShowArrow(wrapper.clientWidth >= 88);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(wrapper);\n return () => observer.disconnect();\n }, []);\n\n // Keyboard navigation\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n setHighlightedIndex(prev => (prev < options.length - 1 ? prev + 1 : 0));\n scrollToHighlightedOption();\n break;\n case 'ArrowUp':\n event.preventDefault();\n setHighlightedIndex(prev => (prev > 0 ? prev - 1 : options.length - 1));\n scrollToHighlightedOption();\n break;\n case 'Enter':\n case ' ': // Space key\n event.preventDefault();\n if (highlightedIndex >= 0 && highlightedIndex < options.length) {\n handleOptionClick(options[highlightedIndex]);\n if (!multiple) setIsOpen(false); // Close dropdown on selection if single mode\n } else if (!multiple) {\n setIsOpen(false); // Close dropdown if Enter/Space is pressed without a highlighted option in single mode\n }\n break;\n case 'Escape':\n setIsOpen(false);\n break;\n default:\n // Optional: Implement type-ahead find\n break;\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen, highlightedIndex, options, multiple]); // Added multiple to dependencies\n\n const scrollToHighlightedOption = useCallback(() => {\n if (optionsListRef.current && highlightedIndex >= 0) {\n const list = optionsListRef.current;\n const optionElement = list.children[highlightedIndex] as HTMLLIElement;\n if (optionElement) {\n const listRect = list.getBoundingClientRect();\n const optionRect = optionElement.getBoundingClientRect();\n\n if (optionRect.bottom > listRect.bottom) {\n list.scrollTop += optionRect.bottom - listRect.bottom;\n } else if (optionRect.top < listRect.top) {\n list.scrollTop -= listRect.top - optionRect.top;\n }\n }\n }\n }, [highlightedIndex]);\n\n const toggleDropdown = () => {\n const next = !isOpen;\n setIsOpen(next);\n setHighlightedIndex(next ? 0 : -1); // Reset or set initial highlight\n if (next) updateDropdownPosition();\n };\n\n const handleOptionClick = (option: Option) => {\n if (multiple) {\n const currentValues = Array.isArray(value) ? value : [];\n let newValue;\n if (currentValues.includes(option.value)) {\n newValue = currentValues.filter(v => v !== option.value);\n } else {\n newValue = [...currentValues, option.value];\n }\n onChange(newValue);\n } else {\n onChange(option.value);\n setIsOpen(false); // Close dropdown on single select\n }\n // Keep highlight on the selected item in multi-select? Maybe not.\n // setHighlightedIndex(options.findIndex(o => o.value === option.value));\n };\n\n // Mouse: select immediately on press (existing desktop behavior).\n // Touch/pen: only record the press — selection happens on pointerup if the\n // gesture turned out to be a tap rather than a scroll. preventDefault() on a\n // touch pointerdown suppresses the browser's native pan gesture, which made\n // long dropdowns impossible to scroll on mobile (and every scroll attempt\n // selected an option instead).\n const handleOptionPointerDown = (event: React.PointerEvent<HTMLLIElement>, option: Option) => {\n if (event.pointerType === 'mouse') {\n event.preventDefault();\n event.stopPropagation();\n handleOptionClick(option);\n return;\n }\n event.stopPropagation();\n touchPressRef.current = { pointerId: event.pointerId, x: event.clientX, y: event.clientY };\n };\n\n const handleOptionPointerUp = (event: React.PointerEvent<HTMLLIElement>, option: Option) => {\n const press = touchPressRef.current;\n touchPressRef.current = null;\n if (!press || event.pointerId !== press.pointerId) return;\n // Select only if the finger did not move much — otherwise it was a scroll.\n const moved = Math.hypot(event.clientX - press.x, event.clientY - press.y);\n if (moved < 10) {\n event.stopPropagation();\n handleOptionClick(option);\n }\n };\n\n const handleOptionPointerCancel = () => {\n touchPressRef.current = null;\n };\n\n const handleRemoveItem = (e: React.MouseEvent, itemValue: string | number) => {\n e.stopPropagation(); // Prevent dropdown from opening/closing\n const currentValues = Array.isArray(value) ? value : [];\n onChange(currentValues.filter(v => v !== itemValue));\n };\n\n // Update tooltip text and check for overflow\n useEffect(() => {\n if (multiple && headerRef.current) {\n const header = headerRef.current;\n const selectedLabels = options\n .filter(opt => selectedValuesArray.includes(opt.value))\n .map(opt => opt.label)\n .join(', ');\n\n // Check if the content (scrollWidth) exceeds the visible area (clientWidth)\n const isOverflowing = header.scrollWidth > header.clientWidth;\n setTooltipText(isOverflowing ? selectedLabels : ''); // Only set text if overflowing\n } else {\n setTooltipText(''); // Clear tooltip for single select or empty multi-select\n }\n }, [value, multiple, options, selectedValuesArray]);\n\n\n const renderSelectedValue = () => {\n if (selectedValuesArray.length === 0) {\n return <span className=\"text-base-content/60 italic\">{placeholder}</span>;\n }\n\n const selectedOptions = options.filter(opt => selectedValuesArray.includes(opt.value));\n\n if (multiple) {\n const isFixed = fixedHeight;\n // Apply overflow-x-auto for horizontal scrolling in fixedHeight mode\n const containerClasses = `\n flex gap-1 \n ${isFixed ? 'flex-nowrap overflow-x-auto overflow-y-hidden' : 'flex-wrap overflow-hidden'} // Enable horizontal scroll, hide vertical scrollbar if any\n ${tooltipText ? 'tooltip tooltip-bottom' : ''} // Keep tooltip for overflow\n `;\n // Removed showEllipsisPrefix\n\n return (\n <div\n ref={headerRef}\n className={containerClasses}\n data-tip={tooltipText ? tooltipText : undefined} // Keep tooltip logic\n // Add scrollbar styling if desired (e.g., using ::-webkit-scrollbar pseudo-element via CSS or a utility)\n style={{\n scrollbarWidth: 'thin',\n // 为固定高度模式添加右侧内边距,避免与下拉图标重叠\n ...(isFixed ? { paddingRight: '1.75rem' } : {})\n }}\n >\n {/* Removed wrapper for ellipsis and its popup */}\n\n {/* Render the badges */}\n {selectedOptions.map(option => (\n <span key={option.value} className=\"badge badge-ghost gap-1 text-xs items-center whitespace-nowrap flex-shrink-0\">\n {option.label}\n <button\n type=\"button\"\n onClick={(e) => handleRemoveItem(e, option.value)}\n className=\"btn btn-xs btn-ghost btn-circle p-0 m-0 hover:bg-error hover:text-error-content\"\n aria-label={`Remove ${option.label}`}\n >\n <RemoveIcon />\n </button>\n </span>\n ))}\n </div>\n );\n } else {\n const selectedOption = options.find(opt => opt.value === selectedValuesArray[0]);\n return selectedOption ? <span className=\"truncate\">{selectedOption.label}</span> : <span className=\"text-base-content/60 italic\">{placeholder}</span>;\n }\n };\n\n // Match the default control height to a normal line of form text. Multi-select\n // may still grow when wrapping tags unless fixedHeight is requested.\n const selectClasses = `\n relative border border-base-300 rounded-lg bg-base-100 w-full\n flex justify-between items-center cursor-pointer px-3 text-sm\n focus:outline-none focus:ring-2 focus:ring-primary focus:ring-opacity-50\n hover:border-base-content/30\n ${multiple\n ? (fixedHeight ? 'h-8' : 'min-h-8 h-auto py-1')\n : 'h-8'}\n `;\n\n return (\n <div\n ref={wrapperRef}\n style={style}\n className={`relative w-full font-sans select-none ${className || ''}`}\n >\n {/* Header */}\n <div\n tabIndex={0}\n className={selectClasses}\n onClick={toggleDropdown}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') toggleDropdown(); }}\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n >\n <div\n className=\"flex-1 min-w-0 overflow-hidden\"\n style={{ paddingRight: showArrow ? 28 : 0 }}\n >\n {renderSelectedValue()}\n </div>\n {/* Inline positioning avoids utility CSS/theme overrides moving the icon. */}\n {showArrow && (\n <div\n aria-hidden=\"true\"\n style={{\n position: 'absolute',\n right: 10,\n top: '50%',\n transform: 'translateY(-50%)',\n pointerEvents: 'none',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: 16,\n height: 16,\n }}\n >\n <DropdownArrow isOpen={isOpen} />\n </div>\n )}\n </div>\n\n {/* Dropdown Options */}\n {isOpen && typeof document !== 'undefined' && createPortal(\n <ul\n ref={optionsListRef}\n className=\"bg-base-100 border border-base-300 rounded-md shadow-lg list-none p-0 m-0 max-h-60 overflow-y-auto focus:outline-none\"\n style={{ ...dropdownStyle, touchAction: 'pan-y' }}\n onPointerDown={(event) => event.stopPropagation()}\n role=\"listbox\" // ARIA role\n aria-activedescendant={highlightedIndex >= 0 ? `option-${options[highlightedIndex]?.value}` : undefined} // For screen readers\n tabIndex={-1} // Allows focus programmatically but not via tab\n >\n {options.length > 0 ? (\n options.map((option, index) => (\n <li\n key={option.value}\n id={`option-${option.value}`} // ID for aria-activedescendant\n className={`p-2 cursor-pointer whitespace-nowrap overflow-hidden text-ellipsis hover:bg-base-200 ${index === highlightedIndex ? 'bg-base-300' : '' // Highlight style\n } ${selectedValuesArray.includes(option.value) && !multiple ? 'font-semibold bg-base-200' : '' // Style for selected single item\n } ${selectedValuesArray.includes(option.value) && multiple ? 'font-semibold' : '' // Style for selected multi items (less prominent background)\n }`}\n onPointerDown={(event) => handleOptionPointerDown(event, option)}\n onPointerUp={(event) => handleOptionPointerUp(event, option)}\n onPointerCancel={handleOptionPointerCancel}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n onMouseEnter={() => setHighlightedIndex(index)} // Highlight on hover\n role=\"option\" // ARIA role\n aria-selected={selectedValuesArray.includes(option.value)}\n >\n {/* Optional: Add a checkmark or similar for selected items, especially in multi-select */}\n {option.label}\n </li>\n ))\n ) : (\n <li className=\"p-2 text-base-content/60 italic\">\n No options available\n </li>\n )}\n </ul>,\n document.body,\n )}\n </div>\n );\n};\n\nexport default Select; "],"mappings":"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"}
|