@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
|
@@ -29,19 +29,80 @@ interface DatePickerBaseProps extends Omit<ComponentPropsWithoutRef<"div">, "onC
|
|
|
29
29
|
disabled?: boolean;
|
|
30
30
|
/** Required and unanswered — {@link FIELD_INVALID}. See {@link Input}'s `invalid`. */
|
|
31
31
|
invalid?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Standing advice for the field (keksdose K4, "uniform field anatomy"), as on a
|
|
34
|
+
* {@link Select}: plain TEXT is a caption under the field, attached with
|
|
35
|
+
* `aria-describedby`; a {@link FieldHint} rides the label line (or, unlabelled, sits
|
|
36
|
+
* at the field's end, outside the box).
|
|
37
|
+
*/
|
|
38
|
+
hint?: ReactNode;
|
|
39
|
+
/**
|
|
40
|
+
* What is wrong with the date, in the caller's words ("The due date is before the
|
|
41
|
+
* invoice date") — {@link Input}'s `error` (keksdose K4: DateField errors had no slot).
|
|
42
|
+
* Rendered under the field (under the whole row, with `step` / `today`), attached to
|
|
43
|
+
* the trigger with `aria-describedby` — merged with any the caller passed, after the
|
|
44
|
+
* caption — and implies `invalid`. Passing the key at all keeps the field's box while
|
|
45
|
+
* there is no message, so the trigger is never remounted as one comes and goes.
|
|
46
|
+
*/
|
|
47
|
+
error?: ReactNode;
|
|
32
48
|
className?: string;
|
|
33
|
-
/** Intl options for the trigger's formatted date (default: locale short date).
|
|
49
|
+
/** Intl options for the trigger's formatted date (default: locale short date). Win
|
|
50
|
+
* over the provider's `formatDate`. */
|
|
34
51
|
formatOptions?: Intl.DateTimeFormatOptions;
|
|
35
|
-
/** Render the trigger's text for an ISO date yourself; wins over `formatOptions
|
|
52
|
+
/** Render the trigger's text for an ISO date yourself; wins over `formatOptions` and
|
|
53
|
+
* over the provider's `formatDate`.
|
|
36
54
|
* For a host whose date rendering is more than one `Intl` call can say — Keksdose
|
|
37
55
|
* puts the weekday's name in the UI language beside digits ordered by a separate
|
|
38
|
-
* format preference, two locales in one string. `locale` still drives the calendar.
|
|
56
|
+
* format preference, two locales in one string. `locale` still drives the calendar.
|
|
57
|
+
* Set that rendering once with `<UiKitProvider formatDate>` (keksdose K12) and this
|
|
58
|
+
* is for the one field that differs. */
|
|
39
59
|
formatValue?: (iso: string) => string;
|
|
40
60
|
/** Passed through to the {@link MiniCalendar} this opens. Its month arrows are
|
|
41
61
|
* icon-only, so their `aria-label` is the only name they have — and the package
|
|
42
62
|
* ships English defaults, which a translating host has to be able to replace.
|
|
43
63
|
* Usually unnecessary now: the calendar reads `miniCalendar` from the provider. */
|
|
44
64
|
calendarLabels?: MiniCalendarProps["labels"];
|
|
65
|
+
/**
|
|
66
|
+
* Make the panel's caption ("July 2026") a button that opens the year's twelve
|
|
67
|
+
* months, with ‹ › stepping a year; picking a month returns to its days. Far dates
|
|
68
|
+
* stop being a march of month arrows.
|
|
69
|
+
*
|
|
70
|
+
* kastlan is why: its service-charge period runs July to June, and with one month on
|
|
71
|
+
* screen and ‹ › the only way across, the end of the period was eleven clicks past
|
|
72
|
+
* the start — so kastlan kept two date fields instead of `RhfDateRangePicker`. With
|
|
73
|
+
* the jump the whole period is open, caption, Jul, 1, caption, next year, Jun, 30.
|
|
74
|
+
*
|
|
75
|
+
* What it adds, for the keyboard and a screen reader:
|
|
76
|
+
* - the caption is a disclosure button (`aria-expanded`). Its name is the month it
|
|
77
|
+
* shows, so speech input can say what it sees; it is `aria-live`, as the
|
|
78
|
+
* calendar's caption was, so paging months still says where you landed; and it is
|
|
79
|
+
* described by `monthPicker.panel` ("Choose a month").
|
|
80
|
+
* - the month grid is `MonthPicker`'s grid: one tab stop, arrows walk the months
|
|
81
|
+
* (across the year's edge), Home/End the row, PageUp/PageDown a year, Enter or a
|
|
82
|
+
* click picks. Focus opens on the month on show and comes back on its days — the
|
|
83
|
+
* selected day if it is in that month, else the 1st. Months outside `min`/`max`
|
|
84
|
+
* are `aria-disabled`, and a year arrow is once the whole year beyond is.
|
|
85
|
+
* - Escape in the month grid goes back to the days without closing the panel (focus
|
|
86
|
+
* on the caption); in the days, Escape closes the panel as before.
|
|
87
|
+
*
|
|
88
|
+
* No new strings: the month arrows keep `miniCalendar.previousMonth` / `nextMonth`
|
|
89
|
+
* (`calendarLabels`), and the month grid speaks with `MonthPicker`'s words —
|
|
90
|
+
* `monthPicker.previousYear` / `nextYear` / `month` / `panel` — because it is that
|
|
91
|
+
* grid, and a host that translated it once should not have to again.
|
|
92
|
+
*
|
|
93
|
+
* Off by default: the caption becomes one more stop in the panel's tab order, which a
|
|
94
|
+
* 0.x minor does not spring on a form. Works in the popover and in
|
|
95
|
+
* `DateRangePicker`'s phone sheet alike, beside presets and in `commit="apply"`
|
|
96
|
+
* (a preset picked while the months are open goes back to the days, on its start).
|
|
97
|
+
*
|
|
98
|
+
* Why not a two-month panel (`months={2}`) instead, or beside it: for a twelve-month
|
|
99
|
+
* period it still pages six times where this takes one year step, and two
|
|
100
|
+
* `MiniCalendar`s side by side each follow the value on their own — picking the end
|
|
101
|
+
* in the right-hand month would pull the left one onto it — so the calendar would
|
|
102
|
+
* have to learn to share a month first. Not worth that for a saving of one arrow on a
|
|
103
|
+
* range across a single month boundary.
|
|
104
|
+
*/
|
|
105
|
+
monthJump?: boolean;
|
|
45
106
|
}
|
|
46
107
|
/**
|
|
47
108
|
* Everything the kit's own trigger button carries, handed to a custom one
|
|
@@ -107,7 +168,7 @@ interface DatePickerProps extends DatePickerBaseProps {
|
|
|
107
168
|
todayLabel?: string;
|
|
108
169
|
}
|
|
109
170
|
/** Single-date picker: a field showing the formatted date, opening a calendar. */
|
|
110
|
-
declare function DatePicker(
|
|
171
|
+
declare function DatePicker(props: DatePickerProps): react.JSX.Element;
|
|
111
172
|
interface DateRangePickerPreset {
|
|
112
173
|
/**
|
|
113
174
|
* The preset's identity, independent of its dates — `"last_3_months"`, not two ISO
|
|
@@ -230,6 +291,6 @@ interface DateRangeTriggerRenderProps {
|
|
|
230
291
|
/** Two-date range picker: click a start then an end; closes once both are set.
|
|
231
292
|
* With `presets`, a column of named ranges is shown beside the calendar; with
|
|
232
293
|
* `commit="apply"` the panel drafts and commits on Apply (see {@link DateRangeCommit}). */
|
|
233
|
-
declare function DateRangePicker(
|
|
294
|
+
declare function DateRangePicker(props: DateRangePickerProps): react.JSX.Element;
|
|
234
295
|
|
|
235
296
|
export { DatePicker, type DatePickerProps, type DateRangeCommit, type DateRangeDraftSummary, DateRangePicker, type DateRangePickerPreset, type DateRangePickerProps, type DateRangeTriggerRenderProps, type DateTriggerAttributes };
|
|
@@ -1,26 +1,40 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
4
|
-
import { Calendar, CalendarClock, ChevronLeft, ChevronRight, X } from "lucide-react";
|
|
4
|
+
import { Calendar, CalendarClock, ChevronDown, ChevronLeft, ChevronRight, X } from "lucide-react";
|
|
5
5
|
import { cn } from "../lib/cn.js";
|
|
6
|
-
import { dirOf } from "../lib/direction.js";
|
|
7
|
-
import { addDaysIso, parseIsoDate } from "../lib/dates.js";
|
|
6
|
+
import { dirOf, horizontalStep } from "../lib/direction.js";
|
|
7
|
+
import { addDaysIso, monthKey, pad, parseIsoDate } from "../lib/dates.js";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_DATE_PICKER_LABELS,
|
|
10
10
|
DEFAULT_PICKER_SHEET_LABELS,
|
|
11
|
+
useKitDateFormatter,
|
|
11
12
|
useKitLabels,
|
|
12
13
|
useKitLocale
|
|
13
14
|
} from "../i18n/kit-labels.js";
|
|
14
15
|
import { splitTriggerAria } from "./trigger-aria.js";
|
|
15
|
-
import { Button,
|
|
16
|
+
import { Button, FIELD_BASE, FIELD_TRIGGER, FIELD_FLOATING_PAD, FIELD_INVALID, PHONE_QUERY } from "./ui.js";
|
|
17
|
+
import { FieldBox, FieldLabelLine, useFieldMessages } from "./field-parts.js";
|
|
16
18
|
import { FullBleedDialog } from "./full-bleed-dialog.js";
|
|
17
19
|
import { useMediaQuery } from "../hooks/use-media-query.js";
|
|
18
|
-
import { MiniCalendar } from "./mini-calendar.js";
|
|
20
|
+
import { DEFAULT_MINI_CALENDAR_LABELS, MiniCalendar } from "./mini-calendar.js";
|
|
21
|
+
import { DEFAULT_MONTH_PICKER_LABELS } from "./month-picker.js";
|
|
19
22
|
import { Popover } from "./popover.js";
|
|
20
23
|
import { Tooltip } from "./tooltip.js";
|
|
21
24
|
function formatDate(iso, locale, options) {
|
|
22
25
|
return parseIsoDate(iso)?.toLocaleDateString(locale, options) ?? "";
|
|
23
26
|
}
|
|
27
|
+
function useTriggerFormat(source, locale, formatOptions, formatValue) {
|
|
28
|
+
const fromProvider = useKitDateFormatter();
|
|
29
|
+
if (formatValue) return formatValue;
|
|
30
|
+
return (iso) => {
|
|
31
|
+
if (formatOptions === void 0 && fromProvider) {
|
|
32
|
+
const text = fromProvider(iso, { unit: "day", source, locale, weekday: source === "datePicker" });
|
|
33
|
+
if (text) return text;
|
|
34
|
+
}
|
|
35
|
+
return formatDate(iso, locale, formatOptions);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
24
38
|
function CustomTrigger({
|
|
25
39
|
render,
|
|
26
40
|
attrs,
|
|
@@ -118,6 +132,7 @@ function DateField({
|
|
|
118
132
|
sheet = false,
|
|
119
133
|
sheetBackCloses = true,
|
|
120
134
|
renderTrigger,
|
|
135
|
+
labelHint,
|
|
121
136
|
children,
|
|
122
137
|
// The trigger's, not the wrapper's: `Field`'s render-prop spreads it with the id
|
|
123
138
|
// pair, and a required date read as optional while it sat on the role-less div.
|
|
@@ -188,7 +203,7 @@ function DateField({
|
|
|
188
203
|
// The caller's attributes land here, on the field's own box — the trigger inside is
|
|
189
204
|
// named by `aria-labelledby` and must keep the id pair it is given.
|
|
190
205
|
/* @__PURE__ */ jsxs("div", { ...wrapperRest, ref: rootRef, className: cn("relative", className), children: [
|
|
191
|
-
label !== void 0 && /* @__PURE__ */ jsx(
|
|
206
|
+
label !== void 0 && /* @__PURE__ */ jsx(FieldLabelLine, { label, hint: labelHint }),
|
|
192
207
|
named && /* @__PURE__ */ jsx("span", { id: labelId, "aria-hidden": true, className: "sr-only-fixed", children: label }),
|
|
193
208
|
sheet ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
194
209
|
fieldTrigger({ open: sheetOpen, toggle: () => setSheetOpen((v) => !v), ref: sheetTriggerRef }),
|
|
@@ -256,6 +271,263 @@ function StepButton({
|
|
|
256
271
|
}
|
|
257
272
|
) });
|
|
258
273
|
}
|
|
274
|
+
const monthIndex = (key) => Number(key.slice(0, 4)) * 12 + Number(key.slice(5, 7)) - 1;
|
|
275
|
+
const keyOfIndex = (index) => `${String(Math.floor(index / 12)).padStart(4, "0")}-${pad(index % 12 + 1)}`;
|
|
276
|
+
const shiftKey = (key, delta) => keyOfIndex(monthIndex(key) + delta);
|
|
277
|
+
const firstOfKey = (key) => new Date(Number(key.slice(0, 4)), Number(key.slice(5, 7)) - 1, 1);
|
|
278
|
+
const upperFirst = (text, locale) => text.charAt(0).toLocaleUpperCase(locale) + text.slice(1);
|
|
279
|
+
const MONTH_COLUMNS = 3;
|
|
280
|
+
function openingMonth(from, to, lo, hi) {
|
|
281
|
+
const start = parseIsoDate(from) ?? parseIsoDate(to) ?? /* @__PURE__ */ new Date();
|
|
282
|
+
if (lo && start < lo) return monthKey(lo);
|
|
283
|
+
if (hi && start > hi) return monthKey(hi);
|
|
284
|
+
return monthKey(start);
|
|
285
|
+
}
|
|
286
|
+
function PanelCalendar({ monthJump, ...calendar }) {
|
|
287
|
+
return monthJump ? /* @__PURE__ */ jsx(JumpCalendar, { ...calendar }) : /* @__PURE__ */ jsx(MiniCalendar, { ...calendar });
|
|
288
|
+
}
|
|
289
|
+
function JumpCalendar({
|
|
290
|
+
from = "",
|
|
291
|
+
to = "",
|
|
292
|
+
mode = "range",
|
|
293
|
+
locale,
|
|
294
|
+
min,
|
|
295
|
+
max,
|
|
296
|
+
labels,
|
|
297
|
+
onSelect,
|
|
298
|
+
focusOnOpen
|
|
299
|
+
}) {
|
|
300
|
+
const calendarText = useKitLabels("miniCalendar", DEFAULT_MINI_CALENDAR_LABELS, labels);
|
|
301
|
+
const monthText = useKitLabels("monthPicker", DEFAULT_MONTH_PICKER_LABELS);
|
|
302
|
+
const id = useId();
|
|
303
|
+
const captionId = `${id}-caption`;
|
|
304
|
+
const hintId = `${id}-hint`;
|
|
305
|
+
const captionRef = useRef(null);
|
|
306
|
+
const monthsRef = useRef(null);
|
|
307
|
+
const lo = min ? parseIsoDate(min) : null;
|
|
308
|
+
const hi = max ? parseIsoDate(max) : null;
|
|
309
|
+
const minKey = lo ? monthKey(lo) : null;
|
|
310
|
+
const maxKey = hi ? monthKey(hi) : null;
|
|
311
|
+
const outOfBounds = (key) => Boolean(minKey && key < minKey || maxKey && key > maxKey);
|
|
312
|
+
const clampKey = (key) => minKey && key < minKey ? minKey : maxKey && key > maxKey ? maxKey : key;
|
|
313
|
+
const [view, setView] = useState("days");
|
|
314
|
+
const [shown, setShown] = useState(() => openingMonth(from, to, lo, hi));
|
|
315
|
+
const [dayGrid, setDayGrid] = useState(() => ({ key: 0, focus: Boolean(focusOnOpen) }));
|
|
316
|
+
const [active, setActive] = useState(shown);
|
|
317
|
+
const [lastValue, setLastValue] = useState({ from, to });
|
|
318
|
+
if (lastValue.from !== from || lastValue.to !== to) {
|
|
319
|
+
const changed = lastValue.from !== from ? from : to;
|
|
320
|
+
setLastValue({ from, to });
|
|
321
|
+
const next = parseIsoDate(changed) ?? parseIsoDate(from) ?? parseIsoDate(to);
|
|
322
|
+
const key = next ? monthKey(next) : null;
|
|
323
|
+
if (key && (key !== shown || view === "months")) {
|
|
324
|
+
setShown(key);
|
|
325
|
+
setView("days");
|
|
326
|
+
setDayGrid((d) => ({ key: d.key + 1, month: key, focus: false }));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
const pendingFocus = useRef(null);
|
|
330
|
+
useEffect(() => {
|
|
331
|
+
const key = pendingFocus.current;
|
|
332
|
+
if (!key) return;
|
|
333
|
+
pendingFocus.current = null;
|
|
334
|
+
monthsRef.current?.querySelector(`[data-month="${key}"]`)?.focus();
|
|
335
|
+
});
|
|
336
|
+
const showMonth = (key) => {
|
|
337
|
+
setShown(key);
|
|
338
|
+
setDayGrid((d) => ({ ...d, month: key }));
|
|
339
|
+
};
|
|
340
|
+
const openMonths = () => {
|
|
341
|
+
const start = clampKey(shown);
|
|
342
|
+
pendingFocus.current = start;
|
|
343
|
+
setActive(start);
|
|
344
|
+
setView("months");
|
|
345
|
+
};
|
|
346
|
+
const closeMonths = (focusCaption) => {
|
|
347
|
+
setView("days");
|
|
348
|
+
setDayGrid((d) => ({ ...d, month: shown, focus: false }));
|
|
349
|
+
if (focusCaption) captionRef.current?.focus();
|
|
350
|
+
};
|
|
351
|
+
const pick = (key) => {
|
|
352
|
+
setShown(key);
|
|
353
|
+
setView("days");
|
|
354
|
+
setDayGrid((d) => ({ key: d.key + 1, month: key, focus: true }));
|
|
355
|
+
};
|
|
356
|
+
const moveActive = (key, focus) => {
|
|
357
|
+
if (focus) pendingFocus.current = key;
|
|
358
|
+
setActive(key);
|
|
359
|
+
};
|
|
360
|
+
const inDays = view === "days";
|
|
361
|
+
const escapeToDays = (e) => {
|
|
362
|
+
if (e.key !== "Escape" || inDays) return;
|
|
363
|
+
e.preventDefault();
|
|
364
|
+
e.stopPropagation();
|
|
365
|
+
closeMonths(true);
|
|
366
|
+
};
|
|
367
|
+
const onMonthKeyDown = (e) => {
|
|
368
|
+
if (e.key === "Escape") return escapeToDays(e);
|
|
369
|
+
const step = horizontalStep(e.key, e.currentTarget);
|
|
370
|
+
const col = monthIndex(active) % 12 % MONTH_COLUMNS;
|
|
371
|
+
let delta;
|
|
372
|
+
switch (step ? "horizontal" : e.key) {
|
|
373
|
+
case "horizontal":
|
|
374
|
+
delta = step;
|
|
375
|
+
break;
|
|
376
|
+
case "ArrowUp":
|
|
377
|
+
delta = -MONTH_COLUMNS;
|
|
378
|
+
break;
|
|
379
|
+
case "ArrowDown":
|
|
380
|
+
delta = MONTH_COLUMNS;
|
|
381
|
+
break;
|
|
382
|
+
case "Home":
|
|
383
|
+
delta = -col;
|
|
384
|
+
break;
|
|
385
|
+
case "End":
|
|
386
|
+
delta = MONTH_COLUMNS - 1 - col;
|
|
387
|
+
break;
|
|
388
|
+
case "PageUp":
|
|
389
|
+
delta = -12;
|
|
390
|
+
break;
|
|
391
|
+
case "PageDown":
|
|
392
|
+
delta = 12;
|
|
393
|
+
break;
|
|
394
|
+
default:
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
e.preventDefault();
|
|
398
|
+
if (delta !== 0) moveActive(shiftKey(active, delta), true);
|
|
399
|
+
};
|
|
400
|
+
const year = Number(active.slice(0, 4));
|
|
401
|
+
const prevYearBlocked = Boolean(minKey && year - 1 < Number(minKey.slice(0, 4)));
|
|
402
|
+
const nextYearBlocked = Boolean(maxKey && year + 1 > Number(maxKey.slice(0, 4)));
|
|
403
|
+
const prevBlocked = !inDays && prevYearBlocked;
|
|
404
|
+
const nextBlocked = !inDays && nextYearBlocked;
|
|
405
|
+
const longName = useMemo(() => new Intl.DateTimeFormat(locale, { month: "long", year: "numeric" }), [locale]);
|
|
406
|
+
const shortNames = useMemo(() => {
|
|
407
|
+
const fmt = new Intl.DateTimeFormat(locale, { month: "short" });
|
|
408
|
+
return Array.from({ length: 12 }, (_, i) => upperFirst(fmt.format(new Date(2e3, i, 1)), locale));
|
|
409
|
+
}, [locale]);
|
|
410
|
+
const caption = inDays ? upperFirst(longName.format(firstOfKey(shown)), locale) : new Intl.DateTimeFormat(locale, { year: "numeric" }).format(new Date(year, 0, 1));
|
|
411
|
+
const fromDate = parseIsoDate(from);
|
|
412
|
+
const toDate = parseIsoDate(to);
|
|
413
|
+
const fromKey = fromDate ? monthKey(fromDate) : null;
|
|
414
|
+
const toKey = toDate ? monthKey(toDate) : null;
|
|
415
|
+
const low = fromKey ?? toKey;
|
|
416
|
+
const high = toKey ?? fromKey;
|
|
417
|
+
const currentKey = monthKey(/* @__PURE__ */ new Date());
|
|
418
|
+
const arrow = "rounded p-1 text-[var(--text-muted)] hover:bg-[var(--bg-hover)] aria-disabled:cursor-not-allowed aria-disabled:opacity-30 aria-disabled:hover:bg-transparent";
|
|
419
|
+
return /* @__PURE__ */ jsxs("div", { className: "select-none", children: [
|
|
420
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-1 pb-1", children: [
|
|
421
|
+
/* @__PURE__ */ jsx(
|
|
422
|
+
"button",
|
|
423
|
+
{
|
|
424
|
+
type: "button",
|
|
425
|
+
"aria-label": inDays ? calendarText.previousMonth : monthText.previousYear,
|
|
426
|
+
"aria-disabled": prevBlocked || void 0,
|
|
427
|
+
onClick: () => {
|
|
428
|
+
if (inDays) showMonth(shiftKey(shown, -1));
|
|
429
|
+
else if (!prevBlocked) moveActive(shiftKey(active, -12), false);
|
|
430
|
+
},
|
|
431
|
+
onKeyDown: escapeToDays,
|
|
432
|
+
className: arrow,
|
|
433
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4 rtl:-scale-x-100", "aria-hidden": true })
|
|
434
|
+
}
|
|
435
|
+
),
|
|
436
|
+
/* @__PURE__ */ jsxs(
|
|
437
|
+
"button",
|
|
438
|
+
{
|
|
439
|
+
ref: captionRef,
|
|
440
|
+
type: "button",
|
|
441
|
+
"aria-expanded": !inDays,
|
|
442
|
+
"aria-describedby": inDays ? hintId : void 0,
|
|
443
|
+
onClick: inDays ? openMonths : () => closeMonths(false),
|
|
444
|
+
onKeyDown: escapeToDays,
|
|
445
|
+
className: "inline-flex min-w-0 items-center gap-1 rounded px-1.5 py-0.5 text-xs font-medium text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]",
|
|
446
|
+
children: [
|
|
447
|
+
/* @__PURE__ */ jsx("span", { id: captionId, "aria-live": "polite", className: "truncate", children: caption }),
|
|
448
|
+
/* @__PURE__ */ jsx(
|
|
449
|
+
ChevronDown,
|
|
450
|
+
{
|
|
451
|
+
"aria-hidden": true,
|
|
452
|
+
className: cn("size-3.5 shrink-0 text-[var(--text-muted)]", !inDays && "rotate-180")
|
|
453
|
+
}
|
|
454
|
+
)
|
|
455
|
+
]
|
|
456
|
+
}
|
|
457
|
+
),
|
|
458
|
+
/* @__PURE__ */ jsx(
|
|
459
|
+
"button",
|
|
460
|
+
{
|
|
461
|
+
type: "button",
|
|
462
|
+
"aria-label": inDays ? calendarText.nextMonth : monthText.nextYear,
|
|
463
|
+
"aria-disabled": nextBlocked || void 0,
|
|
464
|
+
onClick: () => {
|
|
465
|
+
if (inDays) showMonth(shiftKey(shown, 1));
|
|
466
|
+
else if (!nextBlocked) moveActive(shiftKey(active, 12), false);
|
|
467
|
+
},
|
|
468
|
+
onKeyDown: escapeToDays,
|
|
469
|
+
className: arrow,
|
|
470
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 rtl:-scale-x-100", "aria-hidden": true })
|
|
471
|
+
}
|
|
472
|
+
)
|
|
473
|
+
] }),
|
|
474
|
+
/* @__PURE__ */ jsx("span", { id: hintId, hidden: true, children: monthText.panel }),
|
|
475
|
+
inDays ? /* @__PURE__ */ jsx(
|
|
476
|
+
MiniCalendar,
|
|
477
|
+
{
|
|
478
|
+
mode,
|
|
479
|
+
from,
|
|
480
|
+
to,
|
|
481
|
+
locale,
|
|
482
|
+
min,
|
|
483
|
+
max,
|
|
484
|
+
labels,
|
|
485
|
+
onSelect,
|
|
486
|
+
focusOnOpen: dayGrid.focus,
|
|
487
|
+
hideNavigation: true,
|
|
488
|
+
month: dayGrid.month,
|
|
489
|
+
onMonthChange: showMonth
|
|
490
|
+
},
|
|
491
|
+
dayGrid.key
|
|
492
|
+
) : /* @__PURE__ */ jsx("div", { ref: monthsRef, role: "grid", "aria-labelledby": captionId, className: "grid gap-1", children: Array.from({ length: 12 / MONTH_COLUMNS }, (_, row) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-3 gap-1", children: Array.from({ length: MONTH_COLUMNS }, (_2, c) => {
|
|
493
|
+
const index = row * MONTH_COLUMNS + c;
|
|
494
|
+
const key = keyOfIndex(year * 12 + index);
|
|
495
|
+
const disabled = outOfBounds(key);
|
|
496
|
+
const selected = low !== null && high !== null && key >= low && key <= high;
|
|
497
|
+
const end = key === fromKey || key === toKey;
|
|
498
|
+
const current = key === currentKey;
|
|
499
|
+
return /* @__PURE__ */ jsx(
|
|
500
|
+
"button",
|
|
501
|
+
{
|
|
502
|
+
type: "button",
|
|
503
|
+
role: "gridcell",
|
|
504
|
+
"data-month": key,
|
|
505
|
+
tabIndex: key === active ? 0 : -1,
|
|
506
|
+
"aria-label": monthText.month(longName.format(firstOfKey(key))),
|
|
507
|
+
"aria-selected": selected,
|
|
508
|
+
"aria-disabled": disabled || void 0,
|
|
509
|
+
"aria-current": current ? "date" : void 0,
|
|
510
|
+
onClick: () => {
|
|
511
|
+
if (!disabled) pick(key);
|
|
512
|
+
},
|
|
513
|
+
onKeyDown: onMonthKeyDown,
|
|
514
|
+
className: cn(
|
|
515
|
+
// 44px rows: the touch-target size, and four of them stand as tall
|
|
516
|
+
// as a month of days, so the panel does not jump as the views swap.
|
|
517
|
+
"h-11 rounded px-1 text-sm tabular-nums transition-colors",
|
|
518
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset",
|
|
519
|
+
// A --brand ring on a --brand fill exists only in the DOM.
|
|
520
|
+
end && !disabled ? "focus-visible:ring-[var(--brand-contrast)]" : "focus-visible:ring-[var(--brand)]",
|
|
521
|
+
disabled ? "cursor-not-allowed text-[var(--text-placeholder)]" : end ? "bg-[var(--brand)] text-[var(--brand-contrast)] hover:bg-[var(--brand-hover)]" : selected ? "bg-[var(--brand-bg)] font-medium text-[var(--brand-muted)] hover:bg-[var(--brand-bg-hover)]" : "text-[var(--text-primary)] hover:bg-[var(--bg-hover)]",
|
|
522
|
+
current && !selected && !disabled && "ring-1 ring-inset ring-[var(--border-strong)]"
|
|
523
|
+
),
|
|
524
|
+
children: shortNames[index]
|
|
525
|
+
},
|
|
526
|
+
c
|
|
527
|
+
);
|
|
528
|
+
}) }, row)) })
|
|
529
|
+
] });
|
|
530
|
+
}
|
|
259
531
|
function useDatePickerLabels(clearLabel, stepLabels, todayLabel) {
|
|
260
532
|
const prev = stepLabels?.prev;
|
|
261
533
|
const next = stepLabels?.next;
|
|
@@ -269,54 +541,75 @@ function useDatePickerLabels(clearLabel, stepLabels, todayLabel) {
|
|
|
269
541
|
}, [clearLabel, prev, next, todayLabel]);
|
|
270
542
|
return useKitLabels("datePicker", DEFAULT_DATE_PICKER_LABELS, fromProps);
|
|
271
543
|
}
|
|
272
|
-
function
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
544
|
+
function withEndHint(field, hint) {
|
|
545
|
+
if (hint === void 0) return field;
|
|
546
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
547
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: field }),
|
|
548
|
+
/* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-center", children: hint })
|
|
549
|
+
] });
|
|
550
|
+
}
|
|
551
|
+
function DatePicker(props) {
|
|
552
|
+
const {
|
|
553
|
+
value,
|
|
554
|
+
onChange,
|
|
555
|
+
locale: localeProp,
|
|
556
|
+
placeholder,
|
|
557
|
+
min,
|
|
558
|
+
max,
|
|
559
|
+
formatOptions,
|
|
560
|
+
formatValue,
|
|
561
|
+
step,
|
|
562
|
+
stepLabels,
|
|
563
|
+
today,
|
|
564
|
+
todayLabel,
|
|
565
|
+
className,
|
|
566
|
+
calendarLabels,
|
|
567
|
+
monthJump,
|
|
568
|
+
label,
|
|
569
|
+
clearable,
|
|
570
|
+
clearLabel,
|
|
571
|
+
disabled,
|
|
572
|
+
invalid,
|
|
573
|
+
hint,
|
|
574
|
+
error,
|
|
575
|
+
// Named so it reaches the field (and so its trigger) when a step/today row is the
|
|
576
|
+
// root and takes the rest of the caller's props.
|
|
577
|
+
"aria-required": ariaRequired,
|
|
578
|
+
...rest
|
|
579
|
+
} = props;
|
|
297
580
|
const locale = useKitLocale(localeProp);
|
|
298
581
|
const text = useDatePickerLabels(clearLabel, stepLabels, todayLabel);
|
|
299
|
-
const render =
|
|
582
|
+
const render = useTriggerFormat("datePicker", locale, formatOptions, formatValue);
|
|
583
|
+
const messages = useFieldMessages({
|
|
584
|
+
hint,
|
|
585
|
+
error,
|
|
586
|
+
invalid,
|
|
587
|
+
describedBy: rest["aria-describedby"],
|
|
588
|
+
ariaInvalid: rest["aria-invalid"]
|
|
589
|
+
});
|
|
300
590
|
const wrapped = Boolean(step || today);
|
|
301
591
|
const [triggerAria, wrapperRest] = splitTriggerAria(rest);
|
|
302
592
|
const field = /* @__PURE__ */ jsx(
|
|
303
593
|
DateField,
|
|
304
594
|
{
|
|
305
595
|
...wrapped ? triggerAria : rest,
|
|
596
|
+
"aria-describedby": messages.describedBy,
|
|
306
597
|
"aria-required": ariaRequired,
|
|
307
598
|
label,
|
|
599
|
+
labelHint: messages.labelHint,
|
|
308
600
|
clearable,
|
|
309
601
|
clearLabel: text.clear,
|
|
310
602
|
panelLabel: text.panel,
|
|
311
603
|
disabled,
|
|
312
|
-
invalid,
|
|
604
|
+
invalid: messages.isInvalid,
|
|
313
605
|
className: step ? "min-w-0 flex-1" : className,
|
|
314
606
|
hasValue: Boolean(value),
|
|
315
607
|
triggerText: value ? render(value) : placeholder ?? "",
|
|
316
608
|
onClear: () => onChange(""),
|
|
317
609
|
children: (close) => /* @__PURE__ */ jsx(
|
|
318
|
-
|
|
610
|
+
PanelCalendar,
|
|
319
611
|
{
|
|
612
|
+
monthJump,
|
|
320
613
|
mode: "single",
|
|
321
614
|
focusOnOpen: true,
|
|
322
615
|
from: value,
|
|
@@ -333,7 +626,11 @@ function DatePicker({
|
|
|
333
626
|
)
|
|
334
627
|
}
|
|
335
628
|
);
|
|
336
|
-
|
|
629
|
+
const reserve = "error" in props || "hint" in props;
|
|
630
|
+
const endHint = label === void 0 ? messages.labelHint : void 0;
|
|
631
|
+
if (!wrapped) {
|
|
632
|
+
return /* @__PURE__ */ jsx(FieldBox, { below: messages.below, reserve, children: withEndHint(field, endHint) });
|
|
633
|
+
}
|
|
337
634
|
const target = (days) => value ? addDaysIso(value, days) : "";
|
|
338
635
|
const outOfBounds = (iso) => Boolean(min && iso < min || max && iso > max);
|
|
339
636
|
const blocked = (days) => {
|
|
@@ -341,7 +638,7 @@ function DatePicker({
|
|
|
341
638
|
if (!next || disabled) return true;
|
|
342
639
|
return outOfBounds(next);
|
|
343
640
|
};
|
|
344
|
-
|
|
641
|
+
const row = (
|
|
345
642
|
// ONE joined control, not three boxes in a row: the buttons and the field share
|
|
346
643
|
// their borders (each piece overlaps the previous by a pixel) and only the outer
|
|
347
644
|
// ends are rounded — the button-group shape, so ‹ date › reads as one field with
|
|
@@ -400,6 +697,7 @@ function DatePicker({
|
|
|
400
697
|
}
|
|
401
698
|
)
|
|
402
699
|
);
|
|
700
|
+
return /* @__PURE__ */ jsx(FieldBox, { below: messages.below, reserve, children: withEndHint(row, endHint) });
|
|
403
701
|
}
|
|
404
702
|
function markedPreset(presets, from, to, activeId, controlled) {
|
|
405
703
|
const matches = (p) => p.from === from && p.to === to;
|
|
@@ -477,7 +775,7 @@ function RangePanel({
|
|
|
477
775
|
const complete = Boolean(draft.from && draft.to);
|
|
478
776
|
const summary = drafting && renderDraftSummary ? renderDraftSummary({ from: draft.from, to: draft.to, preset: presets?.[marked] }) : null;
|
|
479
777
|
const picker = /* @__PURE__ */ jsx(
|
|
480
|
-
|
|
778
|
+
PanelCalendar,
|
|
481
779
|
{
|
|
482
780
|
...calendarProps,
|
|
483
781
|
focusOnOpen: true,
|
|
@@ -539,34 +837,45 @@ function RangePanel({
|
|
|
539
837
|
] })
|
|
540
838
|
);
|
|
541
839
|
}
|
|
542
|
-
function DateRangePicker({
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
840
|
+
function DateRangePicker(props) {
|
|
841
|
+
const {
|
|
842
|
+
from,
|
|
843
|
+
to,
|
|
844
|
+
onChange,
|
|
845
|
+
locale: localeProp,
|
|
846
|
+
placeholder,
|
|
847
|
+
min,
|
|
848
|
+
max,
|
|
849
|
+
formatOptions,
|
|
850
|
+
formatValue,
|
|
851
|
+
separator = " \u2013 ",
|
|
852
|
+
presets,
|
|
853
|
+
preset,
|
|
854
|
+
commit = "immediate",
|
|
855
|
+
renderTrigger,
|
|
856
|
+
sheetBackCloses,
|
|
857
|
+
renderDraftSummary,
|
|
858
|
+
calendarLabels,
|
|
859
|
+
monthJump,
|
|
860
|
+
label,
|
|
861
|
+
clearable,
|
|
862
|
+
clearLabel,
|
|
863
|
+
disabled,
|
|
864
|
+
invalid,
|
|
865
|
+
hint,
|
|
866
|
+
error,
|
|
867
|
+
...rest
|
|
868
|
+
} = props;
|
|
567
869
|
const locale = useKitLocale(localeProp);
|
|
568
870
|
const text = useDatePickerLabels(clearLabel, void 0, void 0);
|
|
569
|
-
const render =
|
|
871
|
+
const render = useTriggerFormat("dateRangePicker", locale, formatOptions, formatValue);
|
|
872
|
+
const messages = useFieldMessages({
|
|
873
|
+
hint,
|
|
874
|
+
error,
|
|
875
|
+
invalid,
|
|
876
|
+
describedBy: rest["aria-describedby"],
|
|
877
|
+
ariaInvalid: rest["aria-invalid"]
|
|
878
|
+
});
|
|
570
879
|
const [ownPreset, setOwnPreset] = useState(void 0);
|
|
571
880
|
const controlled = preset !== void 0;
|
|
572
881
|
const activeId = controlled ? preset : ownPreset;
|
|
@@ -580,16 +889,18 @@ function DateRangePicker({
|
|
|
580
889
|
if (presetId === void 0) onChange(f, t);
|
|
581
890
|
else onChange(f, t, presetId);
|
|
582
891
|
};
|
|
583
|
-
|
|
892
|
+
const field = /* @__PURE__ */ jsx(
|
|
584
893
|
DateField,
|
|
585
894
|
{
|
|
586
895
|
...rest,
|
|
896
|
+
"aria-describedby": messages.describedBy,
|
|
587
897
|
label,
|
|
898
|
+
labelHint: messages.labelHint,
|
|
588
899
|
clearable,
|
|
589
900
|
clearLabel: text.clear,
|
|
590
901
|
panelLabel: text.rangePanel,
|
|
591
902
|
disabled,
|
|
592
|
-
invalid,
|
|
903
|
+
invalid: messages.isInvalid,
|
|
593
904
|
width: hasPresets ? 440 : void 0,
|
|
594
905
|
hasValue: Boolean(from || to),
|
|
595
906
|
triggerText,
|
|
@@ -618,13 +929,14 @@ function DateRangePicker({
|
|
|
618
929
|
frame,
|
|
619
930
|
sheet,
|
|
620
931
|
commitRange,
|
|
621
|
-
calendarProps: { locale, min, max, labels: calendarLabels },
|
|
932
|
+
calendarProps: { locale, min, max, labels: calendarLabels, monthJump },
|
|
622
933
|
labels: text,
|
|
623
934
|
renderDraftSummary
|
|
624
935
|
}
|
|
625
936
|
)
|
|
626
937
|
}
|
|
627
938
|
);
|
|
939
|
+
return /* @__PURE__ */ jsx(FieldBox, { below: messages.below, reserve: "error" in props || "hint" in props, children: withEndHint(field, label === void 0 ? messages.labelHint : void 0) });
|
|
628
940
|
}
|
|
629
941
|
export {
|
|
630
942
|
DatePicker,
|