@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
|
@@ -5,10 +5,11 @@ import { Calendar, ChevronDown, ChevronLeft, ChevronRight } from "lucide-react";
|
|
|
5
5
|
import { cn } from "../lib/cn.js";
|
|
6
6
|
import { dirOf, horizontalStep } from "../lib/direction.js";
|
|
7
7
|
import { monthKey, pad } from "../lib/dates.js";
|
|
8
|
-
import { Button,
|
|
8
|
+
import { Button, FIELD_FLOATING_PAD, FIELD_INVALID, FIELD_TRIGGER, IconButton } from "./ui.js";
|
|
9
9
|
import { Popover } from "./popover.js";
|
|
10
10
|
import { splitTriggerAria } from "./trigger-aria.js";
|
|
11
|
-
import { useKitLabels, useKitLocale } from "../i18n/kit-labels.js";
|
|
11
|
+
import { useKitDateFormatter, useKitLabels, useKitLocale } from "../i18n/kit-labels.js";
|
|
12
|
+
import { FieldBox, FieldLabelLine, hasContent, useFieldMessages } from "./field-parts.js";
|
|
12
13
|
const DEFAULT_MONTH_PICKER_LABELS = {
|
|
13
14
|
previousYear: "Previous year",
|
|
14
15
|
nextYear: "Next year",
|
|
@@ -16,7 +17,11 @@ const DEFAULT_MONTH_PICKER_LABELS = {
|
|
|
16
17
|
month: (monthYear) => monthYear,
|
|
17
18
|
previousMonth: "Previous month",
|
|
18
19
|
nextMonth: "Next month",
|
|
19
|
-
today: "Today"
|
|
20
|
+
today: "Today",
|
|
21
|
+
yearPanel: "Choose a year",
|
|
22
|
+
earlierYears: "Earlier years",
|
|
23
|
+
laterYears: "Later years",
|
|
24
|
+
thisYear: "This year"
|
|
20
25
|
};
|
|
21
26
|
function useMonthPickerLabels(partial) {
|
|
22
27
|
return useKitLabels("monthPicker", DEFAULT_MONTH_PICKER_LABELS, partial);
|
|
@@ -44,6 +49,12 @@ function firstOf({ year, month }) {
|
|
|
44
49
|
}
|
|
45
50
|
const DEFAULT_TRIGGER_FORMAT = { month: "long", year: "numeric" };
|
|
46
51
|
const MONTH_NAME_FORMAT = { month: "long", year: "numeric" };
|
|
52
|
+
const YEAR_FORMAT = { year: "numeric" };
|
|
53
|
+
const YEAR = /^(\d{4})/;
|
|
54
|
+
function parseYear(key) {
|
|
55
|
+
const m = key ? YEAR.exec(key) : null;
|
|
56
|
+
return m ? Number(m[1]) : null;
|
|
57
|
+
}
|
|
47
58
|
function useFocusBackOnClose(open, triggerRef) {
|
|
48
59
|
const wasOpen = useRef(false);
|
|
49
60
|
useEffect(() => {
|
|
@@ -100,6 +111,7 @@ function MonthFieldTrigger({
|
|
|
100
111
|
valueId,
|
|
101
112
|
panelId,
|
|
102
113
|
padded,
|
|
114
|
+
small,
|
|
103
115
|
disabled,
|
|
104
116
|
invalid,
|
|
105
117
|
className,
|
|
@@ -119,6 +131,7 @@ function MonthFieldTrigger({
|
|
|
119
131
|
"aria-expanded": open,
|
|
120
132
|
id: aria.id,
|
|
121
133
|
"aria-invalid": invalid || aria["aria-invalid"] === true || aria["aria-invalid"] === "true" || void 0,
|
|
134
|
+
"aria-required": aria["aria-required"],
|
|
122
135
|
"aria-labelledby": aria["aria-label"] && !aria["aria-labelledby"] ? void 0 : labelledBy,
|
|
123
136
|
"aria-label": aria["aria-label"],
|
|
124
137
|
"aria-describedby": aria["aria-describedby"],
|
|
@@ -126,6 +139,10 @@ function MonthFieldTrigger({
|
|
|
126
139
|
FIELD_TRIGGER,
|
|
127
140
|
"pe-9",
|
|
128
141
|
padded && FIELD_FLOATING_PAD,
|
|
142
|
+
// keksdose K13 (live #260): an IconButton's 36px, and only as wide as the
|
|
143
|
+
// month — `py-0` with a fixed height so the box is 36px whatever the type's
|
|
144
|
+
// line height. `pe-9` stays: the calendar glyph still sits at the end.
|
|
145
|
+
small && "h-9 w-auto py-0",
|
|
129
146
|
disabled && "cursor-not-allowed opacity-50",
|
|
130
147
|
invalid && FIELD_INVALID,
|
|
131
148
|
className
|
|
@@ -291,50 +308,212 @@ function MonthGrid({
|
|
|
291
308
|
}) }, row)) })
|
|
292
309
|
] });
|
|
293
310
|
}
|
|
311
|
+
const YEAR_PAGE = 12;
|
|
312
|
+
function YearGrid({
|
|
313
|
+
value,
|
|
314
|
+
onPick,
|
|
315
|
+
locale,
|
|
316
|
+
minYear,
|
|
317
|
+
maxYear,
|
|
318
|
+
currentYear,
|
|
319
|
+
labels
|
|
320
|
+
}) {
|
|
321
|
+
const clamp = (y) => Math.min(maxYear ?? y, Math.max(minYear ?? y, y));
|
|
322
|
+
const whole = minYear !== null && maxYear !== null && maxYear >= minYear && maxYear - minYear < YEAR_PAGE ? { first: minYear, count: maxYear - minYear + 1 } : null;
|
|
323
|
+
const [active, setActive] = useState(() => clamp(value ?? currentYear));
|
|
324
|
+
const anchor = minYear ?? (maxYear !== null ? maxYear - (YEAR_PAGE - 1) : 0);
|
|
325
|
+
const first = whole ? whole.first : anchor + Math.floor((active - anchor) / YEAR_PAGE) * YEAR_PAGE;
|
|
326
|
+
const count = whole ? whole.count : YEAR_PAGE;
|
|
327
|
+
const years = Array.from({ length: count }, (_, i) => first + i);
|
|
328
|
+
const outOfBounds = (y) => minYear !== null && y < minYear || maxYear !== null && y > maxYear;
|
|
329
|
+
const gridRef = useRef(null);
|
|
330
|
+
const captionId = `${useId()}-years`;
|
|
331
|
+
const yearFormat = useMemo(() => new Intl.DateTimeFormat(locale, YEAR_FORMAT), [locale]);
|
|
332
|
+
const caption = yearFormat.formatRange(new Date(first, 0, 1), new Date(first + count - 1, 0, 1));
|
|
333
|
+
const pendingFocus = useRef(null);
|
|
334
|
+
useEffect(() => {
|
|
335
|
+
const year = pendingFocus.current;
|
|
336
|
+
if (year === null) return;
|
|
337
|
+
pendingFocus.current = null;
|
|
338
|
+
gridRef.current?.querySelector(`[data-year="${year}"]`)?.focus();
|
|
339
|
+
});
|
|
340
|
+
useEffect(() => {
|
|
341
|
+
gridRef.current?.querySelector('[tabindex="0"]')?.focus();
|
|
342
|
+
}, []);
|
|
343
|
+
const moveTo = (next, focus) => {
|
|
344
|
+
const year = clamp(next);
|
|
345
|
+
if (focus) pendingFocus.current = year;
|
|
346
|
+
setActive(year);
|
|
347
|
+
};
|
|
348
|
+
const onCellKeyDown = (e) => {
|
|
349
|
+
const step = horizontalStep(e.key, e.currentTarget);
|
|
350
|
+
const col = (active - first) % COLUMNS;
|
|
351
|
+
let delta;
|
|
352
|
+
switch (step ? "horizontal" : e.key) {
|
|
353
|
+
case "horizontal":
|
|
354
|
+
delta = step;
|
|
355
|
+
break;
|
|
356
|
+
case "ArrowUp":
|
|
357
|
+
delta = -COLUMNS;
|
|
358
|
+
break;
|
|
359
|
+
case "ArrowDown":
|
|
360
|
+
delta = COLUMNS;
|
|
361
|
+
break;
|
|
362
|
+
case "Home":
|
|
363
|
+
delta = -col;
|
|
364
|
+
break;
|
|
365
|
+
case "End":
|
|
366
|
+
delta = Math.min(COLUMNS - 1 - col, first + count - 1 - active);
|
|
367
|
+
break;
|
|
368
|
+
case "PageUp":
|
|
369
|
+
delta = -YEAR_PAGE;
|
|
370
|
+
break;
|
|
371
|
+
case "PageDown":
|
|
372
|
+
delta = YEAR_PAGE;
|
|
373
|
+
break;
|
|
374
|
+
default:
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
e.preventDefault();
|
|
378
|
+
if (delta !== 0) moveTo(active + delta, true);
|
|
379
|
+
};
|
|
380
|
+
const prevBlocked = minYear !== null && first - 1 < minYear;
|
|
381
|
+
const nextBlocked = maxYear !== null && first + count > maxYear;
|
|
382
|
+
const arrow = "flex size-7 items-center justify-center rounded text-[var(--text-muted)] hover:bg-[var(--bg-hover)] disabled:cursor-not-allowed disabled:opacity-30 disabled:hover:bg-transparent";
|
|
383
|
+
return /* @__PURE__ */ jsxs("div", { className: "select-none", children: [
|
|
384
|
+
/* @__PURE__ */ jsxs("div", { className: cn("mb-1 flex items-center", whole ? "h-7 justify-center" : "justify-between"), children: [
|
|
385
|
+
!whole && /* @__PURE__ */ jsx(
|
|
386
|
+
"button",
|
|
387
|
+
{
|
|
388
|
+
type: "button",
|
|
389
|
+
"aria-label": labels.earlierYears,
|
|
390
|
+
disabled: prevBlocked,
|
|
391
|
+
onClick: () => moveTo(active - YEAR_PAGE, false),
|
|
392
|
+
className: arrow,
|
|
393
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4 rtl:-scale-x-100" })
|
|
394
|
+
}
|
|
395
|
+
),
|
|
396
|
+
/* @__PURE__ */ jsx("div", { id: captionId, "aria-live": "polite", className: "text-sm font-semibold tabular-nums text-[var(--text-primary)]", children: caption }),
|
|
397
|
+
!whole && /* @__PURE__ */ jsx(
|
|
398
|
+
"button",
|
|
399
|
+
{
|
|
400
|
+
type: "button",
|
|
401
|
+
"aria-label": labels.laterYears,
|
|
402
|
+
disabled: nextBlocked,
|
|
403
|
+
onClick: () => moveTo(active + YEAR_PAGE, false),
|
|
404
|
+
className: arrow,
|
|
405
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 rtl:-scale-x-100" })
|
|
406
|
+
}
|
|
407
|
+
)
|
|
408
|
+
] }),
|
|
409
|
+
/* @__PURE__ */ jsx("div", { ref: gridRef, role: "grid", "aria-labelledby": captionId, className: "grid gap-1", children: Array.from({ length: Math.ceil(count / COLUMNS) }, (_, row) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-3 gap-1", children: years.slice(row * COLUMNS, row * COLUMNS + COLUMNS).map((year) => {
|
|
410
|
+
const disabled = outOfBounds(year);
|
|
411
|
+
const selected = year === value;
|
|
412
|
+
const current = year === currentYear;
|
|
413
|
+
return /* @__PURE__ */ jsx(
|
|
414
|
+
"button",
|
|
415
|
+
{
|
|
416
|
+
type: "button",
|
|
417
|
+
role: "gridcell",
|
|
418
|
+
"data-year": year,
|
|
419
|
+
tabIndex: year === active ? 0 : -1,
|
|
420
|
+
"aria-selected": selected,
|
|
421
|
+
"aria-disabled": disabled || void 0,
|
|
422
|
+
"aria-current": current ? "date" : void 0,
|
|
423
|
+
onClick: () => {
|
|
424
|
+
if (disabled) return;
|
|
425
|
+
setActive(year);
|
|
426
|
+
onPick(String(year));
|
|
427
|
+
},
|
|
428
|
+
onKeyDown: onCellKeyDown,
|
|
429
|
+
className: cn(
|
|
430
|
+
"rounded px-2 py-1.5 text-sm tabular-nums transition-colors",
|
|
431
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset",
|
|
432
|
+
selected && !disabled ? "focus-visible:ring-[var(--brand-contrast)]" : "focus-visible:ring-[var(--brand)]",
|
|
433
|
+
disabled ? "cursor-not-allowed text-[var(--text-placeholder)]" : selected ? "bg-[var(--brand)] text-[var(--brand-contrast)] hover:bg-[var(--brand-hover)]" : "text-[var(--text-primary)] hover:bg-[var(--bg-hover)]",
|
|
434
|
+
current && !selected && !disabled && "ring-1 ring-inset ring-[var(--border-strong)]"
|
|
435
|
+
),
|
|
436
|
+
children: yearFormat.format(new Date(year, 0, 1))
|
|
437
|
+
},
|
|
438
|
+
year
|
|
439
|
+
);
|
|
440
|
+
}) }, row)) })
|
|
441
|
+
] });
|
|
442
|
+
}
|
|
294
443
|
function upperFirst(text, locale) {
|
|
295
444
|
return text.charAt(0).toLocaleUpperCase(locale) + text.slice(1);
|
|
296
445
|
}
|
|
297
|
-
function MonthPicker({
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
446
|
+
function MonthPicker(props) {
|
|
447
|
+
const {
|
|
448
|
+
value,
|
|
449
|
+
onChange,
|
|
450
|
+
locale: localeProp,
|
|
451
|
+
min,
|
|
452
|
+
max,
|
|
453
|
+
label,
|
|
454
|
+
placeholder,
|
|
455
|
+
disabled,
|
|
456
|
+
invalid,
|
|
457
|
+
error,
|
|
458
|
+
hint,
|
|
459
|
+
size = "md",
|
|
460
|
+
mode = "month",
|
|
461
|
+
formatOptions,
|
|
462
|
+
currentMonth,
|
|
463
|
+
labels: labelsProp,
|
|
464
|
+
className,
|
|
465
|
+
triggerClassName,
|
|
466
|
+
variant = "field",
|
|
467
|
+
headingLevel = 2,
|
|
468
|
+
showToday = true,
|
|
469
|
+
...rest
|
|
470
|
+
} = props;
|
|
317
471
|
const labels = useMonthPickerLabels(labelsProp);
|
|
318
472
|
const locale = useKitLocale(localeProp);
|
|
319
|
-
const
|
|
473
|
+
const fromProvider = useKitDateFormatter();
|
|
474
|
+
const years = mode === "year";
|
|
475
|
+
const selected = years ? null : parseMonth(value);
|
|
476
|
+
const selectedYear = years ? parseYear(value) : null;
|
|
320
477
|
const minKey = boundKey(min);
|
|
321
478
|
const maxKey = boundKey(max);
|
|
479
|
+
const minYear = parseYear(min);
|
|
480
|
+
const maxYear = parseYear(max);
|
|
322
481
|
const currentKey = boundKey(currentMonth) ?? monthKey(/* @__PURE__ */ new Date());
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
482
|
+
const currentYear = parseYear(currentKey);
|
|
483
|
+
const shownKey = years ? selectedYear !== null ? String(selectedYear) : null : selected ? toKey(selected) : null;
|
|
484
|
+
const triggerText = shownKey ? formatOptions === void 0 && fromProvider?.(shownKey, { unit: years ? "year" : "month", source: "monthPicker", locale, weekday: false }) || upperFirst(
|
|
485
|
+
new Intl.DateTimeFormat(locale, formatOptions ?? (years ? YEAR_FORMAT : DEFAULT_TRIGGER_FORMAT)).format(
|
|
486
|
+
years ? new Date(selectedYear, 0, 1) : firstOf(selected)
|
|
326
487
|
),
|
|
327
488
|
locale
|
|
328
489
|
) : placeholder ?? "";
|
|
329
490
|
const id = useId();
|
|
330
|
-
const
|
|
491
|
+
const messages = useFieldMessages({ hint, error, describedBy: rest["aria-describedby"] });
|
|
492
|
+
const [ownAria, wrapperRest] = splitTriggerAria(rest);
|
|
493
|
+
const aria = { ...ownAria, "aria-describedby": messages.describedBy };
|
|
331
494
|
const labelId = `${id}-label`;
|
|
332
495
|
const valueId = `${id}-value`;
|
|
333
496
|
const panelId = `${id}-panel`;
|
|
334
497
|
const named = typeof label === "string";
|
|
498
|
+
const small = size === "sm" && label === void 0;
|
|
335
499
|
const rootRef = useRef(null);
|
|
336
500
|
const [dir, setDir] = useState("ltr");
|
|
337
|
-
const
|
|
501
|
+
const panelLabel = years ? labels.yearPanel : labels.panel;
|
|
502
|
+
const grid = (close) => years ? /* @__PURE__ */ jsx(
|
|
503
|
+
YearGrid,
|
|
504
|
+
{
|
|
505
|
+
value: selectedYear,
|
|
506
|
+
locale,
|
|
507
|
+
minYear,
|
|
508
|
+
maxYear,
|
|
509
|
+
currentYear,
|
|
510
|
+
labels,
|
|
511
|
+
onPick: (key) => {
|
|
512
|
+
onChange(key);
|
|
513
|
+
close();
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
) : /* @__PURE__ */ jsx(
|
|
338
517
|
MonthGrid,
|
|
339
518
|
{
|
|
340
519
|
value: selected,
|
|
@@ -350,17 +529,33 @@ function MonthPicker({
|
|
|
350
529
|
}
|
|
351
530
|
);
|
|
352
531
|
if (variant === "stepper") {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
532
|
+
let prevKey;
|
|
533
|
+
let nextKey;
|
|
534
|
+
let nowKey;
|
|
535
|
+
let outside;
|
|
536
|
+
if (years) {
|
|
537
|
+
const base = selectedYear ?? currentYear;
|
|
538
|
+
prevKey = String(base - 1);
|
|
539
|
+
nextKey = String(base + 1);
|
|
540
|
+
nowKey = String(currentYear);
|
|
541
|
+
outside = (key) => {
|
|
542
|
+
const y = Number(key);
|
|
543
|
+
return minYear !== null && y < minYear || maxYear !== null && y > maxYear;
|
|
544
|
+
};
|
|
545
|
+
} else {
|
|
546
|
+
const base = selected ?? parseMonth(currentKey);
|
|
547
|
+
prevKey = toKey(shiftMonth(base, -1));
|
|
548
|
+
nextKey = toKey(shiftMonth(base, 1));
|
|
549
|
+
nowKey = currentKey;
|
|
550
|
+
outside = (key) => Boolean(minKey && key < minKey || maxKey && key > maxKey);
|
|
551
|
+
}
|
|
357
552
|
const Heading = headingLevel ? `h${headingLevel}` : null;
|
|
358
553
|
const trigger = /* @__PURE__ */ jsx(
|
|
359
554
|
Popover,
|
|
360
555
|
{
|
|
361
556
|
width: 256,
|
|
362
557
|
panelId,
|
|
363
|
-
labels: { panel:
|
|
558
|
+
labels: { panel: panelLabel },
|
|
364
559
|
dir,
|
|
365
560
|
trigger: ({ open, toggle, ref }) => /* @__PURE__ */ jsx(
|
|
366
561
|
MonthHeadingTrigger,
|
|
@@ -374,7 +569,7 @@ function MonthPicker({
|
|
|
374
569
|
text: triggerText,
|
|
375
570
|
panelId,
|
|
376
571
|
disabled,
|
|
377
|
-
aria
|
|
572
|
+
aria: ownAria
|
|
378
573
|
}
|
|
379
574
|
),
|
|
380
575
|
children: grid
|
|
@@ -388,17 +583,17 @@ function MonthPicker({
|
|
|
388
583
|
{
|
|
389
584
|
variant: "secondary",
|
|
390
585
|
size: "sm",
|
|
391
|
-
disabled: disabled || outside(
|
|
586
|
+
disabled: disabled || outside(nowKey),
|
|
392
587
|
onClick: () => {
|
|
393
|
-
if (
|
|
588
|
+
if (nowKey !== shownKey) onChange(nowKey);
|
|
394
589
|
},
|
|
395
|
-
children: labels.today
|
|
590
|
+
children: years ? labels.thisYear : labels.today
|
|
396
591
|
}
|
|
397
592
|
),
|
|
398
593
|
/* @__PURE__ */ jsx(
|
|
399
594
|
IconButton,
|
|
400
595
|
{
|
|
401
|
-
"aria-label": labels.previousMonth,
|
|
596
|
+
"aria-label": years ? labels.previousYear : labels.previousMonth,
|
|
402
597
|
disabled: disabled || outside(prevKey),
|
|
403
598
|
onClick: () => onChange(prevKey),
|
|
404
599
|
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "rtl:-scale-x-100" })
|
|
@@ -407,7 +602,7 @@ function MonthPicker({
|
|
|
407
602
|
/* @__PURE__ */ jsx(
|
|
408
603
|
IconButton,
|
|
409
604
|
{
|
|
410
|
-
"aria-label": labels.nextMonth,
|
|
605
|
+
"aria-label": years ? labels.nextYear : labels.nextMonth,
|
|
411
606
|
disabled: disabled || outside(nextKey),
|
|
412
607
|
onClick: () => onChange(nextKey),
|
|
413
608
|
children: /* @__PURE__ */ jsx(ChevronRight, { className: "rtl:-scale-x-100" })
|
|
@@ -416,52 +611,62 @@ function MonthPicker({
|
|
|
416
611
|
] })
|
|
417
612
|
] });
|
|
418
613
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
/* @__PURE__ */
|
|
423
|
-
|
|
424
|
-
{
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
614
|
+
const field = (
|
|
615
|
+
// `w-fit` for the toolbar size: the calendar glyph is placed against this box, and a
|
|
616
|
+
// full-width box would park it at the far end of the row, away from its trigger.
|
|
617
|
+
/* @__PURE__ */ jsxs("div", { ...wrapperRest, ref: rootRef, className: cn("relative", small && "w-fit max-w-full", className), children: [
|
|
618
|
+
label !== void 0 && /* @__PURE__ */ jsx(FieldLabelLine, { label, hint: messages.labelHint }),
|
|
619
|
+
named && /* @__PURE__ */ jsx("span", { id: labelId, "aria-hidden": true, className: "sr-only-fixed", children: label }),
|
|
620
|
+
/* @__PURE__ */ jsx(
|
|
621
|
+
Popover,
|
|
622
|
+
{
|
|
623
|
+
width: 256,
|
|
624
|
+
panelId,
|
|
625
|
+
labels: { panel: panelLabel },
|
|
626
|
+
dir,
|
|
627
|
+
trigger: ({ open, toggle, ref }) => /* @__PURE__ */ jsx(
|
|
628
|
+
MonthFieldTrigger,
|
|
629
|
+
{
|
|
630
|
+
open,
|
|
631
|
+
toggle: () => {
|
|
632
|
+
setDir(dirOf(rootRef.current));
|
|
633
|
+
toggle();
|
|
634
|
+
},
|
|
635
|
+
triggerRef: ref,
|
|
636
|
+
triggerText,
|
|
637
|
+
hasValue: shownKey !== null,
|
|
638
|
+
labelledBy: [
|
|
639
|
+
aria["aria-labelledby"],
|
|
640
|
+
named ? labelId : !aria["aria-labelledby"] && aria.id ? aria.id : void 0,
|
|
641
|
+
valueId
|
|
642
|
+
].filter(Boolean).join(" "),
|
|
643
|
+
aria,
|
|
644
|
+
valueId,
|
|
645
|
+
panelId,
|
|
646
|
+
padded: label !== void 0,
|
|
647
|
+
small,
|
|
648
|
+
disabled,
|
|
649
|
+
invalid: invalid || hasContent(error),
|
|
650
|
+
className: triggerClassName
|
|
651
|
+
}
|
|
652
|
+
),
|
|
653
|
+
children: grid
|
|
654
|
+
}
|
|
655
|
+
),
|
|
656
|
+
/* @__PURE__ */ jsx(
|
|
657
|
+
Calendar,
|
|
658
|
+
{
|
|
659
|
+
"aria-hidden": true,
|
|
660
|
+
className: "pointer-events-none absolute end-2.5 top-1/2 size-4 -translate-y-1/2 text-[var(--text-placeholder)]"
|
|
661
|
+
}
|
|
662
|
+
)
|
|
663
|
+
] })
|
|
664
|
+
);
|
|
665
|
+
const endHint = label === void 0 ? messages.labelHint : void 0;
|
|
666
|
+
return /* @__PURE__ */ jsx(FieldBox, { below: messages.below, reserve: "error" in props || "hint" in props, children: endHint === void 0 ? field : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
667
|
+
/* @__PURE__ */ jsx("div", { className: cn("min-w-0", !small && "flex-1"), children: field }),
|
|
668
|
+
/* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-center", children: endHint })
|
|
669
|
+
] }) });
|
|
465
670
|
}
|
|
466
671
|
export {
|
|
467
672
|
DEFAULT_MONTH_PICKER_LABELS,
|