@eifi1/ui-kit 0.8.1 → 0.10.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 +25 -11
- package/dist/components/alert-banner.d.ts +32 -5
- package/dist/components/alert-banner.js +57 -14
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.d.ts +6 -0
- package/dist/components/breadcrumbs.d.ts +60 -0
- package/dist/components/breadcrumbs.js +88 -0
- package/dist/components/breadcrumbs.js.map +1 -0
- package/dist/components/bulk-action-bar.d.ts +66 -0
- package/dist/components/bulk-action-bar.js +149 -0
- package/dist/components/bulk-action-bar.js.map +1 -0
- package/dist/components/calculator.d.ts +6 -0
- package/dist/components/chip.d.ts +58 -10
- package/dist/components/chip.js +91 -7
- package/dist/components/chip.js.map +1 -1
- package/dist/components/copy-button.d.ts +13 -4
- package/dist/components/copy-button.js +17 -4
- package/dist/components/copy-button.js.map +1 -1
- package/dist/components/data-table-filter-popover.d.ts +1 -1
- package/dist/components/data-table-filters.d.ts +1 -1
- package/dist/components/data-table.d.ts +1 -1
- package/dist/components/data-table.js +122 -91
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.d.ts +89 -3
- package/dist/components/date-picker.js +163 -68
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/description-list.d.ts +43 -6
- package/dist/components/description-list.js +91 -11
- package/dist/components/description-list.js.map +1 -1
- package/dist/components/dialog-frame.d.ts +7 -0
- package/dist/components/dialog-frame.js.map +1 -1
- package/dist/components/disclosure.d.ts +68 -4
- package/dist/components/disclosure.js +33 -15
- package/dist/components/disclosure.js.map +1 -1
- package/dist/components/file-dropzone.d.ts +3 -4
- package/dist/components/file-dropzone.js +2 -1
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/floating-panel.d.ts +29 -2
- package/dist/components/floating-panel.js +16 -2
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/full-bleed-dialog.d.ts +23 -4
- package/dist/components/full-bleed-dialog.js +11 -2
- package/dist/components/full-bleed-dialog.js.map +1 -1
- package/dist/components/list.d.ts +174 -0
- package/dist/components/list.js +215 -0
- package/dist/components/list.js.map +1 -0
- package/dist/components/menu-item.d.ts +99 -0
- package/dist/components/menu-item.js +83 -0
- package/dist/components/menu-item.js.map +1 -0
- package/dist/components/modal.d.ts +23 -1
- package/dist/components/modal.js +36 -10
- package/dist/components/modal.js.map +1 -1
- package/dist/components/number-field.d.ts +6 -0
- package/dist/components/number-input.d.ts +6 -0
- package/dist/components/numpad-sheet.d.ts +6 -0
- package/dist/components/page-contents.js +1 -2
- package/dist/components/page-contents.js.map +1 -1
- package/dist/components/page-header.d.ts +37 -0
- package/dist/components/page-header.js +36 -0
- package/dist/components/page-header.js.map +1 -0
- package/dist/components/progress-bar.d.ts +16 -2
- package/dist/components/progress-bar.js +4 -2
- package/dist/components/progress-bar.js.map +1 -1
- package/dist/components/series-chart-labels.d.ts +3 -0
- package/dist/components/series-chart-labels.js +2 -1
- package/dist/components/series-chart-labels.js.map +1 -1
- package/dist/components/series-chart.d.ts +16 -0
- package/dist/components/series-chart.js +137 -3
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/status-dot.d.ts +49 -0
- package/dist/components/status-dot.js +52 -0
- package/dist/components/status-dot.js.map +1 -0
- package/dist/components/table.d.ts +39 -6
- package/dist/components/table.js +43 -4
- package/dist/components/table.js.map +1 -1
- package/dist/components/text.d.ts +63 -0
- package/dist/components/text.js +23 -0
- package/dist/components/text.js.map +1 -0
- package/dist/components/toast.d.ts +167 -0
- package/dist/components/toast.js +226 -0
- package/dist/components/toast.js.map +1 -0
- package/dist/components/toggle-group.d.ts +29 -1
- package/dist/components/toggle-group.js +52 -3
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/tooltip.d.ts +38 -15
- package/dist/components/tooltip.js +85 -47
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/ui.d.ts +139 -16
- package/dist/components/ui.js +136 -26
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -1
- package/dist/{data-table-filters-CF1PXqjQ.d.ts → data-table-filters-Dh9uF_S-.d.ts} +33 -2
- package/dist/data-table.d.ts +1 -1
- package/dist/hooks/use-close-transition.d.ts +7 -1
- package/dist/hooks/use-close-transition.js +5 -2
- package/dist/hooks/use-close-transition.js.map +1 -1
- package/dist/hooks/use-copy-to-clipboard.js +1 -1
- package/dist/hooks/use-copy-to-clipboard.js.map +1 -1
- package/dist/hooks/use-overlay-history.js +84 -4
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/i18n/defaults.d.ts +6 -0
- package/dist/i18n/defaults.js +11 -1
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +11 -0
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/de-CH-informal.d.ts +6 -0
- package/dist/i18n/locales/de-CH.d.ts +6 -0
- package/dist/i18n/locales/de-informal.d.ts +6 -0
- package/dist/i18n/locales/de.d.ts +6 -0
- package/dist/i18n/locales/de.js +31 -1
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +6 -0
- package/dist/i18n/locales/es.js +31 -1
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +6 -0
- package/dist/i18n/locales/fr.js +31 -1
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +6 -0
- package/dist/i18n/locales/hu.js +31 -1
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +6 -0
- package/dist/i18n/locales/it.js +31 -1
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +6 -0
- package/dist/i18n/locales/zh.js +31 -1
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.d.ts +18 -8
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/clipping.d.ts +9 -0
- package/dist/lib/clipping.js +14 -0
- package/dist/lib/clipping.js.map +1 -0
- package/dist/search/command-palette.d.ts +67 -2
- package/dist/search/command-palette.js +147 -33
- package/dist/search/command-palette.js.map +1 -1
- package/dist/search/global-search.d.ts +166 -0
- package/dist/search/global-search.js +293 -0
- package/dist/search/global-search.js.map +1 -0
- package/dist/search/search-index.d.ts +105 -0
- package/dist/search/search-index.js +142 -0
- package/dist/search/search-index.js.map +1 -0
- package/dist/search.d.ts +3 -1
- package/dist/search.js +2 -0
- package/dist/search.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +10 -1
- package/dist/wizard/stepper-nav.js +3 -2
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard/types.d.ts +2 -2
- package/dist/wizard/types.js.map +1 -1
- package/dist/wizard/use-wizard.js +1 -1
- package/dist/wizard/use-wizard.js.map +1 -1
- package/dist/wizard/wizard-summary.js +3 -3
- package/dist/wizard/wizard-summary.js.map +1 -1
- package/package.json +25 -12
- package/src/components/alert-banner.tsx +117 -18
- package/src/components/breadcrumbs.tsx +168 -0
- package/src/components/bulk-action-bar.tsx +256 -0
- package/src/components/chip.tsx +164 -13
- package/src/components/copy-button.tsx +29 -7
- package/src/components/data-table.tsx +81 -5
- package/src/components/date-picker.tsx +377 -118
- package/src/components/description-list.tsx +168 -15
- package/src/components/dialog-frame.tsx +7 -0
- package/src/components/disclosure.tsx +116 -28
- package/src/components/file-dropzone.tsx +9 -10
- package/src/components/floating-panel.tsx +46 -2
- package/src/components/full-bleed-dialog.tsx +42 -5
- package/src/components/list.tsx +417 -0
- package/src/components/menu-item.tsx +214 -0
- package/src/components/modal.tsx +80 -17
- package/src/components/page-contents.tsx +4 -4
- package/src/components/page-header.tsx +68 -0
- package/src/components/progress-bar.tsx +27 -3
- package/src/components/series-chart-labels.ts +4 -0
- package/src/components/series-chart.tsx +253 -3
- package/src/components/status-dot.tsx +99 -0
- package/src/components/table.tsx +91 -6
- package/src/components/text.tsx +89 -0
- package/src/components/toast.tsx +441 -0
- package/src/components/toggle-group.tsx +82 -3
- package/src/components/tooltip.tsx +186 -100
- package/src/components/ui.tsx +321 -41
- package/src/hooks/use-close-transition.ts +14 -5
- package/src/hooks/use-copy-to-clipboard.ts +1 -1
- package/src/hooks/use-overlay-history.ts +181 -4
- package/src/i18n/defaults.ts +10 -0
- package/src/i18n/kit-labels.tsx +10 -0
- package/src/i18n/locales/de.ts +30 -0
- package/src/i18n/locales/es.ts +30 -0
- package/src/i18n/locales/fr.ts +30 -0
- package/src/i18n/locales/hu.ts +30 -0
- package/src/i18n/locales/it.ts +30 -0
- package/src/i18n/locales/zh.ts +30 -0
- package/src/index.ts +30 -0
- package/src/lib/clipping.ts +16 -0
- package/src/search/command-palette.tsx +241 -31
- package/src/search/global-search.tsx +525 -0
- package/src/search/search-index.ts +295 -0
- package/src/search.ts +2 -0
- package/src/wizard/stepper-nav.tsx +13 -2
- package/src/wizard/types.ts +2 -2
- package/src/wizard/use-wizard.ts +3 -3
- package/src/wizard/wizard-summary.tsx +14 -10
- package/tokens.css +97 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
|
+
import { ComponentPropsWithoutRef, ReactNode, RefObject } from 'react';
|
|
3
3
|
import { MiniCalendarProps } from './mini-calendar.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -43,6 +43,32 @@ interface DatePickerBaseProps extends Omit<ComponentPropsWithoutRef<"div">, "onC
|
|
|
43
43
|
* Usually unnecessary now: the calendar reads `miniCalendar` from the provider. */
|
|
44
44
|
calendarLabels?: MiniCalendarProps["labels"];
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Everything the kit's own trigger button carries, handed to a custom one
|
|
48
|
+
* ({@link DateRangePickerProps.renderTrigger}) to spread onto its `<button>`. Spread
|
|
49
|
+
* it WHOLE: the ref is how focus comes back when the panel closes, the id pair and
|
|
50
|
+
* `aria-labelledby` are the 0.5.1 naming (an external `<label htmlFor>`, a form
|
|
51
|
+
* library's `aria-describedby`), and `role`/`aria-haspopup`/`aria-controls`/
|
|
52
|
+
* `aria-expanded` are what tell a screen reader this opens a calendar and whether it
|
|
53
|
+
* is open. `className` is the kit's field look (42px with a label, `pe-9` for the
|
|
54
|
+
* glyph the field draws at its end) — merge yours after it with `cn`.
|
|
55
|
+
*/
|
|
56
|
+
interface DateTriggerAttributes {
|
|
57
|
+
ref: RefObject<HTMLButtonElement | null>;
|
|
58
|
+
type: "button";
|
|
59
|
+
id?: string;
|
|
60
|
+
role: "combobox";
|
|
61
|
+
"aria-haspopup": "dialog";
|
|
62
|
+
"aria-controls": string;
|
|
63
|
+
"aria-expanded": boolean;
|
|
64
|
+
"aria-labelledby"?: string;
|
|
65
|
+
"aria-label"?: string;
|
|
66
|
+
"aria-describedby"?: string;
|
|
67
|
+
"aria-invalid"?: true;
|
|
68
|
+
disabled?: boolean;
|
|
69
|
+
onClick: () => void;
|
|
70
|
+
className: string;
|
|
71
|
+
}
|
|
46
72
|
interface DatePickerProps extends DatePickerBaseProps {
|
|
47
73
|
/** ISO "YYYY-MM-DD", or "" for empty. */
|
|
48
74
|
value: string;
|
|
@@ -138,10 +164,70 @@ interface DateRangePickerProps extends DatePickerBaseProps {
|
|
|
138
164
|
preset?: string | null;
|
|
139
165
|
/** See {@link DateRangeCommit}. Default `"immediate"`. */
|
|
140
166
|
commit?: DateRangeCommit;
|
|
167
|
+
/**
|
|
168
|
+
* Draw the trigger yourself. keksdose's report range field
|
|
169
|
+
* (reports/report-range-field.tsx, "Why this is app-level") is why: its trigger
|
|
170
|
+
* NAMES the active preset ("Last 3 months", the window as a muted suffix) where the
|
|
171
|
+
* kit's shows two dates, sits inside a Tooltip, and is squared off on one side so the
|
|
172
|
+
* granularity control can join it flush at the field's 42px.
|
|
173
|
+
*
|
|
174
|
+
* Spread `props.triggerProps` onto a `<button>` whole and put `props.valueProps` on
|
|
175
|
+
* the element that shows the value — see {@link DateTriggerAttributes} for what each
|
|
176
|
+
* part is for. The field around it (label, hidden name twin, clear/calendar glyph,
|
|
177
|
+
* popover or phone sheet) is unchanged.
|
|
178
|
+
*/
|
|
179
|
+
renderTrigger?: (props: DateRangeTriggerRenderProps) => ReactNode;
|
|
180
|
+
/**
|
|
181
|
+
* Below {@link PHONE_QUERY} the panel opens as a full-screen sheet (`FullBleedDialog`)
|
|
182
|
+
* with presets in a grid above the calendar and Apply pinned in the footer, instead
|
|
183
|
+
* of the 440px popover that hung off a 360px screen (keksdose's report range field,
|
|
184
|
+
* which hand-rolled exactly this). This is its `backCloses`: on by default, so Back
|
|
185
|
+
* dismisses the sheet; off for a caller whose commit rewrites the URL with
|
|
186
|
+
* `replaceState` in the same tick — keksdose's `?preset/from/to` — where the router
|
|
187
|
+
* would overwrite the sheet's history marker.
|
|
188
|
+
*/
|
|
189
|
+
sheetBackCloses?: boolean;
|
|
190
|
+
/**
|
|
191
|
+
* With `commit="apply"`: a line above the calendar saying what Apply would commit —
|
|
192
|
+
* keksdose's report range writes "Custom · 1 Mar 2026 – …" there
|
|
193
|
+
* (report-range-field.tsx), the one place a preset armed and then nudged by a day is
|
|
194
|
+
* seen to have become "Custom", and a half-made range to still lack its end. Called
|
|
195
|
+
* with the DRAFT on every change, in the popover and the phone sheet alike; `preset`
|
|
196
|
+
* is the preset the column marks for it (none once a day was picked by hand), `to` is
|
|
197
|
+
* `""` until the second click. The line is a polite live region, so a screen reader
|
|
198
|
+
* hears the draft change as the calendar is used.
|
|
199
|
+
*
|
|
200
|
+
* Ignored in `"immediate"` mode, where there is no draft: every click is the value.
|
|
201
|
+
*/
|
|
202
|
+
renderDraftSummary?: (draft: DateRangeDraftSummary) => ReactNode;
|
|
203
|
+
}
|
|
204
|
+
/** What {@link DateRangePickerProps.renderDraftSummary} is called with. */
|
|
205
|
+
interface DateRangeDraftSummary {
|
|
206
|
+
from: string;
|
|
207
|
+
to: string;
|
|
208
|
+
/** The preset the column marks for the draft, if any. */
|
|
209
|
+
preset: DateRangePickerPreset | undefined;
|
|
210
|
+
}
|
|
211
|
+
/** What {@link DateRangePickerProps.renderTrigger} is called with. */
|
|
212
|
+
interface DateRangeTriggerRenderProps {
|
|
213
|
+
/** Spread onto the `<button>`, whole. Merge your class after `triggerProps.className`. */
|
|
214
|
+
triggerProps: DateTriggerAttributes;
|
|
215
|
+
/** Put on the element showing the value: the trigger is named "label, value" by
|
|
216
|
+
* reference to this id. Without it the name is the label alone. */
|
|
217
|
+
valueProps: {
|
|
218
|
+
id: string;
|
|
219
|
+
};
|
|
220
|
+
open: boolean;
|
|
221
|
+
from: string;
|
|
222
|
+
to: string;
|
|
223
|
+
/** The preset the column marks for the committed range, if any — the one to name. */
|
|
224
|
+
preset: DateRangePickerPreset | undefined;
|
|
225
|
+
/** What the kit's own trigger would show: the formatted range, or the placeholder. */
|
|
226
|
+
text: string;
|
|
141
227
|
}
|
|
142
228
|
/** Two-date range picker: click a start then an end; closes once both are set.
|
|
143
229
|
* With `presets`, a column of named ranges is shown beside the calendar; with
|
|
144
230
|
* `commit="apply"` the panel drafts and commits on Apply (see {@link DateRangeCommit}). */
|
|
145
|
-
declare function DateRangePicker({ from, to, onChange, locale: localeProp, placeholder, min, max, formatOptions, formatValue, separator, presets, preset, commit, calendarLabels, label, clearable, clearLabel, disabled, invalid, ...rest }: DateRangePickerProps): react.JSX.Element;
|
|
231
|
+
declare function DateRangePicker({ from, to, onChange, locale: localeProp, placeholder, min, max, formatOptions, formatValue, separator, presets, preset, commit, renderTrigger, sheetBackCloses, renderDraftSummary, calendarLabels, label, clearable, clearLabel, disabled, invalid, ...rest }: DateRangePickerProps): react.JSX.Element;
|
|
146
232
|
|
|
147
|
-
export { DatePicker, type DatePickerProps, type DateRangeCommit, DateRangePicker, type DateRangePickerPreset, type DateRangePickerProps };
|
|
233
|
+
export { DatePicker, type DatePickerProps, type DateRangeCommit, type DateRangeDraftSummary, DateRangePicker, type DateRangePickerPreset, type DateRangePickerProps, type DateRangeTriggerRenderProps, type DateTriggerAttributes };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { Calendar, CalendarClock, ChevronLeft, ChevronRight, X } from "lucide-react";
|
|
5
5
|
import { cn } from "../lib/cn.js";
|
|
@@ -7,17 +7,27 @@ import { dirOf } from "../lib/direction.js";
|
|
|
7
7
|
import { addDaysIso, parseIsoDate } from "../lib/dates.js";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_DATE_PICKER_LABELS,
|
|
10
|
+
DEFAULT_PICKER_SHEET_LABELS,
|
|
10
11
|
useKitLabels,
|
|
11
12
|
useKitLocale
|
|
12
13
|
} from "../i18n/kit-labels.js";
|
|
13
14
|
import { splitTriggerAria } from "./trigger-aria.js";
|
|
14
|
-
import { Button, FieldLabel, FIELD_BASE, FIELD_TRIGGER, FIELD_FLOATING_PAD, FIELD_INVALID } from "./ui.js";
|
|
15
|
+
import { Button, FieldLabel, FIELD_BASE, FIELD_TRIGGER, FIELD_FLOATING_PAD, FIELD_INVALID, PHONE_QUERY } from "./ui.js";
|
|
16
|
+
import { FullBleedDialog } from "./full-bleed-dialog.js";
|
|
17
|
+
import { useMediaQuery } from "../hooks/use-media-query.js";
|
|
15
18
|
import { MiniCalendar } from "./mini-calendar.js";
|
|
16
19
|
import { Popover } from "./popover.js";
|
|
17
20
|
import { Tooltip } from "./tooltip.js";
|
|
18
21
|
function formatDate(iso, locale, options) {
|
|
19
22
|
return parseIsoDate(iso)?.toLocaleDateString(locale, options) ?? "";
|
|
20
23
|
}
|
|
24
|
+
function CustomTrigger({
|
|
25
|
+
render,
|
|
26
|
+
attrs,
|
|
27
|
+
valueId
|
|
28
|
+
}) {
|
|
29
|
+
return render(attrs, valueId);
|
|
30
|
+
}
|
|
21
31
|
function DateFieldTrigger({
|
|
22
32
|
open,
|
|
23
33
|
toggle,
|
|
@@ -30,7 +40,8 @@ function DateFieldTrigger({
|
|
|
30
40
|
disabled,
|
|
31
41
|
invalid,
|
|
32
42
|
panelId,
|
|
33
|
-
aria
|
|
43
|
+
aria,
|
|
44
|
+
renderTrigger
|
|
34
45
|
}) {
|
|
35
46
|
const wasOpen = useRef(false);
|
|
36
47
|
useEffect(() => {
|
|
@@ -40,33 +51,54 @@ function DateFieldTrigger({
|
|
|
40
51
|
const active = document.activeElement;
|
|
41
52
|
if (!active || active === document.body) triggerRef.current?.focus();
|
|
42
53
|
}, [open, triggerRef]);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
54
|
+
const attrs = {
|
|
55
|
+
ref: triggerRef,
|
|
56
|
+
type: "button",
|
|
57
|
+
disabled,
|
|
58
|
+
onClick: toggle,
|
|
59
|
+
// The name has to carry the VALUE. A bare `aria-label={label}` — which is what
|
|
60
|
+
// this was — replaces the button's text outright, so the one field in the form
|
|
61
|
+
// whose entire job is to show a date announced "Due date" and stopped there,
|
|
62
|
+
// and a screen-reader user could not read back what they had picked without
|
|
63
|
+
// opening the calendar and hunting for the selected day.
|
|
64
|
+
//
|
|
65
|
+
// Two ids rather than one composed string (`common.fieldValue`): "label: value"
|
|
66
|
+
// is a sentence, and a name reference is spoken as the two texts in order with
|
|
67
|
+
// no punctuation to translate at all. The hidden twin of the FieldLabel lives
|
|
68
|
+
// in DateField, next to the label it copies.
|
|
69
|
+
id: aria.id,
|
|
70
|
+
"aria-labelledby": aria["aria-label"] && !aria["aria-labelledby"] ? void 0 : labelledBy,
|
|
71
|
+
"aria-label": aria["aria-label"],
|
|
72
|
+
"aria-describedby": aria["aria-describedby"],
|
|
73
|
+
// `role="combobox"` on a button that opens a calendar is the APG date-picker
|
|
74
|
+
// shape, and it is what makes the next two lines legal: `button` supports
|
|
75
|
+
// neither `aria-expanded` nor `aria-invalid`, so the previous markup set an
|
|
76
|
+
// invalid state that announced nothing (ESLint's `role-supports-aria-props`).
|
|
77
|
+
//
|
|
78
|
+
// `aria-haspopup="dialog"` is now honest — it was not when this comment first
|
|
79
|
+
// said so. `Popover` gained a real `role="dialog"` in the same wave, so the
|
|
80
|
+
// trigger's promise and the panel's role finally agree. The phone sheet is a
|
|
81
|
+
// `role="dialog"` too, and carries the same id.
|
|
82
|
+
role: "combobox",
|
|
83
|
+
"aria-haspopup": "dialog",
|
|
84
|
+
"aria-controls": panelId,
|
|
85
|
+
"aria-expanded": open,
|
|
86
|
+
"aria-invalid": invalid || aria["aria-invalid"] === true || aria["aria-invalid"] === "true" || void 0,
|
|
87
|
+
className: cn(
|
|
88
|
+
FIELD_TRIGGER,
|
|
89
|
+
"pe-9",
|
|
90
|
+
padded && FIELD_FLOATING_PAD,
|
|
91
|
+
disabled && "cursor-not-allowed opacity-50",
|
|
92
|
+
invalid && FIELD_INVALID
|
|
93
|
+
)
|
|
94
|
+
};
|
|
95
|
+
if (renderTrigger) return /* @__PURE__ */ jsx(CustomTrigger, { render: renderTrigger, attrs, valueId });
|
|
96
|
+
return /* @__PURE__ */ jsx("button", { ...attrs, children: /* @__PURE__ */ jsx("span", { id: valueId, className: cn("truncate", !hasValue && "text-[var(--text-placeholder)]"), children: triggerText || "\xA0" }) });
|
|
69
97
|
}
|
|
98
|
+
const popoverFrame = (body, actions) => actions ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
99
|
+
body,
|
|
100
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-2 border-t border-[var(--border)] pt-2", children: actions })
|
|
101
|
+
] }) : body;
|
|
70
102
|
function DateField({
|
|
71
103
|
triggerText,
|
|
72
104
|
hasValue,
|
|
@@ -79,6 +111,9 @@ function DateField({
|
|
|
79
111
|
width,
|
|
80
112
|
onClear,
|
|
81
113
|
invalid,
|
|
114
|
+
sheet = false,
|
|
115
|
+
sheetBackCloses = true,
|
|
116
|
+
renderTrigger,
|
|
82
117
|
children,
|
|
83
118
|
...rest
|
|
84
119
|
}) {
|
|
@@ -91,44 +126,73 @@ function DateField({
|
|
|
91
126
|
const valueId = `${id}-value`;
|
|
92
127
|
const panelId = `${id}-panel`;
|
|
93
128
|
const named = typeof label === "string";
|
|
129
|
+
const [sheetOpen, setSheetOpen] = useState(false);
|
|
130
|
+
const sheetTriggerRef = useRef(null);
|
|
131
|
+
const closeSheet = () => setSheetOpen(false);
|
|
132
|
+
const sheetLabels = useKitLabels("pickerSheet", DEFAULT_PICKER_SHEET_LABELS);
|
|
133
|
+
const sheetFrame = (body, actions) => /* @__PURE__ */ jsx(
|
|
134
|
+
FullBleedDialog,
|
|
135
|
+
{
|
|
136
|
+
open: true,
|
|
137
|
+
onClose: closeSheet,
|
|
138
|
+
id: panelId,
|
|
139
|
+
"aria-label": panelLabel,
|
|
140
|
+
header: panelLabel,
|
|
141
|
+
closeLabel: sheetLabels.close,
|
|
142
|
+
backCloses: sheetBackCloses,
|
|
143
|
+
dir,
|
|
144
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
145
|
+
footer: actions,
|
|
146
|
+
children: body
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
const fieldTrigger = ({
|
|
150
|
+
open,
|
|
151
|
+
toggle,
|
|
152
|
+
ref
|
|
153
|
+
}) => /* @__PURE__ */ jsx(
|
|
154
|
+
DateFieldTrigger,
|
|
155
|
+
{
|
|
156
|
+
open,
|
|
157
|
+
toggle: () => {
|
|
158
|
+
setDir(dirOf(rootRef.current));
|
|
159
|
+
toggle();
|
|
160
|
+
},
|
|
161
|
+
triggerRef: ref,
|
|
162
|
+
triggerText,
|
|
163
|
+
hasValue,
|
|
164
|
+
labelledBy: [
|
|
165
|
+
aria["aria-labelledby"],
|
|
166
|
+
named ? labelId : !aria["aria-labelledby"] && aria.id ? aria.id : void 0,
|
|
167
|
+
valueId
|
|
168
|
+
].filter(Boolean).join(" "),
|
|
169
|
+
aria,
|
|
170
|
+
panelId,
|
|
171
|
+
valueId,
|
|
172
|
+
padded: label !== void 0,
|
|
173
|
+
disabled,
|
|
174
|
+
invalid,
|
|
175
|
+
renderTrigger
|
|
176
|
+
}
|
|
177
|
+
);
|
|
94
178
|
return (
|
|
95
179
|
// The caller's attributes land here, on the field's own box — the trigger inside is
|
|
96
180
|
// named by `aria-labelledby` and must keep the id pair it is given.
|
|
97
181
|
/* @__PURE__ */ jsxs("div", { ...wrapperRest, ref: rootRef, className: cn("relative", className), children: [
|
|
98
182
|
label !== void 0 && /* @__PURE__ */ jsx(FieldLabel, { children: label }),
|
|
99
183
|
named && /* @__PURE__ */ jsx("span", { id: labelId, "aria-hidden": true, className: "sr-only-fixed", children: label }),
|
|
100
|
-
/* @__PURE__ */
|
|
184
|
+
sheet ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
185
|
+
fieldTrigger({ open: sheetOpen, toggle: () => setSheetOpen((v) => !v), ref: sheetTriggerRef }),
|
|
186
|
+
sheetOpen && children(closeSheet, sheetFrame)
|
|
187
|
+
] }) : /* @__PURE__ */ jsx(
|
|
101
188
|
Popover,
|
|
102
189
|
{
|
|
103
190
|
width,
|
|
104
191
|
panelId,
|
|
105
192
|
labels: { panel: panelLabel },
|
|
106
193
|
dir,
|
|
107
|
-
trigger:
|
|
108
|
-
|
|
109
|
-
{
|
|
110
|
-
open,
|
|
111
|
-
toggle: () => {
|
|
112
|
-
setDir(dirOf(rootRef.current));
|
|
113
|
-
toggle();
|
|
114
|
-
},
|
|
115
|
-
triggerRef: ref,
|
|
116
|
-
triggerText,
|
|
117
|
-
hasValue,
|
|
118
|
-
labelledBy: [
|
|
119
|
-
aria["aria-labelledby"],
|
|
120
|
-
named ? labelId : !aria["aria-labelledby"] && aria.id ? aria.id : void 0,
|
|
121
|
-
valueId
|
|
122
|
-
].filter(Boolean).join(" "),
|
|
123
|
-
aria,
|
|
124
|
-
panelId,
|
|
125
|
-
valueId,
|
|
126
|
-
padded: label !== void 0,
|
|
127
|
-
disabled,
|
|
128
|
-
invalid
|
|
129
|
-
}
|
|
130
|
-
),
|
|
131
|
-
children: (close) => children(close)
|
|
194
|
+
trigger: fieldTrigger,
|
|
195
|
+
children: (close) => children(close, popoverFrame)
|
|
132
196
|
}
|
|
133
197
|
),
|
|
134
198
|
showClear ? /* @__PURE__ */ jsx(
|
|
@@ -338,7 +402,8 @@ function PresetColumn({
|
|
|
338
402
|
presets,
|
|
339
403
|
marked,
|
|
340
404
|
label,
|
|
341
|
-
onPick
|
|
405
|
+
onPick,
|
|
406
|
+
sheet
|
|
342
407
|
}) {
|
|
343
408
|
return (
|
|
344
409
|
// `border-e`/`pe`, not `-r`: the preset column is on the START side, and the rule
|
|
@@ -348,7 +413,7 @@ function PresetColumn({
|
|
|
348
413
|
{
|
|
349
414
|
role: "group",
|
|
350
415
|
"aria-label": label,
|
|
351
|
-
className: "flex w-32 shrink-0 flex-col gap-0.5 border-e border-[var(--border)] pe-2",
|
|
416
|
+
className: sheet ? "grid grid-cols-2 gap-0.5" : "flex w-32 shrink-0 flex-col gap-0.5 border-e border-[var(--border)] pe-2",
|
|
352
417
|
children: presets.map((p, i) => {
|
|
353
418
|
const selected = i === marked;
|
|
354
419
|
return /* @__PURE__ */ jsx(
|
|
@@ -359,7 +424,9 @@ function PresetColumn({
|
|
|
359
424
|
"data-preset": p.id,
|
|
360
425
|
onClick: () => onPick(p),
|
|
361
426
|
className: cn(
|
|
362
|
-
"rounded px-2
|
|
427
|
+
"rounded px-2 text-start",
|
|
428
|
+
// 44px on a phone: the kit's touch-target size (`SHEET_ROW_CLASS`).
|
|
429
|
+
sheet ? "min-h-11 py-2 text-sm" : "py-1.5 text-xs",
|
|
363
430
|
selected ? "bg-[var(--bg-active)] font-medium text-[var(--text-primary)]" : "text-[var(--text-secondary)] hover:bg-[var(--bg-hover)]"
|
|
364
431
|
),
|
|
365
432
|
children: p.label
|
|
@@ -379,9 +446,12 @@ function RangePanel({
|
|
|
379
446
|
controlled,
|
|
380
447
|
commit,
|
|
381
448
|
close,
|
|
449
|
+
frame,
|
|
450
|
+
sheet,
|
|
382
451
|
commitRange,
|
|
383
452
|
calendarProps,
|
|
384
|
-
labels
|
|
453
|
+
labels,
|
|
454
|
+
renderDraftSummary
|
|
385
455
|
}) {
|
|
386
456
|
const drafting = commit === "apply";
|
|
387
457
|
const [draft, setDraft] = useState({
|
|
@@ -392,7 +462,8 @@ function RangePanel({
|
|
|
392
462
|
const shown = drafting ? draft : { from, to, presetId: activeId ?? void 0 };
|
|
393
463
|
const marked = presets ? markedPreset(presets, shown.from, shown.to, drafting ? draft.presetId : activeId, drafting || controlled) : -1;
|
|
394
464
|
const complete = Boolean(draft.from && draft.to);
|
|
395
|
-
const
|
|
465
|
+
const summary = drafting && renderDraftSummary ? renderDraftSummary({ from: draft.from, to: draft.to, preset: presets?.[marked] }) : null;
|
|
466
|
+
const picker = /* @__PURE__ */ jsx(
|
|
396
467
|
MiniCalendar,
|
|
397
468
|
{
|
|
398
469
|
...calendarProps,
|
|
@@ -409,10 +480,15 @@ function RangePanel({
|
|
|
409
480
|
}
|
|
410
481
|
}
|
|
411
482
|
);
|
|
412
|
-
const
|
|
483
|
+
const calendar = drafting && renderDraftSummary ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
484
|
+
summary != null && /* @__PURE__ */ jsx("div", { "aria-live": "polite", "data-draft-summary": "", className: "text-xs text-[var(--text-muted)]", children: summary }),
|
|
485
|
+
picker
|
|
486
|
+
] }) : picker;
|
|
487
|
+
const body = presets && presets.length > 0 ? /* @__PURE__ */ jsxs("div", { className: sheet ? "flex flex-col gap-3" : "flex gap-3", children: [
|
|
413
488
|
/* @__PURE__ */ jsx(
|
|
414
489
|
PresetColumn,
|
|
415
490
|
{
|
|
491
|
+
sheet,
|
|
416
492
|
presets,
|
|
417
493
|
marked,
|
|
418
494
|
label: labels.presets,
|
|
@@ -428,15 +504,16 @@ function RangePanel({
|
|
|
428
504
|
),
|
|
429
505
|
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: calendar })
|
|
430
506
|
] }) : calendar;
|
|
431
|
-
if (!drafting) return body;
|
|
432
|
-
return
|
|
507
|
+
if (!drafting) return frame(body);
|
|
508
|
+
return frame(
|
|
433
509
|
body,
|
|
434
|
-
/* @__PURE__ */ jsxs(
|
|
435
|
-
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: close, children: labels.cancel }),
|
|
510
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
511
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", className: sheet ? "flex-1" : void 0, onClick: close, children: labels.cancel }),
|
|
436
512
|
/* @__PURE__ */ jsx(
|
|
437
513
|
Button,
|
|
438
514
|
{
|
|
439
515
|
type: "button",
|
|
516
|
+
className: sheet ? "flex-1" : void 0,
|
|
440
517
|
disabled: !complete,
|
|
441
518
|
onClick: () => {
|
|
442
519
|
if (!complete) return;
|
|
@@ -447,7 +524,7 @@ function RangePanel({
|
|
|
447
524
|
}
|
|
448
525
|
)
|
|
449
526
|
] })
|
|
450
|
-
|
|
527
|
+
);
|
|
451
528
|
}
|
|
452
529
|
function DateRangePicker({
|
|
453
530
|
from,
|
|
@@ -463,6 +540,9 @@ function DateRangePicker({
|
|
|
463
540
|
presets,
|
|
464
541
|
preset,
|
|
465
542
|
commit = "immediate",
|
|
543
|
+
renderTrigger,
|
|
544
|
+
sheetBackCloses,
|
|
545
|
+
renderDraftSummary,
|
|
466
546
|
calendarLabels,
|
|
467
547
|
label,
|
|
468
548
|
clearable,
|
|
@@ -481,6 +561,7 @@ function DateRangePicker({
|
|
|
481
561
|
const b = to ? render(to) : "";
|
|
482
562
|
const triggerText = from ? to ? `${a}${separator}${b}` : `${a}${separator}\u2026` : placeholder ?? "";
|
|
483
563
|
const hasPresets = Boolean(presets && presets.length > 0);
|
|
564
|
+
const sheet = useMediaQuery(PHONE_QUERY, false);
|
|
484
565
|
const commitRange = (f, t, presetId) => {
|
|
485
566
|
setOwnPreset(presetId);
|
|
486
567
|
if (presetId === void 0) onChange(f, t);
|
|
@@ -500,7 +581,18 @@ function DateRangePicker({
|
|
|
500
581
|
hasValue: Boolean(from || to),
|
|
501
582
|
triggerText,
|
|
502
583
|
onClear: () => commitRange("", "", void 0),
|
|
503
|
-
|
|
584
|
+
sheet,
|
|
585
|
+
sheetBackCloses,
|
|
586
|
+
renderTrigger: renderTrigger && ((triggerProps, valueId) => renderTrigger({
|
|
587
|
+
triggerProps,
|
|
588
|
+
valueProps: { id: valueId },
|
|
589
|
+
open: triggerProps["aria-expanded"],
|
|
590
|
+
from,
|
|
591
|
+
to,
|
|
592
|
+
preset: presets?.[markedPreset(presets, from, to, activeId, controlled)],
|
|
593
|
+
text: triggerText
|
|
594
|
+
})),
|
|
595
|
+
children: (close, frame) => /* @__PURE__ */ jsx(
|
|
504
596
|
RangePanel,
|
|
505
597
|
{
|
|
506
598
|
from,
|
|
@@ -510,9 +602,12 @@ function DateRangePicker({
|
|
|
510
602
|
controlled,
|
|
511
603
|
commit,
|
|
512
604
|
close,
|
|
605
|
+
frame,
|
|
606
|
+
sheet,
|
|
513
607
|
commitRange,
|
|
514
608
|
calendarProps: { locale, min, max, labels: calendarLabels },
|
|
515
|
-
labels: text
|
|
609
|
+
labels: text,
|
|
610
|
+
renderDraftSummary
|
|
516
611
|
}
|
|
517
612
|
)
|
|
518
613
|
}
|