@eifi1/ui-kit 0.22.0 → 0.23.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 +42 -25
- package/dist/chart.d.ts +11 -8
- package/dist/components/amount-input.d.ts +28 -8
- package/dist/components/amount-input.js +3 -1
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.d.ts +21 -0
- package/dist/components/autocomplete.js +128 -103
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/button-group.d.ts +11 -8
- package/dist/components/calculator.d.ts +11 -8
- package/dist/components/column-mapper.d.ts +182 -0
- package/dist/components/column-mapper.js +375 -0
- package/dist/components/column-mapper.js.map +1 -0
- package/dist/components/combobox-core.d.ts +39 -2
- package/dist/components/combobox-core.js +29 -6
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.d.ts +80 -2
- package/dist/components/combobox.js +448 -311
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +11 -8
- package/dist/components/confirm-dialog.js +7 -8
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/copy-button.d.ts +8 -5
- package/dist/components/country-select.d.ts +50 -7
- package/dist/components/country-select.js +65 -9
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +11 -8
- package/dist/components/danger-confirm.js +13 -3
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/date-picker.d.ts +41 -0
- package/dist/components/date-picker.js +269 -8
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/entity-combobox.d.ts +35 -1
- package/dist/components/entity-combobox.js +148 -112
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/facing-pair.d.ts +11 -8
- package/dist/components/field-parts.d.ts +116 -6
- package/dist/components/field-parts.js +84 -0
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/field-strip.d.ts +105 -0
- package/dist/components/field-strip.js +46 -0
- package/dist/components/field-strip.js.map +1 -0
- package/dist/components/file-button.d.ts +11 -8
- package/dist/components/file-dropzone.d.ts +11 -8
- package/dist/components/form-actions.d.ts +10 -7
- package/dist/components/form-actions.js +8 -2
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/iban-input.d.ts +11 -8
- package/dist/components/icon-picker.d.ts +10 -1
- package/dist/components/icon-picker.js +12 -4
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/language-select.d.ts +11 -8
- package/dist/components/money-field.d.ts +14 -8
- package/dist/components/money-field.js.map +1 -1
- package/dist/components/month-picker.js +2 -1
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-entity-combobox.d.ts +26 -1
- package/dist/components/multi-entity-combobox.js +143 -102
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/number-field.d.ts +11 -8
- package/dist/components/number-input.d.ts +11 -8
- package/dist/components/numpad-sheet.d.ts +11 -8
- package/dist/components/phone-input.d.ts +11 -8
- package/dist/components/reauth-dialog.d.ts +2 -2
- package/dist/components/reauth-dialog.js +6 -8
- package/dist/components/reauth-dialog.js.map +1 -1
- package/dist/components/series-chart.d.ts +11 -8
- package/dist/components/settings-fields.d.ts +11 -8
- package/dist/components/share-card.d.ts +10 -7
- package/dist/components/swatch-picker.d.ts +17 -1
- package/dist/components/swatch-picker.js +10 -4
- package/dist/components/swatch-picker.js.map +1 -1
- package/dist/components/text-link.d.ts +10 -7
- package/dist/components/tile-radio.d.ts +20 -0
- package/dist/components/tile-radio.js +25 -8
- package/dist/components/tile-radio.js.map +1 -1
- package/dist/components/time-input.d.ts +11 -8
- package/dist/components/toggle-group.js +2 -2
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/trigger-aria.d.ts +3 -0
- package/dist/components/trigger-aria.js +3 -1
- package/dist/components/trigger-aria.js.map +1 -1
- package/dist/components/ui.d.ts +8 -5
- package/dist/components/ui.js +5 -11
- package/dist/components/ui.js.map +1 -1
- package/dist/feedback/feedback-attachment.d.ts +1 -1
- package/dist/feedback/feedback-attachment.js +156 -56
- package/dist/feedback/feedback-attachment.js.map +1 -1
- package/dist/feedback/feedback-dialog.d.ts +1 -1
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox.d.ts +3 -2
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback/feedback-thread.d.ts +68 -287
- package/dist/feedback/feedback-thread.js +8 -1
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/{kit-labels-R8mIAc9N.d.ts → feedback-BxeQVzwq.d.ts} +405 -22
- package/dist/{feedback-attachment-NhUm7Zga.d.ts → feedback-attachment-fGAzZPf0.d.ts} +112 -10
- package/dist/feedback.d.ts +66 -2
- package/dist/hooks/use-file-drop.d.ts +11 -8
- package/dist/i18n/defaults.d.ts +11 -8
- package/dist/i18n/defaults.js +3 -1
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +11 -8
- package/dist/i18n/german.js +36 -2
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +7 -4
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +11 -8
- package/dist/i18n/locales/de-CH.d.ts +11 -8
- package/dist/i18n/locales/en.d.ts +11 -8
- package/dist/i18n/locales/en.js +7 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +11 -8
- package/dist/i18n/locales/es.js +37 -2
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +11 -8
- package/dist/i18n/locales/fr.js +36 -2
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +11 -8
- package/dist/i18n/locales/hu.js +38 -2
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +11 -8
- package/dist/i18n/locales/it.js +37 -2
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +11 -8
- package/dist/i18n/locales/zh.js +34 -2
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +11 -8
- package/dist/i18n/review.js +20 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/column-mapping.d.ts +81 -0
- package/dist/lib/column-mapping.js +108 -0
- package/dist/lib/column-mapping.js.map +1 -0
- package/dist/lib/table-text.d.ts +109 -1
- package/dist/lib/table-text.js +122 -1
- package/dist/lib/table-text.js.map +1 -1
- package/dist/rhf/fields.d.ts +89 -11
- package/dist/rhf/fields.js +124 -0
- package/dist/rhf/fields.js.map +1 -1
- package/dist/rhf/form.d.ts +11 -8
- package/dist/rhf.d.ts +12 -9
- package/dist/rhf.js.map +1 -1
- package/dist/shell/app-shell.d.ts +10 -7
- package/dist/shell/top-bar-brand.d.ts +11 -8
- package/dist/shell/topbar-action-menu.d.ts +36 -3
- package/dist/shell/topbar-action-menu.js +74 -33
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell.d.ts +10 -7
- package/dist/table-text.d.ts +1 -1
- package/dist/wizard/stepper-nav.d.ts +41 -10
- package/dist/wizard/stepper-nav.js +4 -0
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard.d.ts +11 -8
- package/package.json +1 -1
- package/src/components/amount-input.tsx +20 -1
- package/src/components/autocomplete.tsx +172 -111
- package/src/components/column-mapper.tsx +666 -0
- package/src/components/combobox-core.tsx +82 -9
- package/src/components/combobox.tsx +614 -332
- package/src/components/confirm-dialog.tsx +12 -8
- package/src/components/country-select.tsx +135 -22
- package/src/components/danger-confirm.tsx +91 -12
- package/src/components/date-picker.tsx +423 -10
- package/src/components/entity-combobox.tsx +217 -126
- package/src/components/field-parts.tsx +224 -5
- package/src/components/field-strip.tsx +149 -0
- package/src/components/form-actions.tsx +32 -4
- package/src/components/icon-picker.tsx +23 -4
- package/src/components/money-field.tsx +3 -0
- package/src/components/month-picker.tsx +2 -1
- package/src/components/multi-entity-combobox.tsx +207 -120
- package/src/components/reauth-dialog.tsx +17 -18
- package/src/components/swatch-picker.tsx +29 -5
- package/src/components/tile-radio.tsx +74 -13
- package/src/components/toggle-group.tsx +2 -2
- package/src/components/trigger-aria.ts +5 -0
- package/src/components/ui.tsx +7 -33
- package/src/feedback/feedback-attachment.tsx +308 -61
- package/src/feedback/feedback-dialog.tsx +7 -3
- package/src/feedback/feedback-inbox.tsx +3 -2
- package/src/feedback/feedback-thread.tsx +47 -4
- package/src/i18n/defaults.ts +2 -0
- package/src/i18n/german.ts +42 -0
- package/src/i18n/kit-labels.tsx +4 -0
- package/src/i18n/locales/en.ts +27 -5
- package/src/i18n/locales/es.ts +41 -0
- package/src/i18n/locales/fr.ts +42 -0
- package/src/i18n/locales/hu.ts +37 -0
- package/src/i18n/locales/it.ts +41 -0
- package/src/i18n/locales/zh.ts +32 -0
- package/src/i18n/review.ts +19 -0
- package/src/index.ts +18 -0
- package/src/lib/column-mapping.ts +234 -0
- package/src/lib/table-text.ts +271 -0
- package/src/rhf/fields.tsx +254 -0
- package/src/rhf.ts +2 -1
- package/src/shell/topbar-action-menu.tsx +134 -38
- package/src/wizard/stepper-nav.tsx +35 -1
- package/dist/components/field-anatomy.d.ts +0 -95
- package/dist/components/field-anatomy.js +0 -84
- package/dist/components/field-anatomy.js.map +0 -1
- package/src/components/field-anatomy.tsx +0 -190
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Fragment, useId, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment as Fragment2, useId, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
|
-
import { ChevronDown, X } from "lucide-react";
|
|
5
|
+
import { ChevronDown, Plus, X } from "lucide-react";
|
|
6
6
|
import { FIELD_BASE, FIELD_FLOATING_PAD, FIELD_INVALID, PHONE_QUERY } from "./ui.js";
|
|
7
7
|
import { cn } from "../lib/cn.js";
|
|
8
8
|
import { useDropdown } from "./dropdown.js";
|
|
@@ -13,7 +13,9 @@ import { PickerSheet, SHEET_ROW_CLASS } from "./picker-sheet.js";
|
|
|
13
13
|
import {
|
|
14
14
|
ComboboxFieldLabel,
|
|
15
15
|
DISABLED_ROW_CLASS,
|
|
16
|
+
endHintRowProps,
|
|
16
17
|
isOptionEnabled,
|
|
18
|
+
offersCreate,
|
|
17
19
|
stepEnabled,
|
|
18
20
|
SUGGESTION_LIST_CLASS,
|
|
19
21
|
suggestionRowClass,
|
|
@@ -21,7 +23,17 @@ import {
|
|
|
21
23
|
useComboboxFieldError
|
|
22
24
|
} from "./combobox-core.js";
|
|
23
25
|
import { DEFAULT_COMBOBOX_LABELS, useKitLabels } from "../i18n/kit-labels.js";
|
|
24
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
EndHintRow,
|
|
28
|
+
FieldCaption,
|
|
29
|
+
LABEL_IN_ROW,
|
|
30
|
+
LockedReason,
|
|
31
|
+
StaticLabelRow,
|
|
32
|
+
useFieldHint,
|
|
33
|
+
useLockReason
|
|
34
|
+
} from "./field-parts.js";
|
|
35
|
+
import { hasMessage, mergeDescribedBy } from "./choice-parts.js";
|
|
36
|
+
import { useCommitReason } from "./write-lock.js";
|
|
25
37
|
const LIST_CLASS = SUGGESTION_LIST_CLASS;
|
|
26
38
|
function usePrimaryPressOnly() {
|
|
27
39
|
const auxPress = useRef(false);
|
|
@@ -61,36 +73,43 @@ function SuggestionList({
|
|
|
61
73
|
);
|
|
62
74
|
}
|
|
63
75
|
const rowClass = suggestionRowClass;
|
|
64
|
-
function
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
76
|
+
function lockedKeyDown(e) {
|
|
77
|
+
if (e.key === "Enter") e.preventDefault();
|
|
78
|
+
}
|
|
79
|
+
const CREATE_ROW_CLASS = "flex items-center gap-2 font-medium text-[var(--brand)]";
|
|
80
|
+
function Combobox(props) {
|
|
81
|
+
const {
|
|
82
|
+
value,
|
|
83
|
+
onChange,
|
|
84
|
+
options,
|
|
85
|
+
label,
|
|
86
|
+
id,
|
|
87
|
+
placeholder,
|
|
88
|
+
className,
|
|
89
|
+
groupBy,
|
|
90
|
+
maxSuggestions,
|
|
91
|
+
searchPlaceholder,
|
|
92
|
+
closeLabel,
|
|
93
|
+
createLabel,
|
|
94
|
+
invalid,
|
|
95
|
+
error,
|
|
96
|
+
hint,
|
|
97
|
+
disabled,
|
|
98
|
+
disabledReason,
|
|
99
|
+
commit,
|
|
100
|
+
optionAdornment,
|
|
101
|
+
autoFocus,
|
|
102
|
+
onBlur,
|
|
103
|
+
onSubmit,
|
|
104
|
+
"aria-label": ariaLabel,
|
|
105
|
+
// Off `rest` and onto the <input>, which is the combobox a reader meets: `Field`'s
|
|
106
|
+
// render-prop spreads `{ id, aria-describedby, aria-invalid, aria-required }`, and
|
|
107
|
+
// on the wrapper div the hint and required state described nothing.
|
|
108
|
+
"aria-describedby": ariaDescribedBy,
|
|
109
|
+
"aria-invalid": ariaInvalid,
|
|
110
|
+
"aria-required": ariaRequired,
|
|
111
|
+
...rest
|
|
112
|
+
} = props;
|
|
94
113
|
const hintParts = useFieldHint(hint, ariaDescribedBy);
|
|
95
114
|
const field = useComboboxFieldError(
|
|
96
115
|
error,
|
|
@@ -105,6 +124,10 @@ function Combobox({
|
|
|
105
124
|
const { open, setOpen, wrapperRef, panelRef } = useDropdown({ backCloses: !isPhone });
|
|
106
125
|
const primaryOnly = usePrimaryPressOnly();
|
|
107
126
|
const [active, setActive] = useState(-1);
|
|
127
|
+
const lock = useLockReason(commit, disabledReason);
|
|
128
|
+
const locked = lock.locked;
|
|
129
|
+
const inert = locked || Boolean(disabled);
|
|
130
|
+
if (locked && open) setOpen(false);
|
|
108
131
|
const sheetInputRef = useRef(null);
|
|
109
132
|
const fieldRef = useRef(null);
|
|
110
133
|
const [typing, setTyping] = useState(false);
|
|
@@ -143,7 +166,8 @@ function Combobox({
|
|
|
143
166
|
});
|
|
144
167
|
return heads;
|
|
145
168
|
}, [matches, groupBy]);
|
|
146
|
-
const
|
|
169
|
+
const take = (v) => {
|
|
170
|
+
if (locked) return;
|
|
147
171
|
onChange(v);
|
|
148
172
|
setOpen(false);
|
|
149
173
|
setActive(-1);
|
|
@@ -151,6 +175,7 @@ function Combobox({
|
|
|
151
175
|
};
|
|
152
176
|
const activeId = !isPhone && active >= 0 && active < matches.length ? optionId(active) : void 0;
|
|
153
177
|
useActiveOptionScroll(activeId);
|
|
178
|
+
const withLock = (box) => locked ? /* @__PURE__ */ jsx(LockedReason, { lock, className: "block", children: box }) : box;
|
|
154
179
|
const typed = value.trim();
|
|
155
180
|
const createRow = createLabel && typed.length > 0 && !options.some((o) => o.toLowerCase() === typed.toLowerCase()) ? createLabel(typed) : null;
|
|
156
181
|
return (
|
|
@@ -159,101 +184,117 @@ function Combobox({
|
|
|
159
184
|
// which is the combobox a reader meets. Spread FIRST, so the field's ARIA and the
|
|
160
185
|
// handlers carrying live #309 and dev#549 cannot be replaced from outside.
|
|
161
186
|
/* @__PURE__ */ jsxs("div", { ...rest, ref: wrapperRef, className: cn("relative", className), children: [
|
|
162
|
-
label !== void 0 && hintParts.labelHint === void 0 && /* @__PURE__ */ jsx(ComboboxFieldLabel, { htmlFor: fieldId, className:
|
|
163
|
-
/* @__PURE__ */ jsx(EndHintRow, { hint
|
|
164
|
-
/*
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
"
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
setActive(-1);
|
|
199
|
-
setTyping(true);
|
|
200
|
-
},
|
|
201
|
-
onKeyDown: (e) => {
|
|
202
|
-
if (e.key === "ArrowDown") {
|
|
203
|
-
e.preventDefault();
|
|
187
|
+
label !== void 0 && hintParts.labelHint === void 0 && /* @__PURE__ */ jsx(ComboboxFieldLabel, { htmlFor: fieldId, className: inert ? "opacity-50" : void 0, children: label }),
|
|
188
|
+
/* @__PURE__ */ jsx(EndHintRow, { ...endHintRowProps("hint" in props, label !== void 0, hintParts.labelHint), children: withLock(
|
|
189
|
+
/* The chevron centers against this inner wrapper, which hugs the input.
|
|
190
|
+
The outer div can be taller than the input (as a grid item it
|
|
191
|
+
stretches to the row height, e.g. next to the editor's category cell
|
|
192
|
+
with its split button), which used to drag a top-1/2 chevron down to
|
|
193
|
+
the input's bottom edge (feedback #248).
|
|
194
|
+
Dimmed as a whole when disabled (or locked), the way EntityCombobox dims its
|
|
195
|
+
trigger. FIELD_BASE's grey alone left a disabled picker looking like a
|
|
196
|
+
filled-in one beside the pickers that do dim (the label is not the input's
|
|
197
|
+
`peer`, so it is dimmed by hand above). */
|
|
198
|
+
/* @__PURE__ */ jsxs("div", { ref: fieldRef, className: cn("relative", inert && "cursor-not-allowed opacity-50"), children: [
|
|
199
|
+
/* @__PURE__ */ jsx(
|
|
200
|
+
"input",
|
|
201
|
+
{
|
|
202
|
+
id: fieldId,
|
|
203
|
+
value,
|
|
204
|
+
placeholder,
|
|
205
|
+
"aria-label": ariaLabel,
|
|
206
|
+
role: "combobox",
|
|
207
|
+
"aria-expanded": open,
|
|
208
|
+
"aria-controls": listboxId,
|
|
209
|
+
"aria-activedescendant": activeId,
|
|
210
|
+
"aria-autocomplete": "list",
|
|
211
|
+
"aria-invalid": field.isInvalid || void 0,
|
|
212
|
+
"aria-describedby": mergeDescribedBy(field.describedBy, locked && lock.reasonId),
|
|
213
|
+
"aria-required": ariaRequired,
|
|
214
|
+
autoComplete: "off",
|
|
215
|
+
disabled: locked ? void 0 : disabled,
|
|
216
|
+
readOnly: locked || void 0,
|
|
217
|
+
"aria-disabled": locked || void 0,
|
|
218
|
+
autoFocus,
|
|
219
|
+
onBlur,
|
|
220
|
+
onMouseDown: primaryOnly.onMouseDown,
|
|
221
|
+
onFocus: () => {
|
|
222
|
+
if (primaryOnly.fromAuxButton() || locked) return;
|
|
204
223
|
setOpen(true);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
224
|
+
setTyping(false);
|
|
225
|
+
if (isPhone) sheetInputRef.current?.focus();
|
|
226
|
+
},
|
|
227
|
+
onClick: () => {
|
|
228
|
+
if (locked) return;
|
|
229
|
+
setOpen(true);
|
|
230
|
+
setTyping(false);
|
|
231
|
+
},
|
|
232
|
+
inputMode: isPhone ? "none" : void 0,
|
|
233
|
+
onChange: (e) => {
|
|
234
|
+
if (locked) return;
|
|
235
|
+
onChange(e.target.value);
|
|
236
|
+
setOpen(true);
|
|
237
|
+
setActive(-1);
|
|
238
|
+
setTyping(true);
|
|
239
|
+
},
|
|
240
|
+
onKeyDown: (e) => {
|
|
241
|
+
if (locked) return lockedKeyDown(e);
|
|
242
|
+
if (e.key === "ArrowDown") {
|
|
243
|
+
e.preventDefault();
|
|
244
|
+
setOpen(true);
|
|
245
|
+
setActive((i) => Math.min(i + 1, matches.length - 1));
|
|
246
|
+
} else if (e.key === "ArrowUp") {
|
|
211
247
|
e.preventDefault();
|
|
212
|
-
|
|
213
|
-
} else {
|
|
214
|
-
if (
|
|
248
|
+
setActive((i) => Math.max(i - 1, 0));
|
|
249
|
+
} else if (e.key === "Enter") {
|
|
250
|
+
if (open && active >= 0 && active < matches.length) {
|
|
251
|
+
e.preventDefault();
|
|
252
|
+
take(matches[active]);
|
|
253
|
+
} else {
|
|
254
|
+
if (onSubmit) e.preventDefault();
|
|
255
|
+
setOpen(false);
|
|
256
|
+
onSubmit?.();
|
|
257
|
+
}
|
|
258
|
+
} else if (e.key === "Escape") {
|
|
259
|
+
setOpen(false);
|
|
260
|
+
setActive(-1);
|
|
261
|
+
} else if (e.key === "Tab") {
|
|
215
262
|
setOpen(false);
|
|
216
|
-
|
|
263
|
+
setActive(-1);
|
|
217
264
|
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
!disabled && "cursor-pointer"
|
|
246
|
-
)
|
|
247
|
-
}
|
|
248
|
-
)
|
|
249
|
-
] }) }),
|
|
250
|
-
label !== void 0 && hintParts.labelHint !== void 0 && /* @__PURE__ */ jsx(StaticLabelRow, { hint: hintParts.labelHint, children: /* @__PURE__ */ jsx(ComboboxFieldLabel, { htmlFor: fieldId, className: cn(LABEL_IN_ROW, disabled && "opacity-50"), children: label }) }),
|
|
265
|
+
},
|
|
266
|
+
className: cn(
|
|
267
|
+
FIELD_BASE,
|
|
268
|
+
label !== void 0 && FIELD_FLOATING_PAD,
|
|
269
|
+
"pe-9",
|
|
270
|
+
field.isInvalid && FIELD_INVALID
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
),
|
|
274
|
+
/* @__PURE__ */ jsx(
|
|
275
|
+
ChevronDown,
|
|
276
|
+
{
|
|
277
|
+
"aria-hidden": true,
|
|
278
|
+
onMouseDown: (e) => {
|
|
279
|
+
e.preventDefault();
|
|
280
|
+
if (!inert) setOpen((o) => !o);
|
|
281
|
+
},
|
|
282
|
+
className: cn(
|
|
283
|
+
"absolute end-2.5 top-1/2 size-4 -translate-y-1/2 text-[var(--text-placeholder)]",
|
|
284
|
+
// The box above does the dimming; dimming here too would halve it again.
|
|
285
|
+
!inert && "cursor-pointer"
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
)
|
|
289
|
+
] })
|
|
290
|
+
) }),
|
|
291
|
+
label !== void 0 && hintParts.labelHint !== void 0 && /* @__PURE__ */ jsx(StaticLabelRow, { hint: hintParts.labelHint, children: /* @__PURE__ */ jsx(ComboboxFieldLabel, { htmlFor: fieldId, className: cn(LABEL_IN_ROW, inert && "opacity-50"), children: label }) }),
|
|
251
292
|
/* @__PURE__ */ jsx(FieldCaption, { parts: hintParts }),
|
|
252
293
|
field.errorEl,
|
|
253
294
|
isPhone && /* @__PURE__ */ jsx(
|
|
254
295
|
PickerSheet,
|
|
255
296
|
{
|
|
256
|
-
open: open && !
|
|
297
|
+
open: open && !inert,
|
|
257
298
|
onClose: () => setOpen(false),
|
|
258
299
|
title: label,
|
|
259
300
|
query: value,
|
|
@@ -274,14 +315,14 @@ function Combobox({
|
|
|
274
315
|
type: "button",
|
|
275
316
|
role: "option",
|
|
276
317
|
"aria-selected": false,
|
|
277
|
-
onClick: () =>
|
|
318
|
+
onClick: () => take(typed),
|
|
278
319
|
className: cn(SHEET_ROW_CLASS, "font-medium text-[var(--brand)]"),
|
|
279
320
|
children: createRow
|
|
280
321
|
}
|
|
281
322
|
) }),
|
|
282
323
|
matches.map((o, i) => {
|
|
283
324
|
const group = groupHeadings?.get(i);
|
|
284
|
-
return /* @__PURE__ */ jsxs(
|
|
325
|
+
return /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
285
326
|
group !== void 0 && /* @__PURE__ */ jsx(
|
|
286
327
|
"li",
|
|
287
328
|
{
|
|
@@ -296,7 +337,7 @@ function Combobox({
|
|
|
296
337
|
type: "button",
|
|
297
338
|
role: "option",
|
|
298
339
|
"aria-selected": o === value,
|
|
299
|
-
onClick: () =>
|
|
340
|
+
onClick: () => take(o),
|
|
300
341
|
className: cn(
|
|
301
342
|
SHEET_ROW_CLASS,
|
|
302
343
|
optionAdornment && "flex items-center justify-between gap-2"
|
|
@@ -312,7 +353,7 @@ function Combobox({
|
|
|
312
353
|
] })
|
|
313
354
|
}
|
|
314
355
|
),
|
|
315
|
-
!isPhone && open && !
|
|
356
|
+
!isPhone && open && !inert && (matches.length > 0 || createRow) && /* @__PURE__ */ jsxs(SuggestionList, { id: listboxId, anchorRef: fieldRef, panelRef, children: [
|
|
316
357
|
createRow && /* @__PURE__ */ jsx("li", { role: "presentation", children: /* @__PURE__ */ jsx(
|
|
317
358
|
"button",
|
|
318
359
|
{
|
|
@@ -322,7 +363,7 @@ function Combobox({
|
|
|
322
363
|
tabIndex: -1,
|
|
323
364
|
onMouseDown: (e) => {
|
|
324
365
|
e.preventDefault();
|
|
325
|
-
|
|
366
|
+
take(typed);
|
|
326
367
|
},
|
|
327
368
|
className: cn(rowClass(false), "font-medium text-[var(--brand)]"),
|
|
328
369
|
children: createRow
|
|
@@ -330,7 +371,7 @@ function Combobox({
|
|
|
330
371
|
) }),
|
|
331
372
|
matches.map((o, i) => {
|
|
332
373
|
const group = groupHeadings?.get(i);
|
|
333
|
-
return /* @__PURE__ */ jsxs(
|
|
374
|
+
return /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
334
375
|
group !== void 0 && /* @__PURE__ */ jsx(
|
|
335
376
|
"li",
|
|
336
377
|
{
|
|
@@ -349,7 +390,7 @@ function Combobox({
|
|
|
349
390
|
tabIndex: -1,
|
|
350
391
|
onMouseDown: (e) => {
|
|
351
392
|
e.preventDefault();
|
|
352
|
-
|
|
393
|
+
take(o);
|
|
353
394
|
},
|
|
354
395
|
onMouseEnter: () => setActive(i),
|
|
355
396
|
className: cn(
|
|
@@ -372,34 +413,41 @@ function Combobox({
|
|
|
372
413
|
] })
|
|
373
414
|
);
|
|
374
415
|
}
|
|
375
|
-
function InlineEntityCombobox({
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
416
|
+
function InlineEntityCombobox(props) {
|
|
417
|
+
const {
|
|
418
|
+
value: rawValue,
|
|
419
|
+
onChange,
|
|
420
|
+
clearValue = null,
|
|
421
|
+
options,
|
|
422
|
+
label,
|
|
423
|
+
id,
|
|
424
|
+
placeholder,
|
|
425
|
+
className,
|
|
426
|
+
disabled,
|
|
427
|
+
autoFocus,
|
|
428
|
+
searchPlaceholder,
|
|
429
|
+
emptyLabel,
|
|
430
|
+
closeLabel,
|
|
431
|
+
clearable,
|
|
432
|
+
clearLabel,
|
|
433
|
+
disabledReason,
|
|
434
|
+
commit,
|
|
435
|
+
onCreate,
|
|
436
|
+
createLabel,
|
|
437
|
+
createEmptyLabel,
|
|
438
|
+
createCommit,
|
|
439
|
+
invalid,
|
|
440
|
+
error,
|
|
441
|
+
hint,
|
|
442
|
+
"aria-label": ariaLabel,
|
|
443
|
+
// Off `rest` and onto the <input>, which is the combobox a reader meets: `Field`'s
|
|
444
|
+
// render-prop spreads `{ id, aria-describedby, aria-invalid, aria-required }`, and
|
|
445
|
+
// on the wrapper div the hint and required state described nothing.
|
|
446
|
+
"aria-describedby": ariaDescribedBy,
|
|
447
|
+
"aria-invalid": ariaInvalid,
|
|
448
|
+
"aria-required": ariaRequired,
|
|
449
|
+
...rest
|
|
450
|
+
} = props;
|
|
403
451
|
const value = rawValue == null || rawValue === clearValue ? null : rawValue;
|
|
404
452
|
const hintParts = useFieldHint(hint, ariaDescribedBy);
|
|
405
453
|
const field = useComboboxFieldError(
|
|
@@ -422,14 +470,24 @@ function InlineEntityCombobox({
|
|
|
422
470
|
const labels = useKitLabels("combobox", DEFAULT_COMBOBOX_LABELS, {
|
|
423
471
|
search: searchPlaceholder,
|
|
424
472
|
noResults: emptyLabel,
|
|
425
|
-
clear: clearLabel
|
|
473
|
+
clear: clearLabel,
|
|
474
|
+
create: createLabel
|
|
426
475
|
});
|
|
476
|
+
const lock = useLockReason(commit, disabledReason);
|
|
477
|
+
const locked = lock.locked;
|
|
478
|
+
const inert = locked || Boolean(disabled);
|
|
479
|
+
if (locked && (open || text !== null)) {
|
|
480
|
+
setOpen(false);
|
|
481
|
+
setText(null);
|
|
482
|
+
}
|
|
483
|
+
const createReason = useCommitReason(createCommit, void 0);
|
|
484
|
+
const createLocked = hasMessage(createReason);
|
|
427
485
|
const selected = useMemo(
|
|
428
486
|
() => value == null ? null : options.find((o) => o.value === value) ?? null,
|
|
429
487
|
[options, value]
|
|
430
488
|
);
|
|
431
489
|
const shown = text ?? selected?.label ?? "";
|
|
432
|
-
const showClear = Boolean(clearable && value != null && !
|
|
490
|
+
const showClear = Boolean(clearable && value != null && !inert);
|
|
433
491
|
const typedQuery = text !== null && text !== (selected?.label ?? "") ? text.trim().toLowerCase() : "";
|
|
434
492
|
const query = isPhone ? sheetQuery.trim().toLowerCase() : typedQuery;
|
|
435
493
|
const matches = useMemo(() => {
|
|
@@ -451,21 +509,37 @@ function InlineEntityCombobox({
|
|
|
451
509
|
}
|
|
452
510
|
return [...blocks.values()].flat();
|
|
453
511
|
}, [options, query]);
|
|
454
|
-
const
|
|
512
|
+
const createQuery = isPhone ? sheetQuery.trim() : text !== null && text !== (selected?.label ?? "") ? text.trim() : "";
|
|
513
|
+
const showCreate = offersCreate(
|
|
514
|
+
onCreate,
|
|
515
|
+
createQuery,
|
|
516
|
+
options.map((o) => o.label),
|
|
517
|
+
createEmptyLabel
|
|
518
|
+
);
|
|
519
|
+
const createText = createQuery ? labels.create(createQuery) : createEmptyLabel;
|
|
520
|
+
const rows = showCreate ? [...matches, { disabled: createLocked }] : matches;
|
|
521
|
+
const createIndex = matches.length;
|
|
522
|
+
const activeId = !isPhone && isOptionEnabled(rows[active]) ? optionId(active) : void 0;
|
|
455
523
|
useActiveOptionScroll(activeId);
|
|
456
524
|
const close = () => {
|
|
457
525
|
setOpen(false);
|
|
458
526
|
setActive(-1);
|
|
459
527
|
setSheetQuery("");
|
|
460
528
|
};
|
|
461
|
-
const
|
|
462
|
-
if (o.disabled) return;
|
|
529
|
+
const take = (o) => {
|
|
530
|
+
if (o.disabled || locked) return;
|
|
463
531
|
if (o.value !== value) onChange(o.value);
|
|
464
532
|
setText(null);
|
|
465
533
|
close();
|
|
466
534
|
};
|
|
535
|
+
const create = () => {
|
|
536
|
+
if (!onCreate || locked || createLocked) return;
|
|
537
|
+
onCreate(createQuery);
|
|
538
|
+
setText(null);
|
|
539
|
+
close();
|
|
540
|
+
};
|
|
467
541
|
const reconcile = () => {
|
|
468
|
-
if (text !== null) {
|
|
542
|
+
if (text !== null && !locked) {
|
|
469
543
|
const q = text.trim();
|
|
470
544
|
if (!q) {
|
|
471
545
|
if (value != null) onChange(clearValue);
|
|
@@ -476,124 +550,145 @@ function InlineEntityCombobox({
|
|
|
476
550
|
const ids = new Set(hits.map((h) => h.value));
|
|
477
551
|
if (ids.size === 1 && hits[0].value !== value) onChange(hits[0].value);
|
|
478
552
|
}
|
|
479
|
-
setText(null);
|
|
480
553
|
}
|
|
554
|
+
setText(null);
|
|
481
555
|
close();
|
|
482
556
|
};
|
|
557
|
+
const createRowContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
558
|
+
/* @__PURE__ */ jsx(Plus, { "aria-hidden": true, className: "size-4 shrink-0" }),
|
|
559
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
560
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate", children: createText }),
|
|
561
|
+
createLocked && /* @__PURE__ */ jsx("span", { className: "block truncate text-xs font-normal text-[var(--text-placeholder)]", children: createReason })
|
|
562
|
+
] })
|
|
563
|
+
] });
|
|
564
|
+
const withLock = (box) => locked ? /* @__PURE__ */ jsx(LockedReason, { lock, className: "block", children: box }) : box;
|
|
483
565
|
return (
|
|
484
566
|
// `rest` dresses the outer box — a `data-tour` anchor, a test id. Not the NAME,
|
|
485
567
|
// description, invalid or required state: those belong on the <input> below,
|
|
486
568
|
// which is the combobox a reader meets. Spread FIRST, so the field's ARIA and the
|
|
487
569
|
// handlers carrying live #309 and dev#549 cannot be replaced from outside.
|
|
488
570
|
/* @__PURE__ */ jsxs("div", { ...rest, ref: wrapperRef, className: cn("relative", className), children: [
|
|
489
|
-
label !== void 0 && hintParts.labelHint === void 0 && /* @__PURE__ */ jsx(ComboboxFieldLabel, { htmlFor: fieldId, className:
|
|
490
|
-
/* @__PURE__ */ jsx(EndHintRow, { hint
|
|
491
|
-
/*
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
"
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
setActive(-1);
|
|
525
|
-
},
|
|
526
|
-
onKeyDown: (e) => {
|
|
527
|
-
if (e.key === "ArrowDown") {
|
|
528
|
-
e.preventDefault();
|
|
571
|
+
label !== void 0 && hintParts.labelHint === void 0 && /* @__PURE__ */ jsx(ComboboxFieldLabel, { htmlFor: fieldId, className: inert ? "opacity-50" : void 0, children: label }),
|
|
572
|
+
/* @__PURE__ */ jsx(EndHintRow, { ...endHintRowProps("hint" in props, label !== void 0, hintParts.labelHint), children: withLock(
|
|
573
|
+
/* Inner wrapper for chevron centering — same reasoning as Combobox above.
|
|
574
|
+
It is also what the portalled list anchors to.
|
|
575
|
+
Dimmed as a whole when disabled (or locked), the way EntityCombobox dims its
|
|
576
|
+
trigger. FIELD_BASE's grey alone left a disabled picker looking like a
|
|
577
|
+
filled-in one beside the pickers that do dim (the label is not the input's
|
|
578
|
+
`peer`, so it is dimmed by hand above). */
|
|
579
|
+
/* @__PURE__ */ jsxs("div", { ref: fieldRef, className: cn("relative", inert && "cursor-not-allowed opacity-50"), children: [
|
|
580
|
+
/* @__PURE__ */ jsx(
|
|
581
|
+
"input",
|
|
582
|
+
{
|
|
583
|
+
id: fieldId,
|
|
584
|
+
value: shown,
|
|
585
|
+
placeholder,
|
|
586
|
+
"aria-label": ariaLabel,
|
|
587
|
+
role: "combobox",
|
|
588
|
+
"aria-expanded": open,
|
|
589
|
+
"aria-controls": listboxId,
|
|
590
|
+
"aria-activedescendant": activeId,
|
|
591
|
+
"aria-autocomplete": "list",
|
|
592
|
+
"aria-invalid": field.isInvalid || void 0,
|
|
593
|
+
"aria-describedby": mergeDescribedBy(field.describedBy, locked && lock.reasonId),
|
|
594
|
+
"aria-required": ariaRequired,
|
|
595
|
+
autoComplete: "off",
|
|
596
|
+
disabled: locked ? void 0 : disabled,
|
|
597
|
+
readOnly: locked || void 0,
|
|
598
|
+
"aria-disabled": locked || void 0,
|
|
599
|
+
autoFocus,
|
|
600
|
+
inputMode: isPhone ? "none" : void 0,
|
|
601
|
+
onMouseDown: primaryOnly.onMouseDown,
|
|
602
|
+
onFocus: (e) => {
|
|
603
|
+
if (primaryOnly.fromAuxButton() || locked) return;
|
|
604
|
+
setText(shown);
|
|
605
|
+
e.currentTarget.select();
|
|
529
606
|
setOpen(true);
|
|
530
|
-
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
}
|
|
535
|
-
|
|
607
|
+
if (isPhone) sheetInputRef.current?.focus();
|
|
608
|
+
},
|
|
609
|
+
onBlur: () => {
|
|
610
|
+
if (!isPhone) reconcile();
|
|
611
|
+
},
|
|
612
|
+
onChange: (e) => {
|
|
613
|
+
if (locked) return;
|
|
614
|
+
setText(e.target.value);
|
|
615
|
+
setOpen(true);
|
|
616
|
+
setActive(-1);
|
|
617
|
+
},
|
|
618
|
+
onKeyDown: (e) => {
|
|
619
|
+
if (locked) return lockedKeyDown(e);
|
|
620
|
+
if (e.key === "ArrowDown") {
|
|
621
|
+
e.preventDefault();
|
|
622
|
+
setOpen(true);
|
|
623
|
+
setActive((i) => stepEnabled(rows, i, 1));
|
|
624
|
+
} else if (e.key === "ArrowUp") {
|
|
536
625
|
e.preventDefault();
|
|
537
|
-
|
|
538
|
-
} else {
|
|
626
|
+
setActive((i) => i < 0 ? stepEnabled(rows, -1, 1) : stepEnabled(rows, i, -1));
|
|
627
|
+
} else if (e.key === "Enter") {
|
|
628
|
+
if (open && isOptionEnabled(rows[active])) {
|
|
629
|
+
e.preventDefault();
|
|
630
|
+
if (active === createIndex && showCreate) create();
|
|
631
|
+
else take(matches[active]);
|
|
632
|
+
} else {
|
|
633
|
+
reconcile();
|
|
634
|
+
}
|
|
635
|
+
} else if (e.key === "Escape") {
|
|
636
|
+
setText(null);
|
|
637
|
+
close();
|
|
638
|
+
} else if (e.key === "Tab") {
|
|
539
639
|
reconcile();
|
|
540
640
|
}
|
|
541
|
-
}
|
|
641
|
+
},
|
|
642
|
+
className: cn(
|
|
643
|
+
FIELD_BASE,
|
|
644
|
+
label !== void 0 && FIELD_FLOATING_PAD,
|
|
645
|
+
"pe-9",
|
|
646
|
+
field.isInvalid && FIELD_INVALID
|
|
647
|
+
)
|
|
648
|
+
}
|
|
649
|
+
),
|
|
650
|
+
showClear ? /* @__PURE__ */ jsx(
|
|
651
|
+
"button",
|
|
652
|
+
{
|
|
653
|
+
type: "button",
|
|
654
|
+
tabIndex: -1,
|
|
655
|
+
"aria-label": labels.clear,
|
|
656
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
657
|
+
onClick: () => {
|
|
542
658
|
setText(null);
|
|
543
659
|
close();
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
"hover:text-[var(--text-secondary)]"
|
|
571
|
-
),
|
|
572
|
-
children: /* @__PURE__ */ jsx(X, { "aria-hidden": true, className: "size-4" })
|
|
573
|
-
}
|
|
574
|
-
) : /* @__PURE__ */ jsx(
|
|
575
|
-
ChevronDown,
|
|
576
|
-
{
|
|
577
|
-
"aria-hidden": true,
|
|
578
|
-
onMouseDown: (e) => {
|
|
579
|
-
e.preventDefault();
|
|
580
|
-
if (!disabled) setOpen((o) => !o);
|
|
581
|
-
},
|
|
582
|
-
className: cn(
|
|
583
|
-
"absolute end-2.5 top-1/2 size-4 -translate-y-1/2 text-[var(--text-placeholder)]",
|
|
584
|
-
// The box above does the dimming; dimming here too would halve it again.
|
|
585
|
-
!disabled && "cursor-pointer"
|
|
586
|
-
)
|
|
587
|
-
}
|
|
588
|
-
)
|
|
589
|
-
] }) }),
|
|
590
|
-
label !== void 0 && hintParts.labelHint !== void 0 && /* @__PURE__ */ jsx(StaticLabelRow, { hint: hintParts.labelHint, children: /* @__PURE__ */ jsx(ComboboxFieldLabel, { htmlFor: fieldId, className: cn(LABEL_IN_ROW, disabled && "opacity-50"), children: label }) }),
|
|
660
|
+
if (!locked) onChange(clearValue);
|
|
661
|
+
},
|
|
662
|
+
className: cn(
|
|
663
|
+
"absolute end-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-[var(--text-placeholder)]",
|
|
664
|
+
"hover:text-[var(--text-secondary)]"
|
|
665
|
+
),
|
|
666
|
+
children: /* @__PURE__ */ jsx(X, { "aria-hidden": true, className: "size-4" })
|
|
667
|
+
}
|
|
668
|
+
) : /* @__PURE__ */ jsx(
|
|
669
|
+
ChevronDown,
|
|
670
|
+
{
|
|
671
|
+
"aria-hidden": true,
|
|
672
|
+
onMouseDown: (e) => {
|
|
673
|
+
e.preventDefault();
|
|
674
|
+
if (!inert) setOpen((o) => !o);
|
|
675
|
+
},
|
|
676
|
+
className: cn(
|
|
677
|
+
"absolute end-2.5 top-1/2 size-4 -translate-y-1/2 text-[var(--text-placeholder)]",
|
|
678
|
+
// The box above does the dimming; dimming here too would halve it again.
|
|
679
|
+
!inert && "cursor-pointer"
|
|
680
|
+
)
|
|
681
|
+
}
|
|
682
|
+
)
|
|
683
|
+
] })
|
|
684
|
+
) }),
|
|
685
|
+
label !== void 0 && hintParts.labelHint !== void 0 && /* @__PURE__ */ jsx(StaticLabelRow, { hint: hintParts.labelHint, children: /* @__PURE__ */ jsx(ComboboxFieldLabel, { htmlFor: fieldId, className: cn(LABEL_IN_ROW, inert && "opacity-50"), children: label }) }),
|
|
591
686
|
/* @__PURE__ */ jsx(FieldCaption, { parts: hintParts }),
|
|
592
687
|
field.errorEl,
|
|
593
688
|
isPhone && /* @__PURE__ */ jsx(
|
|
594
689
|
PickerSheet,
|
|
595
690
|
{
|
|
596
|
-
open: open && !
|
|
691
|
+
open: open && !inert,
|
|
597
692
|
onClose: reconcile,
|
|
598
693
|
title: label,
|
|
599
694
|
query: sheetQuery,
|
|
@@ -609,7 +704,7 @@ function InlineEntityCombobox({
|
|
|
609
704
|
// Keyed by group AND value, like combobox-core.tsx: an option may
|
|
610
705
|
// deliberately appear twice (see `reconcile`), and a bare value key
|
|
611
706
|
// would collide.
|
|
612
|
-
/* @__PURE__ */ jsxs(
|
|
707
|
+
/* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
613
708
|
o.group && o.group !== matches[i - 1]?.group && /* @__PURE__ */ jsx(
|
|
614
709
|
"li",
|
|
615
710
|
{
|
|
@@ -625,7 +720,7 @@ function InlineEntityCombobox({
|
|
|
625
720
|
role: "option",
|
|
626
721
|
"aria-selected": o.value === value,
|
|
627
722
|
"aria-disabled": o.disabled || void 0,
|
|
628
|
-
onClick: () =>
|
|
723
|
+
onClick: () => take(o),
|
|
629
724
|
className: cn(
|
|
630
725
|
SHEET_ROW_CLASS,
|
|
631
726
|
o.value === value && "font-medium",
|
|
@@ -636,58 +731,100 @@ function InlineEntityCombobox({
|
|
|
636
731
|
) })
|
|
637
732
|
] }, `${o.group ?? ""}|${String(o.value)}`)
|
|
638
733
|
)),
|
|
639
|
-
|
|
734
|
+
showCreate && /* @__PURE__ */ jsx("li", { role: "presentation", children: /* @__PURE__ */ jsx(
|
|
735
|
+
"button",
|
|
736
|
+
{
|
|
737
|
+
type: "button",
|
|
738
|
+
role: "option",
|
|
739
|
+
"aria-selected": false,
|
|
740
|
+
"aria-disabled": createLocked || void 0,
|
|
741
|
+
onClick: create,
|
|
742
|
+
className: cn(
|
|
743
|
+
SHEET_ROW_CLASS,
|
|
744
|
+
CREATE_ROW_CLASS,
|
|
745
|
+
createLocked && DISABLED_ROW_CLASS
|
|
746
|
+
),
|
|
747
|
+
children: createRowContent
|
|
748
|
+
}
|
|
749
|
+
) }),
|
|
750
|
+
matches.length === 0 && !showCreate && /* @__PURE__ */ jsx("li", { className: "px-4 py-3 text-sm text-[var(--text-muted)]", children: labels.noResults })
|
|
640
751
|
] })
|
|
641
752
|
}
|
|
642
753
|
),
|
|
643
|
-
!isPhone && open && !
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
"
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
e
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
754
|
+
!isPhone && open && !inert && (matches.length > 0 || showCreate) && /* @__PURE__ */ jsxs(SuggestionList, { id: listboxId, anchorRef: fieldRef, panelRef, children: [
|
|
755
|
+
matches.map((o, i) => (
|
|
756
|
+
// A group heading is emitted at each group boundary rather than repeating
|
|
757
|
+
// the group on every row (feedback #136). `matches` is group-contiguous,
|
|
758
|
+
// so comparing with the previous row is enough. Fragment key sits here;
|
|
759
|
+
// the heading and the option carry their own list semantics — keyed by
|
|
760
|
+
// group AND value, because an option may deliberately appear twice (see
|
|
761
|
+
// `reconcile`).
|
|
762
|
+
/* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
763
|
+
o.group && o.group !== matches[i - 1]?.group && /* @__PURE__ */ jsx(
|
|
764
|
+
"li",
|
|
765
|
+
{
|
|
766
|
+
role: "presentation",
|
|
767
|
+
className: "px-3 pb-0.5 pt-2 text-[11px] font-semibold uppercase tracking-wide text-[var(--text-muted)] first:pt-1",
|
|
768
|
+
children: o.group
|
|
769
|
+
}
|
|
770
|
+
),
|
|
771
|
+
/* @__PURE__ */ jsx("li", { role: "presentation", children: /* @__PURE__ */ jsxs(
|
|
772
|
+
"button",
|
|
773
|
+
{
|
|
774
|
+
type: "button",
|
|
775
|
+
id: optionId(i),
|
|
776
|
+
role: "option",
|
|
777
|
+
"aria-selected": o.value === value,
|
|
778
|
+
"aria-disabled": o.disabled || void 0,
|
|
779
|
+
tabIndex: -1,
|
|
780
|
+
onMouseDown: (e) => {
|
|
781
|
+
e.preventDefault();
|
|
782
|
+
take(o);
|
|
783
|
+
},
|
|
784
|
+
onMouseEnter: () => {
|
|
785
|
+
if (!o.disabled) setActive(i);
|
|
786
|
+
},
|
|
787
|
+
className: cn(
|
|
788
|
+
rowClass(i === active && !o.disabled),
|
|
789
|
+
o.disabled && DISABLED_ROW_CLASS,
|
|
790
|
+
// Indented under its heading, so the hierarchy is readable at a
|
|
791
|
+
// glance instead of inferred from grey trailing text.
|
|
792
|
+
o.group && "ps-6",
|
|
793
|
+
o.value === value && "font-medium"
|
|
794
|
+
),
|
|
795
|
+
children: [
|
|
796
|
+
o.label,
|
|
797
|
+
o.sublabel && /* @__PURE__ */ jsx("span", { className: "ms-2 text-xs text-[var(--text-placeholder)]", children: o.sublabel })
|
|
798
|
+
]
|
|
799
|
+
}
|
|
800
|
+
) })
|
|
801
|
+
] }, `${o.group ?? ""}|${String(o.value)}`)
|
|
802
|
+
)),
|
|
803
|
+
showCreate && /* @__PURE__ */ jsx("li", { role: "presentation", children: /* @__PURE__ */ jsx(
|
|
804
|
+
"button",
|
|
805
|
+
{
|
|
806
|
+
type: "button",
|
|
807
|
+
id: optionId(createIndex),
|
|
808
|
+
role: "option",
|
|
809
|
+
"aria-selected": false,
|
|
810
|
+
"aria-disabled": createLocked || void 0,
|
|
811
|
+
tabIndex: -1,
|
|
812
|
+
onMouseDown: (e) => {
|
|
813
|
+
e.preventDefault();
|
|
814
|
+
create();
|
|
815
|
+
},
|
|
816
|
+
onMouseEnter: () => {
|
|
817
|
+
if (!createLocked) setActive(createIndex);
|
|
818
|
+
},
|
|
819
|
+
className: cn(
|
|
820
|
+
rowClass(active === createIndex && !createLocked),
|
|
821
|
+
CREATE_ROW_CLASS,
|
|
822
|
+
createLocked && DISABLED_ROW_CLASS
|
|
823
|
+
),
|
|
824
|
+
children: createRowContent
|
|
825
|
+
}
|
|
826
|
+
) })
|
|
827
|
+
] })
|
|
691
828
|
] })
|
|
692
829
|
);
|
|
693
830
|
}
|