@datum-cloud/datum-ui 0.8.1 → 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/dist/{adapter-context-NyGTDZYq.mjs → adapter-context-DemTWhel.mjs} +3 -3
- package/dist/alert/index.mjs +1 -1
- package/dist/{alert-BDj6od5I.mjs → alert-Cz56SqdN.mjs} +2 -2
- package/dist/app-navigation/index.mjs +2 -2
- package/dist/{app-navigation-rSOfo1KV.mjs → app-navigation-CnGkJvwF.mjs} +1 -1
- package/dist/autocomplete/index.mjs +1 -1
- package/dist/{autocomplete-DdbTQe6u.mjs → autocomplete-ChuPNldi.mjs} +6 -6
- package/dist/autosearch/index.mjs +12 -12
- package/dist/avatar-stack/index.mjs +1 -1
- package/dist/{avatar-stack-CDhlA1Nm.mjs → avatar-stack-WqoQ3l06.mjs} +1 -1
- package/dist/{button-D3RrsMfQ.mjs → button-Rw1xI-k9.mjs} +2 -2
- package/dist/calendar/index.mjs +1 -1
- package/dist/calendar-D_DriVHT.mjs +77 -0
- package/dist/{calendar-C-Hbf74r.mjs → calendar-Dwvq3Vu_.mjs} +6 -6
- package/dist/calendar-date-picker-CchHKodM.mjs +52 -0
- package/dist/chart/index.mjs +1 -1
- package/dist/{chart-CUa21ynK.mjs → chart-DgcOwkOh.mjs} +5 -5
- package/dist/code-editor/index.mjs +1 -1
- package/dist/{col-DISdGlqY.mjs → col-Q6yazFwL.mjs} +2 -1
- package/dist/components/base/button/button.d.ts.map +1 -1
- package/dist/components/features/calendar-date-picker/calendar-date-picker.d.ts +6 -5
- package/dist/components/features/calendar-date-picker/calendar-date-picker.d.ts.map +1 -1
- package/dist/components/features/calendar-date-picker/types.d.ts +19 -0
- package/dist/components/features/calendar-date-picker/types.d.ts.map +1 -1
- package/dist/components/features/code-editor/code-editor.d.ts +1 -1
- package/dist/components/features/code-editor/code-editor.d.ts.map +1 -1
- package/dist/components/features/code-editor/index.d.ts +1 -1
- package/dist/components/features/code-editor/index.d.ts.map +1 -1
- package/dist/components/features/code-editor/types.d.ts +25 -2
- package/dist/components/features/code-editor/types.d.ts.map +1 -1
- package/dist/components/features/data-table/core/client-provider.d.ts.map +1 -1
- package/dist/components/features/date-time-picker/date-time-picker.d.ts +12 -4
- package/dist/components/features/date-time-picker/date-time-picker.d.ts.map +1 -1
- package/dist/components/features/date-time-picker/types.d.ts +9 -0
- package/dist/components/features/date-time-picker/types.d.ts.map +1 -1
- package/dist/components/features/grid/components/col.d.ts +1 -1
- package/dist/components/features/grid/components/col.d.ts.map +1 -1
- package/dist/components/features/grid/components/row.d.ts +1 -1
- package/dist/components/features/grid/components/row.d.ts.map +1 -1
- package/dist/components/features/picker/components/calendar.d.ts +14 -0
- package/dist/components/features/picker/components/calendar.d.ts.map +1 -0
- package/dist/components/features/picker/components/content.d.ts +18 -0
- package/dist/components/features/picker/components/content.d.ts.map +1 -0
- package/dist/components/features/picker/components/context.d.ts +57 -0
- package/dist/components/features/picker/components/context.d.ts.map +1 -0
- package/dist/components/features/picker/components/footer.d.ts +35 -0
- package/dist/components/features/picker/components/footer.d.ts.map +1 -0
- package/dist/components/features/picker/components/index.d.ts +36 -0
- package/dist/components/features/picker/components/index.d.ts.map +1 -0
- package/dist/components/features/picker/components/presets.d.ts +9 -0
- package/dist/components/features/picker/components/presets.d.ts.map +1 -0
- package/dist/components/features/picker/components/root.d.ts +40 -0
- package/dist/components/features/picker/components/root.d.ts.map +1 -0
- package/dist/components/features/picker/components/time-input-field.d.ts +13 -0
- package/dist/components/features/picker/components/time-input-field.d.ts.map +1 -0
- package/dist/components/features/picker/components/time-input.d.ts +13 -0
- package/dist/components/features/picker/components/time-input.d.ts.map +1 -0
- package/dist/components/features/picker/components/timezone-indicator.d.ts +14 -0
- package/dist/components/features/picker/components/timezone-indicator.d.ts.map +1 -0
- package/dist/components/features/picker/components/timezone-select.d.ts +16 -0
- package/dist/components/features/picker/components/timezone-select.d.ts.map +1 -0
- package/dist/components/features/picker/components/trigger.d.ts +23 -0
- package/dist/components/features/picker/components/trigger.d.ts.map +1 -0
- package/dist/components/features/picker/hooks/index.d.ts +5 -0
- package/dist/components/features/picker/hooks/index.d.ts.map +1 -0
- package/dist/components/features/picker/hooks/use-keyboard-shortcuts.d.ts +25 -0
- package/dist/components/features/picker/hooks/use-keyboard-shortcuts.d.ts.map +1 -0
- package/dist/components/features/picker/hooks/use-picker-state.d.ts +51 -0
- package/dist/components/features/picker/hooks/use-picker-state.d.ts.map +1 -0
- package/dist/components/features/picker/hooks/use-presets.d.ts +24 -0
- package/dist/components/features/picker/hooks/use-presets.d.ts.map +1 -0
- package/dist/components/features/picker/hooks/use-time-slots.d.ts +21 -0
- package/dist/components/features/picker/hooks/use-time-slots.d.ts.map +1 -0
- package/dist/components/features/picker/index.d.ts +8 -0
- package/dist/components/features/picker/index.d.ts.map +1 -0
- package/dist/components/features/picker/internal/use-deprecation-warning.d.ts +9 -0
- package/dist/components/features/picker/internal/use-deprecation-warning.d.ts.map +1 -0
- package/dist/components/features/picker/presets/defaults.d.ts +16 -0
- package/dist/components/features/picker/presets/defaults.d.ts.map +1 -0
- package/dist/components/features/picker/presets/index.d.ts +2 -0
- package/dist/components/features/picker/presets/index.d.ts.map +1 -0
- package/dist/components/features/picker/types.d.ts +70 -0
- package/dist/components/features/picker/types.d.ts.map +1 -0
- package/dist/components/features/picker/utils/commit.d.ts +16 -0
- package/dist/components/features/picker/utils/commit.d.ts.map +1 -0
- package/dist/components/features/picker/utils/compare.d.ts +12 -0
- package/dist/components/features/picker/utils/compare.d.ts.map +1 -0
- package/dist/components/features/picker/utils/format-value.d.ts +25 -0
- package/dist/components/features/picker/utils/format-value.d.ts.map +1 -0
- package/dist/components/features/picker/utils/format.d.ts +38 -0
- package/dist/components/features/picker/utils/format.d.ts.map +1 -0
- package/dist/components/features/picker/utils/index.d.ts +7 -0
- package/dist/components/features/picker/utils/index.d.ts.map +1 -0
- package/dist/components/features/picker/utils/range.d.ts +26 -0
- package/dist/components/features/picker/utils/range.d.ts.map +1 -0
- package/dist/components/features/picker/utils/timezone.d.ts +38 -0
- package/dist/components/features/picker/utils/timezone.d.ts.map +1 -0
- package/dist/components/features/picker/wrappers/date-picker.d.ts +10 -0
- package/dist/components/features/picker/wrappers/date-picker.d.ts.map +1 -0
- package/dist/components/features/picker/wrappers/date-range-picker.d.ts +16 -0
- package/dist/components/features/picker/wrappers/date-range-picker.d.ts.map +1 -0
- package/dist/components/features/picker/wrappers/date-range-time-picker.d.ts +16 -0
- package/dist/components/features/picker/wrappers/date-range-time-picker.d.ts.map +1 -0
- package/dist/components/features/picker/wrappers/date-time-picker.d.ts +20 -0
- package/dist/components/features/picker/wrappers/date-time-picker.d.ts.map +1 -0
- package/dist/components/features/picker/wrappers/date-time-range-picker.d.ts +16 -0
- package/dist/components/features/picker/wrappers/date-time-range-picker.d.ts.map +1 -0
- package/dist/components/features/picker/wrappers/index.d.ts +16 -0
- package/dist/components/features/picker/wrappers/index.d.ts.map +1 -0
- package/dist/components/features/picker/wrappers/internal/default-footer.d.ts +7 -0
- package/dist/components/features/picker/wrappers/internal/default-footer.d.ts.map +1 -0
- package/dist/components/features/picker/wrappers/time-picker.d.ts +14 -0
- package/dist/components/features/picker/wrappers/time-picker.d.ts.map +1 -0
- package/dist/components/features/picker/wrappers/time-range-picker.d.ts +16 -0
- package/dist/components/features/picker/wrappers/time-range-picker.d.ts.map +1 -0
- package/dist/components/features/picker/wrappers/types.d.ts +118 -0
- package/dist/components/features/picker/wrappers/types.d.ts.map +1 -0
- package/dist/components/features/tag-input/tag-input.d.ts +1 -1
- package/dist/components/features/tag-input/tag-input.d.ts.map +1 -1
- package/dist/components/features/time-picker/time-picker.d.ts +5 -0
- package/dist/components/features/time-picker/time-picker.d.ts.map +1 -1
- package/dist/components/features/time-picker/types.d.ts +5 -0
- package/dist/components/features/time-picker/types.d.ts.map +1 -1
- package/dist/components/features/time-range-picker/index.d.ts +5 -0
- package/dist/components/features/time-range-picker/index.d.ts.map +1 -1
- package/dist/components/features/time-range-picker/time-range-picker.d.ts +19 -14
- package/dist/components/features/time-range-picker/time-range-picker.d.ts.map +1 -1
- package/dist/components/features/time-range-picker/types.d.ts +20 -0
- package/dist/components/features/time-range-picker/types.d.ts.map +1 -1
- package/dist/data-table/index.mjs +22 -15
- package/dist/date-picker/index.mjs +2 -2
- package/dist/date-range-picker-DNZh06zo.mjs +77 -0
- package/dist/date-time-picker/index.mjs +1 -1
- package/dist/date-time-picker-BiobghTJ.mjs +43 -0
- package/dist/date-time-picker-C0fF7s_e.mjs +109 -0
- package/dist/date-time-range-picker-cW4rbuFn.mjs +82 -0
- package/dist/default-footer-DbpemJVl.mjs +1037 -0
- package/dist/dropzone/index.mjs +1 -1
- package/dist/{dropzone-Bt0plEuw.mjs → dropzone-DXH0xHso.mjs} +1 -1
- package/dist/empty-content/index.mjs +1 -1
- package/dist/form/adapters/conform/index.mjs +19 -19
- package/dist/form/adapters/rhf/index.mjs +18 -18
- package/dist/form/index.mjs +2 -2
- package/dist/form/stepper/index.mjs +23 -23
- package/dist/{form-CCNN9VtJ.mjs → form-DvgKb4s4.mjs} +49 -42
- package/dist/{form-context-CeKyvO-A.mjs → form-context-0usxTumz.mjs} +3 -3
- package/dist/grid/index.mjs +1 -1
- package/dist/hooks/index.mjs +2 -2
- package/dist/index.mjs +41 -41
- package/dist/input-group/index.mjs +1 -1
- package/dist/{input-group-DDtz-RT7.mjs → input-group-CeMsDhOk.mjs} +1 -1
- package/dist/input-number/index.mjs +1 -1
- package/dist/{input-number-Diu-C6d5.mjs → input-number-BU4nno8J.mjs} +1 -1
- package/dist/loader-overlay/index.mjs +1 -1
- package/dist/map/index.mjs +1 -1
- package/dist/{map-qo7bY_g_.mjs → map-l7iwhEwM.mjs} +24 -27
- package/dist/more-actions/index.mjs +2 -2
- package/dist/{more-actions-Ca5qqd0H.mjs → more-actions-Baqor0yr.mjs} +2 -2
- package/dist/multi-select/index.mjs +1 -1
- package/dist/{multi-select-DM_dxnSV.mjs → multi-select-BHmtkQIi.mjs} +6 -6
- package/dist/page-title/index.mjs +1 -1
- package/dist/picker/index.mjs +273 -0
- package/dist/rich-text-editor/index.mjs +1 -1
- package/dist/{rich-text-editor-CQH_U4T5.mjs → rich-text-editor-aWuLRaj9.mjs} +1 -1
- package/dist/select/index.mjs +1 -1
- package/dist/select-By1ZqPgr.mjs +94 -0
- package/dist/select-Ck0szhAH.mjs +73 -0
- package/dist/sidebar/index.mjs +1 -1
- package/dist/{sidebar-B8LQJiNI.mjs → sidebar-CUnFkH7o.mjs} +32 -32
- package/dist/skeleton/index.mjs +1 -1
- package/dist/{skeleton-D4HOEiOZ.mjs → skeleton-CxAhQT6T.mjs} +1 -1
- package/dist/stepper/index.mjs +1 -1
- package/dist/{stepper-Beb-zbdL.mjs → stepper-adDdiJMx.mjs} +7 -7
- package/dist/styles/root.css +4 -2
- package/dist/styles/shadcn/shadcn.css +212 -213
- package/dist/switch/index.mjs +1 -1
- package/dist/table/index.mjs +1 -1
- package/dist/tag-input/index.mjs +1 -1
- package/dist/{tag-input-Bf4GMptp.mjs → tag-input-D3NYy9-_.mjs} +1 -1
- package/dist/task-queue/index.mjs +1 -1
- package/dist/{task-queue-dropdown-D-LncEWm.mjs → task-queue-dropdown-t9KKIL6j.mjs} +3 -3
- package/dist/textarea/index.mjs +1 -1
- package/dist/theme/index.mjs +1 -1
- package/dist/{themes-CAiN4b6G.mjs → themes-08-znmBI.mjs} +16 -16
- package/dist/time-input-9LdNL0Us.mjs +196 -0
- package/dist/time-picker/index.mjs +1 -1
- package/dist/time-picker-B-vpUClR.mjs +45 -0
- package/dist/time-picker-C840fLl6.mjs +49 -0
- package/dist/timezone-indicator-COoeMKKs.mjs +27 -0
- package/dist/{to-api-format-CgKcC9SK.mjs → to-api-format-CNqrcrz7.mjs} +58 -243
- package/dist/toast/index.mjs +2 -2
- package/dist/{toast-DDdLgY53.mjs → toast-Bd5Kk7BB.mjs} +1 -1
- package/dist/tooltip/index.mjs +1 -1
- package/dist/transfer/index.mjs +1 -1
- package/dist/{transfer-CoGPwOc6.mjs → transfer-CuJGL420.mjs} +6 -6
- package/dist/{types-CKIe2WlV.mjs → types-DvMIxilw.mjs} +9 -3
- package/dist/typography/index.mjs +1 -1
- package/dist/{typography-TRKP_CLT.mjs → typography-CBwfg-vz.mjs} +5 -5
- package/dist/{use-copy-to-clipboard-D7KyLIAt.mjs → use-copy-to-clipboard-ZHDvfV3W.mjs} +1 -1
- package/dist/use-deprecation-warning-Dy_DOyLu.mjs +20 -0
- package/dist/{use-display-touched-C-afz17j.mjs → use-display-touched-DpX3fsOl.mjs} +5 -5
- package/dist/{use-option-picker-BXQOfyrK.mjs → use-option-picker-DV5O68eV.mjs} +1 -1
- package/dist/utils/index.mjs +1 -1
- package/dist/visually-hidden/index.mjs +1 -1
- package/package.json +28 -23
- package/dist/calendar-date-picker-BaykEs6j.mjs +0 -749
- package/dist/date-time-picker-DKOxrhmc.mjs +0 -193
- package/dist/select-zxwykvQn.mjs +0 -163
- package/dist/time-picker-BZF5jbF6.mjs +0 -99
- package/dist/use-date-constraints-R3H4lIoT.mjs +0 -41
- /package/dist/{action-row-DnhBhMtt.mjs → action-row-ZaMsJ8cP.mjs} +0 -0
- /package/dist/{empty-content-CBh5bbtJ.mjs → empty-content-DTk_lwnh.mjs} +0 -0
- /package/dist/{hooks-DQXVwbrs.mjs → hooks-CnphNpwz.mjs} +0 -0
- /package/dist/{loader-overlay-C2WDla6V.mjs → loader-overlay-B3YEoOFJ.mjs} +0 -0
- /package/dist/{map-leaflet-imports-yWwH4CHB.mjs → map-leaflet-imports-Ix8F7E8j.mjs} +0 -0
- /package/dist/{page-title-ChLiv6gB.mjs → page-title-D5JhOpxV.mjs} +0 -0
- /package/dist/{skeleton-D2xuJdE1.mjs → skeleton-B1NOdZGM.mjs} +0 -0
- /package/dist/{switch-DcSF42Kc.mjs → switch-BcQaR1Bp.mjs} +0 -0
- /package/dist/{table-DWGT4cqh.mjs → table-ouGk4Vxe.mjs} +0 -0
- /package/dist/{textarea-BoChBcFz.mjs → textarea-q-k7DYwi.mjs} +0 -0
- /package/dist/{toast-D5XD7goD.mjs → toast-BWol1pyV.mjs} +0 -0
- /package/dist/{tooltip-a7NTDCWw.mjs → tooltip-CHuzXR_O.mjs} +0 -0
- /package/dist/{utils-BwB1mIdZ.mjs → utils-bUueJ2r9.mjs} +0 -0
- /package/dist/{visuallyhidden-BHOPczmW.mjs → visuallyhidden-CoIJOJ9z.mjs} +0 -0
|
@@ -0,0 +1,1037 @@
|
|
|
1
|
+
import { t as cn } from "./cn-D2KYQ917.mjs";
|
|
2
|
+
import { t as Button } from "./button-BllvE9Lm.mjs";
|
|
3
|
+
import { t as Button$1 } from "./button-Rw1xI-k9.mjs";
|
|
4
|
+
import { t as useBreakpoint } from "./use-breakpoint-DGcVmB3c.mjs";
|
|
5
|
+
import { t as ResponsivePopover } from "./responsive-popover-D-t9bxSN.mjs";
|
|
6
|
+
import { CalendarIcon, X } from "lucide-react";
|
|
7
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useReducer, useRef } from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { endOfDay, endOfMonth, endOfWeek, endOfYear, format, startOfDay, startOfMonth, startOfWeek, startOfYear, subDays, subHours, subMinutes } from "date-fns";
|
|
10
|
+
import { formatInTimeZone, fromZonedTime, toZonedTime } from "date-fns-tz";
|
|
11
|
+
//#region src/components/base/date-picker/use-date-constraints.ts
|
|
12
|
+
function useDateConstraints({ minDate, maxDate, disablePast, disableFuture }) {
|
|
13
|
+
const today = useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
14
|
+
const effectiveMinDate = useMemo(() => {
|
|
15
|
+
let min = minDate;
|
|
16
|
+
if (disablePast) {
|
|
17
|
+
const todayStart = startOfDay(today);
|
|
18
|
+
min = min ? min > todayStart ? min : todayStart : todayStart;
|
|
19
|
+
}
|
|
20
|
+
return min;
|
|
21
|
+
}, [
|
|
22
|
+
minDate,
|
|
23
|
+
disablePast,
|
|
24
|
+
today
|
|
25
|
+
]);
|
|
26
|
+
const effectiveMaxDate = useMemo(() => {
|
|
27
|
+
let max = maxDate;
|
|
28
|
+
if (disableFuture) {
|
|
29
|
+
const todayEnd = endOfDay(today);
|
|
30
|
+
max = max ? max < todayEnd ? max : todayEnd : todayEnd;
|
|
31
|
+
}
|
|
32
|
+
return max;
|
|
33
|
+
}, [
|
|
34
|
+
maxDate,
|
|
35
|
+
disableFuture,
|
|
36
|
+
today
|
|
37
|
+
]);
|
|
38
|
+
return {
|
|
39
|
+
effectiveMinDate,
|
|
40
|
+
effectiveMaxDate,
|
|
41
|
+
isDateDisabled: useCallback((date) => {
|
|
42
|
+
if (effectiveMinDate && date < effectiveMinDate) return true;
|
|
43
|
+
if (effectiveMaxDate && date > effectiveMaxDate) return true;
|
|
44
|
+
return false;
|
|
45
|
+
}, [effectiveMinDate, effectiveMaxDate])
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/components/features/picker/types.ts
|
|
50
|
+
const RANGE_MODES = [
|
|
51
|
+
"date-range",
|
|
52
|
+
"time-range",
|
|
53
|
+
"datetime-range",
|
|
54
|
+
"date-range-time"
|
|
55
|
+
];
|
|
56
|
+
const TIME_BEARING_MODES = [
|
|
57
|
+
"time",
|
|
58
|
+
"time-range",
|
|
59
|
+
"datetime",
|
|
60
|
+
"datetime-range",
|
|
61
|
+
"date-range-time"
|
|
62
|
+
];
|
|
63
|
+
const DATE_BEARING_MODES = [
|
|
64
|
+
"date",
|
|
65
|
+
"date-range",
|
|
66
|
+
"datetime",
|
|
67
|
+
"datetime-range",
|
|
68
|
+
"date-range-time"
|
|
69
|
+
];
|
|
70
|
+
function isRangeMode(mode) {
|
|
71
|
+
return RANGE_MODES.includes(mode);
|
|
72
|
+
}
|
|
73
|
+
function isTimeBearingMode(mode) {
|
|
74
|
+
return TIME_BEARING_MODES.includes(mode);
|
|
75
|
+
}
|
|
76
|
+
function isDateBearingMode(mode) {
|
|
77
|
+
return DATE_BEARING_MODES.includes(mode);
|
|
78
|
+
}
|
|
79
|
+
const ALLOWED_STEPS = [
|
|
80
|
+
1,
|
|
81
|
+
5,
|
|
82
|
+
10,
|
|
83
|
+
15,
|
|
84
|
+
30,
|
|
85
|
+
60
|
|
86
|
+
];
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/components/features/picker/utils/timezone.ts
|
|
89
|
+
/** Browser-detected IANA timezone, falling back to UTC if unavailable. */
|
|
90
|
+
function getBrowserTimezone() {
|
|
91
|
+
try {
|
|
92
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
93
|
+
} catch {
|
|
94
|
+
return "UTC";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* UTC offset for a timezone in `±HH:MM` format.
|
|
99
|
+
* Returns `+00:00` for UTC or any timezone the runtime cannot resolve.
|
|
100
|
+
*/
|
|
101
|
+
function getTimezoneOffset(timezone) {
|
|
102
|
+
try {
|
|
103
|
+
const offsetPart = new Intl.DateTimeFormat("en-US", {
|
|
104
|
+
timeZone: timezone,
|
|
105
|
+
timeZoneName: "shortOffset"
|
|
106
|
+
}).formatToParts(/* @__PURE__ */ new Date()).find((p) => p.type === "timeZoneName");
|
|
107
|
+
if (!offsetPart) return "+00:00";
|
|
108
|
+
const match = /GMT([+-])(\d+)(?::(\d+))?/.exec(offsetPart.value);
|
|
109
|
+
if (match) return `${match[1]}${match[2].padStart(2, "0")}:${match[3]?.padStart(2, "0") ?? "00"}`;
|
|
110
|
+
if (offsetPart.value === "GMT") return "+00:00";
|
|
111
|
+
return "+00:00";
|
|
112
|
+
} catch {
|
|
113
|
+
return "+00:00";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Human-readable timezone label.
|
|
118
|
+
* Example: `'Asia/Jakarta'` → `'Asia/Jakarta (UTC+07:00)'`.
|
|
119
|
+
*/
|
|
120
|
+
function formatTimezoneLabel(timezone) {
|
|
121
|
+
const offset = getTimezoneOffset(timezone);
|
|
122
|
+
return `${timezone.replace(/_/g, " ")} (UTC${offset})`;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Convert a UTC ISO string to a Date object whose wall-clock components
|
|
126
|
+
* (year/month/day/hours/minutes) reflect the value as seen in `timezone`.
|
|
127
|
+
*
|
|
128
|
+
* Use this to feed Calendar / time slot UI that reads `getHours()` etc.
|
|
129
|
+
*
|
|
130
|
+
* INVARIANT: `zonedDateToIso(isoToZonedDate(iso, tz), tz) === iso` for any
|
|
131
|
+
* valid ISO and tz.
|
|
132
|
+
*/
|
|
133
|
+
function isoToZonedDate(iso, timezone) {
|
|
134
|
+
return toZonedTime(new Date(iso), timezone);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Date-input variant of `isoToZonedDate`. Skips the ISO round-trip when the
|
|
138
|
+
* caller already has a Date instance (e.g. preset `getRange(tz)` results).
|
|
139
|
+
*/
|
|
140
|
+
function dateToZoned(date, timezone) {
|
|
141
|
+
return toZonedTime(date, timezone);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Inverse of `isoToZonedDate`. Treat the Date's wall-clock components
|
|
145
|
+
* as `timezone`-local and convert back to a UTC ISO instant.
|
|
146
|
+
*/
|
|
147
|
+
function zonedDateToIso(date, timezone) {
|
|
148
|
+
return fromZonedTime(date, timezone).toISOString();
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Format a UTC ISO string in the given timezone using a date-fns format pattern.
|
|
152
|
+
* Returns empty string if the input is not a valid date.
|
|
153
|
+
*/
|
|
154
|
+
function formatInTimezone(iso, timezone, pattern) {
|
|
155
|
+
try {
|
|
156
|
+
const d = new Date(iso);
|
|
157
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
158
|
+
return formatInTimeZone(d, timezone, pattern);
|
|
159
|
+
} catch {
|
|
160
|
+
return "";
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//#endregion
|
|
164
|
+
//#region src/components/features/picker/components/context.ts
|
|
165
|
+
const PickerContext = createContext(null);
|
|
166
|
+
/** Throws when used outside `<Picker.Root>` — enforces compound-component discipline. */
|
|
167
|
+
function usePickerContext() {
|
|
168
|
+
const ctx = useContext(PickerContext);
|
|
169
|
+
if (!ctx) throw new Error("Picker primitives must be rendered inside <Picker.Root>");
|
|
170
|
+
return ctx;
|
|
171
|
+
}
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/components/features/picker/components/content.tsx
|
|
174
|
+
function PickerContent({ trigger, sheetTitle, sheetDescription, footer, align = "start", side = "bottom", modal, contentClassName, children }) {
|
|
175
|
+
const { state, actions, effectiveCommit, responsive, breakpoint } = usePickerContext();
|
|
176
|
+
const isMobileSheet = responsive && breakpoint === "mobile";
|
|
177
|
+
const desktopFooter = !isMobileSheet && effectiveCommit === "apply" ? footer : null;
|
|
178
|
+
const sheetFooter = isMobileSheet ? footer : void 0;
|
|
179
|
+
return /* @__PURE__ */ jsx(ResponsivePopover, {
|
|
180
|
+
open: state.open,
|
|
181
|
+
onOpenChange: (open) => open ? actions.open() : actions.close(),
|
|
182
|
+
trigger,
|
|
183
|
+
sheetTitle,
|
|
184
|
+
sheetDescription,
|
|
185
|
+
sheetFooter,
|
|
186
|
+
align,
|
|
187
|
+
side,
|
|
188
|
+
modal,
|
|
189
|
+
responsive,
|
|
190
|
+
contentClassName: cn("w-auto", contentClassName),
|
|
191
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
192
|
+
className: "flex flex-col",
|
|
193
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
194
|
+
className: "flex flex-col",
|
|
195
|
+
children
|
|
196
|
+
}), desktopFooter && /* @__PURE__ */ jsx("div", {
|
|
197
|
+
className: "border-t p-3",
|
|
198
|
+
children: desktopFooter
|
|
199
|
+
})]
|
|
200
|
+
})
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
PickerContent.displayName = "Picker.Content";
|
|
204
|
+
//#endregion
|
|
205
|
+
//#region src/components/features/picker/hooks/use-keyboard-shortcuts.ts
|
|
206
|
+
/**
|
|
207
|
+
* Bind preset keyboard shortcuts to a scoped root element (NOT document).
|
|
208
|
+
*
|
|
209
|
+
* Why root-scoped: binding on `document` causes presets to fire when the
|
|
210
|
+
* user is typing in any input on the page — a well-known bug in the legacy
|
|
211
|
+
* TimeRangePicker. Scoping to the picker's root element fixes it.
|
|
212
|
+
*
|
|
213
|
+
* Modifier keys (Ctrl, Meta, Alt) are ignored to avoid colliding with
|
|
214
|
+
* browser/OS shortcuts.
|
|
215
|
+
*/
|
|
216
|
+
function useKeyboardShortcuts({ rootRef, presets, onSelect, enabled }) {
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
if (!enabled) return;
|
|
219
|
+
const root = rootRef.current;
|
|
220
|
+
if (!root) return;
|
|
221
|
+
function handler(e) {
|
|
222
|
+
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
223
|
+
const matched = presets.find((p) => p.shortcut && p.shortcut.toLowerCase() === e.key.toLowerCase());
|
|
224
|
+
if (matched) {
|
|
225
|
+
e.preventDefault();
|
|
226
|
+
onSelect(matched);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
root.addEventListener("keydown", handler);
|
|
230
|
+
return () => root.removeEventListener("keydown", handler);
|
|
231
|
+
}, [
|
|
232
|
+
rootRef,
|
|
233
|
+
presets,
|
|
234
|
+
onSelect,
|
|
235
|
+
enabled
|
|
236
|
+
]);
|
|
237
|
+
}
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region src/components/features/picker/utils/commit.ts
|
|
240
|
+
/**
|
|
241
|
+
* Resolves the effective commit semantics for a picker.
|
|
242
|
+
*
|
|
243
|
+
* - Date + time combined modes (`datetime` / `datetime-range` /
|
|
244
|
+
* `date-range-time`) **always** commit on Apply, regardless of the
|
|
245
|
+
* caller-supplied override. Picking a date alone shouldn't publish a
|
|
246
|
+
* value with an unconfirmed 00:00 time — the user needs to set the
|
|
247
|
+
* time too, then explicitly Apply. The wrappers don't expose a
|
|
248
|
+
* `commit` prop for these modes; primitive consumers can still pass
|
|
249
|
+
* one through `Picker.Root` but it's silently overridden here.
|
|
250
|
+
* - Range modes (`date-range`, `time-range`) default to `'apply'`.
|
|
251
|
+
* - Everything else defaults to `'immediate'`.
|
|
252
|
+
*/
|
|
253
|
+
function resolveCommit(mode, commit) {
|
|
254
|
+
if (isDateBearingMode(mode) && isTimeBearingMode(mode)) return "apply";
|
|
255
|
+
return commit ?? (isRangeMode(mode) ? "apply" : "immediate");
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
258
|
+
//#region src/components/features/picker/utils/format.ts
|
|
259
|
+
/**
|
|
260
|
+
* Format a Date as YYYY-MM-DD using local-time components.
|
|
261
|
+
*
|
|
262
|
+
* Note: this is the consumer-friendly format for date-only modes.
|
|
263
|
+
* It does NOT round-trip through timezones; that's intentional —
|
|
264
|
+
* a calendar day has no timezone.
|
|
265
|
+
*/
|
|
266
|
+
function dateToYYYYMMDD(d) {
|
|
267
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Extract `"HH:mm"` from a Date using its wall-clock components.
|
|
271
|
+
*
|
|
272
|
+
* Caller is responsible for ensuring those components reflect the
|
|
273
|
+
* intended timezone (typically via `dateToZoned` / `isoToZonedDate`
|
|
274
|
+
* upstream). Pads single-digit hour/minute to two characters.
|
|
275
|
+
*/
|
|
276
|
+
function dateToHHmm(d) {
|
|
277
|
+
return `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
|
|
278
|
+
}
|
|
279
|
+
const TIME_REGEX = /^(\d{2}):(\d{2})$/;
|
|
280
|
+
/**
|
|
281
|
+
* Strict HH:mm validation. Rejects single-digit components,
|
|
282
|
+
* out-of-range hours/minutes, and any non-numeric content.
|
|
283
|
+
*/
|
|
284
|
+
function isValidTimeString(s) {
|
|
285
|
+
const match = TIME_REGEX.exec(s);
|
|
286
|
+
if (!match) return false;
|
|
287
|
+
const h = Number(match[1]);
|
|
288
|
+
const m = Number(match[2]);
|
|
289
|
+
return h >= 0 && h <= 23 && m >= 0 && m <= 59;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Parse a HH:mm string. Returns null for invalid input.
|
|
293
|
+
*/
|
|
294
|
+
function parseTimeString(s) {
|
|
295
|
+
if (!isValidTimeString(s)) return null;
|
|
296
|
+
const match = TIME_REGEX.exec(s);
|
|
297
|
+
return {
|
|
298
|
+
h: Number(match[1]),
|
|
299
|
+
m: Number(match[2])
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Format a HH:mm string for user display, respecting hour cycle.
|
|
304
|
+
*
|
|
305
|
+
* - `'24'`: returns the input as-is (`"14:30"`)
|
|
306
|
+
* - `'12'`: returns `"2:30 PM"` style with AM/PM and no leading zero on hour
|
|
307
|
+
*
|
|
308
|
+
* Returns empty string for invalid input — callers should validate first.
|
|
309
|
+
*/
|
|
310
|
+
function formatTimeLabel(time, hourCycle) {
|
|
311
|
+
const parsed = parseTimeString(time);
|
|
312
|
+
if (!parsed) return "";
|
|
313
|
+
if (hourCycle === "24") return time;
|
|
314
|
+
const period = parsed.h >= 12 ? "PM" : "AM";
|
|
315
|
+
return `${parsed.h === 0 ? 12 : parsed.h > 12 ? parsed.h - 12 : parsed.h}:${String(parsed.m).padStart(2, "0")} ${period}`;
|
|
316
|
+
}
|
|
317
|
+
//#endregion
|
|
318
|
+
//#region src/components/features/picker/hooks/use-picker-state.ts
|
|
319
|
+
function reducer(state, action) {
|
|
320
|
+
switch (action.type) {
|
|
321
|
+
case "SET_SINGLE_DATE":
|
|
322
|
+
case "SET_SINGLE_TIME":
|
|
323
|
+
case "SET_SINGLE_DATETIME":
|
|
324
|
+
case "SET_RANGE":
|
|
325
|
+
case "SET_TIME_RANGE":
|
|
326
|
+
case "SET_DATETIME_RANGE": return {
|
|
327
|
+
...state,
|
|
328
|
+
pendingValue: action.payload,
|
|
329
|
+
selectedPresetKey: void 0
|
|
330
|
+
};
|
|
331
|
+
case "SELECT_PRESET": return {
|
|
332
|
+
...state,
|
|
333
|
+
pendingValue: action.payload.pendingValue,
|
|
334
|
+
selectedPresetKey: action.payload.key,
|
|
335
|
+
monthFrom: action.payload.monthFrom,
|
|
336
|
+
monthTo: action.payload.monthTo
|
|
337
|
+
};
|
|
338
|
+
case "SET_MONTH_FROM": return {
|
|
339
|
+
...state,
|
|
340
|
+
monthFrom: action.payload
|
|
341
|
+
};
|
|
342
|
+
case "SET_MONTH_TO": return {
|
|
343
|
+
...state,
|
|
344
|
+
monthTo: action.payload
|
|
345
|
+
};
|
|
346
|
+
case "OPEN": return {
|
|
347
|
+
...state,
|
|
348
|
+
open: true
|
|
349
|
+
};
|
|
350
|
+
case "CLOSE": return {
|
|
351
|
+
...state,
|
|
352
|
+
open: false
|
|
353
|
+
};
|
|
354
|
+
case "RESET_TO": return {
|
|
355
|
+
...state,
|
|
356
|
+
pendingValue: action.payload,
|
|
357
|
+
selectedPresetKey: void 0
|
|
358
|
+
};
|
|
359
|
+
case "CLEAR_PRESET": return {
|
|
360
|
+
...state,
|
|
361
|
+
selectedPresetKey: void 0
|
|
362
|
+
};
|
|
363
|
+
default: return state;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Convert a preset's `{ from: Date, to: Date }` (real UTC instants) into the
|
|
368
|
+
* value shape that the picker's `mode` actually emits.
|
|
369
|
+
*
|
|
370
|
+
* - `date-range`: pass through (Dates).
|
|
371
|
+
* - `datetime-range` / `date-range-time`: `.toISOString()` — instants already match.
|
|
372
|
+
* - `time-range`: extract wall-clock `HH:mm` in the active timezone.
|
|
373
|
+
* - others (date / time / datetime): no preset value — return `null`.
|
|
374
|
+
*/
|
|
375
|
+
function presetValueForMode(mode, range, key, timezone) {
|
|
376
|
+
switch (mode) {
|
|
377
|
+
case "date-range": return {
|
|
378
|
+
from: range.from,
|
|
379
|
+
to: range.to,
|
|
380
|
+
preset: key
|
|
381
|
+
};
|
|
382
|
+
case "datetime-range":
|
|
383
|
+
case "date-range-time": return {
|
|
384
|
+
from: range.from.toISOString(),
|
|
385
|
+
to: range.to.toISOString(),
|
|
386
|
+
preset: key
|
|
387
|
+
};
|
|
388
|
+
case "time-range": return {
|
|
389
|
+
from: dateToHHmm(dateToZoned(range.from, timezone)),
|
|
390
|
+
to: dateToHHmm(dateToZoned(range.to, timezone)),
|
|
391
|
+
preset: key
|
|
392
|
+
};
|
|
393
|
+
default: return null;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
function usePickerState({ mode, value, onChange, commit, timezone }) {
|
|
397
|
+
const effectiveCommit = resolveCommit(mode, commit);
|
|
398
|
+
const [state, dispatch] = useReducer(reducer, void 0, () => ({
|
|
399
|
+
pendingValue: value,
|
|
400
|
+
open: false,
|
|
401
|
+
selectedPresetKey: void 0,
|
|
402
|
+
monthFrom: void 0,
|
|
403
|
+
monthTo: void 0
|
|
404
|
+
}));
|
|
405
|
+
useEffect(() => {
|
|
406
|
+
dispatch({
|
|
407
|
+
type: "RESET_TO",
|
|
408
|
+
payload: value
|
|
409
|
+
});
|
|
410
|
+
}, [value]);
|
|
411
|
+
const onChangeRef = useRef(onChange);
|
|
412
|
+
const valueRef = useRef(value);
|
|
413
|
+
const pendingValueRef = useRef(state.pendingValue);
|
|
414
|
+
const effectiveCommitRef = useRef(effectiveCommit);
|
|
415
|
+
const modeRef = useRef(mode);
|
|
416
|
+
const timezoneRef = useRef(timezone);
|
|
417
|
+
useEffect(() => {
|
|
418
|
+
onChangeRef.current = onChange;
|
|
419
|
+
valueRef.current = value;
|
|
420
|
+
pendingValueRef.current = state.pendingValue;
|
|
421
|
+
effectiveCommitRef.current = effectiveCommit;
|
|
422
|
+
modeRef.current = mode;
|
|
423
|
+
timezoneRef.current = timezone;
|
|
424
|
+
});
|
|
425
|
+
const commitValue = useCallback((next) => {
|
|
426
|
+
onChangeRef.current(next);
|
|
427
|
+
}, []);
|
|
428
|
+
const actions = useMemo(() => {
|
|
429
|
+
const setSingleValue = (action) => {
|
|
430
|
+
dispatch(action);
|
|
431
|
+
if (effectiveCommitRef.current === "immediate") {
|
|
432
|
+
commitValue(action.payload);
|
|
433
|
+
dispatch({ type: "CLOSE" });
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
return {
|
|
437
|
+
setSingleDate: (d) => setSingleValue({
|
|
438
|
+
type: "SET_SINGLE_DATE",
|
|
439
|
+
payload: d
|
|
440
|
+
}),
|
|
441
|
+
setSingleTime: (t) => setSingleValue({
|
|
442
|
+
type: "SET_SINGLE_TIME",
|
|
443
|
+
payload: t
|
|
444
|
+
}),
|
|
445
|
+
setSingleDatetime: (iso) => setSingleValue({
|
|
446
|
+
type: "SET_SINGLE_DATETIME",
|
|
447
|
+
payload: iso
|
|
448
|
+
}),
|
|
449
|
+
setRange: (r) => {
|
|
450
|
+
dispatch({
|
|
451
|
+
type: "SET_RANGE",
|
|
452
|
+
payload: r
|
|
453
|
+
});
|
|
454
|
+
if (effectiveCommitRef.current === "immediate" && r !== null) {
|
|
455
|
+
commitValue(r);
|
|
456
|
+
dispatch({ type: "CLOSE" });
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
setTimeRange: (r) => {
|
|
460
|
+
dispatch({
|
|
461
|
+
type: "SET_TIME_RANGE",
|
|
462
|
+
payload: r
|
|
463
|
+
});
|
|
464
|
+
if (effectiveCommitRef.current === "immediate" && r !== null) {
|
|
465
|
+
commitValue(r);
|
|
466
|
+
dispatch({ type: "CLOSE" });
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
setDatetimeRange: (r) => {
|
|
470
|
+
dispatch({
|
|
471
|
+
type: "SET_DATETIME_RANGE",
|
|
472
|
+
payload: r
|
|
473
|
+
});
|
|
474
|
+
if (effectiveCommitRef.current === "immediate" && r !== null) {
|
|
475
|
+
commitValue(r);
|
|
476
|
+
dispatch({ type: "CLOSE" });
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
selectPreset: (range, key) => {
|
|
480
|
+
const pendingValue = presetValueForMode(modeRef.current, range, key, timezoneRef.current);
|
|
481
|
+
dispatch({
|
|
482
|
+
type: "SELECT_PRESET",
|
|
483
|
+
payload: {
|
|
484
|
+
pendingValue,
|
|
485
|
+
key,
|
|
486
|
+
monthFrom: range.from,
|
|
487
|
+
monthTo: range.to
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
commitValue(pendingValue);
|
|
491
|
+
dispatch({ type: "CLOSE" });
|
|
492
|
+
},
|
|
493
|
+
setMonthFrom: (d) => dispatch({
|
|
494
|
+
type: "SET_MONTH_FROM",
|
|
495
|
+
payload: d
|
|
496
|
+
}),
|
|
497
|
+
setMonthTo: (d) => dispatch({
|
|
498
|
+
type: "SET_MONTH_TO",
|
|
499
|
+
payload: d
|
|
500
|
+
}),
|
|
501
|
+
open: () => dispatch({ type: "OPEN" }),
|
|
502
|
+
close: () => dispatch({ type: "CLOSE" }),
|
|
503
|
+
apply: () => {
|
|
504
|
+
commitValue(pendingValueRef.current);
|
|
505
|
+
dispatch({ type: "CLOSE" });
|
|
506
|
+
},
|
|
507
|
+
reset: () => dispatch({
|
|
508
|
+
type: "RESET_TO",
|
|
509
|
+
payload: valueRef.current
|
|
510
|
+
}),
|
|
511
|
+
cancel: () => {
|
|
512
|
+
dispatch({
|
|
513
|
+
type: "RESET_TO",
|
|
514
|
+
payload: valueRef.current
|
|
515
|
+
});
|
|
516
|
+
dispatch({ type: "CLOSE" });
|
|
517
|
+
},
|
|
518
|
+
clear: () => {
|
|
519
|
+
dispatch({
|
|
520
|
+
type: "RESET_TO",
|
|
521
|
+
payload: null
|
|
522
|
+
});
|
|
523
|
+
commitValue(null);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
}, [commitValue]);
|
|
527
|
+
return {
|
|
528
|
+
state: {
|
|
529
|
+
pendingValue: state.pendingValue,
|
|
530
|
+
open: state.open,
|
|
531
|
+
selectedPresetKey: state.selectedPresetKey,
|
|
532
|
+
monthFrom: state.monthFrom,
|
|
533
|
+
monthTo: state.monthTo
|
|
534
|
+
},
|
|
535
|
+
actions
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
//#endregion
|
|
539
|
+
//#region src/components/features/picker/presets/defaults.ts
|
|
540
|
+
function startOfDayInTz(d, tz) {
|
|
541
|
+
const zoned = toZonedTime(d, tz);
|
|
542
|
+
zoned.setHours(0, 0, 0, 0);
|
|
543
|
+
return fromZonedTime(zoned, tz);
|
|
544
|
+
}
|
|
545
|
+
function endOfDayInTz(d, tz) {
|
|
546
|
+
const zoned = toZonedTime(d, tz);
|
|
547
|
+
zoned.setHours(23, 59, 59, 999);
|
|
548
|
+
return fromZonedTime(zoned, tz);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Date-bearing presets. Operate on calendar days; ignore time-of-day.
|
|
552
|
+
*/
|
|
553
|
+
const DATE_PRESETS = [
|
|
554
|
+
{
|
|
555
|
+
key: "today",
|
|
556
|
+
label: "Today",
|
|
557
|
+
shortcut: "D",
|
|
558
|
+
getRange: (tz) => ({
|
|
559
|
+
from: startOfDayInTz(/* @__PURE__ */ new Date(), tz),
|
|
560
|
+
to: endOfDayInTz(/* @__PURE__ */ new Date(), tz)
|
|
561
|
+
})
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
key: "yesterday",
|
|
565
|
+
label: "Yesterday",
|
|
566
|
+
shortcut: "Y",
|
|
567
|
+
getRange: (tz) => {
|
|
568
|
+
const y = subDays(/* @__PURE__ */ new Date(), 1);
|
|
569
|
+
return {
|
|
570
|
+
from: startOfDayInTz(y, tz),
|
|
571
|
+
to: endOfDayInTz(y, tz)
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
key: "this-week",
|
|
577
|
+
label: "This Week",
|
|
578
|
+
getRange: () => {
|
|
579
|
+
const now = /* @__PURE__ */ new Date();
|
|
580
|
+
return {
|
|
581
|
+
from: startOfWeek(now, { weekStartsOn: 1 }),
|
|
582
|
+
to: endOfWeek(now, { weekStartsOn: 1 })
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
key: "last-7-days",
|
|
588
|
+
label: "Last 7 Days",
|
|
589
|
+
shortcut: "W",
|
|
590
|
+
getRange: (tz) => ({
|
|
591
|
+
from: startOfDayInTz(subDays(/* @__PURE__ */ new Date(), 6), tz),
|
|
592
|
+
to: endOfDayInTz(/* @__PURE__ */ new Date(), tz)
|
|
593
|
+
})
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
key: "this-month",
|
|
597
|
+
label: "This Month",
|
|
598
|
+
getRange: () => {
|
|
599
|
+
const now = /* @__PURE__ */ new Date();
|
|
600
|
+
return {
|
|
601
|
+
from: startOfMonth(now),
|
|
602
|
+
to: endOfMonth(now)
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
key: "last-30-days",
|
|
608
|
+
label: "Last 30 Days",
|
|
609
|
+
shortcut: "M",
|
|
610
|
+
getRange: (tz) => ({
|
|
611
|
+
from: startOfDayInTz(subDays(/* @__PURE__ */ new Date(), 29), tz),
|
|
612
|
+
to: endOfDayInTz(/* @__PURE__ */ new Date(), tz)
|
|
613
|
+
})
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
key: "this-year",
|
|
617
|
+
label: "This Year",
|
|
618
|
+
getRange: () => {
|
|
619
|
+
const now = /* @__PURE__ */ new Date();
|
|
620
|
+
return {
|
|
621
|
+
from: startOfYear(now),
|
|
622
|
+
to: endOfYear(now)
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
];
|
|
627
|
+
/**
|
|
628
|
+
* Datetime-bearing presets. Use "now" as the upper bound for past windows
|
|
629
|
+
* (so the picker doesn't propose future timestamps).
|
|
630
|
+
*/
|
|
631
|
+
const DATETIME_PRESETS = [
|
|
632
|
+
{
|
|
633
|
+
key: "last-15m",
|
|
634
|
+
label: "Last 15 minutes",
|
|
635
|
+
shortcut: "1",
|
|
636
|
+
getRange: () => {
|
|
637
|
+
const now = /* @__PURE__ */ new Date();
|
|
638
|
+
return {
|
|
639
|
+
from: subMinutes(now, 15),
|
|
640
|
+
to: now
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
key: "last-1h",
|
|
646
|
+
label: "Last hour",
|
|
647
|
+
shortcut: "H",
|
|
648
|
+
getRange: () => {
|
|
649
|
+
const now = /* @__PURE__ */ new Date();
|
|
650
|
+
return {
|
|
651
|
+
from: subHours(now, 1),
|
|
652
|
+
to: now
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
key: "last-24h",
|
|
658
|
+
label: "Last 24 hours",
|
|
659
|
+
getRange: () => {
|
|
660
|
+
const now = /* @__PURE__ */ new Date();
|
|
661
|
+
return {
|
|
662
|
+
from: subHours(now, 24),
|
|
663
|
+
to: now
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
key: "today",
|
|
669
|
+
label: "Today",
|
|
670
|
+
shortcut: "D",
|
|
671
|
+
getRange: (tz) => ({
|
|
672
|
+
from: startOfDayInTz(/* @__PURE__ */ new Date(), tz),
|
|
673
|
+
to: /* @__PURE__ */ new Date()
|
|
674
|
+
})
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
key: "last-7-days",
|
|
678
|
+
label: "Last 7 days",
|
|
679
|
+
shortcut: "W",
|
|
680
|
+
getRange: () => {
|
|
681
|
+
const now = /* @__PURE__ */ new Date();
|
|
682
|
+
return {
|
|
683
|
+
from: subDays(now, 7),
|
|
684
|
+
to: now
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
key: "last-30-days",
|
|
690
|
+
label: "Last 30 days",
|
|
691
|
+
shortcut: "M",
|
|
692
|
+
getRange: () => {
|
|
693
|
+
const now = /* @__PURE__ */ new Date();
|
|
694
|
+
return {
|
|
695
|
+
from: subDays(now, 30),
|
|
696
|
+
to: now
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
];
|
|
701
|
+
const EMPTY = [];
|
|
702
|
+
/**
|
|
703
|
+
* Default preset set for a given mode. Time-only modes return empty —
|
|
704
|
+
* presets rarely make sense for picking a wall-clock time.
|
|
705
|
+
*/
|
|
706
|
+
function getDefaultPresets(mode) {
|
|
707
|
+
switch (mode) {
|
|
708
|
+
case "date":
|
|
709
|
+
case "date-range": return DATE_PRESETS;
|
|
710
|
+
case "datetime":
|
|
711
|
+
case "datetime-range":
|
|
712
|
+
case "date-range-time": return DATETIME_PRESETS;
|
|
713
|
+
default: return EMPTY;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
//#endregion
|
|
717
|
+
//#region src/components/features/picker/hooks/use-presets.ts
|
|
718
|
+
/**
|
|
719
|
+
* Resolve the effective list of presets for a picker.
|
|
720
|
+
*
|
|
721
|
+
* Resolution order:
|
|
722
|
+
* 1. If `custom` is provided, use it as-is (no exclusion, no constraint check).
|
|
723
|
+
* 2. Otherwise: defaults for `mode`, minus `excludeKeys`, minus presets
|
|
724
|
+
* whose `getRange(timezone).from` or `.to` is rejected by `isDateDisabled`.
|
|
725
|
+
*
|
|
726
|
+
* Returns a memoized array; identity-stable when inputs haven't changed.
|
|
727
|
+
*/
|
|
728
|
+
function usePresets({ mode, timezone, custom, excludeKeys, isDateDisabled }) {
|
|
729
|
+
return useMemo(() => {
|
|
730
|
+
if (custom) return custom;
|
|
731
|
+
const base = getDefaultPresets(mode);
|
|
732
|
+
const excludeSet = new Set(excludeKeys ?? []);
|
|
733
|
+
return base.filter((preset) => {
|
|
734
|
+
if (excludeSet.has(preset.key)) return false;
|
|
735
|
+
const range = preset.getRange(timezone);
|
|
736
|
+
if (isDateDisabled(range.from)) return false;
|
|
737
|
+
if (isDateDisabled(range.to)) return false;
|
|
738
|
+
return true;
|
|
739
|
+
});
|
|
740
|
+
}, [
|
|
741
|
+
mode,
|
|
742
|
+
timezone,
|
|
743
|
+
custom,
|
|
744
|
+
excludeKeys,
|
|
745
|
+
isDateDisabled
|
|
746
|
+
]);
|
|
747
|
+
}
|
|
748
|
+
//#endregion
|
|
749
|
+
//#region src/components/features/picker/components/root.tsx
|
|
750
|
+
function detectHourCycle() {
|
|
751
|
+
try {
|
|
752
|
+
const opts = new Intl.DateTimeFormat(void 0, { hour: "numeric" }).resolvedOptions();
|
|
753
|
+
if (opts.hourCycle === "h23" || opts.hourCycle === "h24") return "24";
|
|
754
|
+
return "12";
|
|
755
|
+
} catch {
|
|
756
|
+
return "24";
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
function PickerRoot({ mode, value, onChange, commit, timezone: timezoneProp, step = 15, hourCycle: hourCycleProp, hideTimezone = false, responsive = true, presets: customPresets, excludePresets, minDate, maxDate, disablePast, disableFuture, children }) {
|
|
760
|
+
const rootRef = useRef(null);
|
|
761
|
+
const breakpoint = useBreakpoint();
|
|
762
|
+
const timezone = timezoneProp ?? getBrowserTimezone();
|
|
763
|
+
const hourCycle = hourCycleProp ?? detectHourCycle();
|
|
764
|
+
const { isDateDisabled } = useDateConstraints({
|
|
765
|
+
minDate,
|
|
766
|
+
maxDate,
|
|
767
|
+
disablePast,
|
|
768
|
+
disableFuture
|
|
769
|
+
});
|
|
770
|
+
const presets = usePresets({
|
|
771
|
+
mode,
|
|
772
|
+
timezone,
|
|
773
|
+
custom: customPresets,
|
|
774
|
+
excludeKeys: excludePresets,
|
|
775
|
+
isDateDisabled
|
|
776
|
+
});
|
|
777
|
+
const { state, actions } = usePickerState({
|
|
778
|
+
mode,
|
|
779
|
+
value,
|
|
780
|
+
onChange,
|
|
781
|
+
commit,
|
|
782
|
+
timezone
|
|
783
|
+
});
|
|
784
|
+
const effectiveCommit = resolveCommit(mode, commit);
|
|
785
|
+
useKeyboardShortcuts({
|
|
786
|
+
rootRef,
|
|
787
|
+
presets,
|
|
788
|
+
onSelect: useCallback((preset) => {
|
|
789
|
+
const range = preset.getRange(timezone);
|
|
790
|
+
actions.selectPreset(range, preset.key);
|
|
791
|
+
}, [timezone, actions]),
|
|
792
|
+
enabled: state.open
|
|
793
|
+
});
|
|
794
|
+
const ctx = useMemo(() => ({
|
|
795
|
+
mode,
|
|
796
|
+
timezone,
|
|
797
|
+
effectiveCommit,
|
|
798
|
+
hourCycle,
|
|
799
|
+
step,
|
|
800
|
+
hideTimezone,
|
|
801
|
+
responsive,
|
|
802
|
+
presets,
|
|
803
|
+
rootRef,
|
|
804
|
+
breakpoint,
|
|
805
|
+
state,
|
|
806
|
+
actions
|
|
807
|
+
}), [
|
|
808
|
+
mode,
|
|
809
|
+
timezone,
|
|
810
|
+
effectiveCommit,
|
|
811
|
+
hourCycle,
|
|
812
|
+
step,
|
|
813
|
+
hideTimezone,
|
|
814
|
+
responsive,
|
|
815
|
+
presets,
|
|
816
|
+
breakpoint,
|
|
817
|
+
state,
|
|
818
|
+
actions
|
|
819
|
+
]);
|
|
820
|
+
return /* @__PURE__ */ jsx(PickerContext.Provider, {
|
|
821
|
+
value: ctx,
|
|
822
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
823
|
+
ref: rootRef,
|
|
824
|
+
children
|
|
825
|
+
})
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
PickerRoot.displayName = "Picker.Root";
|
|
829
|
+
/**
|
|
830
|
+
* Public namespace export. Subsequent tasks add Trigger, Content, etc.
|
|
831
|
+
*/
|
|
832
|
+
const Picker = { Root: PickerRoot };
|
|
833
|
+
//#endregion
|
|
834
|
+
//#region src/components/features/picker/components/trigger.tsx
|
|
835
|
+
const DEFAULT_ICON = /* @__PURE__ */ jsx(CalendarIcon, { className: "text-muted-foreground size-4 shrink-0" });
|
|
836
|
+
function PickerTrigger({ placeholder = "Pick a date", clearable = false, disabled = false, children, className, triggerClassName, id, icon, onClick, ...slotProps }) {
|
|
837
|
+
const { state, actions } = usePickerContext();
|
|
838
|
+
const hasValue = state.pendingValue !== null && state.pendingValue !== void 0;
|
|
839
|
+
const renderedIcon = icon === false ? null : icon ?? DEFAULT_ICON;
|
|
840
|
+
return /* @__PURE__ */ jsxs(Button$1, {
|
|
841
|
+
id,
|
|
842
|
+
type: "button",
|
|
843
|
+
variant: "outline",
|
|
844
|
+
role: "combobox",
|
|
845
|
+
"aria-label": placeholder,
|
|
846
|
+
"aria-expanded": state.open,
|
|
847
|
+
disabled,
|
|
848
|
+
onClick: (e) => {
|
|
849
|
+
onClick?.(e);
|
|
850
|
+
if (state.open) actions.close();
|
|
851
|
+
else actions.open();
|
|
852
|
+
},
|
|
853
|
+
className: cn("w-full justify-between gap-2 font-normal", triggerClassName, className),
|
|
854
|
+
...slotProps,
|
|
855
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
856
|
+
className: "flex flex-1 items-center gap-2 truncate",
|
|
857
|
+
children: [renderedIcon, /* @__PURE__ */ jsx("span", {
|
|
858
|
+
className: cn("truncate", !hasValue && "text-muted-foreground"),
|
|
859
|
+
children: hasValue ? children ? children(state.pendingValue) : String(state.pendingValue) : placeholder
|
|
860
|
+
})]
|
|
861
|
+
}), clearable && hasValue && /* @__PURE__ */ jsx("button", {
|
|
862
|
+
type: "button",
|
|
863
|
+
"aria-label": "Clear",
|
|
864
|
+
onClick: (e) => {
|
|
865
|
+
e.stopPropagation();
|
|
866
|
+
actions.clear();
|
|
867
|
+
},
|
|
868
|
+
className: "text-muted-foreground hover:text-destructive shrink-0 rounded-sm p-0.5 transition-colors",
|
|
869
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
|
|
870
|
+
})]
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
PickerTrigger.displayName = "Picker.Trigger";
|
|
874
|
+
//#endregion
|
|
875
|
+
//#region src/components/features/picker/utils/format-value.ts
|
|
876
|
+
const DATE_OPTS = {
|
|
877
|
+
year: "numeric",
|
|
878
|
+
month: "short",
|
|
879
|
+
day: "2-digit"
|
|
880
|
+
};
|
|
881
|
+
function safeDate(input) {
|
|
882
|
+
if (input instanceof Date && !Number.isNaN(input.getTime())) return input;
|
|
883
|
+
return null;
|
|
884
|
+
}
|
|
885
|
+
function safeIso(input, timezone) {
|
|
886
|
+
if (typeof input !== "string") return null;
|
|
887
|
+
try {
|
|
888
|
+
const d = isoToZonedDate(input, timezone);
|
|
889
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
890
|
+
} catch {
|
|
891
|
+
return null;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
function formatDate(d, locale, dateFormat) {
|
|
895
|
+
if (dateFormat) return format(d, dateFormat);
|
|
896
|
+
return d.toLocaleDateString(locale, DATE_OPTS);
|
|
897
|
+
}
|
|
898
|
+
/** Renders `HH:mm` from a Date whose wall-clock fields are already in the target timezone. */
|
|
899
|
+
function formatZonedTimeOfDay(d, hourCycle, timeFormat) {
|
|
900
|
+
if (timeFormat) return format(d, timeFormat);
|
|
901
|
+
return formatTimeLabel(dateToHHmm(d), hourCycle);
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Renders a `"HH:mm"` time-of-day string. Honors `timeFormat` (date-fns pattern)
|
|
905
|
+
* by lifting the value into a Date and formatting; falls back to `formatTimeLabel`
|
|
906
|
+
* (hourCycle-aware) otherwise.
|
|
907
|
+
*/
|
|
908
|
+
function formatTimeOfDayString(value, hourCycle, timeFormat) {
|
|
909
|
+
if (!timeFormat) return formatTimeLabel(value, hourCycle);
|
|
910
|
+
const parsed = parseTimeString(value);
|
|
911
|
+
if (!parsed) return "";
|
|
912
|
+
const d = /* @__PURE__ */ new Date();
|
|
913
|
+
d.setHours(parsed.h, parsed.m, 0, 0);
|
|
914
|
+
return format(d, timeFormat);
|
|
915
|
+
}
|
|
916
|
+
function isSameZonedDay(a, b) {
|
|
917
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Renders a human-readable trigger label for any picker mode.
|
|
921
|
+
* Returns the empty string when the value is null/undefined or unparseable.
|
|
922
|
+
*/
|
|
923
|
+
function formatPickerValue(value, mode, opts = {}) {
|
|
924
|
+
if (value === null || value === void 0) return "";
|
|
925
|
+
const timezone = opts.timezone ?? "UTC";
|
|
926
|
+
const hourCycle = opts.hourCycle ?? "24";
|
|
927
|
+
const locale = opts.locale;
|
|
928
|
+
const dateFormat = opts.dateFormat;
|
|
929
|
+
const timeFormat = opts.timeFormat;
|
|
930
|
+
if (mode === "date") {
|
|
931
|
+
const d = safeDate(value);
|
|
932
|
+
return d ? formatDate(d, locale, dateFormat) : "";
|
|
933
|
+
}
|
|
934
|
+
if (mode === "date-range") {
|
|
935
|
+
const v = value;
|
|
936
|
+
const from = safeDate(v?.from);
|
|
937
|
+
const to = safeDate(v?.to);
|
|
938
|
+
if (!from || !to) return "";
|
|
939
|
+
return `${formatDate(from, locale, dateFormat)} - ${formatDate(to, locale, dateFormat)}`;
|
|
940
|
+
}
|
|
941
|
+
if (mode === "time") return typeof value === "string" ? formatTimeOfDayString(value, hourCycle, timeFormat) : "";
|
|
942
|
+
if (mode === "time-range") {
|
|
943
|
+
const v = value;
|
|
944
|
+
if (typeof v?.from !== "string" || typeof v?.to !== "string") return "";
|
|
945
|
+
return `${formatTimeOfDayString(v.from, hourCycle, timeFormat)} - ${formatTimeOfDayString(v.to, hourCycle, timeFormat)}`;
|
|
946
|
+
}
|
|
947
|
+
if (mode === "datetime") {
|
|
948
|
+
const d = safeIso(value, timezone);
|
|
949
|
+
return d ? `${formatDate(d, locale, dateFormat)} ${formatZonedTimeOfDay(d, hourCycle, timeFormat)}` : "";
|
|
950
|
+
}
|
|
951
|
+
if (mode === "datetime-range") {
|
|
952
|
+
const v = value;
|
|
953
|
+
const from = safeIso(v?.from, timezone);
|
|
954
|
+
const to = safeIso(v?.to, timezone);
|
|
955
|
+
if (!from || !to) return "";
|
|
956
|
+
if (isSameZonedDay(from, to)) return `${formatDate(from, locale, dateFormat)} ${formatZonedTimeOfDay(from, hourCycle, timeFormat)} - ${formatZonedTimeOfDay(to, hourCycle, timeFormat)}`;
|
|
957
|
+
return `${formatDate(from, locale, dateFormat)} ${formatZonedTimeOfDay(from, hourCycle, timeFormat)} - ${formatDate(to, locale, dateFormat)} ${formatZonedTimeOfDay(to, hourCycle, timeFormat)}`;
|
|
958
|
+
}
|
|
959
|
+
if (mode === "date-range-time") {
|
|
960
|
+
const v = value;
|
|
961
|
+
const from = safeIso(v?.from, timezone);
|
|
962
|
+
const to = safeIso(v?.to, timezone);
|
|
963
|
+
if (!from || !to) return "";
|
|
964
|
+
return `${formatDate(from, locale, dateFormat)} - ${formatDate(to, locale, dateFormat)} (${formatZonedTimeOfDay(from, hourCycle, timeFormat)})`;
|
|
965
|
+
}
|
|
966
|
+
return "";
|
|
967
|
+
}
|
|
968
|
+
//#endregion
|
|
969
|
+
//#region src/components/features/picker/components/footer.tsx
|
|
970
|
+
function PickerFooter({ children, className }) {
|
|
971
|
+
return /* @__PURE__ */ jsx("div", {
|
|
972
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
973
|
+
children
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
PickerFooter.displayName = "Picker.Footer";
|
|
977
|
+
function PickerApply({ children = "Apply" }) {
|
|
978
|
+
const { state, actions } = usePickerContext();
|
|
979
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
980
|
+
type: "primary",
|
|
981
|
+
theme: "solid",
|
|
982
|
+
size: "xs",
|
|
983
|
+
disabled: state.pendingValue === null || state.pendingValue === void 0,
|
|
984
|
+
onClick: actions.apply,
|
|
985
|
+
children
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
PickerApply.displayName = "Picker.Apply";
|
|
989
|
+
function PickerReset({ children = "Reset" }) {
|
|
990
|
+
const { actions } = usePickerContext();
|
|
991
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
992
|
+
type: "quaternary",
|
|
993
|
+
theme: "outline",
|
|
994
|
+
size: "xs",
|
|
995
|
+
onClick: actions.reset,
|
|
996
|
+
children
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
PickerReset.displayName = "Picker.Reset";
|
|
1000
|
+
function PickerCancel({ children = "Cancel" }) {
|
|
1001
|
+
const { actions } = usePickerContext();
|
|
1002
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
1003
|
+
type: "quaternary",
|
|
1004
|
+
theme: "borderless",
|
|
1005
|
+
size: "xs",
|
|
1006
|
+
onClick: actions.cancel,
|
|
1007
|
+
children
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
PickerCancel.displayName = "Picker.Cancel";
|
|
1011
|
+
function PickerClear({ children = "Clear" }) {
|
|
1012
|
+
const { actions } = usePickerContext();
|
|
1013
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
1014
|
+
type: "primary",
|
|
1015
|
+
theme: "borderless",
|
|
1016
|
+
size: "xs",
|
|
1017
|
+
onClick: actions.clear,
|
|
1018
|
+
children
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
PickerClear.displayName = "Picker.Clear";
|
|
1022
|
+
//#endregion
|
|
1023
|
+
//#region src/components/features/picker/wrappers/internal/default-footer.tsx
|
|
1024
|
+
/**
|
|
1025
|
+
* The standard Cancel / Reset / Apply footer used by every wrapper.
|
|
1026
|
+
* `Picker.Content` decides whether to render it - desktop popover renders
|
|
1027
|
+
* it only when `commit === 'apply'`; mobile sheet always renders it.
|
|
1028
|
+
*/
|
|
1029
|
+
function DefaultFooter() {
|
|
1030
|
+
return /* @__PURE__ */ jsxs(PickerFooter, { children: [
|
|
1031
|
+
/* @__PURE__ */ jsx(PickerCancel, {}),
|
|
1032
|
+
/* @__PURE__ */ jsx(PickerReset, {}),
|
|
1033
|
+
/* @__PURE__ */ jsx(PickerApply, {})
|
|
1034
|
+
] });
|
|
1035
|
+
}
|
|
1036
|
+
//#endregion
|
|
1037
|
+
export { zonedDateToIso as A, PickerContext as C, getBrowserTimezone as D, formatTimezoneLabel as E, isDateBearingMode as F, isRangeMode as I, isTimeBearingMode as L, DATE_BEARING_MODES as M, RANGE_MODES as N, getTimezoneOffset as O, TIME_BEARING_MODES as P, useDateConstraints as R, PickerContent as S, formatInTimezone as T, formatTimeLabel as _, PickerFooter as a, resolveCommit as b, PickerTrigger as c, DATETIME_PRESETS as d, DATE_PRESETS as f, dateToYYYYMMDD as g, dateToHHmm as h, PickerClear as i, ALLOWED_STEPS as j, isoToZonedDate as k, Picker as l, usePickerState as m, PickerApply as n, PickerReset as o, getDefaultPresets as p, PickerCancel as r, formatPickerValue as s, DefaultFooter as t, usePresets as u, isValidTimeString as v, usePickerContext as w, useKeyboardShortcuts as x, parseTimeString as y };
|