@utk09/finra-ui 0.0.7 → 0.0.8
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/README.md +8 -4
- package/dist/ComboBox-B7w5n-lW.js +451 -0
- package/dist/ComboBox-B7w5n-lW.js.map +1 -0
- package/dist/components/componentIds.d.ts +0 -6
- package/dist/cx-Cj1p8CM7.js +15 -0
- package/dist/cx-Cj1p8CM7.js.map +1 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.js +613 -593
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/global.d.ts +1 -0
- package/dist/unstyled.d.ts +1 -5
- package/dist/unstyled.js +83 -84
- package/dist/unstyled.js.map +1 -1
- package/dist/utils.d.ts +1 -4
- package/dist/utils.js +2 -3
- package/package.json +3 -6
- package/dist/Calendar.module-AHlPlLw_.js +0 -362
- package/dist/Calendar.module-AHlPlLw_.js.map +0 -1
- package/dist/DateInput-D3AUs_l2.js +0 -224
- package/dist/DateInput-D3AUs_l2.js.map +0 -1
- package/dist/assets/icons/CalendarIcon.d.ts +0 -2
- package/dist/assets/icons/CheckIcon.d.ts +0 -2
- package/dist/assets/icons/ChevronDownIcon.d.ts +0 -2
- package/dist/assets/icons/ChevronLeftIcon.d.ts +0 -2
- package/dist/assets/icons/ChevronRightIcon.d.ts +0 -2
- package/dist/assets/icons/CloseIcon.d.ts +0 -2
- package/dist/assets/icons/CloseSmallIcon.d.ts +0 -2
- package/dist/assets/icons/DashIcon.d.ts +0 -2
- package/dist/assets/icons/MinusIcon.d.ts +0 -2
- package/dist/assets/icons/PlusIcon.d.ts +0 -2
- package/dist/assets/icons/SpinnerIcon.d.ts +0 -2
- package/dist/assets/icons/UploadIcon.d.ts +0 -2
- package/dist/assets/icons/index.d.ts +0 -12
- package/dist/components/Calendar/Calendar.d.ts +0 -6
- package/dist/components/DateInput/DateInput.d.ts +0 -16
- package/dist/components/DateTenorInput/DateTenorInput.d.ts +0 -16
- package/dist/components/TenorInput/TenorInput.d.ts +0 -14
- package/dist/dateFormat-CdClN4CU.js +0 -200
- package/dist/dateFormat-CdClN4CU.js.map +0 -1
- package/dist/dateInput-4sdYyWq0.js +0 -551
- package/dist/dateInput-4sdYyWq0.js.map +0 -1
- package/dist/finance.d.ts +0 -8
- package/dist/finance.js +0 -390
- package/dist/finance.js.map +0 -1
- package/dist/logic/calendar.d.ts +0 -27
- package/dist/logic/dateInput.d.ts +0 -13
- package/dist/tenor-GS2kfKqC.js +0 -111
- package/dist/tenor-GS2kfKqC.js.map +0 -1
- package/dist/unstyled/Calendar/Calendar.d.ts +0 -48
- package/dist/unstyled/DateInput/DateInput.d.ts +0 -58
- package/dist/unstyled/DateTenorInput/DateTenorInput.d.ts +0 -78
- package/dist/unstyled/TenorInput/TenorInput.d.ts +0 -27
- package/dist/utils/dateFormat.d.ts +0 -17
- package/dist/utils/tenor.d.ts +0 -15
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Finra UI
|
|
1
|
+
# Finra UI - Core
|
|
2
2
|
|
|
3
3
|
React component library for web applications.
|
|
4
4
|
|
|
@@ -156,7 +156,7 @@ Every component renders a stable `data-finra-ui` attribute for targeted CSS over
|
|
|
156
156
|
|
|
157
157
|
### Zero External Runtime Dependencies
|
|
158
158
|
|
|
159
|
-
The only runtime dependencies are `clsx
|
|
159
|
+
The only runtime dependencies are `clsx`, `class-variance-authority`, and `@utk09/finra-ui-icons`.
|
|
160
160
|
|
|
161
161
|
## Development
|
|
162
162
|
|
|
@@ -188,8 +188,12 @@ pnpm run typecheck && pnpm run lint && pnpm run test
|
|
|
188
188
|
### Project Structure
|
|
189
189
|
|
|
190
190
|
```txt
|
|
191
|
-
packages/core/
|
|
192
|
-
|
|
191
|
+
packages/core/ - Core component library (@utk09/finra-ui)
|
|
192
|
+
packages/finance/ - Financial domain components (@utk09/finra-ui-finance)
|
|
193
|
+
packages/icons/ - Icon library (@utk09/finra-ui-icons)
|
|
194
|
+
apps/storybook/ - Storybook documentation app
|
|
195
|
+
apps/react-example-basic/ - E-commerce store demo
|
|
196
|
+
apps/react-example-advanced/ - Financial dashboard demo
|
|
193
197
|
```
|
|
194
198
|
|
|
195
199
|
## License
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
import { n as e, t } from "./cx-Cj1p8CM7.js";
|
|
2
|
+
import { cloneElement as n, forwardRef as r, isValidElement as i, useCallback as a, useEffect as o, useId as s, useMemo as c, useRef as l, useState as u } from "react";
|
|
3
|
+
import { Fragment as ee, jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
4
|
+
//#region src/hooks/useClickOutside.ts
|
|
5
|
+
function p(e, t, n) {
|
|
6
|
+
o(() => {
|
|
7
|
+
if (!n) return;
|
|
8
|
+
let r = (n) => {
|
|
9
|
+
e.current && !e.current.contains(n.target) && t();
|
|
10
|
+
};
|
|
11
|
+
return document.addEventListener("mousedown", r), () => document.removeEventListener("mousedown", r);
|
|
12
|
+
}, [
|
|
13
|
+
e,
|
|
14
|
+
t,
|
|
15
|
+
n
|
|
16
|
+
]);
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/hooks/useControlledValue.ts
|
|
20
|
+
function m(e, t, n) {
|
|
21
|
+
let [r, i] = u(t), s = e !== void 0, c = s ? e : r;
|
|
22
|
+
return o(() => {
|
|
23
|
+
s && i(e);
|
|
24
|
+
}, [s, e]), [c, a((e) => {
|
|
25
|
+
s || i(e), n?.(e);
|
|
26
|
+
}, [s, n])];
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/unstyled/Slot.tsx
|
|
30
|
+
function h(e, t) {
|
|
31
|
+
let n = {
|
|
32
|
+
...e,
|
|
33
|
+
...t
|
|
34
|
+
};
|
|
35
|
+
for (let r of Object.keys(e)) {
|
|
36
|
+
if (r === "children" || r === "ref") continue;
|
|
37
|
+
let i = e[r], a = t[r];
|
|
38
|
+
typeof i == "function" && typeof a == "function" && (n[r] = (...e) => {
|
|
39
|
+
a(...e), i(...e);
|
|
40
|
+
}), r === "className" && typeof i == "string" && typeof a == "string" && (n[r] = `${i} ${a}`.trim()), r === "style" && typeof i == "object" && typeof a == "object" && (n[r] = {
|
|
41
|
+
...i,
|
|
42
|
+
...a
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return n;
|
|
46
|
+
}
|
|
47
|
+
var g = r(({ children: t, ...r }, a) => {
|
|
48
|
+
if (!i(t)) return null;
|
|
49
|
+
let o = t.props, s = t.ref;
|
|
50
|
+
return n(t, {
|
|
51
|
+
...h(r, o),
|
|
52
|
+
ref: e(a, s)
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
g.displayName = "Slot";
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/unstyled/Button/Button.tsx
|
|
58
|
+
var _ = r(({ asChild: e = !1, ...t }, n) => /* @__PURE__ */ d(e ? g : "button", {
|
|
59
|
+
ref: n,
|
|
60
|
+
...t
|
|
61
|
+
}));
|
|
62
|
+
_.displayName = "ButtonBase";
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/unstyled/IconButton/IconButton.tsx
|
|
65
|
+
var v = r(({ asChild: e = !1, icon: t, children: n, ...r }, i) => /* @__PURE__ */ f(e ? g : "button", {
|
|
66
|
+
ref: i,
|
|
67
|
+
...r,
|
|
68
|
+
children: [t, n]
|
|
69
|
+
}));
|
|
70
|
+
v.displayName = "IconButtonBase";
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/unstyled/Checkbox/Checkbox.tsx
|
|
73
|
+
var y = r(({ indeterminate: t, ...n }, r) => /* @__PURE__ */ d("input", {
|
|
74
|
+
ref: e(r, a((e) => {
|
|
75
|
+
e && (e.indeterminate = t ?? !1);
|
|
76
|
+
}, [t])),
|
|
77
|
+
type: "checkbox",
|
|
78
|
+
...n
|
|
79
|
+
}));
|
|
80
|
+
y.displayName = "CheckboxBase";
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/unstyled/Switch/Switch.tsx
|
|
83
|
+
var b = r((e, t) => /* @__PURE__ */ d("input", {
|
|
84
|
+
ref: t,
|
|
85
|
+
type: "checkbox",
|
|
86
|
+
role: "switch",
|
|
87
|
+
...e
|
|
88
|
+
}));
|
|
89
|
+
b.displayName = "SwitchBase";
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/unstyled/RadioButton/RadioButton.tsx
|
|
92
|
+
var x = r((e, t) => /* @__PURE__ */ d("input", {
|
|
93
|
+
ref: t,
|
|
94
|
+
type: "radio",
|
|
95
|
+
...e
|
|
96
|
+
}));
|
|
97
|
+
x.displayName = "RadioButtonBase";
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/unstyled/Slider/Slider.tsx
|
|
100
|
+
var S = r((e, t) => /* @__PURE__ */ d("input", {
|
|
101
|
+
ref: t,
|
|
102
|
+
type: "range",
|
|
103
|
+
...e
|
|
104
|
+
}));
|
|
105
|
+
S.displayName = "SliderBase";
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/logic/combobox.ts
|
|
108
|
+
function te(e, t) {
|
|
109
|
+
return t ? e.label.toLowerCase().includes(t.toLowerCase()) : !0;
|
|
110
|
+
}
|
|
111
|
+
function ne(e) {
|
|
112
|
+
let t = [], n = /* @__PURE__ */ new Map(), r = [];
|
|
113
|
+
for (let i of e) if (i.favourite && t.push(i), i.group) {
|
|
114
|
+
let e = n.get(i.group) ?? [];
|
|
115
|
+
e.push(i), n.set(i.group, e);
|
|
116
|
+
} else r.push(i);
|
|
117
|
+
let i = [];
|
|
118
|
+
for (let [e, t] of n) i.push({
|
|
119
|
+
label: e,
|
|
120
|
+
options: t
|
|
121
|
+
});
|
|
122
|
+
return {
|
|
123
|
+
favourites: t,
|
|
124
|
+
groups: i,
|
|
125
|
+
ungrouped: r
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/unstyled/ComboBox/ComboBox.tsx
|
|
130
|
+
function C({ options: n, value: r, onChange: i, multiple: h = !1, inputValue: g, onInputChange: _, filterFn: v, loading: y = !1, onLoadOptions: b, creatable: x = !1, onCreateOption: S, formatCreateLabel: C, header: w, footer: re, placeholder: T, disabled: E = !1, noOptionsMessage: ie = "No options", renderOption: ae, renderValue: D, renderCheckIcon: oe, renderIndicator: se, renderPillRemoveIcon: O, renderLoading: ce, open: le, onOpenChange: ue, classNames: k, dataAttributes: de, "aria-label": fe, "aria-labelledby": pe, ...me }, he) {
|
|
131
|
+
let ge = s(), A = `${ge}-listbox`, j = l(null), M = l(null), _e = l(null), [N, P] = m(le, !1, ue), [F, I] = m(g, "", _), [L, R] = u(-1), z = c(() => r == null ? [] : Array.isArray(r) ? r : [r], [r]), B = a((e) => z.some((t) => t === e), [z]), V = v ?? te, H = c(() => n.filter((e) => V(e, F)), [
|
|
132
|
+
n,
|
|
133
|
+
V,
|
|
134
|
+
F
|
|
135
|
+
]), U = c(() => {
|
|
136
|
+
let { favourites: e, groups: t, ungrouped: n } = ne(H), r = [];
|
|
137
|
+
for (let t of e) r.push(t);
|
|
138
|
+
for (let e of t) for (let t of e.options) t.favourite || r.push(t);
|
|
139
|
+
for (let e of n) e.favourite || r.push(e);
|
|
140
|
+
return r;
|
|
141
|
+
}, [H]), W = x && F.trim() !== "" && !n.some((e) => e.label.toLowerCase() === F.trim().toLowerCase()), ve = C ? C(F.trim()) : `Create "${F.trim()}"`, G = U.length + (W ? 1 : 0), K = a((e) => {
|
|
142
|
+
if (!e.disabled) {
|
|
143
|
+
if (h) {
|
|
144
|
+
let t = B(e.value) ? z.filter((t) => t !== e.value) : [...z, e.value];
|
|
145
|
+
i?.(t), I("");
|
|
146
|
+
} else i?.(e.value), I(e.label), P(!1);
|
|
147
|
+
j.current?.focus();
|
|
148
|
+
}
|
|
149
|
+
}, [
|
|
150
|
+
h,
|
|
151
|
+
B,
|
|
152
|
+
z,
|
|
153
|
+
i,
|
|
154
|
+
I,
|
|
155
|
+
P
|
|
156
|
+
]), q = a((e) => {
|
|
157
|
+
if (!h) return;
|
|
158
|
+
let t = z.filter((t) => t !== e);
|
|
159
|
+
i?.(t.length > 0 ? t : null), j.current?.focus();
|
|
160
|
+
}, [
|
|
161
|
+
h,
|
|
162
|
+
z,
|
|
163
|
+
i
|
|
164
|
+
]), ye = a((e) => {
|
|
165
|
+
if (!E) switch (e.key) {
|
|
166
|
+
case "ArrowDown":
|
|
167
|
+
e.preventDefault(), N ? R((e) => (e + 1) % G) : (P(!0), R(0));
|
|
168
|
+
break;
|
|
169
|
+
case "ArrowUp":
|
|
170
|
+
e.preventDefault(), N ? R((e) => (e - 1 + G) % G) : (P(!0), R(G - 1));
|
|
171
|
+
break;
|
|
172
|
+
case "Enter":
|
|
173
|
+
e.preventDefault(), N && L >= 0 ? L < U.length ? K(U[L]) : W && (S?.(F.trim()), I("")) : N || P(!0);
|
|
174
|
+
break;
|
|
175
|
+
case "Escape":
|
|
176
|
+
N && (e.preventDefault(), P(!1), R(-1));
|
|
177
|
+
break;
|
|
178
|
+
case "Backspace":
|
|
179
|
+
h && F === "" && z.length > 0 && q(z[z.length - 1]);
|
|
180
|
+
break;
|
|
181
|
+
case "Home":
|
|
182
|
+
N && (e.preventDefault(), R(0));
|
|
183
|
+
break;
|
|
184
|
+
case "End":
|
|
185
|
+
N && (e.preventDefault(), R(G - 1));
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}, [
|
|
189
|
+
E,
|
|
190
|
+
N,
|
|
191
|
+
P,
|
|
192
|
+
L,
|
|
193
|
+
G,
|
|
194
|
+
U,
|
|
195
|
+
K,
|
|
196
|
+
W,
|
|
197
|
+
S,
|
|
198
|
+
F,
|
|
199
|
+
I,
|
|
200
|
+
h,
|
|
201
|
+
z,
|
|
202
|
+
q
|
|
203
|
+
]), be = a((e) => {
|
|
204
|
+
let t = e.target.value;
|
|
205
|
+
I(t), N || P(!0), R(0), b?.(t), !h && r != null && i?.(null);
|
|
206
|
+
}, [
|
|
207
|
+
I,
|
|
208
|
+
N,
|
|
209
|
+
P,
|
|
210
|
+
b,
|
|
211
|
+
h,
|
|
212
|
+
r,
|
|
213
|
+
i
|
|
214
|
+
]), xe = a(() => {
|
|
215
|
+
!E && !N && P(!0);
|
|
216
|
+
}, [
|
|
217
|
+
E,
|
|
218
|
+
N,
|
|
219
|
+
P
|
|
220
|
+
]);
|
|
221
|
+
p(_e, a(() => {
|
|
222
|
+
P(!1), R(-1);
|
|
223
|
+
}, [P]), N), o(() => {
|
|
224
|
+
if (L < 0 || !M.current) return;
|
|
225
|
+
let e = M.current.querySelector(`[data-index="${L}"]`);
|
|
226
|
+
e && e.scrollIntoView?.({ block: "nearest" });
|
|
227
|
+
}, [L]);
|
|
228
|
+
let { favourites: J, groups: Se, ungrouped: Ce } = c(() => ne(H), [H]), Y = (e) => `${ge}-option-${e}`, X = (e, n) => {
|
|
229
|
+
let r = {
|
|
230
|
+
isSelected: B(e.value),
|
|
231
|
+
isHighlighted: L === n,
|
|
232
|
+
isDisabled: e.disabled ?? !1,
|
|
233
|
+
isFavourite: e.favourite ?? !1
|
|
234
|
+
};
|
|
235
|
+
return /* @__PURE__ */ d("div", {
|
|
236
|
+
id: Y(n),
|
|
237
|
+
role: "option",
|
|
238
|
+
tabIndex: -1,
|
|
239
|
+
"data-index": n,
|
|
240
|
+
"aria-selected": r.isSelected,
|
|
241
|
+
"aria-disabled": r.isDisabled || void 0,
|
|
242
|
+
"data-highlighted": r.isHighlighted || void 0,
|
|
243
|
+
"data-selected": r.isSelected || void 0,
|
|
244
|
+
"data-disabled": r.isDisabled || void 0,
|
|
245
|
+
className: t(k?.option, r.isHighlighted && k?.optionHighlighted, r.isSelected && k?.optionSelected, r.isDisabled && k?.optionDisabled),
|
|
246
|
+
onMouseDown: (t) => {
|
|
247
|
+
t.preventDefault(), K(e);
|
|
248
|
+
},
|
|
249
|
+
onMouseEnter: () => R(n),
|
|
250
|
+
children: ae ? ae(e, r) : /* @__PURE__ */ f(ee, { children: [/* @__PURE__ */ d("span", {
|
|
251
|
+
className: k?.optionLabel,
|
|
252
|
+
children: e.label
|
|
253
|
+
}), r.isSelected && oe ? oe() : null] })
|
|
254
|
+
}, `${n}-${String(e.value)}`);
|
|
255
|
+
}, we = () => h ? z.map((e) => {
|
|
256
|
+
let t = n.find((t) => t.value === e);
|
|
257
|
+
return t ? /* @__PURE__ */ f("span", {
|
|
258
|
+
className: k?.pill,
|
|
259
|
+
"data-combobox-pill": !0,
|
|
260
|
+
children: [/* @__PURE__ */ d("span", {
|
|
261
|
+
className: k?.pillText,
|
|
262
|
+
children: D ? D(t) : t.label
|
|
263
|
+
}), E ? null : /* @__PURE__ */ d("button", {
|
|
264
|
+
type: "button",
|
|
265
|
+
className: k?.pillRemove,
|
|
266
|
+
tabIndex: -1,
|
|
267
|
+
"aria-label": `Remove ${t.label}`,
|
|
268
|
+
onMouseDown: (t) => {
|
|
269
|
+
t.preventDefault(), t.stopPropagation(), q(e);
|
|
270
|
+
},
|
|
271
|
+
children: O ? O() : "×"
|
|
272
|
+
})]
|
|
273
|
+
}, String(e)) : null;
|
|
274
|
+
}) : null, Te = c(() => {
|
|
275
|
+
if (h || N) return F;
|
|
276
|
+
if (r != null && !D) {
|
|
277
|
+
let e = n.find((e) => e.value === r);
|
|
278
|
+
if (e) return e.label;
|
|
279
|
+
}
|
|
280
|
+
return F;
|
|
281
|
+
}, [
|
|
282
|
+
h,
|
|
283
|
+
N,
|
|
284
|
+
F,
|
|
285
|
+
r,
|
|
286
|
+
n,
|
|
287
|
+
D
|
|
288
|
+
]), Ee = c(() => {
|
|
289
|
+
if (h || N || r == null || !D) return null;
|
|
290
|
+
let e = n.find((e) => e.value === r);
|
|
291
|
+
return e ? /* @__PURE__ */ d("span", {
|
|
292
|
+
className: k?.singleValue,
|
|
293
|
+
children: D(e)
|
|
294
|
+
}) : null;
|
|
295
|
+
}, [
|
|
296
|
+
h,
|
|
297
|
+
N,
|
|
298
|
+
r,
|
|
299
|
+
n,
|
|
300
|
+
D,
|
|
301
|
+
k?.singleValue
|
|
302
|
+
]), Z = [], Q = 0;
|
|
303
|
+
J.length > 0 && Z.push(/* @__PURE__ */ f("div", {
|
|
304
|
+
role: "group",
|
|
305
|
+
"aria-label": "Favourites",
|
|
306
|
+
className: k?.group,
|
|
307
|
+
"data-combobox-group": "favourites",
|
|
308
|
+
children: [/* @__PURE__ */ d("div", {
|
|
309
|
+
className: k?.groupLabel,
|
|
310
|
+
"data-combobox-group-label": !0,
|
|
311
|
+
"aria-hidden": "true",
|
|
312
|
+
children: "Favourites"
|
|
313
|
+
}), J.map((e) => {
|
|
314
|
+
let t = X(e, Q);
|
|
315
|
+
return Q++, t;
|
|
316
|
+
})]
|
|
317
|
+
}, "__fav-group"));
|
|
318
|
+
for (let e of Se) {
|
|
319
|
+
let t = e.options.filter((e) => !e.favourite);
|
|
320
|
+
t.length !== 0 && Z.push(/* @__PURE__ */ f("div", {
|
|
321
|
+
role: "group",
|
|
322
|
+
"aria-label": e.label,
|
|
323
|
+
className: k?.group,
|
|
324
|
+
"data-combobox-group": e.label,
|
|
325
|
+
children: [/* @__PURE__ */ d("div", {
|
|
326
|
+
className: k?.groupLabel,
|
|
327
|
+
"data-combobox-group-label": !0,
|
|
328
|
+
"aria-hidden": "true",
|
|
329
|
+
children: e.label
|
|
330
|
+
}), t.map((e) => {
|
|
331
|
+
let t = X(e, Q);
|
|
332
|
+
return Q++, t;
|
|
333
|
+
})]
|
|
334
|
+
}, `__group-${e.label}`));
|
|
335
|
+
}
|
|
336
|
+
let $ = Ce.filter((e) => !e.favourite);
|
|
337
|
+
if ($.length > 0) if (J.length > 0 || Se.length > 0) Z.push(/* @__PURE__ */ f("div", {
|
|
338
|
+
role: "group",
|
|
339
|
+
"aria-label": "All",
|
|
340
|
+
className: k?.group,
|
|
341
|
+
"data-combobox-group": "all",
|
|
342
|
+
children: [/* @__PURE__ */ d("div", {
|
|
343
|
+
className: k?.groupLabel,
|
|
344
|
+
"data-combobox-group-label": !0,
|
|
345
|
+
"aria-hidden": "true",
|
|
346
|
+
children: "All"
|
|
347
|
+
}), $.map((e) => {
|
|
348
|
+
let t = X(e, Q);
|
|
349
|
+
return Q++, t;
|
|
350
|
+
})]
|
|
351
|
+
}, "__ungrouped"));
|
|
352
|
+
else for (let e of $) Z.push(X(e, Q)), Q++;
|
|
353
|
+
if (W) {
|
|
354
|
+
let e = Q;
|
|
355
|
+
Z.push(/* @__PURE__ */ d("div", {
|
|
356
|
+
id: Y(e),
|
|
357
|
+
role: "option",
|
|
358
|
+
tabIndex: -1,
|
|
359
|
+
"data-index": e,
|
|
360
|
+
"aria-selected": !1,
|
|
361
|
+
"data-highlighted": L === e || void 0,
|
|
362
|
+
"data-combobox-create": !0,
|
|
363
|
+
className: t(k?.option, k?.optionCreate, L === e && k?.optionHighlighted),
|
|
364
|
+
onMouseDown: (e) => {
|
|
365
|
+
e.preventDefault(), S?.(F.trim()), I("");
|
|
366
|
+
},
|
|
367
|
+
onMouseEnter: () => R(e),
|
|
368
|
+
children: ve
|
|
369
|
+
}, "__create"));
|
|
370
|
+
}
|
|
371
|
+
let De = U.length > 0 || W, Oe = {
|
|
372
|
+
type: "text",
|
|
373
|
+
role: "searchbox",
|
|
374
|
+
"aria-autocomplete": "list",
|
|
375
|
+
"aria-controls": N ? A : void 0,
|
|
376
|
+
"aria-activedescendant": N && L >= 0 ? Y(L) : void 0,
|
|
377
|
+
"aria-label": fe ?? T,
|
|
378
|
+
"aria-labelledby": pe,
|
|
379
|
+
onChange: be,
|
|
380
|
+
onKeyDown: ye,
|
|
381
|
+
onFocus: xe,
|
|
382
|
+
disabled: E
|
|
383
|
+
};
|
|
384
|
+
return /* @__PURE__ */ f("div", {
|
|
385
|
+
ref: _e,
|
|
386
|
+
className: k?.root,
|
|
387
|
+
...de,
|
|
388
|
+
...me,
|
|
389
|
+
children: [/* @__PURE__ */ f("div", {
|
|
390
|
+
role: "combobox",
|
|
391
|
+
"aria-expanded": N,
|
|
392
|
+
"aria-controls": N ? A : void 0,
|
|
393
|
+
"aria-haspopup": "listbox",
|
|
394
|
+
"aria-disabled": E || void 0,
|
|
395
|
+
className: k?.wrapper,
|
|
396
|
+
children: [h ? /* @__PURE__ */ f("div", {
|
|
397
|
+
className: k?.multiValueContainer,
|
|
398
|
+
children: [we(), /* @__PURE__ */ d("input", {
|
|
399
|
+
ref: e(he, j),
|
|
400
|
+
className: k?.input,
|
|
401
|
+
...Oe,
|
|
402
|
+
value: F,
|
|
403
|
+
placeholder: z.length === 0 ? T : void 0
|
|
404
|
+
})]
|
|
405
|
+
}) : /* @__PURE__ */ f(ee, { children: [Ee, /* @__PURE__ */ d("input", {
|
|
406
|
+
ref: e(he, j),
|
|
407
|
+
className: t(k?.input, Ee ? k?.inputHidden : void 0),
|
|
408
|
+
...Oe,
|
|
409
|
+
value: Te,
|
|
410
|
+
placeholder: T
|
|
411
|
+
})] }), se ? se(N) : null]
|
|
412
|
+
}), N ? /* @__PURE__ */ f("div", {
|
|
413
|
+
className: k?.listbox,
|
|
414
|
+
children: [
|
|
415
|
+
w ? /* @__PURE__ */ d("div", {
|
|
416
|
+
className: k?.header,
|
|
417
|
+
children: w
|
|
418
|
+
}) : null,
|
|
419
|
+
/* @__PURE__ */ d("div", {
|
|
420
|
+
ref: M,
|
|
421
|
+
id: A,
|
|
422
|
+
role: "listbox",
|
|
423
|
+
"aria-multiselectable": h || void 0,
|
|
424
|
+
className: k?.options,
|
|
425
|
+
tabIndex: -1,
|
|
426
|
+
children: y ? /* @__PURE__ */ d("div", {
|
|
427
|
+
role: "presentation",
|
|
428
|
+
className: k?.loading,
|
|
429
|
+
"aria-live": "polite",
|
|
430
|
+
children: ce ? ce() : "Loading..."
|
|
431
|
+
}) : De ? Z : /* @__PURE__ */ d("div", {
|
|
432
|
+
role: "presentation",
|
|
433
|
+
className: k?.empty,
|
|
434
|
+
"aria-live": "polite",
|
|
435
|
+
children: ie
|
|
436
|
+
})
|
|
437
|
+
}),
|
|
438
|
+
re ? /* @__PURE__ */ d("div", {
|
|
439
|
+
className: k?.footer,
|
|
440
|
+
children: re
|
|
441
|
+
}) : null
|
|
442
|
+
]
|
|
443
|
+
}) : null]
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
var w = r(C);
|
|
447
|
+
w.displayName = "ComboBoxBase";
|
|
448
|
+
//#endregion
|
|
449
|
+
export { y as a, g as c, b as i, m as l, S as n, v as o, x as r, _ as s, w as t, p as u };
|
|
450
|
+
|
|
451
|
+
//# sourceMappingURL=ComboBox-B7w5n-lW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComboBox-B7w5n-lW.js","names":[],"sources":["../src/hooks/useClickOutside.ts","../src/hooks/useControlledValue.ts","../src/unstyled/Slot.tsx","../src/unstyled/Button/Button.tsx","../src/unstyled/IconButton/IconButton.tsx","../src/unstyled/Checkbox/Checkbox.tsx","../src/unstyled/Switch/Switch.tsx","../src/unstyled/RadioButton/RadioButton.tsx","../src/unstyled/Slider/Slider.tsx","../src/logic/combobox.ts","../src/unstyled/ComboBox/ComboBox.tsx"],"sourcesContent":["import { type RefObject, useEffect } from \"react\";\n\n/**\n * Calls `onClickOutside` when a mousedown event occurs outside the referenced element.\n * Automatically subscribes/unsubscribes based on the `enabled` flag.\n */\nexport function useClickOutside(\n ref: RefObject<HTMLElement | null>,\n onClickOutside: () => void,\n enabled: boolean,\n): void {\n useEffect(() => {\n if (!enabled) return;\n\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n onClickOutside();\n }\n };\n\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [ref, onClickOutside, enabled]);\n}\n","import { useCallback, useEffect, useState } from \"react\";\n\n/**\n * Manages the controlled/uncontrolled value pattern.\n *\n * When `controlledValue` is not `undefined`, the component is controlled:\n * - `setValue` only fires `onChange`, the parent owns the state.\n * When `controlledValue` is `undefined`, the component is uncontrolled:\n * - `setValue` updates internal state AND fires `onChange`.\n *\n * @returns `[value, setValue]` - current value and a setter that respects mode.\n */\nexport function useControlledValue<T>(\n controlledValue: T | undefined,\n defaultValue: T,\n onChange?: (next: T) => void,\n): [T, (next: T) => void] {\n const [internalValue, setInternalValue] = useState<T>(defaultValue);\n\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n\n // Sync controlled value → internal (keeps internal in sync for transitions)\n useEffect(() => {\n if (isControlled) {\n setInternalValue(controlledValue);\n }\n }, [isControlled, controlledValue]);\n\n const setValue = useCallback(\n (next: T) => {\n if (!isControlled) {\n setInternalValue(next);\n }\n onChange?.(next);\n },\n [isControlled, onChange],\n );\n\n return [value, setValue];\n}\n","import {\n cloneElement,\n forwardRef,\n type HTMLAttributes,\n isValidElement,\n type ReactNode,\n type Ref,\n} from \"react\";\n\nimport { mergeRefs } from \"../utils/mergeRefs\";\n\nfunction mergeProps(\n slotProps: Record<string, unknown>,\n childProps: Record<string, unknown>,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...slotProps, ...childProps };\n\n for (const key of Object.keys(slotProps)) {\n if (key === \"children\" || key === \"ref\") continue;\n\n const slotVal = slotProps[key];\n const childVal = childProps[key];\n\n // Merge event handlers\n if (typeof slotVal === \"function\" && typeof childVal === \"function\") {\n merged[key] = (...args: unknown[]) => {\n childVal(...args);\n slotVal(...args);\n };\n }\n\n // Merge className\n if (key === \"className\" && typeof slotVal === \"string\" && typeof childVal === \"string\") {\n merged[key] = `${slotVal} ${childVal}`.trim();\n }\n\n // Merge style\n if (key === \"style\" && typeof slotVal === \"object\" && typeof childVal === \"object\") {\n merged[key] = { ...(slotVal as object), ...(childVal as object) };\n }\n }\n\n return merged;\n}\n\nexport interface SlotProps extends HTMLAttributes<HTMLElement> {\n children?: ReactNode;\n}\n\nexport const Slot = forwardRef<HTMLElement, SlotProps>(\n ({ children, ...slotProps }, forwardedRef) => {\n if (!isValidElement(children)) {\n return null;\n }\n\n const childProps = children.props as Record<string, unknown>;\n const childRef = (children as unknown as { ref?: Ref<HTMLElement> }).ref;\n\n return cloneElement(children, {\n ...mergeProps(slotProps, childProps),\n ref: mergeRefs(forwardedRef, childRef),\n } as Record<string, unknown>);\n },\n);\n\nSlot.displayName = \"Slot\";\n","import { type ButtonHTMLAttributes, forwardRef } from \"react\";\n\nimport { Slot } from \"../Slot\";\n\nexport interface ButtonBaseProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean;\n}\n\nexport const ButtonBase = forwardRef<HTMLButtonElement, ButtonBaseProps>(\n ({ asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n\n return <Comp ref={ref} {...props} />;\n },\n);\n\nButtonBase.displayName = \"ButtonBase\";\n","import { type ButtonHTMLAttributes, forwardRef, type ReactNode } from \"react\";\n\nimport { Slot } from \"../Slot\";\n\nexport interface IconButtonBaseProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n asChild?: boolean;\n icon: ReactNode;\n \"aria-label\": string;\n}\n\nexport const IconButtonBase = forwardRef<HTMLButtonElement, IconButtonBaseProps>(\n ({ asChild = false, icon, children, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp ref={ref} {...props}>\n {icon}\n {children}\n </Comp>\n );\n },\n);\n\nIconButtonBase.displayName = \"IconButtonBase\";\n","import { forwardRef, type InputHTMLAttributes, useCallback } from \"react\";\n\nimport { mergeRefs } from \"../../utils/mergeRefs\";\n\nexport interface CheckboxBaseProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {\n indeterminate?: boolean;\n}\n\nexport const CheckboxBase = forwardRef<HTMLInputElement, CheckboxBaseProps>(\n ({ indeterminate, ...props }, forwardedRef) => {\n const setIndeterminate = useCallback(\n (node: HTMLInputElement | null) => {\n if (node) {\n node.indeterminate = indeterminate ?? false;\n }\n },\n [indeterminate],\n );\n\n return <input ref={mergeRefs(forwardedRef, setIndeterminate)} type=\"checkbox\" {...props} />;\n },\n);\n\nCheckboxBase.displayName = \"CheckboxBase\";\n","import { forwardRef, type InputHTMLAttributes } from \"react\";\n\nexport interface SwitchBaseProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"role\"\n> {}\n\nexport const SwitchBase = forwardRef<HTMLInputElement, SwitchBaseProps>((props, ref) => {\n return <input ref={ref} type=\"checkbox\" role=\"switch\" {...props} />;\n});\n\nSwitchBase.displayName = \"SwitchBase\";\n","import { forwardRef, type InputHTMLAttributes } from \"react\";\n\nexport interface RadioButtonBaseProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {}\n\nexport const RadioButtonBase = forwardRef<HTMLInputElement, RadioButtonBaseProps>((props, ref) => {\n return <input ref={ref} type=\"radio\" {...props} />;\n});\n\nRadioButtonBase.displayName = \"RadioButtonBase\";\n","import { forwardRef, type InputHTMLAttributes } from \"react\";\n\nexport interface SliderBaseProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\"> {}\n\nexport const SliderBase = forwardRef<HTMLInputElement, SliderBaseProps>((props, ref) => {\n return <input ref={ref} type=\"range\" {...props} />;\n});\n\nSliderBase.displayName = \"SliderBase\";\n","/**\n * Pure ComboBox computation logic - zero framework imports.\n * Used by React ComboBoxBase and future Lit finra-combobox.\n */\n\nexport interface ComboBoxOptionLike<T = string> {\n value: T;\n label: string;\n group?: string;\n disabled?: boolean;\n favourite?: boolean;\n}\n\nexport interface ComboBoxGroupResult<T = string> {\n label: string;\n options: ComboBoxOptionLike<T>[];\n}\n\n/** Default case-insensitive substring filter. */\nexport function defaultFilter<T>(option: ComboBoxOptionLike<T>, input: string): boolean {\n if (!input) return true;\n return option.label.toLowerCase().includes(input.toLowerCase());\n}\n\n/** Partition options into favourites, named groups, and ungrouped. */\nexport function groupOptions<T>(options: ComboBoxOptionLike<T>[]): {\n favourites: ComboBoxOptionLike<T>[];\n groups: ComboBoxGroupResult<T>[];\n ungrouped: ComboBoxOptionLike<T>[];\n} {\n const favourites: ComboBoxOptionLike<T>[] = [];\n const groupMap = new Map<string, ComboBoxOptionLike<T>[]>();\n const ungrouped: ComboBoxOptionLike<T>[] = [];\n\n for (const opt of options) {\n if (opt.favourite) {\n favourites.push(opt);\n }\n if (opt.group) {\n const list = groupMap.get(opt.group) ?? [];\n list.push(opt);\n groupMap.set(opt.group, list);\n } else {\n ungrouped.push(opt);\n }\n }\n\n const groups: ComboBoxGroupResult<T>[] = [];\n for (const [label, opts] of groupMap) {\n groups.push({ label, options: opts });\n }\n\n return { favourites, groups, ungrouped };\n}\n","import {\n type ForwardedRef,\n forwardRef,\n type HTMLAttributes,\n type KeyboardEvent,\n type ReactNode,\n type Ref,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { useClickOutside } from \"../../hooks/useClickOutside\";\nimport { useControlledValue } from \"../../hooks/useControlledValue\";\nimport { defaultFilter, groupOptions } from \"../../logic/combobox\";\nimport { cx } from \"../../logic/cx\";\nimport { mergeRefs } from \"../../utils/mergeRefs\";\n\n// Public Types\n\nexport interface ComboBoxOption<T = string> {\n value: T;\n label: string;\n group?: string;\n disabled?: boolean;\n favourite?: boolean;\n}\n\nexport interface ComboBoxRenderOptionState {\n isSelected: boolean;\n isHighlighted: boolean;\n isDisabled: boolean;\n isFavourite: boolean;\n}\n\nexport interface ComboBoxGroup<T = string> {\n label: string;\n options: ComboBoxOption<T>[];\n}\n\n/**\n * CSS class overrides that the styled layer injects into the unstyled base.\n * Every key is optional - when absent, no className is applied.\n */\nexport interface ComboBoxClassNames {\n root?: string;\n wrapper?: string;\n multiValueContainer?: string;\n pill?: string;\n pillText?: string;\n pillRemove?: string;\n singleValue?: string;\n input?: string;\n inputHidden?: string;\n indicator?: string;\n indicatorOpen?: string;\n listbox?: string;\n header?: string;\n footer?: string;\n options?: string;\n option?: string;\n optionHighlighted?: string;\n optionSelected?: string;\n optionDisabled?: string;\n optionCreate?: string;\n optionLabel?: string;\n checkIcon?: string;\n group?: string;\n groupLabel?: string;\n loading?: string;\n spinner?: string;\n empty?: string;\n}\n\nexport interface ComboBoxBaseProps<T = string> extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"onChange\" | \"defaultValue\"\n> {\n /** Available options. */\n options: ComboBoxOption<T>[];\n\n // Value\n /** Selected value(s). Single value or array for multiple. */\n value?: T | T[] | null;\n /** Called when selection changes. */\n onChange?: (value: T | T[] | null) => void;\n /** Enable multi-select mode. */\n multiple?: boolean;\n\n // Typeahead\n /** Controlled input text. */\n inputValue?: string;\n /** Called when input text changes. */\n onInputChange?: (value: string) => void;\n /** Custom filter function. Return true to keep option. */\n filterFn?: (option: ComboBoxOption<T>, inputValue: string) => boolean;\n\n // Async\n /** Show loading indicator. */\n loading?: boolean;\n /** Called when input changes to trigger async loading. */\n onLoadOptions?: (inputValue: string) => void;\n\n // Creatable\n /** Allow creating new options from input. */\n creatable?: boolean;\n /** Called when user creates a new option. */\n onCreateOption?: (inputValue: string) => void;\n /** Custom label for the create option. */\n formatCreateLabel?: (inputValue: string) => string;\n\n // Sections\n /** Content rendered above the options list. */\n header?: ReactNode;\n /** Content rendered below the options list. */\n footer?: ReactNode;\n\n // Display\n placeholder?: string;\n disabled?: boolean;\n /** Message shown when no options match. */\n noOptionsMessage?: string | ReactNode;\n\n // Rendering\n /** Custom option renderer. */\n renderOption?: (option: ComboBoxOption<T>, state: ComboBoxRenderOptionState) => ReactNode;\n /** Custom selected value renderer (single mode). */\n renderValue?: (option: ComboBoxOption<T>) => ReactNode;\n /** Render the \"selected check\" icon beside a selected option. Return null to suppress. */\n renderCheckIcon?: () => ReactNode;\n /** Render the chevron/indicator icon. */\n renderIndicator?: (isOpen: boolean) => ReactNode;\n /** Render the pill remove button icon. */\n renderPillRemoveIcon?: () => ReactNode;\n /** Render the loading spinner content. */\n renderLoading?: () => ReactNode;\n\n // Open state\n /** Controlled open state. */\n open?: boolean;\n /** Called when open state changes. */\n onOpenChange?: (open: boolean) => void;\n\n // Style injection\n /** CSS class overrides injected by the styled layer. */\n classNames?: ComboBoxClassNames;\n /** Root element data attributes. */\n dataAttributes?: Record<string, string>;\n}\n\n// Component\n\nfunction ComboBoxBaseRender<T = string>(\n {\n options,\n value,\n onChange,\n multiple = false,\n inputValue: controlledInputValue,\n onInputChange,\n filterFn,\n loading = false,\n onLoadOptions,\n creatable = false,\n onCreateOption,\n formatCreateLabel,\n header,\n footer,\n placeholder,\n disabled = false,\n noOptionsMessage = \"No options\",\n renderOption,\n renderValue,\n renderCheckIcon,\n renderIndicator,\n renderPillRemoveIcon,\n renderLoading,\n open: controlledOpen,\n onOpenChange,\n classNames: cn,\n dataAttributes,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n ...props\n }: ComboBoxBaseProps<T>,\n forwardedRef: ForwardedRef<HTMLInputElement>,\n): React.ReactElement {\n const id = useId();\n const listboxId = `${id}-listbox`;\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Internal state\n const [isOpen, setOpen] = useControlledValue(controlledOpen, false, onOpenChange);\n const [currentInputValue, setInputValue] = useControlledValue(\n controlledInputValue,\n \"\",\n onInputChange,\n );\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n\n // Selected values as array\n const selectedValues = useMemo<T[]>(() => {\n if (value == null) return [];\n return Array.isArray(value) ? value : [value];\n }, [value]);\n\n const isSelected = useCallback(\n (optValue: T) => selectedValues.some((v) => v === optValue),\n [selectedValues],\n );\n\n // Filtered options\n const filter = filterFn ?? defaultFilter;\n const filteredOptions = useMemo(\n () => options.filter((opt) => filter(opt, currentInputValue)),\n [options, filter, currentInputValue],\n );\n\n // Flat list for keyboard navigation\n const flatOptions = useMemo(() => {\n const { favourites, groups, ungrouped } = groupOptions(filteredOptions);\n const flat: ComboBoxOption<T>[] = [];\n for (const f of favourites) flat.push(f);\n for (const g of groups) {\n for (const o of g.options) {\n if (!o.favourite) flat.push(o);\n }\n }\n for (const o of ungrouped) {\n if (!o.favourite) flat.push(o);\n }\n return flat;\n }, [filteredOptions]);\n\n // Show create option?\n const showCreateOption =\n creatable &&\n currentInputValue.trim() !== \"\" &&\n !options.some((o) => o.label.toLowerCase() === currentInputValue.trim().toLowerCase());\n\n const createLabel = formatCreateLabel\n ? formatCreateLabel(currentInputValue.trim())\n : `Create \"${currentInputValue.trim()}\"`;\n\n const totalNavigable = flatOptions.length + (showCreateOption ? 1 : 0);\n\n // Selection logic\n const selectOption = useCallback(\n (opt: ComboBoxOption<T>) => {\n if (opt.disabled) return;\n\n if (multiple) {\n const next = isSelected(opt.value)\n ? selectedValues.filter((v) => v !== opt.value)\n : [...selectedValues, opt.value];\n onChange?.(next);\n setInputValue(\"\");\n } else {\n onChange?.(opt.value);\n setInputValue(opt.label);\n setOpen(false);\n }\n\n inputRef.current?.focus();\n },\n [multiple, isSelected, selectedValues, onChange, setInputValue, setOpen],\n );\n\n const removeValue = useCallback(\n (val: T) => {\n if (!multiple) return;\n const next = selectedValues.filter((v) => v !== val);\n onChange?.(next.length > 0 ? next : null);\n inputRef.current?.focus();\n },\n [multiple, selectedValues, onChange],\n );\n\n // Keyboard\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (disabled) return;\n\n switch (e.key) {\n case \"ArrowDown\": {\n e.preventDefault();\n if (!isOpen) {\n setOpen(true);\n setHighlightedIndex(0);\n } else {\n setHighlightedIndex((prev) => (prev + 1) % totalNavigable);\n }\n break;\n }\n case \"ArrowUp\": {\n e.preventDefault();\n if (!isOpen) {\n setOpen(true);\n setHighlightedIndex(totalNavigable - 1);\n } else {\n setHighlightedIndex((prev) => (prev - 1 + totalNavigable) % totalNavigable);\n }\n break;\n }\n case \"Enter\": {\n e.preventDefault();\n if (isOpen && highlightedIndex >= 0) {\n if (highlightedIndex < flatOptions.length) {\n selectOption(flatOptions[highlightedIndex]);\n } else if (showCreateOption) {\n onCreateOption?.(currentInputValue.trim());\n setInputValue(\"\");\n }\n } else if (!isOpen) {\n setOpen(true);\n }\n break;\n }\n case \"Escape\": {\n if (isOpen) {\n e.preventDefault();\n setOpen(false);\n setHighlightedIndex(-1);\n }\n break;\n }\n case \"Backspace\": {\n if (multiple && currentInputValue === \"\" && selectedValues.length > 0) {\n removeValue(selectedValues[selectedValues.length - 1]);\n }\n break;\n }\n case \"Home\": {\n if (isOpen) {\n e.preventDefault();\n setHighlightedIndex(0);\n }\n break;\n }\n case \"End\": {\n if (isOpen) {\n e.preventDefault();\n setHighlightedIndex(totalNavigable - 1);\n }\n break;\n }\n }\n },\n [\n disabled,\n isOpen,\n setOpen,\n highlightedIndex,\n totalNavigable,\n flatOptions,\n selectOption,\n showCreateOption,\n onCreateOption,\n currentInputValue,\n setInputValue,\n multiple,\n selectedValues,\n removeValue,\n ],\n );\n\n // Input change\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const val = e.target.value;\n setInputValue(val);\n if (!isOpen) setOpen(true);\n setHighlightedIndex(0);\n onLoadOptions?.(val);\n // Single mode: clear selection when user edits input text\n if (!multiple && value != null) {\n onChange?.(null);\n }\n },\n [setInputValue, isOpen, setOpen, onLoadOptions, multiple, value, onChange],\n );\n\n // Focus\n const handleFocus = useCallback(() => {\n if (!disabled && !isOpen) {\n setOpen(true);\n }\n }, [disabled, isOpen, setOpen]);\n\n // Close on outside click\n const handleClickOutside = useCallback(() => {\n setOpen(false);\n setHighlightedIndex(-1);\n }, [setOpen]);\n useClickOutside(containerRef, handleClickOutside, isOpen);\n\n // Scroll highlighted into view\n useEffect(() => {\n if (highlightedIndex < 0 || !listRef.current) return;\n const el = listRef.current.querySelector(`[data-index=\"${highlightedIndex}\"]`);\n if (el) {\n el.scrollIntoView?.({ block: \"nearest\" });\n }\n }, [highlightedIndex]);\n\n // Grouped rendering data\n const { favourites, groups, ungrouped } = useMemo(\n () => groupOptions(filteredOptions),\n [filteredOptions],\n );\n\n // Helper: get option id\n const getOptionId = (index: number) => `${id}-option-${index}`;\n\n // Helper: render a single option\n const renderSingleOption = (opt: ComboBoxOption<T>, flatIdx: number) => {\n const state: ComboBoxRenderOptionState = {\n isSelected: isSelected(opt.value),\n isHighlighted: highlightedIndex === flatIdx,\n isDisabled: opt.disabled ?? false,\n isFavourite: opt.favourite ?? false,\n };\n\n return (\n <div\n key={`${flatIdx}-${String(opt.value)}`}\n id={getOptionId(flatIdx)}\n role=\"option\"\n tabIndex={-1}\n data-index={flatIdx}\n aria-selected={state.isSelected}\n aria-disabled={state.isDisabled || undefined}\n data-highlighted={state.isHighlighted || undefined}\n data-selected={state.isSelected || undefined}\n data-disabled={state.isDisabled || undefined}\n className={cx(\n cn?.option,\n state.isHighlighted && cn?.optionHighlighted,\n state.isSelected && cn?.optionSelected,\n state.isDisabled && cn?.optionDisabled,\n )}\n onMouseDown={(e) => {\n e.preventDefault(); // keep focus on input\n selectOption(opt);\n }}\n onMouseEnter={() => setHighlightedIndex(flatIdx)}>\n {renderOption ? (\n renderOption(opt, state)\n ) : (\n <>\n <span className={cn?.optionLabel}>{opt.label}</span>\n {state.isSelected && renderCheckIcon ? renderCheckIcon() : null}\n </>\n )}\n </div>\n );\n };\n\n // Render selected values (multi mode)\n const renderSelectedPills = () => {\n if (!multiple) return null;\n return selectedValues.map((val) => {\n const opt = options.find((o) => o.value === val);\n if (!opt) return null;\n return (\n <span key={String(val)} className={cn?.pill} data-combobox-pill>\n <span className={cn?.pillText}>{renderValue ? renderValue(opt) : opt.label}</span>\n {!disabled ? (\n <button\n type=\"button\"\n className={cn?.pillRemove}\n tabIndex={-1}\n aria-label={`Remove ${opt.label}`}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n removeValue(val);\n }}>\n {renderPillRemoveIcon ? renderPillRemoveIcon() : \"\\u00d7\"}\n </button>\n ) : null}\n </span>\n );\n });\n };\n\n // Display value for single mode\n const singleDisplayValue = useMemo(() => {\n if (multiple) return currentInputValue;\n if (isOpen) return currentInputValue;\n if (value != null && !renderValue) {\n const opt = options.find((o) => o.value === value);\n if (opt) return opt.label;\n }\n return currentInputValue;\n }, [multiple, isOpen, currentInputValue, value, options, renderValue]);\n\n // Custom single value display\n const singleValueNode = useMemo(() => {\n if (multiple || isOpen || value == null || !renderValue) return null;\n const opt = options.find((o) => o.value === value);\n if (!opt) return null;\n return <span className={cn?.singleValue}>{renderValue(opt)}</span>;\n }, [multiple, isOpen, value, options, renderValue, cn?.singleValue]);\n\n // Build option list sections\n const optionSections: ReactNode[] = [];\n let runningIndex = 0;\n\n // Favourites section\n if (favourites.length > 0) {\n optionSections.push(\n <div\n key=\"__fav-group\"\n role=\"group\"\n aria-label=\"Favourites\"\n className={cn?.group}\n data-combobox-group=\"favourites\">\n <div className={cn?.groupLabel} data-combobox-group-label aria-hidden=\"true\">\n Favourites\n </div>\n {favourites.map((opt) => {\n const node = renderSingleOption(opt, runningIndex);\n runningIndex++;\n return node;\n })}\n </div>,\n );\n }\n\n // Named groups\n for (const group of groups) {\n const nonFavOpts = group.options.filter((o) => !o.favourite);\n if (nonFavOpts.length === 0) continue;\n optionSections.push(\n <div\n key={`__group-${group.label}`}\n role=\"group\"\n aria-label={group.label}\n className={cn?.group}\n data-combobox-group={group.label}>\n <div className={cn?.groupLabel} data-combobox-group-label aria-hidden=\"true\">\n {group.label}\n </div>\n {nonFavOpts.map((opt) => {\n const node = renderSingleOption(opt, runningIndex);\n runningIndex++;\n return node;\n })}\n </div>,\n );\n }\n\n // Ungrouped (non-favourite)\n const ungroupedNonFav = ungrouped.filter((o) => !o.favourite);\n if (ungroupedNonFav.length > 0) {\n if (favourites.length > 0 || groups.length > 0) {\n optionSections.push(\n <div\n key=\"__ungrouped\"\n role=\"group\"\n aria-label=\"All\"\n className={cn?.group}\n data-combobox-group=\"all\">\n <div className={cn?.groupLabel} data-combobox-group-label aria-hidden=\"true\">\n All\n </div>\n {ungroupedNonFav.map((opt) => {\n const node = renderSingleOption(opt, runningIndex);\n runningIndex++;\n return node;\n })}\n </div>,\n );\n } else {\n for (const opt of ungroupedNonFav) {\n optionSections.push(renderSingleOption(opt, runningIndex));\n runningIndex++;\n }\n }\n }\n\n // Create option\n if (showCreateOption) {\n const createIdx = runningIndex;\n optionSections.push(\n <div\n key=\"__create\"\n id={getOptionId(createIdx)}\n role=\"option\"\n tabIndex={-1}\n data-index={createIdx}\n aria-selected={false}\n data-highlighted={highlightedIndex === createIdx || undefined}\n data-combobox-create\n className={cx(\n cn?.option,\n cn?.optionCreate,\n highlightedIndex === createIdx && cn?.optionHighlighted,\n )}\n onMouseDown={(e) => {\n e.preventDefault();\n onCreateOption?.(currentInputValue.trim());\n setInputValue(\"\");\n }}\n onMouseEnter={() => setHighlightedIndex(createIdx)}>\n {createLabel}\n </div>,\n );\n }\n\n const hasOptions = flatOptions.length > 0 || showCreateOption;\n\n // Shared input props\n const inputProps = {\n type: \"text\" as const,\n role: \"searchbox\" as const,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": isOpen ? listboxId : undefined,\n \"aria-activedescendant\":\n isOpen && highlightedIndex >= 0 ? getOptionId(highlightedIndex) : undefined,\n \"aria-label\": ariaLabel ?? placeholder,\n \"aria-labelledby\": ariaLabelledBy,\n onChange: handleInputChange,\n onKeyDown: handleKeyDown,\n onFocus: handleFocus,\n disabled,\n };\n\n return (\n <div ref={containerRef} className={cn?.root} {...dataAttributes} {...props}>\n <div\n role=\"combobox\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? listboxId : undefined}\n aria-haspopup=\"listbox\"\n aria-disabled={disabled || undefined}\n className={cn?.wrapper}>\n {multiple ? (\n <div className={cn?.multiValueContainer}>\n {renderSelectedPills()}\n <input\n ref={mergeRefs(forwardedRef, inputRef)}\n className={cn?.input}\n {...inputProps}\n value={currentInputValue}\n placeholder={selectedValues.length === 0 ? placeholder : undefined}\n />\n </div>\n ) : (\n <>\n {singleValueNode}\n <input\n ref={mergeRefs(forwardedRef, inputRef)}\n className={cx(cn?.input, singleValueNode ? cn?.inputHidden : undefined)}\n {...inputProps}\n value={singleDisplayValue}\n placeholder={placeholder}\n />\n </>\n )}\n {renderIndicator ? renderIndicator(isOpen) : null}\n </div>\n\n {isOpen ? (\n <div className={cn?.listbox}>\n {header ? <div className={cn?.header}>{header}</div> : null}\n\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n className={cn?.options}\n tabIndex={-1}>\n {loading ? (\n <div role=\"presentation\" className={cn?.loading} aria-live=\"polite\">\n {renderLoading ? renderLoading() : \"Loading...\"}\n </div>\n ) : !hasOptions ? (\n <div role=\"presentation\" className={cn?.empty} aria-live=\"polite\">\n {noOptionsMessage}\n </div>\n ) : (\n optionSections\n )}\n </div>\n\n {footer ? <div className={cn?.footer}>{footer}</div> : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nexport const ComboBoxBase = forwardRef(ComboBoxBaseRender) as <T = string>(\n props: ComboBoxBaseProps<T> & { ref?: Ref<HTMLInputElement> },\n) => React.ReactElement | null;\n\n(ComboBoxBase as { displayName?: string }).displayName = \"ComboBoxBase\";\n"],"mappings":"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"}
|
|
@@ -34,11 +34,5 @@ export declare const componentIds: {
|
|
|
34
34
|
readonly badge: "badge";
|
|
35
35
|
readonly comboBox: "combo-box";
|
|
36
36
|
readonly divider: "divider";
|
|
37
|
-
readonly calendar: "calendar";
|
|
38
|
-
readonly dateInput: "date-input";
|
|
39
|
-
readonly dateInputField: "date-input-field";
|
|
40
|
-
readonly calendarIcon: "calendar-icon";
|
|
41
|
-
readonly tenorInput: "tenor-input";
|
|
42
|
-
readonly dateTenorInput: "date-tenor-input";
|
|
43
37
|
};
|
|
44
38
|
export type ComponentId = (typeof componentIds)[keyof typeof componentIds];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/utils/mergeRefs.ts
|
|
2
|
+
function e(...e) {
|
|
3
|
+
return (t) => {
|
|
4
|
+
for (let n of e) typeof n == "function" ? n(t) : n && typeof n == "object" && (n.current = t);
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/logic/cx.ts
|
|
9
|
+
function t(...e) {
|
|
10
|
+
return e.filter(Boolean).join(" ") || void 0;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { e as n, t };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=cx-Cj1p8CM7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cx-Cj1p8CM7.js","names":[],"sources":["../src/utils/mergeRefs.ts","../src/logic/cx.ts"],"sourcesContent":["import type { Ref } from \"react\";\n\nexport function mergeRefs<T>(...refs: (Ref<T> | undefined)[]): (value: T | null) => void {\n return (value: T | null) => {\n for (const ref of refs) {\n if (typeof ref === \"function\") {\n ref(value);\n } else if (ref && typeof ref === \"object\") {\n (ref as React.MutableRefObject<T | null>).current = value;\n }\n }\n };\n}\n","/**\n * Lightweight class-name joiner for unstyled components.\n * Only joins truthy values - returns undefined when empty.\n * Styled components use `clsx` from the clsx package instead.\n */\nexport function cx(...classes: (string | false | undefined | null)[]): string | undefined {\n const result = classes.filter(Boolean).join(\" \");\n return result || undefined;\n}\n"],"mappings":";AAEA,SAAgB,EAAa,GAAG,GAAyD;AACvF,SAAQ,MAAoB;AAC1B,OAAK,IAAM,KAAO,EAChB,CAAI,OAAO,KAAQ,aACjB,EAAI,EAAM,GACD,KAAO,OAAO,KAAQ,aAC9B,EAAyC,UAAU;;;;;ACH5D,SAAgB,EAAG,GAAG,GAAoE;AAExF,QADe,EAAQ,OAAO,QAAQ,CAAC,KAAK,IAAI,IAC/B,KAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export type { ComponentId } from './components/componentIds';
|
|
2
2
|
export { componentIds, FINRA_UI_ATTR } from './components/componentIds';
|
|
3
|
+
export { useClickOutside } from './hooks/useClickOutside';
|
|
4
|
+
export { useControlledValue } from './hooks/useControlledValue';
|
|
3
5
|
export type { ButtonProps, ButtonSentiment } from './components/Button/Button';
|
|
4
6
|
export { Button } from './components/Button/Button';
|
|
5
7
|
export type { IconButtonProps, IconButtonSentiment } from './components/IconButton/IconButton';
|
|
@@ -28,10 +30,6 @@ export type { FileDropZoneProps } from './components/FileDropZone/FileDropZone';
|
|
|
28
30
|
export { FileDropZone } from './components/FileDropZone/FileDropZone';
|
|
29
31
|
export type { ComboBoxGroup, ComboBoxOption, ComboBoxProps, ComboBoxRenderOptionState, } from './components/ComboBox/ComboBox';
|
|
30
32
|
export { ComboBox } from './components/ComboBox/ComboBox';
|
|
31
|
-
export type { CalendarProps } from './components/Calendar/Calendar';
|
|
32
|
-
export { Calendar } from './components/Calendar/Calendar';
|
|
33
|
-
export type { DateInputProps } from './components/DateInput/DateInput';
|
|
34
|
-
export { DateInput } from './components/DateInput/DateInput';
|
|
35
33
|
export type { BadgeProps, BadgeSentiment } from './components/Badge/Badge';
|
|
36
34
|
export { Badge } from './components/Badge/Badge';
|
|
37
35
|
export type { DividerProps } from './components/Divider/Divider';
|