@nexus-cross/design-system 1.1.0 → 1.1.1
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/cursor-rules/nexus-ui-api.mdc +127 -41
- package/cursor-rules/nexus-ui-decisions.mdc +6 -2
- package/dist/chunks/{chunk-G3RLK2HS.js → chunk-3SCSND6S.js} +1 -1
- package/dist/chunks/{chunk-56ZOOQFE.mjs → chunk-AG2UJPFX.mjs} +124 -17
- package/dist/chunks/{chunk-EILXBLEV.mjs → chunk-QWK4CLS2.mjs} +1 -1
- package/dist/chunks/{chunk-5ASTWFJW.js → chunk-RC2Y4UH7.js} +127 -17
- package/dist/combobox.js +15 -3
- package/dist/combobox.mjs +1 -1
- package/dist/components/Combobox.d.ts +53 -8
- package/dist/components/Combobox.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -3
- package/dist/index.mjs +1 -1
- package/dist/schemas/_all.json +62 -17
- package/dist/schemas/combobox.d.ts +33 -10
- package/dist/schemas/combobox.d.ts.map +1 -1
- package/dist/schemas/combobox.json +6 -6
- package/dist/schemas/comboboxOption.json +16 -11
- package/dist/schemas/comboboxOptionDescription.json +20 -0
- package/dist/schemas/comboboxOptionMeta.json +20 -0
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas.js +74 -13
- package/dist/schemas.mjs +72 -13
- package/dist/styles/.generated/built.d.ts +1 -1
- package/dist/styles/.generated/built.d.ts.map +1 -1
- package/dist/styles/layer.js +2 -2
- package/dist/styles/layer.mjs +1 -1
- package/dist/styles.css +13 -0
- package/dist/styles.js +2 -2
- package/dist/styles.layered.css +13 -0
- package/dist/styles.mjs +1 -1
- package/package.json +2 -2
|
@@ -19,6 +19,97 @@ var comboboxInputVariants = cva("nexus-combobox", {
|
|
|
19
19
|
},
|
|
20
20
|
defaultVariants: { size: "md", state: "default" }
|
|
21
21
|
});
|
|
22
|
+
function ComboboxOption(_) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
ComboboxOption.displayName = "Combobox.Option";
|
|
26
|
+
function ComboboxOptionDescription(_) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
ComboboxOptionDescription.displayName = "Combobox.OptionDescription";
|
|
30
|
+
function ComboboxOptionMeta(_) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
ComboboxOptionMeta.displayName = "Combobox.OptionMeta";
|
|
34
|
+
function isElementOfType(node, type) {
|
|
35
|
+
return React.isValidElement(node) && node.type === type;
|
|
36
|
+
}
|
|
37
|
+
function extractText(node) {
|
|
38
|
+
if (node == null || typeof node === "boolean") return "";
|
|
39
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
40
|
+
if (Array.isArray(node)) {
|
|
41
|
+
return node.map(extractText).filter(Boolean).join(" ");
|
|
42
|
+
}
|
|
43
|
+
if (React.isValidElement(node)) {
|
|
44
|
+
if (node.type === ComboboxOptionDescription || node.type === ComboboxOptionMeta) {
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
47
|
+
const children = node.props?.children;
|
|
48
|
+
return extractText(children);
|
|
49
|
+
}
|
|
50
|
+
return "";
|
|
51
|
+
}
|
|
52
|
+
function resolveOptionsFromChildren(children) {
|
|
53
|
+
const resolved = [];
|
|
54
|
+
const seenValues = /* @__PURE__ */ new Set();
|
|
55
|
+
React.Children.forEach(children, (child) => {
|
|
56
|
+
if (!React.isValidElement(child)) return;
|
|
57
|
+
if (child.type !== ComboboxOption) {
|
|
58
|
+
if (process.env.NODE_ENV !== "production") {
|
|
59
|
+
const name = typeof child.type === "string" ? child.type : child.type?.displayName ?? child.type?.name ?? "Unknown";
|
|
60
|
+
console.warn(
|
|
61
|
+
`[Combobox] Ignoring child <${name}>. Only <Combobox.Option> is allowed as a direct child of <Combobox>.`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const props = child.props;
|
|
67
|
+
const value = props.value;
|
|
68
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
69
|
+
if (process.env.NODE_ENV !== "production") {
|
|
70
|
+
console.error(
|
|
71
|
+
"[Combobox] <Combobox.Option> requires a non-empty string `value` prop."
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (seenValues.has(value)) {
|
|
77
|
+
if (process.env.NODE_ENV !== "production") {
|
|
78
|
+
console.error(
|
|
79
|
+
`[Combobox] Duplicate option value: "${value}". Each <Combobox.Option> must have a unique \`value\`. The duplicate will be ignored.`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
seenValues.add(value);
|
|
85
|
+
const labelNodes = [];
|
|
86
|
+
let description = null;
|
|
87
|
+
let meta = null;
|
|
88
|
+
React.Children.forEach(props.children, (slot) => {
|
|
89
|
+
if (isElementOfType(slot, ComboboxOptionDescription)) {
|
|
90
|
+
description = slot.props.children;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (isElementOfType(slot, ComboboxOptionMeta)) {
|
|
94
|
+
meta = slot.props.children;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
labelNodes.push(slot);
|
|
98
|
+
});
|
|
99
|
+
const label = labelNodes.length === 1 ? labelNodes[0] : labelNodes;
|
|
100
|
+
const textValue = typeof props.textValue === "string" && props.textValue.length > 0 ? props.textValue : extractText(label);
|
|
101
|
+
resolved.push({
|
|
102
|
+
value,
|
|
103
|
+
disabled: !!props.disabled,
|
|
104
|
+
textValue,
|
|
105
|
+
className: props.className,
|
|
106
|
+
label,
|
|
107
|
+
description,
|
|
108
|
+
meta
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
return resolved;
|
|
112
|
+
}
|
|
22
113
|
var ChevronDown = ({ className }) => /* @__PURE__ */ jsx(
|
|
23
114
|
"svg",
|
|
24
115
|
{
|
|
@@ -67,8 +158,8 @@ var CloseIcon = ({ className }) => /* @__PURE__ */ jsx(
|
|
|
67
158
|
);
|
|
68
159
|
function defaultFilter(option, query) {
|
|
69
160
|
if (!query) return true;
|
|
70
|
-
const
|
|
71
|
-
return
|
|
161
|
+
const haystack = option.textValue || option.value;
|
|
162
|
+
return haystack.toLowerCase().includes(query.toLowerCase());
|
|
72
163
|
}
|
|
73
164
|
function useDebouncedCallback(callback, delay) {
|
|
74
165
|
const cbRef = React.useRef(callback);
|
|
@@ -89,10 +180,10 @@ function useDebouncedCallback(callback, delay) {
|
|
|
89
180
|
[delay]
|
|
90
181
|
);
|
|
91
182
|
}
|
|
92
|
-
var
|
|
93
|
-
function
|
|
183
|
+
var ComboboxImpl = React.forwardRef(
|
|
184
|
+
function Combobox(props, ref) {
|
|
94
185
|
const {
|
|
95
|
-
|
|
186
|
+
children,
|
|
96
187
|
onSearch,
|
|
97
188
|
searchDebounce = 250,
|
|
98
189
|
loading = false,
|
|
@@ -164,11 +255,20 @@ var Combobox = React.forwardRef(
|
|
|
164
255
|
const [query, setQuery] = React.useState("");
|
|
165
256
|
const [activeIndex, setActiveIndex] = React.useState(0);
|
|
166
257
|
const debouncedSearch = useDebouncedCallback(onSearch, searchDebounce);
|
|
258
|
+
const resolvedOptions = React.useMemo(
|
|
259
|
+
() => resolveOptionsFromChildren(children),
|
|
260
|
+
[children]
|
|
261
|
+
);
|
|
167
262
|
const visibleOptions = React.useMemo(() => {
|
|
168
|
-
if (onSearch) return
|
|
263
|
+
if (onSearch) return resolvedOptions;
|
|
169
264
|
const filterFn = filter ?? defaultFilter;
|
|
170
|
-
return
|
|
171
|
-
|
|
265
|
+
return resolvedOptions.filter(
|
|
266
|
+
(o) => filterFn(
|
|
267
|
+
{ value: o.value, textValue: o.textValue, disabled: o.disabled },
|
|
268
|
+
query
|
|
269
|
+
)
|
|
270
|
+
);
|
|
271
|
+
}, [onSearch, resolvedOptions, filter, query]);
|
|
172
272
|
React.useEffect(() => {
|
|
173
273
|
if (activeIndex >= visibleOptions.length) {
|
|
174
274
|
setActiveIndex(visibleOptions.length > 0 ? 0 : -1);
|
|
@@ -196,7 +296,7 @@ var Combobox = React.forwardRef(
|
|
|
196
296
|
inputRef.current?.focus();
|
|
197
297
|
} else {
|
|
198
298
|
updateValue(option.value);
|
|
199
|
-
const labelText =
|
|
299
|
+
const labelText = option.textValue || option.value;
|
|
200
300
|
setQuery(labelText);
|
|
201
301
|
setOpen(false);
|
|
202
302
|
inputRef.current?.blur();
|
|
@@ -288,9 +388,9 @@ var Combobox = React.forwardRef(
|
|
|
288
388
|
};
|
|
289
389
|
const selectedOptionMap = React.useMemo(() => {
|
|
290
390
|
const map = /* @__PURE__ */ new Map();
|
|
291
|
-
for (const opt of
|
|
391
|
+
for (const opt of resolvedOptions) map.set(opt.value, opt);
|
|
292
392
|
return map;
|
|
293
|
-
}, [
|
|
393
|
+
}, [resolvedOptions]);
|
|
294
394
|
const prevValueRef = React.useRef(
|
|
295
395
|
currentValue
|
|
296
396
|
);
|
|
@@ -306,7 +406,7 @@ var Combobox = React.forwardRef(
|
|
|
306
406
|
return;
|
|
307
407
|
}
|
|
308
408
|
const opt = selectedOptionMap.get(currentValue);
|
|
309
|
-
const labelText = opt ?
|
|
409
|
+
const labelText = opt ? opt.textValue || currentValue : currentValue;
|
|
310
410
|
if (valueChanged) {
|
|
311
411
|
setQuery(labelText);
|
|
312
412
|
} else {
|
|
@@ -332,8 +432,9 @@ var Combobox = React.forwardRef(
|
|
|
332
432
|
/* @__PURE__ */ jsxs("div", { className: "nexus-combobox__content", children: [
|
|
333
433
|
isMultiple && selectedValues.map((val) => {
|
|
334
434
|
const opt = selectedOptionMap.get(val);
|
|
435
|
+
const chipLabel = opt ? opt.label ?? opt.textValue ?? val : val;
|
|
335
436
|
return /* @__PURE__ */ jsxs("span", { className: "nexus-combobox__chip", children: [
|
|
336
|
-
/* @__PURE__ */ jsx("span", { className: "nexus-combobox__chip-label", children:
|
|
437
|
+
/* @__PURE__ */ jsx("span", { className: "nexus-combobox__chip-label", children: chipLabel }),
|
|
337
438
|
!disabled && /* @__PURE__ */ jsx(
|
|
338
439
|
"button",
|
|
339
440
|
{
|
|
@@ -453,7 +554,8 @@ var Combobox = React.forwardRef(
|
|
|
453
554
|
"nexus-combobox-option",
|
|
454
555
|
active && "nexus-combobox-option--active",
|
|
455
556
|
selected && "nexus-combobox-option--selected",
|
|
456
|
-
option.disabled && "nexus-combobox-option--disabled"
|
|
557
|
+
option.disabled && "nexus-combobox-option--disabled",
|
|
558
|
+
option.className
|
|
457
559
|
),
|
|
458
560
|
onMouseEnter: () => setActiveIndex(idx),
|
|
459
561
|
onMouseDown: (e) => {
|
|
@@ -463,8 +565,9 @@ var Combobox = React.forwardRef(
|
|
|
463
565
|
children: [
|
|
464
566
|
/* @__PURE__ */ jsxs("div", { className: "nexus-combobox-option__body", children: [
|
|
465
567
|
/* @__PURE__ */ jsx("div", { className: "nexus-combobox-option__label", children: option.label }),
|
|
466
|
-
option.description && /* @__PURE__ */ jsx("div", { className: "nexus-combobox-option__description", children: option.description })
|
|
568
|
+
option.description != null && /* @__PURE__ */ jsx("div", { className: "nexus-combobox-option__description", children: option.description })
|
|
467
569
|
] }),
|
|
570
|
+
option.meta != null && /* @__PURE__ */ jsx("div", { className: "nexus-combobox-option__meta", children: option.meta }),
|
|
468
571
|
selected && /* @__PURE__ */ jsx(
|
|
469
572
|
"svg",
|
|
470
573
|
{
|
|
@@ -509,6 +612,10 @@ var Combobox = React.forwardRef(
|
|
|
509
612
|
] });
|
|
510
613
|
}
|
|
511
614
|
);
|
|
512
|
-
|
|
615
|
+
ComboboxImpl.displayName = "Combobox";
|
|
616
|
+
var Combobox2 = ComboboxImpl;
|
|
617
|
+
Combobox2.Option = ComboboxOption;
|
|
618
|
+
Combobox2.OptionDescription = ComboboxOptionDescription;
|
|
619
|
+
Combobox2.OptionMeta = ComboboxOptionMeta;
|
|
513
620
|
|
|
514
|
-
export { Combobox, comboboxInputVariants };
|
|
621
|
+
export { Combobox2 as Combobox, ComboboxOption, ComboboxOptionDescription, ComboboxOptionMeta, comboboxInputVariants };
|