@eifi1/ui-kit 0.21.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 +19 -14
- package/dist/components/account-chips.d.ts +10 -3
- package/dist/components/account-chips.js +5 -2
- package/dist/components/account-chips.js.map +1 -1
- package/dist/components/account-settings.d.ts +33 -2
- package/dist/components/account-settings.js +43 -21
- package/dist/components/account-settings.js.map +1 -1
- package/dist/components/amount-input.d.ts +53 -14
- package/dist/components/amount-input.js +17 -28
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.d.ts +29 -0
- package/dist/components/autocomplete.js +134 -104
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/button-group.d.ts +19 -14
- package/dist/components/calculator.d.ts +19 -14
- package/dist/components/checkbox-group.d.ts +104 -0
- package/dist/components/checkbox-group.js +111 -0
- package/dist/components/checkbox-group.js.map +1 -0
- package/dist/components/checkbox.d.ts +19 -0
- package/dist/components/checkbox.js +30 -7
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/chip.d.ts +18 -0
- package/dist/components/chip.js +47 -10
- package/dist/components/chip.js.map +1 -1
- 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 +91 -2
- package/dist/components/combobox.js +454 -308
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +69 -161
- package/dist/components/confirm-dialog.js +7 -8
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/copy-button.d.ts +16 -11
- package/dist/components/country-select.d.ts +167 -0
- package/dist/components/country-select.js +293 -0
- package/dist/components/country-select.js.map +1 -0
- package/dist/components/currency-select.d.ts +17 -1
- package/dist/components/currency-select.js +56 -23
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +69 -166
- package/dist/components/danger-confirm.js +144 -50
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-cells.d.ts +1 -2
- package/dist/components/data-table-filter-popover.d.ts +1 -2
- package/dist/components/data-table-filters.d.ts +1 -2
- package/dist/components/data-table-labels.d.ts +4 -97
- package/dist/components/data-table-labels.js +9 -1
- package/dist/components/data-table-labels.js.map +1 -1
- package/dist/components/data-table-pagination.d.ts +3 -1
- package/dist/components/data-table.d.ts +1 -2
- package/dist/components/data-table.js +98 -3
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.d.ts +66 -5
- package/dist/components/date-picker.js +378 -66
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/entity-combobox.d.ts +42 -1
- package/dist/components/entity-combobox.js +154 -113
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/facing-pair.d.ts +19 -14
- package/dist/components/field-parts.d.ts +224 -0
- package/dist/components/field-parts.js +156 -0
- package/dist/components/field-parts.js.map +1 -0
- 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 +19 -14
- package/dist/components/file-button.js +13 -3
- package/dist/components/file-button.js.map +1 -1
- package/dist/components/file-dropzone.d.ts +41 -15
- package/dist/components/file-dropzone.js +57 -34
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/form-actions.d.ts +18 -13
- package/dist/components/form-actions.js +69 -5
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/iban-input.d.ts +69 -0
- package/dist/components/iban-input.js +125 -0
- package/dist/components/iban-input.js.map +1 -0
- package/dist/components/icon-picker.d.ts +21 -2
- package/dist/components/icon-picker.js +19 -4
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/inline-edit-field.d.ts +167 -0
- package/dist/components/inline-edit-field.js +293 -0
- package/dist/components/inline-edit-field.js.map +1 -0
- package/dist/components/language-select.d.ts +130 -0
- package/dist/components/language-select.js +18 -0
- package/dist/components/language-select.js.map +1 -0
- package/dist/components/line-items.d.ts +25 -3
- package/dist/components/line-items.js +55 -46
- package/dist/components/line-items.js.map +1 -1
- package/dist/components/list.d.ts +25 -0
- package/dist/components/list.js +16 -5
- package/dist/components/list.js.map +1 -1
- package/dist/components/money-field.d.ts +32 -14
- package/dist/components/money-field.js.map +1 -1
- package/dist/components/month-picker.d.ts +52 -4
- package/dist/components/month-picker.js +291 -86
- 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/multi-select.d.ts +8 -1
- package/dist/components/multi-select.js +9 -4
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/number-field.d.ts +34 -19
- package/dist/components/number-field.js +6 -20
- package/dist/components/number-field.js.map +1 -1
- package/dist/components/number-input.d.ts +79 -19
- package/dist/components/number-input.js +90 -38
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.d.ts +19 -14
- package/dist/components/one-time-code-input.d.ts +100 -0
- package/dist/components/one-time-code-input.js +137 -0
- package/dist/components/one-time-code-input.js.map +1 -0
- package/dist/components/phone-input.d.ts +69 -0
- package/dist/components/phone-input.js +171 -0
- package/dist/components/phone-input.js.map +1 -0
- 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 +19 -14
- package/dist/components/settings-fields.d.ts +19 -14
- package/dist/components/share-card.d.ts +16 -11
- package/dist/components/sign-chip.d.ts +66 -0
- package/dist/components/sign-chip.js +39 -0
- package/dist/components/sign-chip.js.map +1 -0
- package/dist/components/swatch-picker.d.ts +43 -2
- package/dist/components/swatch-picker.js +80 -32
- package/dist/components/swatch-picker.js.map +1 -1
- package/dist/components/switch.d.ts +19 -0
- package/dist/components/switch.js +24 -6
- package/dist/components/switch.js.map +1 -1
- package/dist/components/text-link.d.ts +18 -13
- package/dist/components/tile-radio.d.ts +88 -13
- package/dist/components/tile-radio.js +28 -11
- package/dist/components/tile-radio.js.map +1 -1
- package/dist/components/time-input.d.ts +24 -15
- package/dist/components/time-input.js.map +1 -1
- package/dist/components/toggle-group.d.ts +47 -1
- package/dist/components/toggle-group.js +110 -69
- 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 +16 -11
- package/dist/components/ui.js +284 -88
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -2
- package/dist/{data-table-3mi2R3so.d.ts → data-table-labels-B7OdnM0S.d.ts} +140 -3
- package/dist/data-table.d.ts +1 -2
- package/dist/data-table.js +2 -1
- package/dist/data-table.js.map +1 -1
- package/dist/feedback/feedback-attachment.d.ts +1 -1
- package/dist/feedback/feedback-attachment.js +348 -41
- 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 -253
- package/dist/feedback/feedback-thread.js +46 -10
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/{kit-labels-D1J2_jyD.d.ts → feedback-BxeQVzwq.d.ts} +1206 -20
- package/dist/{feedback-attachment-WFiXJ8We.d.ts → feedback-attachment-fGAzZPf0.d.ts} +178 -11
- package/dist/feedback.d.ts +66 -2
- package/dist/hooks/use-file-drop.d.ts +19 -14
- package/dist/i18n/defaults.d.ts +19 -14
- package/dist/i18n/defaults.js +19 -2
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +19 -14
- package/dist/i18n/german.js +84 -5
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +15 -10
- package/dist/i18n/kit-labels.js +8 -2
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +19 -14
- package/dist/i18n/locales/de-CH.d.ts +19 -14
- package/dist/i18n/locales/en.d.ts +19 -14
- package/dist/i18n/locales/en.js +16 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +19 -14
- package/dist/i18n/locales/es.js +83 -5
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +19 -14
- package/dist/i18n/locales/fr.js +82 -5
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +19 -14
- package/dist/i18n/locales/hu.js +85 -5
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +19 -14
- package/dist/i18n/locales/it.js +84 -5
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +19 -14
- package/dist/i18n/locales/zh.js +80 -5
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +19 -14
- package/dist/i18n/review.js +27 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +21 -10
- package/dist/index.js +73 -2
- 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/countries.d.ts +43 -0
- package/dist/lib/countries.js +39 -0
- package/dist/lib/countries.js.map +1 -0
- package/dist/lib/decimal-marks.d.ts +46 -0
- package/dist/lib/decimal-marks.js +40 -0
- package/dist/lib/decimal-marks.js.map +1 -0
- package/dist/lib/iban.d.ts +98 -0
- package/dist/lib/iban.js +154 -0
- package/dist/lib/iban.js.map +1 -0
- package/dist/lib/isin.d.ts +30 -0
- package/dist/lib/isin.js +36 -0
- package/dist/lib/isin.js.map +1 -0
- package/dist/lib/phone.d.ts +69 -0
- package/dist/lib/phone.js +121 -0
- package/dist/lib/phone.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 +233 -18
- package/dist/rhf/fields.js +456 -3
- package/dist/rhf/fields.js.map +1 -1
- package/dist/rhf/form.d.ts +19 -14
- package/dist/rhf.d.ts +22 -15
- package/dist/rhf.js.map +1 -1
- package/dist/shell/app-shell.d.ts +18 -13
- package/dist/shell/top-bar-brand.d.ts +19 -14
- 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 +18 -13
- package/dist/table-text.d.ts +1 -1
- package/dist/tour/tour.js +20 -24
- package/dist/tour/tour.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +49 -16
- package/dist/wizard/stepper-nav.js +4 -0
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard.d.ts +19 -14
- package/package.json +1 -1
- package/src/components/account-chips.tsx +17 -3
- package/src/components/account-settings.tsx +92 -26
- package/src/components/amount-input.tsx +68 -56
- package/src/components/autocomplete.tsx +198 -114
- package/src/components/checkbox-group.tsx +229 -0
- package/src/components/checkbox.tsx +72 -8
- package/src/components/chip.tsx +80 -10
- package/src/components/column-mapper.tsx +666 -0
- package/src/components/combobox-core.tsx +82 -9
- package/src/components/combobox.tsx +661 -340
- package/src/components/confirm-dialog.tsx +12 -8
- package/src/components/country-select.tsx +556 -0
- package/src/components/currency-select.tsx +109 -33
- package/src/components/danger-confirm.tsx +429 -82
- package/src/components/data-table-labels.ts +16 -1
- package/src/components/data-table.tsx +175 -6
- package/src/components/date-picker.tsx +595 -71
- package/src/components/entity-combobox.tsx +235 -124
- package/src/components/field-parts.tsx +403 -0
- package/src/components/field-strip.tsx +149 -0
- package/src/components/file-button.tsx +36 -3
- package/src/components/file-dropzone.tsx +106 -38
- package/src/components/form-actions.tsx +147 -6
- package/src/components/iban-input.tsx +231 -0
- package/src/components/icon-picker.tsx +47 -6
- package/src/components/inline-edit-field.tsx +533 -0
- package/src/components/language-select.tsx +78 -0
- package/src/components/line-items.tsx +35 -2
- package/src/components/list.tsx +55 -6
- package/src/components/money-field.tsx +13 -0
- package/src/components/month-picker.tsx +400 -63
- package/src/components/multi-entity-combobox.tsx +207 -120
- package/src/components/multi-select.tsx +80 -58
- package/src/components/number-field.tsx +28 -46
- package/src/components/number-input.tsx +210 -43
- package/src/components/one-time-code-input.tsx +288 -0
- package/src/components/phone-input.tsx +299 -0
- package/src/components/reauth-dialog.tsx +17 -18
- package/src/components/sign-chip.tsx +103 -0
- package/src/components/swatch-picker.tsx +143 -31
- package/src/components/switch.tsx +58 -7
- package/src/components/tile-radio.tsx +145 -29
- package/src/components/time-input.tsx +8 -1
- package/src/components/toggle-group.tsx +206 -73
- package/src/components/trigger-aria.ts +5 -0
- package/src/components/ui.tsx +479 -138
- package/src/data-table.ts +2 -1
- package/src/feedback/feedback-attachment.tsx +597 -46
- package/src/feedback/feedback-dialog.tsx +9 -3
- package/src/feedback/feedback-inbox.tsx +3 -2
- package/src/feedback/feedback-thread.tsx +113 -9
- package/src/i18n/defaults.ts +18 -1
- package/src/i18n/german.ts +89 -0
- package/src/i18n/kit-labels.tsx +82 -2
- package/src/i18n/locales/en.ts +36 -4
- package/src/i18n/locales/es.ts +87 -0
- package/src/i18n/locales/fr.ts +87 -0
- package/src/i18n/locales/hu.ts +83 -0
- package/src/i18n/locales/it.ts +88 -0
- package/src/i18n/locales/zh.ts +76 -0
- package/src/i18n/review.ts +26 -0
- package/src/index.ts +71 -3
- package/src/lib/column-mapping.ts +234 -0
- package/src/lib/countries.ts +91 -0
- package/src/lib/decimal-marks.ts +99 -0
- package/src/lib/iban.ts +171 -0
- package/src/lib/isin.ts +62 -0
- package/src/lib/phone.ts +211 -0
- package/src/lib/table-text.ts +271 -0
- package/src/rhf/fields.tsx +860 -9
- package/src/rhf.ts +3 -1
- package/src/shell/topbar-action-menu.tsx +134 -38
- package/src/tour/tour.tsx +66 -28
- package/src/wizard/stepper-nav.tsx +35 -1
|
@@ -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,6 +23,17 @@ import {
|
|
|
21
23
|
useComboboxFieldError
|
|
22
24
|
} from "./combobox-core.js";
|
|
23
25
|
import { DEFAULT_COMBOBOX_LABELS, useKitLabels } from "../i18n/kit-labels.js";
|
|
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";
|
|
24
37
|
const LIST_CLASS = SUGGESTION_LIST_CLASS;
|
|
25
38
|
function usePrimaryPressOnly() {
|
|
26
39
|
const auxPress = useRef(false);
|
|
@@ -60,39 +73,48 @@ function SuggestionList({
|
|
|
60
73
|
);
|
|
61
74
|
}
|
|
62
75
|
const rowClass = suggestionRowClass;
|
|
63
|
-
function
|
|
64
|
-
|
|
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
|
-
|
|
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;
|
|
113
|
+
const hintParts = useFieldHint(hint, ariaDescribedBy);
|
|
92
114
|
const field = useComboboxFieldError(
|
|
93
115
|
error,
|
|
94
116
|
invalid || ariaInvalid === true || ariaInvalid === "true",
|
|
95
|
-
|
|
117
|
+
hintParts.describedBy
|
|
96
118
|
);
|
|
97
119
|
const generated = useId();
|
|
98
120
|
const fieldId = id ?? generated;
|
|
@@ -102,6 +124,10 @@ function Combobox({
|
|
|
102
124
|
const { open, setOpen, wrapperRef, panelRef } = useDropdown({ backCloses: !isPhone });
|
|
103
125
|
const primaryOnly = usePrimaryPressOnly();
|
|
104
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);
|
|
105
131
|
const sheetInputRef = useRef(null);
|
|
106
132
|
const fieldRef = useRef(null);
|
|
107
133
|
const [typing, setTyping] = useState(false);
|
|
@@ -140,7 +166,8 @@ function Combobox({
|
|
|
140
166
|
});
|
|
141
167
|
return heads;
|
|
142
168
|
}, [matches, groupBy]);
|
|
143
|
-
const
|
|
169
|
+
const take = (v) => {
|
|
170
|
+
if (locked) return;
|
|
144
171
|
onChange(v);
|
|
145
172
|
setOpen(false);
|
|
146
173
|
setActive(-1);
|
|
@@ -148,6 +175,7 @@ function Combobox({
|
|
|
148
175
|
};
|
|
149
176
|
const activeId = !isPhone && active >= 0 && active < matches.length ? optionId(active) : void 0;
|
|
150
177
|
useActiveOptionScroll(activeId);
|
|
178
|
+
const withLock = (box) => locked ? /* @__PURE__ */ jsx(LockedReason, { lock, className: "block", children: box }) : box;
|
|
151
179
|
const typed = value.trim();
|
|
152
180
|
const createRow = createLabel && typed.length > 0 && !options.some((o) => o.toLowerCase() === typed.toLowerCase()) ? createLabel(typed) : null;
|
|
153
181
|
return (
|
|
@@ -156,99 +184,117 @@ function Combobox({
|
|
|
156
184
|
// which is the combobox a reader meets. Spread FIRST, so the field's ARIA and the
|
|
157
185
|
// handlers carrying live #309 and dev#549 cannot be replaced from outside.
|
|
158
186
|
/* @__PURE__ */ jsxs("div", { ...rest, ref: wrapperRef, className: cn("relative", className), children: [
|
|
159
|
-
label !== void 0 && /* @__PURE__ */ jsx(ComboboxFieldLabel, { htmlFor: fieldId, className:
|
|
160
|
-
/* @__PURE__ */
|
|
161
|
-
/*
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
setActive(-1);
|
|
196
|
-
setTyping(true);
|
|
197
|
-
},
|
|
198
|
-
onKeyDown: (e) => {
|
|
199
|
-
if (e.key === "ArrowDown") {
|
|
200
|
-
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;
|
|
201
223
|
setOpen(true);
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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") {
|
|
208
247
|
e.preventDefault();
|
|
209
|
-
|
|
210
|
-
} else {
|
|
211
|
-
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") {
|
|
212
262
|
setOpen(false);
|
|
213
|
-
|
|
263
|
+
setActive(-1);
|
|
214
264
|
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
)
|
|
246
|
-
] }),
|
|
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 }) }),
|
|
292
|
+
/* @__PURE__ */ jsx(FieldCaption, { parts: hintParts }),
|
|
247
293
|
field.errorEl,
|
|
248
294
|
isPhone && /* @__PURE__ */ jsx(
|
|
249
295
|
PickerSheet,
|
|
250
296
|
{
|
|
251
|
-
open: open && !
|
|
297
|
+
open: open && !inert,
|
|
252
298
|
onClose: () => setOpen(false),
|
|
253
299
|
title: label,
|
|
254
300
|
query: value,
|
|
@@ -269,14 +315,14 @@ function Combobox({
|
|
|
269
315
|
type: "button",
|
|
270
316
|
role: "option",
|
|
271
317
|
"aria-selected": false,
|
|
272
|
-
onClick: () =>
|
|
318
|
+
onClick: () => take(typed),
|
|
273
319
|
className: cn(SHEET_ROW_CLASS, "font-medium text-[var(--brand)]"),
|
|
274
320
|
children: createRow
|
|
275
321
|
}
|
|
276
322
|
) }),
|
|
277
323
|
matches.map((o, i) => {
|
|
278
324
|
const group = groupHeadings?.get(i);
|
|
279
|
-
return /* @__PURE__ */ jsxs(
|
|
325
|
+
return /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
280
326
|
group !== void 0 && /* @__PURE__ */ jsx(
|
|
281
327
|
"li",
|
|
282
328
|
{
|
|
@@ -291,7 +337,7 @@ function Combobox({
|
|
|
291
337
|
type: "button",
|
|
292
338
|
role: "option",
|
|
293
339
|
"aria-selected": o === value,
|
|
294
|
-
onClick: () =>
|
|
340
|
+
onClick: () => take(o),
|
|
295
341
|
className: cn(
|
|
296
342
|
SHEET_ROW_CLASS,
|
|
297
343
|
optionAdornment && "flex items-center justify-between gap-2"
|
|
@@ -307,7 +353,7 @@ function Combobox({
|
|
|
307
353
|
] })
|
|
308
354
|
}
|
|
309
355
|
),
|
|
310
|
-
!isPhone && open && !
|
|
356
|
+
!isPhone && open && !inert && (matches.length > 0 || createRow) && /* @__PURE__ */ jsxs(SuggestionList, { id: listboxId, anchorRef: fieldRef, panelRef, children: [
|
|
311
357
|
createRow && /* @__PURE__ */ jsx("li", { role: "presentation", children: /* @__PURE__ */ jsx(
|
|
312
358
|
"button",
|
|
313
359
|
{
|
|
@@ -317,7 +363,7 @@ function Combobox({
|
|
|
317
363
|
tabIndex: -1,
|
|
318
364
|
onMouseDown: (e) => {
|
|
319
365
|
e.preventDefault();
|
|
320
|
-
|
|
366
|
+
take(typed);
|
|
321
367
|
},
|
|
322
368
|
className: cn(rowClass(false), "font-medium text-[var(--brand)]"),
|
|
323
369
|
children: createRow
|
|
@@ -325,7 +371,7 @@ function Combobox({
|
|
|
325
371
|
) }),
|
|
326
372
|
matches.map((o, i) => {
|
|
327
373
|
const group = groupHeadings?.get(i);
|
|
328
|
-
return /* @__PURE__ */ jsxs(
|
|
374
|
+
return /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
329
375
|
group !== void 0 && /* @__PURE__ */ jsx(
|
|
330
376
|
"li",
|
|
331
377
|
{
|
|
@@ -344,7 +390,7 @@ function Combobox({
|
|
|
344
390
|
tabIndex: -1,
|
|
345
391
|
onMouseDown: (e) => {
|
|
346
392
|
e.preventDefault();
|
|
347
|
-
|
|
393
|
+
take(o);
|
|
348
394
|
},
|
|
349
395
|
onMouseEnter: () => setActive(i),
|
|
350
396
|
className: cn(
|
|
@@ -367,38 +413,47 @@ function Combobox({
|
|
|
367
413
|
] })
|
|
368
414
|
);
|
|
369
415
|
}
|
|
370
|
-
function InlineEntityCombobox({
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
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;
|
|
397
451
|
const value = rawValue == null || rawValue === clearValue ? null : rawValue;
|
|
452
|
+
const hintParts = useFieldHint(hint, ariaDescribedBy);
|
|
398
453
|
const field = useComboboxFieldError(
|
|
399
454
|
error,
|
|
400
455
|
invalid || ariaInvalid === true || ariaInvalid === "true",
|
|
401
|
-
|
|
456
|
+
hintParts.describedBy
|
|
402
457
|
);
|
|
403
458
|
const generated = useId();
|
|
404
459
|
const fieldId = id ?? generated;
|
|
@@ -415,14 +470,24 @@ function InlineEntityCombobox({
|
|
|
415
470
|
const labels = useKitLabels("combobox", DEFAULT_COMBOBOX_LABELS, {
|
|
416
471
|
search: searchPlaceholder,
|
|
417
472
|
noResults: emptyLabel,
|
|
418
|
-
clear: clearLabel
|
|
473
|
+
clear: clearLabel,
|
|
474
|
+
create: createLabel
|
|
419
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);
|
|
420
485
|
const selected = useMemo(
|
|
421
486
|
() => value == null ? null : options.find((o) => o.value === value) ?? null,
|
|
422
487
|
[options, value]
|
|
423
488
|
);
|
|
424
489
|
const shown = text ?? selected?.label ?? "";
|
|
425
|
-
const showClear = Boolean(clearable && value != null && !
|
|
490
|
+
const showClear = Boolean(clearable && value != null && !inert);
|
|
426
491
|
const typedQuery = text !== null && text !== (selected?.label ?? "") ? text.trim().toLowerCase() : "";
|
|
427
492
|
const query = isPhone ? sheetQuery.trim().toLowerCase() : typedQuery;
|
|
428
493
|
const matches = useMemo(() => {
|
|
@@ -444,21 +509,37 @@ function InlineEntityCombobox({
|
|
|
444
509
|
}
|
|
445
510
|
return [...blocks.values()].flat();
|
|
446
511
|
}, [options, query]);
|
|
447
|
-
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;
|
|
448
523
|
useActiveOptionScroll(activeId);
|
|
449
524
|
const close = () => {
|
|
450
525
|
setOpen(false);
|
|
451
526
|
setActive(-1);
|
|
452
527
|
setSheetQuery("");
|
|
453
528
|
};
|
|
454
|
-
const
|
|
455
|
-
if (o.disabled) return;
|
|
529
|
+
const take = (o) => {
|
|
530
|
+
if (o.disabled || locked) return;
|
|
456
531
|
if (o.value !== value) onChange(o.value);
|
|
457
532
|
setText(null);
|
|
458
533
|
close();
|
|
459
534
|
};
|
|
535
|
+
const create = () => {
|
|
536
|
+
if (!onCreate || locked || createLocked) return;
|
|
537
|
+
onCreate(createQuery);
|
|
538
|
+
setText(null);
|
|
539
|
+
close();
|
|
540
|
+
};
|
|
460
541
|
const reconcile = () => {
|
|
461
|
-
if (text !== null) {
|
|
542
|
+
if (text !== null && !locked) {
|
|
462
543
|
const q = text.trim();
|
|
463
544
|
if (!q) {
|
|
464
545
|
if (value != null) onChange(clearValue);
|
|
@@ -469,122 +550,145 @@ function InlineEntityCombobox({
|
|
|
469
550
|
const ids = new Set(hits.map((h) => h.value));
|
|
470
551
|
if (ids.size === 1 && hits[0].value !== value) onChange(hits[0].value);
|
|
471
552
|
}
|
|
472
|
-
setText(null);
|
|
473
553
|
}
|
|
554
|
+
setText(null);
|
|
474
555
|
close();
|
|
475
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;
|
|
476
565
|
return (
|
|
477
566
|
// `rest` dresses the outer box — a `data-tour` anchor, a test id. Not the NAME,
|
|
478
567
|
// description, invalid or required state: those belong on the <input> below,
|
|
479
568
|
// which is the combobox a reader meets. Spread FIRST, so the field's ARIA and the
|
|
480
569
|
// handlers carrying live #309 and dev#549 cannot be replaced from outside.
|
|
481
570
|
/* @__PURE__ */ jsxs("div", { ...rest, ref: wrapperRef, className: cn("relative", className), children: [
|
|
482
|
-
label !== void 0 && /* @__PURE__ */ jsx(ComboboxFieldLabel, { htmlFor: fieldId, className:
|
|
483
|
-
/* @__PURE__ */
|
|
484
|
-
/*
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
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
|
-
setActive(-1);
|
|
518
|
-
},
|
|
519
|
-
onKeyDown: (e) => {
|
|
520
|
-
if (e.key === "ArrowDown") {
|
|
521
|
-
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();
|
|
522
606
|
setOpen(true);
|
|
523
|
-
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
}
|
|
528
|
-
|
|
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") {
|
|
529
625
|
e.preventDefault();
|
|
530
|
-
|
|
531
|
-
} 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") {
|
|
532
639
|
reconcile();
|
|
533
640
|
}
|
|
534
|
-
}
|
|
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: () => {
|
|
535
658
|
setText(null);
|
|
536
659
|
close();
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
),
|
|
565
|
-
children: /* @__PURE__ */ jsx(X, { "aria-hidden": true, className: "size-4" })
|
|
566
|
-
}
|
|
567
|
-
) : /* @__PURE__ */ jsx(
|
|
568
|
-
ChevronDown,
|
|
569
|
-
{
|
|
570
|
-
"aria-hidden": true,
|
|
571
|
-
onMouseDown: (e) => {
|
|
572
|
-
e.preventDefault();
|
|
573
|
-
if (!disabled) setOpen((o) => !o);
|
|
574
|
-
},
|
|
575
|
-
className: cn(
|
|
576
|
-
"absolute end-2.5 top-1/2 size-4 -translate-y-1/2 text-[var(--text-placeholder)]",
|
|
577
|
-
// The box above does the dimming; dimming here too would halve it again.
|
|
578
|
-
!disabled && "cursor-pointer"
|
|
579
|
-
)
|
|
580
|
-
}
|
|
581
|
-
)
|
|
582
|
-
] }),
|
|
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 }) }),
|
|
686
|
+
/* @__PURE__ */ jsx(FieldCaption, { parts: hintParts }),
|
|
583
687
|
field.errorEl,
|
|
584
688
|
isPhone && /* @__PURE__ */ jsx(
|
|
585
689
|
PickerSheet,
|
|
586
690
|
{
|
|
587
|
-
open: open && !
|
|
691
|
+
open: open && !inert,
|
|
588
692
|
onClose: reconcile,
|
|
589
693
|
title: label,
|
|
590
694
|
query: sheetQuery,
|
|
@@ -600,7 +704,7 @@ function InlineEntityCombobox({
|
|
|
600
704
|
// Keyed by group AND value, like combobox-core.tsx: an option may
|
|
601
705
|
// deliberately appear twice (see `reconcile`), and a bare value key
|
|
602
706
|
// would collide.
|
|
603
|
-
/* @__PURE__ */ jsxs(
|
|
707
|
+
/* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
604
708
|
o.group && o.group !== matches[i - 1]?.group && /* @__PURE__ */ jsx(
|
|
605
709
|
"li",
|
|
606
710
|
{
|
|
@@ -616,7 +720,7 @@ function InlineEntityCombobox({
|
|
|
616
720
|
role: "option",
|
|
617
721
|
"aria-selected": o.value === value,
|
|
618
722
|
"aria-disabled": o.disabled || void 0,
|
|
619
|
-
onClick: () =>
|
|
723
|
+
onClick: () => take(o),
|
|
620
724
|
className: cn(
|
|
621
725
|
SHEET_ROW_CLASS,
|
|
622
726
|
o.value === value && "font-medium",
|
|
@@ -627,58 +731,100 @@ function InlineEntityCombobox({
|
|
|
627
731
|
) })
|
|
628
732
|
] }, `${o.group ?? ""}|${String(o.value)}`)
|
|
629
733
|
)),
|
|
630
|
-
|
|
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 })
|
|
631
751
|
] })
|
|
632
752
|
}
|
|
633
753
|
),
|
|
634
|
-
!isPhone && open && !
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
"
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
e
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
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
|
+
] })
|
|
682
828
|
] })
|
|
683
829
|
);
|
|
684
830
|
}
|