@tensor_1/react 2.46.0 → 2.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +509 -1
- package/dist/{SchedulingCalendar-B6TakO2h.d.ts → SchedulingCalendar-WWyFL3Eo.d.ts} +51 -2
- package/dist/announce.d.ts +10 -0
- package/dist/announce.js +30 -0
- package/dist/chart-analytic.cjs +33 -25
- package/dist/chart-preset.cjs +23 -15
- package/dist/chart.cjs +23 -15
- package/dist/combobox-model.d.ts +10 -1
- package/dist/combobox-model.js +15 -0
- package/dist/command-palette-model.d.ts +44 -0
- package/dist/command-palette-model.js +36 -0
- package/dist/components/AccountMenu.d.ts +44 -0
- package/dist/components/AccountMenu.js +43 -0
- package/dist/components/AppShell.d.ts +45 -2
- package/dist/components/AppShell.js +116 -5
- package/dist/components/AuditLog.d.ts +128 -0
- package/dist/components/AuditLog.js +196 -0
- package/dist/components/BrandProfiles.js +4 -3
- package/dist/components/Breadcrumbs.d.ts +9 -2
- package/dist/components/Breadcrumbs.js +3 -2
- package/dist/components/BusyBar.d.ts +13 -0
- package/dist/components/BusyBar.js +10 -0
- package/dist/components/BusyRegion.d.ts +18 -0
- package/dist/components/BusyRegion.js +12 -0
- package/dist/components/Button.d.ts +33 -5
- package/dist/components/Button.js +12 -6
- package/dist/components/ButtonFeedback.d.ts +30 -0
- package/dist/components/ButtonFeedback.js +78 -0
- package/dist/components/Card.d.ts +18 -1
- package/dist/components/Card.js +5 -1
- package/dist/components/ChangeHighlight.d.ts +30 -0
- package/dist/components/ChangeHighlight.js +21 -0
- package/dist/components/ChartCore.js +2 -1
- package/dist/components/Checkbox.d.ts +27 -1
- package/dist/components/Checkbox.js +31 -2
- package/dist/components/CodeDisplay.d.ts +65 -0
- package/dist/components/CodeDisplay.js +124 -0
- package/dist/components/Combobox.d.ts +27 -6
- package/dist/components/Combobox.js +195 -58
- package/dist/components/CommandPalette.d.ts +36 -1
- package/dist/components/CommandPalette.js +254 -2
- package/dist/components/ContactCard.d.ts +66 -0
- package/dist/components/ContactCard.js +74 -0
- package/dist/components/Count.d.ts +24 -0
- package/dist/components/Count.js +32 -0
- package/dist/components/DataWorkspace.d.ts +167 -0
- package/dist/components/DataWorkspace.js +383 -0
- package/dist/components/DateFieldParts.d.ts +2 -1
- package/dist/components/DateFieldParts.js +7 -0
- package/dist/components/DatePicker.d.ts +9 -2
- package/dist/components/DatePicker.js +67 -28
- package/dist/components/DateRangePicker.d.ts +12 -2
- package/dist/components/DateRangePicker.js +13 -12
- package/dist/components/DelayedRender.d.ts +15 -0
- package/dist/components/DelayedRender.js +10 -0
- package/dist/components/DetailPage.d.ts +7 -1
- package/dist/components/DetailPage.js +2 -1
- package/dist/components/Dialogs.d.ts +71 -10
- package/dist/components/Dialogs.js +130 -30
- package/dist/components/DiffViewer.d.ts +23 -3
- package/dist/components/DiffViewer.js +26 -12
- package/dist/components/DiscardPrompt.d.ts +1 -0
- package/dist/components/DiscardPrompt.js +16 -0
- package/dist/components/DisplayPreferences.d.ts +83 -0
- package/dist/components/DisplayPreferences.js +185 -0
- package/dist/components/Drawer.d.ts +1 -0
- package/dist/components/EditorialHome.d.ts +23 -3
- package/dist/components/EditorialHome.js +16 -11
- package/dist/components/EntityPicker.d.ts +20 -3
- package/dist/components/EntityPicker.js +32 -13
- package/dist/components/FilterEditor.d.ts +18 -4
- package/dist/components/FilterEditor.js +141 -19
- package/dist/components/InfoTip.js +11 -12
- package/dist/components/InlineEdit.d.ts +87 -20
- package/dist/components/InlineEdit.js +197 -54
- package/dist/components/Input.d.ts +12 -2
- package/dist/components/Input.js +5 -3
- package/dist/components/Kbd.d.ts +6 -1
- package/dist/components/Kbd.js +6 -6
- package/dist/components/Lightbox.d.ts +41 -5
- package/dist/components/Lightbox.js +95 -9
- package/dist/components/MatchReview.d.ts +40 -1
- package/dist/components/MatchReview.js +130 -4
- package/dist/components/MetricInput.js +3 -2
- package/dist/components/Modal.d.ts +3 -1
- package/dist/components/Modal.js +13 -4
- package/dist/components/NavFavourites.d.ts +5 -0
- package/dist/components/NavFavourites.js +7 -7
- package/dist/components/OtpInput.d.ts +33 -0
- package/dist/components/OtpInput.js +123 -0
- package/dist/components/PageHeader.d.ts +7 -1
- package/dist/components/PageHeader.js +2 -2
- package/dist/components/Pagination.js +6 -5
- package/dist/components/PasswordInput.d.ts +34 -0
- package/dist/components/PasswordInput.js +101 -0
- package/dist/components/Peek.js +3 -3
- package/dist/components/Popover.js +2 -0
- package/dist/components/PrintLayout.d.ts +63 -0
- package/dist/components/PrintLayout.js +114 -0
- package/dist/components/QrCode.d.ts +47 -0
- package/dist/components/QrCode.js +55 -0
- package/dist/components/QrScanner.d.ts +95 -0
- package/dist/components/QrScanner.js +266 -0
- package/dist/components/RelationshipGraph.d.ts +32 -1
- package/dist/components/RelationshipGraph.js +18 -5
- package/dist/components/RelationshipGraphLayered.d.ts +1 -1
- package/dist/components/RelationshipGraphLayered.js +190 -115
- package/dist/components/RelationshipGraphList.js +33 -6
- package/dist/components/RuleBuilder.js +39 -7
- package/dist/components/SaveStatus.d.ts +7 -1
- package/dist/components/SaveStatus.js +13 -4
- package/dist/components/SchedulingAgenda.d.ts +3 -1
- package/dist/components/SchedulingCalendar.d.ts +3 -1
- package/dist/components/SchedulingCalendar.js +43 -4
- package/dist/components/SchedulingResourceDay.d.ts +57 -0
- package/dist/components/SchedulingResourceDay.js +287 -0
- package/dist/components/SchedulingTimeGrid.d.ts +3 -1
- package/dist/components/SchedulingTimeline.d.ts +3 -1
- package/dist/components/SearchBar.d.ts +1 -0
- package/dist/components/SearchSuggest.d.ts +23 -3
- package/dist/components/SearchSuggest.js +48 -17
- package/dist/components/Segmented.d.ts +39 -4
- package/dist/components/Segmented.js +31 -3
- package/dist/components/Select.d.ts +3 -2
- package/dist/components/Select.js +1 -1
- package/dist/components/ShortcutHint.d.ts +11 -10
- package/dist/components/ShortcutHint.js +44 -38
- package/dist/components/Sidebar.d.ts +36 -4
- package/dist/components/Sidebar.js +37 -12
- package/dist/components/SortableList.d.ts +45 -0
- package/dist/components/SortableList.js +134 -0
- package/dist/components/Spinner.d.ts +7 -1
- package/dist/components/Spinner.js +7 -1
- package/dist/components/Stat.d.ts +28 -3
- package/dist/components/Stat.js +13 -3
- package/dist/components/States.d.ts +7 -1
- package/dist/components/States.js +7 -1
- package/dist/components/StatusPill.d.ts +14 -3
- package/dist/components/StatusPill.js +11 -3
- package/dist/components/Steps.js +2 -1
- package/dist/components/Table.d.ts +16 -2
- package/dist/components/Table.js +8 -4
- package/dist/components/TableControls.js +18 -58
- package/dist/components/TableOverflowProbe.d.ts +12 -0
- package/dist/components/TableOverflowProbe.js +27 -0
- package/dist/components/Tabs.d.ts +2 -1
- package/dist/components/Tabs.js +1 -0
- package/dist/components/TagInput.d.ts +67 -0
- package/dist/components/TagInput.js +342 -0
- package/dist/components/Textarea.d.ts +5 -0
- package/dist/components/Textarea.js +2 -2
- package/dist/components/TimePicker.d.ts +80 -0
- package/dist/components/TimePicker.js +347 -0
- package/dist/components/Toast.js +3 -2
- package/dist/components/Tooltip.d.ts +8 -4
- package/dist/components/Tooltip.js +24 -21
- package/dist/components/Tree.d.ts +8 -0
- package/dist/components/Tree.js +11 -5
- package/dist/display-preferences-model.d.ts +53 -0
- package/dist/display-preferences-model.js +64 -0
- package/dist/emoji.cjs +28 -35
- package/dist/filter-model.d.ts +59 -3
- package/dist/filter-model.js +67 -2
- package/dist/hooks/useChangeHighlight.d.ts +33 -0
- package/dist/hooks/useChangeHighlight.js +44 -0
- package/dist/hooks/useDelayedPending.d.ts +22 -0
- package/dist/hooks/useDelayedPending.js +35 -0
- package/dist/hooks/useDialog.d.ts +5 -0
- package/dist/hooks/useDialog.js +3 -2
- package/dist/hooks/useOptimisticValue.d.ts +51 -0
- package/dist/hooks/useOptimisticValue.js +61 -0
- package/dist/hooks/useReducedMotion.d.ts +4 -1
- package/dist/hooks/useReducedMotion.js +7 -1
- package/dist/hooks/useResolvedFilterLabels.d.ts +15 -0
- package/dist/hooks/useResolvedFilterLabels.js +34 -0
- package/dist/hooks/useVirtualRows.d.ts +21 -2
- package/dist/hooks/useVirtualRows.js +30 -3
- package/dist/icons/Icon.d.ts +1 -1
- package/dist/index.cjs +18977 -13378
- package/dist/index.d.cts +3065 -664
- package/dist/index.d.ts +46 -16
- package/dist/index.js +149 -7
- package/dist/labels-context.d.ts +93 -3
- package/dist/motion-timing.d.ts +8 -0
- package/dist/motion-timing.js +8 -0
- package/dist/overlay-stack.d.ts +6 -0
- package/dist/overlay-stack.js +13 -0
- package/dist/qr-model.d.ts +65 -0
- package/dist/qr-model.js +323 -0
- package/dist/relationship-graph-model.d.ts +78 -3
- package/dist/relationship-graph-model.js +112 -5
- package/dist/reorder.d.ts +30 -0
- package/dist/reorder.js +74 -0
- package/dist/rich-text.cjs +4 -2
- package/dist/scheduling-resource-model.d.ts +76 -0
- package/dist/scheduling-resource-model.js +74 -0
- package/dist/search-suggest-model.js +3 -1
- package/dist/shell-context.d.ts +11 -0
- package/dist/shell-context.js +7 -0
- package/dist/time-field-model.d.ts +46 -0
- package/dist/time-field-model.js +152 -0
- package/dist/toast-store.d.ts +17 -1
- package/dist/toast-store.js +23 -7
- package/package.json +2 -1
|
@@ -1,19 +1,40 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { HTMLAttributes } from 'react';
|
|
3
|
-
import { ComboboxOption } from '../combobox-model.js';
|
|
2
|
+
import { HTMLAttributes, AriaAttributes } from 'react';
|
|
3
|
+
import { ComboboxOption, ComboboxGroup } from '../combobox-model.js';
|
|
4
|
+
import { Placement } from '../overlay-position.js';
|
|
4
5
|
|
|
5
6
|
interface ComboboxProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
6
|
-
options
|
|
7
|
+
/** The options, and groups of options (`{ label, options }`, HAR-1588). */
|
|
8
|
+
options: readonly (ComboboxOption | ComboboxGroup)[];
|
|
7
9
|
value?: string;
|
|
8
10
|
defaultValue?: string;
|
|
9
11
|
onValueChange?: (value: string, option: ComboboxOption) => void;
|
|
12
|
+
/** The field's name. Not used as its name when `aria-labelledby` points at a visible label. */
|
|
10
13
|
label: string;
|
|
11
14
|
placeholder?: string;
|
|
15
|
+
/** Shown in the open list when nothing matches (outside the listbox, so it is never an option). */
|
|
12
16
|
emptyLabel: string;
|
|
13
17
|
name?: string;
|
|
14
18
|
disabled?: boolean;
|
|
19
|
+
/** Ids of the visible label(s) that name the field; replaces `label` as its name. */
|
|
20
|
+
'aria-labelledby'?: string;
|
|
21
|
+
/** Ids of hint or error text; lands on the input. */
|
|
22
|
+
'aria-describedby'?: string;
|
|
23
|
+
'aria-invalid'?: AriaAttributes['aria-invalid'];
|
|
24
|
+
/** Id of the input itself (for a `<label for>`); `id` stays on the wrapper. */
|
|
25
|
+
inputId?: string;
|
|
26
|
+
/** Preferred side of the list. Default `'bottom-start'`; it flips when there is no room. */
|
|
27
|
+
placement?: Placement;
|
|
15
28
|
}
|
|
16
|
-
/**
|
|
17
|
-
|
|
29
|
+
/**
|
|
30
|
+
* An editable combobox (HAR-1588): type to filter, choose with the keyboard or the pointer. It
|
|
31
|
+
* follows the WAI-ARIA APG combobox with a listbox popup, at parity with `Select`: the list is a
|
|
32
|
+
* top-layer popover placed with `useAnchoredPosition`, so a Drawer, a Popover or an
|
|
33
|
+
* `overflow: hidden` cell never clips it; ↑ ↓ PageUp PageDown move (Home and End too while an
|
|
34
|
+
* option is active), disabled options are skipped and the list does not wrap; Enter chooses;
|
|
35
|
+
* Escape closes the list and puts the chosen option's text back, as leaving the field does.
|
|
36
|
+
* Groups render as `role="group"`; the no-match row sits outside the listbox.
|
|
37
|
+
*/
|
|
38
|
+
declare function Combobox({ options, value, defaultValue, onValueChange, label, placeholder, emptyLabel, name, disabled, className, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, 'aria-invalid': ariaInvalid, inputId, placement, ...props }: ComboboxProps): react.JSX.Element;
|
|
18
39
|
|
|
19
|
-
export { Combobox, ComboboxOption, type ComboboxProps };
|
|
40
|
+
export { Combobox, ComboboxGroup, ComboboxOption, type ComboboxProps };
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { Fragment, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { cx } from "../cx.js";
|
|
5
|
-
import {
|
|
5
|
+
import { filterComboboxItems } from "../combobox-model.js";
|
|
6
|
+
import { useAnchoredPosition, zoomOf } from "../hooks/useAnchoredPosition.js";
|
|
7
|
+
import { CheckIcon } from "../icons/components.js";
|
|
8
|
+
import { buildSelectModel, firstEnabled, lastEnabled, moveActive } from "../select-model.js";
|
|
9
|
+
const useIsomorphicLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : useEffect;
|
|
10
|
+
const OFFSET = 4;
|
|
11
|
+
const EDGE = 8;
|
|
12
|
+
const MAX_HEIGHT = 320;
|
|
6
13
|
function Combobox({
|
|
7
14
|
options,
|
|
8
15
|
value,
|
|
@@ -14,105 +21,235 @@ function Combobox({
|
|
|
14
21
|
name,
|
|
15
22
|
disabled,
|
|
16
23
|
className,
|
|
24
|
+
"aria-labelledby": ariaLabelledBy,
|
|
25
|
+
"aria-describedby": ariaDescribedBy,
|
|
26
|
+
"aria-invalid": ariaInvalid,
|
|
27
|
+
inputId,
|
|
28
|
+
placement = "bottom-start",
|
|
17
29
|
...props
|
|
18
30
|
}) {
|
|
19
|
-
const
|
|
20
|
-
const listboxId = `${
|
|
31
|
+
const uid = useId();
|
|
32
|
+
const listboxId = `${uid}-listbox`;
|
|
33
|
+
const optionId = (index) => `${listboxId}-${index}`;
|
|
21
34
|
const rootRef = useRef(null);
|
|
35
|
+
const inputRef = useRef(null);
|
|
36
|
+
const popupRef = useRef(null);
|
|
37
|
+
const listRef = useRef(null);
|
|
22
38
|
const [internalValue, setInternalValue] = useState(defaultValue ?? "");
|
|
23
39
|
const selectedValue = value ?? internalValue;
|
|
24
|
-
const
|
|
40
|
+
const all = useMemo(() => buildSelectModel(options).all, [options]);
|
|
41
|
+
const selected = all.find((entry) => entry.option.value === selectedValue)?.option;
|
|
25
42
|
const [query, setQuery] = useState(selected?.label ?? "");
|
|
43
|
+
const [filter, setFilter] = useState("");
|
|
26
44
|
const [open, setOpen] = useState(false);
|
|
27
|
-
const [activeIndex, setActiveIndex] = useState(
|
|
28
|
-
const
|
|
29
|
-
const
|
|
45
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
46
|
+
const model = useMemo(() => buildSelectModel(filterComboboxItems(options, open ? filter : "")), [open, options, filter]);
|
|
47
|
+
const entries = model.entries;
|
|
48
|
+
const active = activeIndex >= 0 ? entries[activeIndex] : void 0;
|
|
49
|
+
const selectedLabel = () => all.find((entry) => entry.option.value === selectedValue)?.option.label ?? "";
|
|
30
50
|
useEffect(() => {
|
|
31
|
-
if (!open) setQuery(
|
|
51
|
+
if (!open) setQuery(selectedLabel());
|
|
32
52
|
}, [open, options, selectedValue]);
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
53
|
+
const openList = (target = "selected", list = entries) => {
|
|
54
|
+
if (disabled) return;
|
|
55
|
+
const chosen = list.findIndex((entry) => entry.option.value === selectedValue && !entry.disabled);
|
|
56
|
+
setActiveIndex(target === "last" ? lastEnabled(list) : target === "first" || chosen < 0 ? firstEnabled(list) : chosen);
|
|
57
|
+
setOpen(true);
|
|
58
|
+
};
|
|
59
|
+
const select = (entry) => {
|
|
60
|
+
if (!entry || entry.disabled) return;
|
|
61
|
+
const option = entry.option;
|
|
35
62
|
if (value == null) setInternalValue(option.value);
|
|
36
63
|
setQuery(option.label);
|
|
64
|
+
setFilter("");
|
|
37
65
|
setOpen(false);
|
|
66
|
+
setActiveIndex(-1);
|
|
38
67
|
onValueChange?.(option.value, option);
|
|
39
68
|
};
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (!filtered[next]?.disabled) break;
|
|
46
|
-
}
|
|
47
|
-
setActiveIndex(next);
|
|
69
|
+
const restore = () => {
|
|
70
|
+
setFilter("");
|
|
71
|
+
setOpen(false);
|
|
72
|
+
setActiveIndex(-1);
|
|
73
|
+
setQuery(selectedLabel());
|
|
48
74
|
};
|
|
49
75
|
const handleKeyDown = (event) => {
|
|
50
|
-
if (event.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
76
|
+
if (event.nativeEvent.isComposing || event.keyCode === 229) return;
|
|
77
|
+
const { key, altKey } = event;
|
|
78
|
+
switch (key) {
|
|
79
|
+
case "ArrowDown":
|
|
80
|
+
case "ArrowUp":
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
if (!open) {
|
|
83
|
+
openList(key === "ArrowUp" && !altKey ? "last" : "selected");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (altKey) return;
|
|
87
|
+
setActiveIndex((index) => moveActive(entries, index, key === "ArrowDown" ? 1 : -1));
|
|
88
|
+
return;
|
|
89
|
+
case "PageDown":
|
|
90
|
+
case "PageUp":
|
|
91
|
+
if (!open) return;
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
setActiveIndex((index) => moveActive(entries, index, key === "PageDown" ? 10 : -10));
|
|
94
|
+
return;
|
|
95
|
+
case "Home":
|
|
96
|
+
case "End":
|
|
97
|
+
if (!open || activeIndex < 0) return;
|
|
98
|
+
event.preventDefault();
|
|
99
|
+
setActiveIndex(key === "Home" ? firstEnabled(entries) : lastEnabled(entries));
|
|
100
|
+
return;
|
|
101
|
+
case "Enter":
|
|
102
|
+
if (open && active) {
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
select(active);
|
|
105
|
+
}
|
|
106
|
+
return;
|
|
107
|
+
case "Escape":
|
|
108
|
+
if (open || query !== selectedLabel()) {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
event.stopPropagation();
|
|
111
|
+
restore();
|
|
112
|
+
}
|
|
113
|
+
return;
|
|
114
|
+
default:
|
|
60
115
|
}
|
|
61
116
|
};
|
|
62
117
|
const handleBlur = (event) => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
setQuery(options.find((option) => option.value === selectedValue)?.label ?? "");
|
|
66
|
-
}
|
|
118
|
+
const next = event.relatedTarget;
|
|
119
|
+
if (!rootRef.current?.contains(next)) restore();
|
|
67
120
|
};
|
|
68
121
|
const handleChange = (event) => {
|
|
69
|
-
|
|
70
|
-
|
|
122
|
+
const text = event.target.value;
|
|
123
|
+
setQuery(text);
|
|
124
|
+
setFilter(text);
|
|
125
|
+
const list = buildSelectModel(filterComboboxItems(options, text)).entries;
|
|
126
|
+
setActiveIndex(firstEnabled(list));
|
|
71
127
|
setOpen(true);
|
|
72
128
|
};
|
|
129
|
+
useIsomorphicLayoutEffect(() => {
|
|
130
|
+
if (open && activeIndex >= entries.length) setActiveIndex(firstEnabled(entries));
|
|
131
|
+
}, [open, entries.length]);
|
|
132
|
+
useIsomorphicLayoutEffect(() => {
|
|
133
|
+
const popup = popupRef.current;
|
|
134
|
+
const input = inputRef.current;
|
|
135
|
+
if (!popup || !input) return;
|
|
136
|
+
const isOpen = () => {
|
|
137
|
+
try {
|
|
138
|
+
return popup.matches(":popover-open");
|
|
139
|
+
} catch {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
if (open) {
|
|
144
|
+
const zoom = zoomOf(input);
|
|
145
|
+
const r = input.getBoundingClientRect();
|
|
146
|
+
const room = Math.max(r.top, window.innerHeight - r.bottom) / zoom - OFFSET - EDGE;
|
|
147
|
+
popup.style.minWidth = `${Math.round(r.width / zoom)}px`;
|
|
148
|
+
popup.style.maxHeight = `${Math.max(96, Math.min(MAX_HEIGHT, Math.floor(room)))}px`;
|
|
149
|
+
try {
|
|
150
|
+
if (!isOpen()) popup.showPopover();
|
|
151
|
+
} catch {
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
try {
|
|
155
|
+
if (isOpen()) popup.hidePopover();
|
|
156
|
+
} catch {
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}, [open]);
|
|
160
|
+
useAnchoredPosition(inputRef, popupRef, { open, placement, offset: OFFSET, padding: EDGE });
|
|
161
|
+
useIsomorphicLayoutEffect(() => {
|
|
162
|
+
const list = listRef.current;
|
|
163
|
+
if (!open || !list || activeIndex < 0) return;
|
|
164
|
+
const el = list.ownerDocument.getElementById(optionId(activeIndex));
|
|
165
|
+
if (!el || !list.contains(el)) return;
|
|
166
|
+
const top = el.offsetTop;
|
|
167
|
+
const bottom = top + el.offsetHeight;
|
|
168
|
+
if (top < list.scrollTop) list.scrollTop = top;
|
|
169
|
+
else if (bottom > list.scrollTop + list.clientHeight) list.scrollTop = bottom - list.clientHeight;
|
|
170
|
+
}, [open, activeIndex]);
|
|
171
|
+
const popoverAttr = { popover: "manual" };
|
|
172
|
+
const invalid = ariaInvalid != null && ariaInvalid !== false && ariaInvalid !== "false";
|
|
173
|
+
const renderEntry = (entry) => /* @__PURE__ */ jsxs(
|
|
174
|
+
"div",
|
|
175
|
+
{
|
|
176
|
+
id: optionId(entry.index),
|
|
177
|
+
className: "uix-listbox__option",
|
|
178
|
+
role: "option",
|
|
179
|
+
"aria-selected": entry.option.value === selectedValue,
|
|
180
|
+
"aria-disabled": entry.disabled || void 0,
|
|
181
|
+
"data-active": open && entry.index === activeIndex || void 0,
|
|
182
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
183
|
+
onPointerMove: () => {
|
|
184
|
+
if (entry.index !== activeIndex && !entry.disabled) setActiveIndex(entry.index);
|
|
185
|
+
},
|
|
186
|
+
onClick: () => select(entry),
|
|
187
|
+
children: [
|
|
188
|
+
/* @__PURE__ */ jsx("span", { className: "uix-listbox__text", children: /* @__PURE__ */ jsx("span", { className: "uix-listbox__label", children: entry.option.label }) }),
|
|
189
|
+
/* @__PURE__ */ jsx("span", { className: "uix-listbox__check", "aria-hidden": "true", children: entry.option.value === selectedValue && /* @__PURE__ */ jsx(CheckIcon, { size: "sm" }) })
|
|
190
|
+
]
|
|
191
|
+
},
|
|
192
|
+
`${entry.option.value}-${entry.index}`
|
|
193
|
+
);
|
|
73
194
|
return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: cx("uix-combobox", className), onBlur: handleBlur, ...props, children: [
|
|
74
195
|
name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: selectedValue }),
|
|
75
196
|
/* @__PURE__ */ jsx(
|
|
76
197
|
"input",
|
|
77
198
|
{
|
|
199
|
+
ref: inputRef,
|
|
200
|
+
id: inputId,
|
|
78
201
|
className: "uix-input",
|
|
79
202
|
role: "combobox",
|
|
80
|
-
"aria-label": label,
|
|
203
|
+
"aria-label": ariaLabelledBy ? void 0 : label,
|
|
204
|
+
"aria-labelledby": ariaLabelledBy,
|
|
205
|
+
"aria-describedby": ariaDescribedBy,
|
|
206
|
+
"aria-invalid": invalid || void 0,
|
|
81
207
|
"aria-autocomplete": "list",
|
|
82
208
|
"aria-expanded": open,
|
|
83
209
|
"aria-controls": listboxId,
|
|
84
|
-
"aria-activedescendant": open &&
|
|
210
|
+
"aria-activedescendant": open && active ? optionId(activeIndex) : void 0,
|
|
211
|
+
autoComplete: "off",
|
|
212
|
+
spellCheck: false,
|
|
85
213
|
value: query,
|
|
86
214
|
placeholder,
|
|
87
215
|
disabled,
|
|
88
216
|
onChange: handleChange,
|
|
89
217
|
onFocus: () => {
|
|
90
218
|
setQuery("");
|
|
91
|
-
|
|
92
|
-
setActiveIndex(Math.max(0, options.findIndex((option) => option.value === selectedValue)));
|
|
219
|
+
openList("selected", buildSelectModel(options).entries);
|
|
93
220
|
},
|
|
94
221
|
onKeyDown: handleKeyDown
|
|
95
222
|
}
|
|
96
223
|
),
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
224
|
+
/* @__PURE__ */ jsxs(
|
|
225
|
+
"div",
|
|
226
|
+
{
|
|
227
|
+
ref: popupRef,
|
|
228
|
+
className: "uix-select__popup uix-combobox__popup",
|
|
229
|
+
hidden: !open,
|
|
230
|
+
...popoverAttr,
|
|
231
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
232
|
+
children: [
|
|
233
|
+
/* @__PURE__ */ jsx(
|
|
234
|
+
"div",
|
|
235
|
+
{
|
|
236
|
+
ref: listRef,
|
|
237
|
+
id: listboxId,
|
|
238
|
+
role: "listbox",
|
|
239
|
+
"aria-label": label,
|
|
240
|
+
className: "uix-listbox uix-select__listbox",
|
|
241
|
+
hidden: entries.length === 0 || void 0,
|
|
242
|
+
children: model.sections.map((section, i) => section.label != null ? /* @__PURE__ */ jsxs("div", { role: "group", className: "uix-listbox__group", "aria-labelledby": `${uid}-group-${i}`, "aria-disabled": section.disabled || void 0, children: [
|
|
243
|
+
/* @__PURE__ */ jsx("div", { id: `${uid}-group-${i}`, role: "presentation", className: "uix-listbox__group-label", children: section.label }),
|
|
244
|
+
section.entries.map(renderEntry)
|
|
245
|
+
] }, `g${i}`) : /* @__PURE__ */ jsx(Fragment, { children: section.entries.map(renderEntry) }, `s${i}`))
|
|
246
|
+
}
|
|
247
|
+
),
|
|
248
|
+
entries.length === 0 && /* @__PURE__ */ jsx("div", { className: "uix-select__state", children: emptyLabel })
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
),
|
|
252
|
+
/* @__PURE__ */ jsx("span", { className: "uix-visually-hidden", role: "status", "aria-live": "polite", children: open && entries.length === 0 ? emptyLabel : "" })
|
|
116
253
|
] });
|
|
117
254
|
}
|
|
118
255
|
export {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, HTMLAttributes, InputHTMLAttributes } from 'react';
|
|
3
|
+
import { CommandPaletteItem } from '../command-palette-model.js';
|
|
3
4
|
|
|
4
5
|
interface CommandPaletteProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
6
|
/** TENSOR RX-125 (UIX-04): translatable; English default. */
|
|
@@ -12,6 +13,40 @@ interface CommandPaletteProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
12
13
|
/** Props for the search input (value/onChange/placeholder wired by the consumer). */
|
|
13
14
|
inputProps?: InputHTMLAttributes<HTMLInputElement>;
|
|
14
15
|
children?: ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* Items mode (HAR-1378): pass the commands and the palette filters them itself (case and
|
|
18
|
+
* diacritics folded, best match first), groups them, moves the active one with ↑ / ↓ (Home / End
|
|
19
|
+
* while the query is empty) through `aria-activedescendant`, and runs it on Enter or a click.
|
|
20
|
+
* Without `items`, `children` render as before and the consumer wires everything.
|
|
21
|
+
*/
|
|
22
|
+
items?: readonly CommandPaletteItem[];
|
|
23
|
+
/** Items mode: the query (controlled). Pair with `onQueryChange`. */
|
|
24
|
+
query?: string;
|
|
25
|
+
/** Items mode: the query as it changes (also when the palette clears it on close). */
|
|
26
|
+
onQueryChange?: (query: string) => void;
|
|
27
|
+
/** Items mode: what an empty query shows above all items, under the `recentLabel` heading. */
|
|
28
|
+
recent?: readonly CommandPaletteItem[];
|
|
29
|
+
/** Items mode: your own matching instead of the built-in one (`filterCommandItems`). */
|
|
30
|
+
filter?: (items: readonly CommandPaletteItem[], query: string) => CommandPaletteItem[];
|
|
31
|
+
/** Items mode: called with every chosen item, after its own `onSelect`, e.g. to record it as recent. */
|
|
32
|
+
onItemSelect?: (item: CommandPaletteItem) => void;
|
|
33
|
+
/** Items mode: follow an item's `href` with your router. Default: the browser goes there. */
|
|
34
|
+
onNavigate?: (href: string, item: CommandPaletteItem) => void;
|
|
35
|
+
/** Items mode: shown when nothing matches. Default: `UixLabelsProvider` `commandPalette.empty`, then "No results". */
|
|
36
|
+
emptyLabel?: ReactNode;
|
|
37
|
+
/** Items mode: the heading of `recent`. Default: `commandPalette.recent`, then "Recent". */
|
|
38
|
+
recentLabel?: string;
|
|
39
|
+
/** Items mode: the input's placeholder. */
|
|
40
|
+
placeholder?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Items mode: host the palette in a modal native `<dialog>` (focus stays inside, Escape and a
|
|
43
|
+
* click outside close it, focus returns to the opener). Closing it clears the query. Without
|
|
44
|
+
* `open`, the palette renders in place.
|
|
45
|
+
*/
|
|
46
|
+
open?: boolean;
|
|
47
|
+
onOpenChange?: (open: boolean) => void;
|
|
48
|
+
/** Items mode: render at most this many found items (the count still says how many were found). Default 100. */
|
|
49
|
+
limit?: number;
|
|
15
50
|
}
|
|
16
51
|
/**
|
|
17
52
|
* ⌘K command palette surface over `.uix-cmdk`. Presentational: mount it inside a
|
|
@@ -23,7 +58,7 @@ interface CommandPaletteProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
23
58
|
* popover it sits in `[data-uix-instant]`: it opens and closes with no animation, without the
|
|
24
59
|
* consumer knowing the attribute (or the older `data-uix-cmdk-dialog`).
|
|
25
60
|
*/
|
|
26
|
-
declare function CommandPalette(
|
|
61
|
+
declare function CommandPalette(props: CommandPaletteProps): react.JSX.Element;
|
|
27
62
|
interface CommandGroupProps {
|
|
28
63
|
label?: ReactNode;
|
|
29
64
|
children?: ReactNode;
|