@columenlabs/lumen-ui 0.1.211 → 0.1.212
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/lumen-selector.js +20 -11
- package/package.json +2 -2
package/dist/lumen-selector.js
CHANGED
|
@@ -130,7 +130,7 @@ function useDuplicateWarning(all) {
|
|
|
130
130
|
}
|
|
131
131
|
}, [all]);
|
|
132
132
|
}
|
|
133
|
-
const ROW = 'relative flex w-full cursor-default items-center gap-2 rounded-md px-2 text-sm outline-hidden select-none h-8 max-md:h-11 max-md:px-4 max-md:text-[15px] data-highlighted:bg-accent data-highlighted:text-accent-foreground data-selected:bg-muted data-disabled:pointer-events-none
|
|
133
|
+
const ROW = 'relative flex w-full cursor-default items-center gap-2 rounded-md px-2 text-sm outline-hidden select-none h-8 max-md:h-11 max-md:px-4 max-md:text-[15px] data-highlighted:bg-accent data-highlighted:text-accent-foreground data-selected:bg-muted data-disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-4';
|
|
134
134
|
/** A row with a description or thumbnail grows to fit it. */
|
|
135
135
|
const TALL = 'h-auto min-h-8 py-1.5 max-md:h-auto';
|
|
136
136
|
const GROUP_LABEL = 'sticky top-0 z-10 bg-popover px-2 pt-2 pb-1 text-xs font-medium text-muted-foreground max-md:px-4';
|
|
@@ -138,12 +138,14 @@ const MORE = 'flex h-7 w-full items-center gap-1.5 rounded-md pr-2 pl-8 text-lef
|
|
|
138
138
|
/** One row's inside: box or icon, label, detail, and the check when picked. */
|
|
139
139
|
export function SelectorRowContent({ option, selected, multiple, trailing, }) {
|
|
140
140
|
const Icon = option.icon;
|
|
141
|
-
|
|
141
|
+
const off = !!option.disabled;
|
|
142
|
+
const reason = typeof option.disabled === 'string' ? option.disabled : null;
|
|
143
|
+
return (_jsxs(_Fragment, { children: [option.indent && _jsx("span", { "aria-hidden": true, className: "w-4 shrink-0" }), multiple && (_jsx("span", { "aria-hidden": true, className: cn('flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input', selected && 'border-primary bg-primary text-primary-foreground'), children: selected && _jsx(CheckIcon, { className: "size-3" }) })), option.thumb ? (_jsx("span", { "aria-hidden": true, className: "shrink-0", children: option.thumb })) : (Icon && _jsx(Icon, { className: cn('text-muted-foreground', off && 'opacity-60') })), option.description ? (_jsxs("span", { className: cn('flex min-w-0 flex-1 flex-col', off && 'text-muted-foreground'), children: [_jsx("span", { className: "truncate", children: option.content ?? option.label }), _jsx("span", { className: "truncate text-xs text-muted-foreground", children: option.description })] })) : (_jsx("span", { className: cn('min-w-0 truncate', option.detail || reason ? 'max-w-2/3 shrink-0' : 'flex-1', off && 'text-muted-foreground'), children: option.content ?? option.label })), reason ? (_jsxs("span", { className: "ml-auto inline-flex shrink-0 items-center gap-1 rounded-full border px-2 py-px text-xs text-foreground/80", children: [_jsx(CheckIcon, { className: "size-3! text-emerald-600 dark:text-emerald-400" }), reason] })) : (option.detail && (_jsx("span", { className: "min-w-0 flex-1 truncate text-right text-xs text-muted-foreground", title: option.detail, children: option.detail }))), trailing] }));
|
|
142
144
|
}
|
|
143
145
|
function Rows({ shown, picked, multiple, full, expand, }) {
|
|
144
146
|
return shown.map((g) => (_jsxs(Base.Group, { items: g.rows.map((o) => o.value), children: [g.label && _jsx(Base.GroupLabel, { className: GROUP_LABEL, children: g.label }), g.rows.map((o) => {
|
|
145
147
|
const row = (_jsx(Base.Item, { value: o.value, disabled: !!o.disabled || (full && !picked.has(o.value)), className: cn(ROW, (o.description || o.thumb) && TALL), children: _jsx(SelectorRowContent, { option: o, selected: picked.has(o.value), multiple: multiple && o.value !== CREATE }) }, o.value));
|
|
146
|
-
return
|
|
148
|
+
return row;
|
|
147
149
|
}), g.more > 0 && (_jsxs("button", { type: "button", className: MORE, onMouseDown: (e) => e.preventDefault(), onClick: () => expand(g.label), children: [_jsx(ChevronDownIcon, { className: "size-3.5" }), g.more, " more"] }))] }, g.label || '\u0000')));
|
|
148
150
|
}
|
|
149
151
|
const FIELD = "flex w-fit min-w-0 items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4";
|
|
@@ -283,12 +285,13 @@ export function LumenSelector(props) {
|
|
|
283
285
|
export function LumenSelectorList({ options, groups, query, onPick, onClose, empty, header, className, handle, label, fuzzy, }) {
|
|
284
286
|
const none = useMemo(() => new Set(), []);
|
|
285
287
|
const { shown, flat, expand } = useSelectorRows(options, groups, query, none, fuzzy);
|
|
286
|
-
const
|
|
288
|
+
const first = flat.findIndex((o) => !o.disabled);
|
|
289
|
+
const [at, setAt] = useState(first);
|
|
287
290
|
const listId = useId();
|
|
288
|
-
// biome-ignore lint/correctness/useExhaustiveDependencies: a new query starts at the first row.
|
|
289
|
-
useEffect(() => setAt(
|
|
290
|
-
const index =
|
|
291
|
-
const active = flat[index];
|
|
291
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: a new query starts at the first pickable row.
|
|
292
|
+
useEffect(() => setAt(first), [query]);
|
|
293
|
+
const index = flat[at] && !flat[at].disabled ? at : first;
|
|
294
|
+
const active = index < 0 ? undefined : flat[index];
|
|
292
295
|
useEffect(() => {
|
|
293
296
|
spotlight(active?.target, active?.targetName ?? active?.label);
|
|
294
297
|
}, [active]);
|
|
@@ -300,7 +303,13 @@ export function LumenSelectorList({ options, groups, query, onPick, onClose, emp
|
|
|
300
303
|
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
|
301
304
|
e.preventDefault();
|
|
302
305
|
const step = e.key === 'ArrowDown' ? 1 : -1;
|
|
303
|
-
|
|
306
|
+
if (index < 0)
|
|
307
|
+
return true;
|
|
308
|
+
let i = index;
|
|
309
|
+
do
|
|
310
|
+
i = (i + step + flat.length) % flat.length;
|
|
311
|
+
while (flat[i]?.disabled && i !== index);
|
|
312
|
+
setAt(i);
|
|
304
313
|
return true;
|
|
305
314
|
}
|
|
306
315
|
if ((e.key === 'Enter' && !e.shiftKey) || e.key === 'Tab') {
|
|
@@ -317,9 +326,9 @@ export function LumenSelectorList({ options, groups, query, onPick, onClose, emp
|
|
|
317
326
|
}
|
|
318
327
|
return false;
|
|
319
328
|
},
|
|
320
|
-
}), [flat, active, onPick, onClose]);
|
|
329
|
+
}), [flat, index, active, onPick, onClose]);
|
|
321
330
|
return (_jsxs("div", { "data-slot": "lumen-selector-list", className: cn('flex max-h-80 flex-col overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10', className), children: [header, _jsxs("div", { id: listId, "aria-label": label, className: "min-h-0 overflow-y-auto overscroll-contain p-1", children: [!flat.length && (_jsx("p", { className: "px-2 py-3 text-center text-sm text-muted-foreground", children: empty ?? 'Nothing matches' })), shown.map((g) => (_jsxs("section", { "aria-label": g.label || undefined, children: [g.label && _jsx("div", { className: GROUP_LABEL, children: g.label }), g.rows.map((o) => {
|
|
322
331
|
const i = flat.indexOf(o);
|
|
323
|
-
return (_jsx("button", { type: "button", tabIndex: -1, "aria-current": i === index || undefined, disabled: !!o.disabled, "data-highlighted": i === index ? '' : undefined, className: cn(ROW, 'text-left'), onMouseMove: () => i !== index && setAt(i), onMouseDown: (e) => e.preventDefault(), onClick: () => !o.disabled && onPick(o), children: _jsx(SelectorRowContent, { option: o, trailing: i ===
|
|
332
|
+
return (_jsx("button", { type: "button", tabIndex: -1, "aria-current": i === index || undefined, disabled: !!o.disabled, "data-disabled": o.disabled ? '' : undefined, "data-highlighted": i === index ? '' : undefined, className: cn(ROW, 'text-left'), onMouseMove: () => i !== index && setAt(i), onMouseDown: (e) => e.preventDefault(), onClick: () => !o.disabled && onPick(o), children: _jsx(SelectorRowContent, { option: o, trailing: i === index ? (_jsx("kbd", { className: "rounded border px-1 font-mono text-[11px] text-muted-foreground", children: "Tab" })) : undefined }) }, o.value));
|
|
324
333
|
}), g.more > 0 && (_jsxs("button", { type: "button", className: MORE, onMouseDown: (e) => e.preventDefault(), onClick: () => expand(g.label), children: [_jsx(ChevronDownIcon, { className: "size-3.5" }), g.more, " more ", g.label.toLowerCase()] }))] }, g.label || '\u0000')))] })] }));
|
|
325
334
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.212",
|
|
4
4
|
"description": "Lumen: shared React components (frame, views, widgets, charts, drawers).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@codemirror/lang-javascript": "6.2.5",
|
|
50
50
|
"@codemirror/lang-json": "6.0.2",
|
|
51
51
|
"@codemirror/lang-sql": "6.10.0",
|
|
52
|
-
"@columenlabs/lumen-ui-types": "0.1.
|
|
52
|
+
"@columenlabs/lumen-ui-types": "0.1.212",
|
|
53
53
|
"@dnd-kit/core": "6.3.1",
|
|
54
54
|
"@dnd-kit/sortable": "10.0.0",
|
|
55
55
|
"@dnd-kit/utilities": "3.2.2",
|