@eifi1/ui-kit 0.8.0 → 0.9.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 +4 -0
- package/dist/components/amount-input.d.ts +2 -0
- package/dist/components/calculator.d.ts +2 -0
- package/dist/components/chip.d.ts +27 -5
- package/dist/components/chip.js +6 -2
- package/dist/components/chip.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 +69 -3
- package/dist/components/date-picker.js +152 -65
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/disclosure.d.ts +11 -2
- package/dist/components/disclosure.js +10 -4
- package/dist/components/disclosure.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.js +3 -1
- package/dist/components/full-bleed-dialog.js.map +1 -1
- package/dist/components/number-field.d.ts +2 -0
- package/dist/components/number-input.d.ts +2 -0
- package/dist/components/numpad-sheet.d.ts +2 -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/treemap.js +4 -1
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/ui.d.ts +44 -14
- package/dist/components/ui.js +28 -22
- 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-overlay-history.js +84 -4
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/i18n/defaults.d.ts +2 -0
- package/dist/i18n/defaults.js +2 -0
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +3 -0
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/de-CH-informal.d.ts +2 -0
- package/dist/i18n/locales/de-CH.d.ts +2 -0
- package/dist/i18n/locales/de-informal.d.ts +2 -0
- package/dist/i18n/locales/de.d.ts +2 -0
- package/dist/i18n/locales/de.js +10 -0
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +2 -0
- package/dist/i18n/locales/es.js +10 -0
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +2 -0
- package/dist/i18n/locales/fr.js +10 -0
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +2 -0
- package/dist/i18n/locales/hu.js +10 -0
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +2 -0
- package/dist/i18n/locales/it.js +10 -0
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +2 -0
- package/dist/i18n/locales/zh.js +10 -0
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/search/command-palette.d.ts +49 -1
- package/dist/search/command-palette.js +132 -29
- package/dist/search/command-palette.js.map +1 -1
- package/dist/search/global-search.d.ts +141 -0
- package/dist/search/global-search.js +277 -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 +2 -0
- 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 +2 -1
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/package.json +12 -3
- package/src/components/chip.tsx +36 -6
- package/src/components/data-table.tsx +81 -5
- package/src/components/date-picker.tsx +328 -117
- package/src/components/disclosure.tsx +24 -8
- package/src/components/floating-panel.tsx +46 -2
- package/src/components/full-bleed-dialog.tsx +7 -2
- package/src/components/progress-bar.tsx +27 -3
- package/src/components/treemap.tsx +3 -0
- package/src/components/ui.tsx +95 -37
- package/src/hooks/use-overlay-history.ts +181 -4
- package/src/i18n/defaults.ts +2 -0
- package/src/i18n/kit-labels.tsx +2 -0
- package/src/i18n/locales/de.ts +10 -0
- package/src/i18n/locales/es.ts +10 -0
- package/src/i18n/locales/fr.ts +10 -0
- package/src/i18n/locales/hu.ts +10 -0
- package/src/i18n/locales/it.ts +10 -0
- package/src/i18n/locales/zh.ts +10 -0
- package/src/index.ts +4 -0
- package/src/search/command-palette.tsx +200 -27
- package/src/search/global-search.tsx +484 -0
- package/src/search/search-index.ts +295 -0
- package/src/search.ts +2 -0
- package/src/wizard/stepper-nav.tsx +11 -1
|
@@ -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,50 @@ 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
|
+
/** What {@link DateRangePickerProps.renderTrigger} is called with. */
|
|
192
|
+
interface DateRangeTriggerRenderProps {
|
|
193
|
+
/** Spread onto the `<button>`, whole. Merge your class after `triggerProps.className`. */
|
|
194
|
+
triggerProps: DateTriggerAttributes;
|
|
195
|
+
/** Put on the element showing the value: the trigger is named "label, value" by
|
|
196
|
+
* reference to this id. Without it the name is the label alone. */
|
|
197
|
+
valueProps: {
|
|
198
|
+
id: string;
|
|
199
|
+
};
|
|
200
|
+
open: boolean;
|
|
201
|
+
from: string;
|
|
202
|
+
to: string;
|
|
203
|
+
/** The preset the column marks for the committed range, if any — the one to name. */
|
|
204
|
+
preset: DateRangePickerPreset | undefined;
|
|
205
|
+
/** What the kit's own trigger would show: the formatted range, or the placeholder. */
|
|
206
|
+
text: string;
|
|
141
207
|
}
|
|
142
208
|
/** Two-date range picker: click a start then an end; closes once both are set.
|
|
143
209
|
* With `presets`, a column of named ranges is shown beside the calendar; with
|
|
144
210
|
* `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;
|
|
211
|
+
declare function DateRangePicker({ from, to, onChange, locale: localeProp, placeholder, min, max, formatOptions, formatValue, separator, presets, preset, commit, renderTrigger, sheetBackCloses, calendarLabels, label, clearable, clearLabel, disabled, invalid, ...rest }: DateRangePickerProps): react.JSX.Element;
|
|
146
212
|
|
|
147
|
-
export { DatePicker, type DatePickerProps, type DateRangeCommit, DateRangePicker, type DateRangePickerPreset, type DateRangePickerProps };
|
|
213
|
+
export { DatePicker, type DatePickerProps, type DateRangeCommit, 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,6 +446,8 @@ function RangePanel({
|
|
|
379
446
|
controlled,
|
|
380
447
|
commit,
|
|
381
448
|
close,
|
|
449
|
+
frame,
|
|
450
|
+
sheet,
|
|
382
451
|
commitRange,
|
|
383
452
|
calendarProps,
|
|
384
453
|
labels
|
|
@@ -409,10 +478,11 @@ function RangePanel({
|
|
|
409
478
|
}
|
|
410
479
|
}
|
|
411
480
|
);
|
|
412
|
-
const body = presets && presets.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
481
|
+
const body = presets && presets.length > 0 ? /* @__PURE__ */ jsxs("div", { className: sheet ? "flex flex-col gap-3" : "flex gap-3", children: [
|
|
413
482
|
/* @__PURE__ */ jsx(
|
|
414
483
|
PresetColumn,
|
|
415
484
|
{
|
|
485
|
+
sheet,
|
|
416
486
|
presets,
|
|
417
487
|
marked,
|
|
418
488
|
label: labels.presets,
|
|
@@ -428,15 +498,16 @@ function RangePanel({
|
|
|
428
498
|
),
|
|
429
499
|
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: calendar })
|
|
430
500
|
] }) : calendar;
|
|
431
|
-
if (!drafting) return body;
|
|
432
|
-
return
|
|
501
|
+
if (!drafting) return frame(body);
|
|
502
|
+
return frame(
|
|
433
503
|
body,
|
|
434
|
-
/* @__PURE__ */ jsxs(
|
|
435
|
-
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: close, children: labels.cancel }),
|
|
504
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
505
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", className: sheet ? "flex-1" : void 0, onClick: close, children: labels.cancel }),
|
|
436
506
|
/* @__PURE__ */ jsx(
|
|
437
507
|
Button,
|
|
438
508
|
{
|
|
439
509
|
type: "button",
|
|
510
|
+
className: sheet ? "flex-1" : void 0,
|
|
440
511
|
disabled: !complete,
|
|
441
512
|
onClick: () => {
|
|
442
513
|
if (!complete) return;
|
|
@@ -447,7 +518,7 @@ function RangePanel({
|
|
|
447
518
|
}
|
|
448
519
|
)
|
|
449
520
|
] })
|
|
450
|
-
|
|
521
|
+
);
|
|
451
522
|
}
|
|
452
523
|
function DateRangePicker({
|
|
453
524
|
from,
|
|
@@ -463,6 +534,8 @@ function DateRangePicker({
|
|
|
463
534
|
presets,
|
|
464
535
|
preset,
|
|
465
536
|
commit = "immediate",
|
|
537
|
+
renderTrigger,
|
|
538
|
+
sheetBackCloses,
|
|
466
539
|
calendarLabels,
|
|
467
540
|
label,
|
|
468
541
|
clearable,
|
|
@@ -481,6 +554,7 @@ function DateRangePicker({
|
|
|
481
554
|
const b = to ? render(to) : "";
|
|
482
555
|
const triggerText = from ? to ? `${a}${separator}${b}` : `${a}${separator}\u2026` : placeholder ?? "";
|
|
483
556
|
const hasPresets = Boolean(presets && presets.length > 0);
|
|
557
|
+
const sheet = useMediaQuery(PHONE_QUERY, false);
|
|
484
558
|
const commitRange = (f, t, presetId) => {
|
|
485
559
|
setOwnPreset(presetId);
|
|
486
560
|
if (presetId === void 0) onChange(f, t);
|
|
@@ -500,7 +574,18 @@ function DateRangePicker({
|
|
|
500
574
|
hasValue: Boolean(from || to),
|
|
501
575
|
triggerText,
|
|
502
576
|
onClear: () => commitRange("", "", void 0),
|
|
503
|
-
|
|
577
|
+
sheet,
|
|
578
|
+
sheetBackCloses,
|
|
579
|
+
renderTrigger: renderTrigger && ((triggerProps, valueId) => renderTrigger({
|
|
580
|
+
triggerProps,
|
|
581
|
+
valueProps: { id: valueId },
|
|
582
|
+
open: triggerProps["aria-expanded"],
|
|
583
|
+
from,
|
|
584
|
+
to,
|
|
585
|
+
preset: presets?.[markedPreset(presets, from, to, activeId, controlled)],
|
|
586
|
+
text: triggerText
|
|
587
|
+
})),
|
|
588
|
+
children: (close, frame) => /* @__PURE__ */ jsx(
|
|
504
589
|
RangePanel,
|
|
505
590
|
{
|
|
506
591
|
from,
|
|
@@ -510,6 +595,8 @@ function DateRangePicker({
|
|
|
510
595
|
controlled,
|
|
511
596
|
commit,
|
|
512
597
|
close,
|
|
598
|
+
frame,
|
|
599
|
+
sheet,
|
|
513
600
|
commitRange,
|
|
514
601
|
calendarProps: { locale, min, max, labels: calendarLabels },
|
|
515
602
|
labels: text
|