@crisp-ui-kit/crisp 0.7.1 → 0.7.2
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.
|
@@ -64,6 +64,12 @@ function Chip({ opt }) {
|
|
|
64
64
|
* click (the menu stays open). Keyboard: ↑/↓ move, Enter toggles, Esc closes.
|
|
65
65
|
*/
|
|
66
66
|
function MultiSelect({ options, value: valueProp, defaultValue, onValueChange, placeholder = "Select…", searchable = true, searchPlaceholder = "Search…", disabled, className, "aria-label": ariaLabel, ...rest }) {
|
|
67
|
+
// Virtual focus: DOM focus stays on the trigger (or the search field) and the
|
|
68
|
+
// active option is named by `aria-activedescendant`. `data-highlighted` is a
|
|
69
|
+
// styling hook only -- a screen reader cannot see it.
|
|
70
|
+
const autoId = React.useId();
|
|
71
|
+
const listboxId = `${autoId}-listbox`;
|
|
72
|
+
const optionId = (i) => `${autoId}-opt-${i}`;
|
|
67
73
|
const [open, setOpen] = React.useState(false);
|
|
68
74
|
const [up, setUp] = React.useState(false);
|
|
69
75
|
const [pos, setPos] = React.useState({});
|
|
@@ -105,6 +111,9 @@ function MultiSelect({ options, value: valueProp, defaultValue, onValueChange, p
|
|
|
105
111
|
setOpen(false);
|
|
106
112
|
triggerRef.current?.focus({ preventScroll: true });
|
|
107
113
|
};
|
|
114
|
+
const activeId = open && highlight >= 0 && highlight < filtered.length
|
|
115
|
+
? optionId(highlight)
|
|
116
|
+
: undefined;
|
|
108
117
|
const toggle = (v) => {
|
|
109
118
|
const next = selectedSet.has(v)
|
|
110
119
|
? value.filter((x) => x !== v)
|
|
@@ -143,19 +152,19 @@ function MultiSelect({ options, value: valueProp, defaultValue, onValueChange, p
|
|
|
143
152
|
document.addEventListener("pointerdown", onDown);
|
|
144
153
|
return () => document.removeEventListener("pointerdown", onDown);
|
|
145
154
|
}, [open]);
|
|
146
|
-
return ((0, jsx_runtime_1.jsxs)("div", { ref: rootRef, className: (0, multiselect_recipe_1.multiselectRecipe)({ className }), ...rest, children: [(0, jsx_runtime_1.jsxs)("button", { ref: triggerRef, type: "button", "aria-haspopup": "listbox", "aria-expanded": open, "aria-label": ariaLabel, disabled: disabled, "data-open": open ? "" : undefined, className: "multiselect-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: (e) => {
|
|
155
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: rootRef, className: (0, multiselect_recipe_1.multiselectRecipe)({ className }), ...rest, children: [(0, jsx_runtime_1.jsxs)("button", { ref: triggerRef, type: "button", role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": open ? listboxId : undefined, "aria-activedescendant": searchable ? undefined : activeId, "aria-label": ariaLabel, disabled: disabled, "data-open": open ? "" : undefined, className: "multiselect-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: (e) => {
|
|
147
156
|
if (open && !searchable)
|
|
148
157
|
onNavKeys(e);
|
|
149
158
|
else if (!open && (e.key === "ArrowDown" || e.key === "Enter")) {
|
|
150
159
|
e.preventDefault();
|
|
151
160
|
openMenu();
|
|
152
161
|
}
|
|
153
|
-
}, children: [(0, jsx_runtime_1.jsx)("span", { className: "multiselect-chips", children: selectedOptions.length === 0 ? ((0, jsx_runtime_1.jsx)("span", { className: "multiselect-placeholder", children: placeholder })) : (selectedOptions.map((o) => (0, jsx_runtime_1.jsx)(Chip, { opt: o }, o.value))) }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "multiselect-chevron", size: 16, strokeWidth: 1.75 })] }), open && ((0, jsx_runtime_1.jsxs)("div", { className: "multiselect-listbox", role: "listbox", "aria-multiselectable": "true", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && ((0, jsx_runtime_1.jsxs)("div", { className: "multiselect-search", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 15, strokeWidth: 1.75 }), (0, jsx_runtime_1.jsx)("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, value: query, onChange: (e) => {
|
|
162
|
+
}, children: [(0, jsx_runtime_1.jsx)("span", { className: "multiselect-chips", children: selectedOptions.length === 0 ? ((0, jsx_runtime_1.jsx)("span", { className: "multiselect-placeholder", children: placeholder })) : (selectedOptions.map((o) => (0, jsx_runtime_1.jsx)(Chip, { opt: o }, o.value))) }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "multiselect-chevron", size: 16, strokeWidth: 1.75 })] }), open && ((0, jsx_runtime_1.jsxs)("div", { id: listboxId, className: "multiselect-listbox", role: "listbox", "aria-multiselectable": "true", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && ((0, jsx_runtime_1.jsxs)("div", { className: "multiselect-search", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 15, strokeWidth: 1.75 }), (0, jsx_runtime_1.jsx)("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, "aria-controls": listboxId, "aria-activedescendant": activeId, value: query, onChange: (e) => {
|
|
154
163
|
setQuery(e.target.value);
|
|
155
164
|
setHighlight(0);
|
|
156
165
|
}, onKeyDown: onNavKeys })] })), filtered.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "multiselect-empty", children: "No results" })) : (filtered.map((opt, i) => {
|
|
157
166
|
const sel = selectedSet.has(opt.value);
|
|
158
|
-
return ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "option", "aria-selected": sel, "data-highlighted": i === highlight ? "" : undefined, className: "multiselect-option", onClick: () => toggle(opt.value), onMouseEnter: () => setHighlight(i), children: [(0, jsx_runtime_1.jsx)("span", { className: "multiselect-option-chip", children: (0, jsx_runtime_1.jsx)(Chip, { opt: opt }) }), (0, jsx_runtime_1.jsx)("span", { className: "multiselect-check", children: sel && (0, jsx_runtime_1.jsx)(lucide_react_1.Check, { size: 12, strokeWidth: 3 }) })] }, opt.value));
|
|
167
|
+
return ((0, jsx_runtime_1.jsxs)("button", { type: "button", id: optionId(i), role: "option", "aria-selected": sel, tabIndex: -1, "data-highlighted": i === highlight ? "" : undefined, className: "multiselect-option", onClick: () => toggle(opt.value), onMouseEnter: () => setHighlight(i), children: [(0, jsx_runtime_1.jsx)("span", { className: "multiselect-option-chip", children: (0, jsx_runtime_1.jsx)(Chip, { opt: opt }) }), (0, jsx_runtime_1.jsx)("span", { className: "multiselect-check", children: sel && (0, jsx_runtime_1.jsx)(lucide_react_1.Check, { size: 12, strokeWidth: 3 }) })] }, opt.value));
|
|
159
168
|
}))] }))] }));
|
|
160
169
|
}
|
|
161
170
|
MultiSelect.displayName = "MultiSelect";
|
|
@@ -51,6 +51,14 @@ function optionText(o) {
|
|
|
51
51
|
* Esc close, Home/End jump, opens upward when tight. Controlled or uncontrolled.
|
|
52
52
|
*/
|
|
53
53
|
function Select({ options, value, defaultValue, onValueChange, placeholder = "Select…", variant = "default", width = "full", searchable, searchPlaceholder = "Search…", disabled, className, "aria-label": ariaLabel, id, ...rest }) {
|
|
54
|
+
// Virtual focus: DOM focus stays on the trigger (or the search field), and the
|
|
55
|
+
// active option is named by `aria-activedescendant`. That is the only thing a
|
|
56
|
+
// screen reader has to go on -- `data-highlighted` is invisible to it -- so the
|
|
57
|
+
// ids below have to resolve to the element the highlight is actually drawn on.
|
|
58
|
+
const autoId = React.useId();
|
|
59
|
+
const baseId = id ?? autoId;
|
|
60
|
+
const listboxId = `${baseId}-listbox`;
|
|
61
|
+
const optionId = (i) => `${baseId}-opt-${i}`;
|
|
54
62
|
const [internal, setInternal] = React.useState(defaultValue);
|
|
55
63
|
const selected = value ?? internal;
|
|
56
64
|
const [open, setOpen] = React.useState(false);
|
|
@@ -70,6 +78,9 @@ function Select({ options, value, defaultValue, onValueChange, placeholder = "Se
|
|
|
70
78
|
const enabledIndexes = filtered
|
|
71
79
|
.map((o, i) => (o.disabled ? -1 : i))
|
|
72
80
|
.filter((i) => i >= 0);
|
|
81
|
+
const activeId = open && highlight >= 0 && highlight < filtered.length
|
|
82
|
+
? optionId(highlight)
|
|
83
|
+
: undefined;
|
|
73
84
|
const openMenu = () => {
|
|
74
85
|
if (disabled)
|
|
75
86
|
return;
|
|
@@ -169,12 +180,12 @@ function Select({ options, value, defaultValue, onValueChange, placeholder = "Se
|
|
|
169
180
|
document.addEventListener("pointerdown", onDown);
|
|
170
181
|
return () => document.removeEventListener("pointerdown", onDown);
|
|
171
182
|
}, [open]);
|
|
172
|
-
return ((0, jsx_runtime_1.jsxs)("div", { ref: rootRef, className: (0, select_recipe_1.selectRecipe)({ variant, width, className }), ...rest, children: [(0, jsx_runtime_1.jsxs)("button", { ref: triggerRef, type: "button", id: id, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-label": ariaLabel, disabled: disabled, "data-open": open ? "" : undefined, className: "select-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: onTriggerKeyDown, children: [(0, jsx_runtime_1.jsx)("span", { className: "select-value", children: selectedOption ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [selectedOption.color && ((0, jsx_runtime_1.jsx)("span", { className: "select-option-dot", style: { background: selectedOption.color } })), selectedOption.label] })) : ((0, jsx_runtime_1.jsx)("span", { className: "select-placeholder", children: placeholder })) }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "select-chevron", size: 16, strokeWidth: 1.75 })] }), open && ((0, jsx_runtime_1.jsxs)("div", { className: "select-listbox", role: "listbox", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && ((0, jsx_runtime_1.jsxs)("div", { className: "select-search", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 15, strokeWidth: 1.75 }), (0, jsx_runtime_1.jsx)("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, value: query, onChange: (e) => {
|
|
183
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: rootRef, className: (0, select_recipe_1.selectRecipe)({ variant, width, className }), ...rest, children: [(0, jsx_runtime_1.jsxs)("button", { ref: triggerRef, type: "button", id: id, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": open ? listboxId : undefined, "aria-activedescendant": searchable ? undefined : activeId, "aria-label": ariaLabel, disabled: disabled, "data-open": open ? "" : undefined, className: "select-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: onTriggerKeyDown, children: [(0, jsx_runtime_1.jsx)("span", { className: "select-value", children: selectedOption ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [selectedOption.color && ((0, jsx_runtime_1.jsx)("span", { className: "select-option-dot", style: { background: selectedOption.color } })), selectedOption.label] })) : ((0, jsx_runtime_1.jsx)("span", { className: "select-placeholder", children: placeholder })) }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { className: "select-chevron", size: 16, strokeWidth: 1.75 })] }), open && ((0, jsx_runtime_1.jsxs)("div", { id: listboxId, className: "select-listbox", role: "listbox", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && ((0, jsx_runtime_1.jsxs)("div", { className: "select-search", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Search, { size: 15, strokeWidth: 1.75 }), (0, jsx_runtime_1.jsx)("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, "aria-controls": listboxId, "aria-activedescendant": activeId, value: query, onChange: (e) => {
|
|
173
184
|
setQuery(e.target.value);
|
|
174
185
|
setHighlight(0);
|
|
175
186
|
}, onKeyDown: onNavKeys })] })), filtered.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "select-empty", children: "No results" })) : (filtered.map((opt, i) => {
|
|
176
187
|
const isSel = opt.value === selected;
|
|
177
|
-
return ((0, jsx_runtime_1.jsxs)("button", { type: "button", role: "option", "aria-selected": isSel, disabled: opt.disabled, "data-disabled": opt.disabled ? "" : undefined, "data-highlighted": i === highlight ? "" : undefined, className: "select-option", onClick: () => pick(opt), onMouseEnter: () => setHighlight(i), children: [opt.color && ((0, jsx_runtime_1.jsx)("span", { className: "select-option-dot", style: { background: opt.color } })), (0, jsx_runtime_1.jsx)("span", { className: "select-option-label", children: opt.label }), isSel && ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "select-option-check", size: 15, strokeWidth: 2 }))] }, opt.value));
|
|
188
|
+
return ((0, jsx_runtime_1.jsxs)("button", { type: "button", id: optionId(i), role: "option", "aria-selected": isSel, tabIndex: -1, disabled: opt.disabled, "data-disabled": opt.disabled ? "" : undefined, "data-highlighted": i === highlight ? "" : undefined, className: "select-option", onClick: () => pick(opt), onMouseEnter: () => setHighlight(i), children: [opt.color && ((0, jsx_runtime_1.jsx)("span", { className: "select-option-dot", style: { background: opt.color } })), (0, jsx_runtime_1.jsx)("span", { className: "select-option-label", children: opt.label }), isSel && ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "select-option-check", size: 15, strokeWidth: 2 }))] }, opt.value));
|
|
178
189
|
}))] }))] }));
|
|
179
190
|
}
|
|
180
191
|
Select.displayName = "Select";
|
|
@@ -28,6 +28,12 @@ function Chip({ opt }) {
|
|
|
28
28
|
* click (the menu stays open). Keyboard: ↑/↓ move, Enter toggles, Esc closes.
|
|
29
29
|
*/
|
|
30
30
|
export function MultiSelect({ options, value: valueProp, defaultValue, onValueChange, placeholder = "Select…", searchable = true, searchPlaceholder = "Search…", disabled, className, "aria-label": ariaLabel, ...rest }) {
|
|
31
|
+
// Virtual focus: DOM focus stays on the trigger (or the search field) and the
|
|
32
|
+
// active option is named by `aria-activedescendant`. `data-highlighted` is a
|
|
33
|
+
// styling hook only -- a screen reader cannot see it.
|
|
34
|
+
const autoId = React.useId();
|
|
35
|
+
const listboxId = `${autoId}-listbox`;
|
|
36
|
+
const optionId = (i) => `${autoId}-opt-${i}`;
|
|
31
37
|
const [open, setOpen] = React.useState(false);
|
|
32
38
|
const [up, setUp] = React.useState(false);
|
|
33
39
|
const [pos, setPos] = React.useState({});
|
|
@@ -69,6 +75,9 @@ export function MultiSelect({ options, value: valueProp, defaultValue, onValueCh
|
|
|
69
75
|
setOpen(false);
|
|
70
76
|
triggerRef.current?.focus({ preventScroll: true });
|
|
71
77
|
};
|
|
78
|
+
const activeId = open && highlight >= 0 && highlight < filtered.length
|
|
79
|
+
? optionId(highlight)
|
|
80
|
+
: undefined;
|
|
72
81
|
const toggle = (v) => {
|
|
73
82
|
const next = selectedSet.has(v)
|
|
74
83
|
? value.filter((x) => x !== v)
|
|
@@ -107,19 +116,19 @@ export function MultiSelect({ options, value: valueProp, defaultValue, onValueCh
|
|
|
107
116
|
document.addEventListener("pointerdown", onDown);
|
|
108
117
|
return () => document.removeEventListener("pointerdown", onDown);
|
|
109
118
|
}, [open]);
|
|
110
|
-
return (_jsxs("div", { ref: rootRef, className: multiselectRecipe({ className }), ...rest, children: [_jsxs("button", { ref: triggerRef, type: "button", "aria-haspopup": "listbox", "aria-expanded": open, "aria-label": ariaLabel, disabled: disabled, "data-open": open ? "" : undefined, className: "multiselect-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: (e) => {
|
|
119
|
+
return (_jsxs("div", { ref: rootRef, className: multiselectRecipe({ className }), ...rest, children: [_jsxs("button", { ref: triggerRef, type: "button", role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": open ? listboxId : undefined, "aria-activedescendant": searchable ? undefined : activeId, "aria-label": ariaLabel, disabled: disabled, "data-open": open ? "" : undefined, className: "multiselect-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: (e) => {
|
|
111
120
|
if (open && !searchable)
|
|
112
121
|
onNavKeys(e);
|
|
113
122
|
else if (!open && (e.key === "ArrowDown" || e.key === "Enter")) {
|
|
114
123
|
e.preventDefault();
|
|
115
124
|
openMenu();
|
|
116
125
|
}
|
|
117
|
-
}, children: [_jsx("span", { className: "multiselect-chips", children: selectedOptions.length === 0 ? (_jsx("span", { className: "multiselect-placeholder", children: placeholder })) : (selectedOptions.map((o) => _jsx(Chip, { opt: o }, o.value))) }), _jsx(ChevronDown, { className: "multiselect-chevron", size: 16, strokeWidth: 1.75 })] }), open && (_jsxs("div", { className: "multiselect-listbox", role: "listbox", "aria-multiselectable": "true", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && (_jsxs("div", { className: "multiselect-search", children: [_jsx(Search, { size: 15, strokeWidth: 1.75 }), _jsx("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, value: query, onChange: (e) => {
|
|
126
|
+
}, children: [_jsx("span", { className: "multiselect-chips", children: selectedOptions.length === 0 ? (_jsx("span", { className: "multiselect-placeholder", children: placeholder })) : (selectedOptions.map((o) => _jsx(Chip, { opt: o }, o.value))) }), _jsx(ChevronDown, { className: "multiselect-chevron", size: 16, strokeWidth: 1.75 })] }), open && (_jsxs("div", { id: listboxId, className: "multiselect-listbox", role: "listbox", "aria-multiselectable": "true", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && (_jsxs("div", { className: "multiselect-search", children: [_jsx(Search, { size: 15, strokeWidth: 1.75 }), _jsx("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, "aria-controls": listboxId, "aria-activedescendant": activeId, value: query, onChange: (e) => {
|
|
118
127
|
setQuery(e.target.value);
|
|
119
128
|
setHighlight(0);
|
|
120
129
|
}, onKeyDown: onNavKeys })] })), filtered.length === 0 ? (_jsx("div", { className: "multiselect-empty", children: "No results" })) : (filtered.map((opt, i) => {
|
|
121
130
|
const sel = selectedSet.has(opt.value);
|
|
122
|
-
return (_jsxs("button", { type: "button", role: "option", "aria-selected": sel, "data-highlighted": i === highlight ? "" : undefined, className: "multiselect-option", onClick: () => toggle(opt.value), onMouseEnter: () => setHighlight(i), children: [_jsx("span", { className: "multiselect-option-chip", children: _jsx(Chip, { opt: opt }) }), _jsx("span", { className: "multiselect-check", children: sel && _jsx(Check, { size: 12, strokeWidth: 3 }) })] }, opt.value));
|
|
131
|
+
return (_jsxs("button", { type: "button", id: optionId(i), role: "option", "aria-selected": sel, tabIndex: -1, "data-highlighted": i === highlight ? "" : undefined, className: "multiselect-option", onClick: () => toggle(opt.value), onMouseEnter: () => setHighlight(i), children: [_jsx("span", { className: "multiselect-option-chip", children: _jsx(Chip, { opt: opt }) }), _jsx("span", { className: "multiselect-check", children: sel && _jsx(Check, { size: 12, strokeWidth: 3 }) })] }, opt.value));
|
|
123
132
|
}))] }))] }));
|
|
124
133
|
}
|
|
125
134
|
MultiSelect.displayName = "MultiSelect";
|
|
@@ -15,6 +15,14 @@ function optionText(o) {
|
|
|
15
15
|
* Esc close, Home/End jump, opens upward when tight. Controlled or uncontrolled.
|
|
16
16
|
*/
|
|
17
17
|
export function Select({ options, value, defaultValue, onValueChange, placeholder = "Select…", variant = "default", width = "full", searchable, searchPlaceholder = "Search…", disabled, className, "aria-label": ariaLabel, id, ...rest }) {
|
|
18
|
+
// Virtual focus: DOM focus stays on the trigger (or the search field), and the
|
|
19
|
+
// active option is named by `aria-activedescendant`. That is the only thing a
|
|
20
|
+
// screen reader has to go on -- `data-highlighted` is invisible to it -- so the
|
|
21
|
+
// ids below have to resolve to the element the highlight is actually drawn on.
|
|
22
|
+
const autoId = React.useId();
|
|
23
|
+
const baseId = id ?? autoId;
|
|
24
|
+
const listboxId = `${baseId}-listbox`;
|
|
25
|
+
const optionId = (i) => `${baseId}-opt-${i}`;
|
|
18
26
|
const [internal, setInternal] = React.useState(defaultValue);
|
|
19
27
|
const selected = value ?? internal;
|
|
20
28
|
const [open, setOpen] = React.useState(false);
|
|
@@ -34,6 +42,9 @@ export function Select({ options, value, defaultValue, onValueChange, placeholde
|
|
|
34
42
|
const enabledIndexes = filtered
|
|
35
43
|
.map((o, i) => (o.disabled ? -1 : i))
|
|
36
44
|
.filter((i) => i >= 0);
|
|
45
|
+
const activeId = open && highlight >= 0 && highlight < filtered.length
|
|
46
|
+
? optionId(highlight)
|
|
47
|
+
: undefined;
|
|
37
48
|
const openMenu = () => {
|
|
38
49
|
if (disabled)
|
|
39
50
|
return;
|
|
@@ -133,12 +144,12 @@ export function Select({ options, value, defaultValue, onValueChange, placeholde
|
|
|
133
144
|
document.addEventListener("pointerdown", onDown);
|
|
134
145
|
return () => document.removeEventListener("pointerdown", onDown);
|
|
135
146
|
}, [open]);
|
|
136
|
-
return (_jsxs("div", { ref: rootRef, className: selectRecipe({ variant, width, className }), ...rest, children: [_jsxs("button", { ref: triggerRef, type: "button", id: id, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-label": ariaLabel, disabled: disabled, "data-open": open ? "" : undefined, className: "select-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: onTriggerKeyDown, children: [_jsx("span", { className: "select-value", children: selectedOption ? (_jsxs(_Fragment, { children: [selectedOption.color && (_jsx("span", { className: "select-option-dot", style: { background: selectedOption.color } })), selectedOption.label] })) : (_jsx("span", { className: "select-placeholder", children: placeholder })) }), _jsx(ChevronDown, { className: "select-chevron", size: 16, strokeWidth: 1.75 })] }), open && (_jsxs("div", { className: "select-listbox", role: "listbox", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && (_jsxs("div", { className: "select-search", children: [_jsx(Search, { size: 15, strokeWidth: 1.75 }), _jsx("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, value: query, onChange: (e) => {
|
|
147
|
+
return (_jsxs("div", { ref: rootRef, className: selectRecipe({ variant, width, className }), ...rest, children: [_jsxs("button", { ref: triggerRef, type: "button", id: id, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": open ? listboxId : undefined, "aria-activedescendant": searchable ? undefined : activeId, "aria-label": ariaLabel, disabled: disabled, "data-open": open ? "" : undefined, className: "select-trigger", onClick: () => (open ? setOpen(false) : openMenu()), onKeyDown: onTriggerKeyDown, children: [_jsx("span", { className: "select-value", children: selectedOption ? (_jsxs(_Fragment, { children: [selectedOption.color && (_jsx("span", { className: "select-option-dot", style: { background: selectedOption.color } })), selectedOption.label] })) : (_jsx("span", { className: "select-placeholder", children: placeholder })) }), _jsx(ChevronDown, { className: "select-chevron", size: 16, strokeWidth: 1.75 })] }), open && (_jsxs("div", { id: listboxId, className: "select-listbox", role: "listbox", "aria-label": ariaLabel, "data-up": up ? "" : undefined, style: pos, children: [searchable && (_jsxs("div", { className: "select-search", children: [_jsx(Search, { size: 15, strokeWidth: 1.75 }), _jsx("input", { ref: searchRef, type: "text", placeholder: searchPlaceholder, "aria-label": searchPlaceholder, "aria-controls": listboxId, "aria-activedescendant": activeId, value: query, onChange: (e) => {
|
|
137
148
|
setQuery(e.target.value);
|
|
138
149
|
setHighlight(0);
|
|
139
150
|
}, onKeyDown: onNavKeys })] })), filtered.length === 0 ? (_jsx("div", { className: "select-empty", children: "No results" })) : (filtered.map((opt, i) => {
|
|
140
151
|
const isSel = opt.value === selected;
|
|
141
|
-
return (_jsxs("button", { type: "button", role: "option", "aria-selected": isSel, disabled: opt.disabled, "data-disabled": opt.disabled ? "" : undefined, "data-highlighted": i === highlight ? "" : undefined, className: "select-option", onClick: () => pick(opt), onMouseEnter: () => setHighlight(i), children: [opt.color && (_jsx("span", { className: "select-option-dot", style: { background: opt.color } })), _jsx("span", { className: "select-option-label", children: opt.label }), isSel && (_jsx(Check, { className: "select-option-check", size: 15, strokeWidth: 2 }))] }, opt.value));
|
|
152
|
+
return (_jsxs("button", { type: "button", id: optionId(i), role: "option", "aria-selected": isSel, tabIndex: -1, disabled: opt.disabled, "data-disabled": opt.disabled ? "" : undefined, "data-highlighted": i === highlight ? "" : undefined, className: "select-option", onClick: () => pick(opt), onMouseEnter: () => setHighlight(i), children: [opt.color && (_jsx("span", { className: "select-option-dot", style: { background: opt.color } })), _jsx("span", { className: "select-option-label", children: opt.label }), isSel && (_jsx(Check, { className: "select-option-check", size: 15, strokeWidth: 2 }))] }, opt.value));
|
|
142
153
|
}))] }))] }));
|
|
143
154
|
}
|
|
144
155
|
Select.displayName = "Select";
|