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