@photon-ai/pho-ui 4.0.0 → 4.2.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.
@@ -1,404 +0,0 @@
1
- "use client";
2
- import { t as h } from "./cn-ChIgwEl3.js";
3
- import { t as Ae } from "./createReactComponent-BqCmnqfX.js";
4
- import { t as ie } from "./calendar-4OFiCLAv.js";
5
- import { t as _ } from "./popover-BhBJO346.js";
6
- import { useCallback as _e, useId as Ve, useRef as B, useState as w, useSyncExternalStore as Le } from "react";
7
- import { Fragment as J, jsx as l, jsxs as b } from "react/jsx-runtime";
8
- var Ge = [
9
- ["path", {
10
- d: "M4 7a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12",
11
- key: "svg-0"
12
- }],
13
- ["path", {
14
- d: "M16 3v4",
15
- key: "svg-1"
16
- }],
17
- ["path", {
18
- d: "M8 3v4",
19
- key: "svg-2"
20
- }],
21
- ["path", {
22
- d: "M4 11h16",
23
- key: "svg-3"
24
- }],
25
- ["path", {
26
- d: "M11 15h1",
27
- key: "svg-4"
28
- }],
29
- ["path", {
30
- d: "M12 15v3",
31
- key: "svg-5"
32
- }]
33
- ], se = Ae("outline", "calendar", "Calendar", Ge), ve = {
34
- hour: 3600,
35
- minute: 60,
36
- second: 1
37
- }, le = {
38
- sm: "px-3 py-2 text-md md:text-base",
39
- md: "px-3 py-2 text-md",
40
- lg: "px-3.5 py-2.5 text-md"
41
- }, ue = {
42
- sm: "rounded-base",
43
- md: "rounded-base",
44
- lg: "squircle rounded-base"
45
- }, ce = h("bg-pho-primary ring-pho-primary text-pho-primary relative flex w-full cursor-pointer items-center gap-2 text-left ring-1 ring-inset", "transition-shadow duration-100 ease-linear focus-visible:outline-none", "data-[invalid]:ring-pho-error-subtle data-[invalid]:ring-[1.5px]"), je = h("has-[input:focus-visible]:ring-pho-brand data-[popup-open]:ring-pho-brand has-[input:focus-visible]:ring-2 data-[popup-open]:ring-2", "data-[invalid]:has-[input:focus-visible]:ring-pho-error data-[invalid]:data-[popup-open]:ring-pho-error", "has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"), ze = h("has-[input:focus-visible]:ring-pho-brand has-[input:focus-visible]:ring-2", "data-[invalid]:has-[input:focus-visible]:ring-pho-error", "has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"), Ye = h("flex shrink-0 cursor-pointer items-center rounded-sm px-2.5 py-1.5 text-left text-base whitespace-nowrap select-none", "text-pho-secondary transition-[color,background-color] duration-150 ease-out", "hover:bg-pho-ghost-hover hover:text-pho-primary", "outline-pho-brand focus-visible:outline-2 focus-visible:-outline-offset-1", "sm:w-full"), qe = "bg-pho-ghost-hover text-pho-primary font-medium", He = /[\u00a0\u2000-\u200a\u202f\u205f\u3000]/g, F = (e) => e.replace(He, " "), be = {
46
- year: "numeric",
47
- month: "2-digit",
48
- day: "2-digit"
49
- }, Ke = {
50
- hour: {
51
- hour: "2-digit",
52
- minute: "2-digit",
53
- hourCycle: "h23"
54
- },
55
- minute: {
56
- hour: "2-digit",
57
- minute: "2-digit",
58
- hourCycle: "h23"
59
- },
60
- second: {
61
- hour: "2-digit",
62
- minute: "2-digit",
63
- second: "2-digit",
64
- hourCycle: "h23"
65
- }
66
- }, ye = new Date(2026, 8, 12, 15, 4, 5);
67
- function xe(e, t) {
68
- return new Intl.DateTimeFormat(e, {
69
- ...be,
70
- ...t ? Ke[t] : {}
71
- });
72
- }
73
- var we = (e) => e === "year" || e === "month" || e === "day";
74
- function Be(e) {
75
- return new Intl.DateTimeFormat(e, be).formatToParts(ye).map((t) => t.type).filter(we);
76
- }
77
- var Ue = {
78
- year: "yyyy",
79
- month: "mm",
80
- day: "dd"
81
- };
82
- function Ze(e, t) {
83
- return F(xe(e, t).formatToParts(ye).map((n) => we(n.type) ? Ue[n.type] : n.type === "hour" ? "hh" : n.type === "minute" ? "mm" : n.type === "second" ? "ss" : n.value).join(""));
84
- }
85
- function Je(e, t, n) {
86
- if (e == null) return "";
87
- const s = xe(t, n);
88
- return e instanceof Date ? F(s.format(e)) : e.from == null ? "" : e.to == null || n == null && e.from.getFullYear() === e.to.getFullYear() && e.from.getMonth() === e.to.getMonth() && e.from.getDate() === e.to.getDate() ? F(s.format(e.from)) : F(`${s.format(e.from)} – ${s.format(e.to)}`);
89
- }
90
- var I = (e) => String(e).padStart(2, "0");
91
- function D(e) {
92
- return `${e.getFullYear()}-${I(e.getMonth() + 1)}-${I(e.getDate())}`;
93
- }
94
- function De(e, t) {
95
- const n = `${I(e.getHours())}:${I(e.getMinutes())}`;
96
- return t === "second" ? `${n}:${I(e.getSeconds())}` : n;
97
- }
98
- function U(e, t) {
99
- return `${D(e)}T${De(e, t)}`;
100
- }
101
- function V(e) {
102
- const t = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2}))?)?$/.exec(e);
103
- if (!t) return;
104
- const [, n, s, i, u, f, d] = t, m = new Date(Number(n), Number(s) - 1, Number(i), Number(u ?? 0), Number(f ?? 0), Number(d ?? 0), 0);
105
- return Number.isNaN(m.getTime()) ? void 0 : m;
106
- }
107
- function de(e, t, n, s) {
108
- const i = e < 100 ? 2e3 + e : e;
109
- if (t < 1 || t > 12 || n < 1 || n > 31) return;
110
- const [u = 0, f = 0, d = 0] = s;
111
- if (u > 23 || f > 59 || d > 59) return;
112
- const m = new Date(i, t - 1, n, u, f, d, 0);
113
- return m.getMonth() === t - 1 && m.getDate() === n ? m : void 0;
114
- }
115
- function Qe(e, t) {
116
- const n = e.trim();
117
- if (n === "") return;
118
- const s = (n.match(/\d+/g) ?? []).map(Number);
119
- if (s.length >= 3) {
120
- const u = s.slice(3);
121
- if (/\bpm\b/i.test(n) && u[0] !== void 0 && u[0] < 12 ? u[0] += 12 : /\bam\b/i.test(n) && u[0] === 12 && (u[0] = 0), /^\d{4}\D/.test(n)) {
122
- const [d, m, C] = s;
123
- return de(d, m, C, u);
124
- }
125
- const f = {};
126
- if (Be(t).forEach((d, m) => {
127
- f[d] = s[m];
128
- }), f.year != null && f.month != null && f.day != null) {
129
- const d = de(f.year, f.month, f.day, u);
130
- if (d) return d;
131
- }
132
- }
133
- if (!/[a-z]/i.test(n) || s.length < 2 || !/\b\d{4}\b/.test(n)) return;
134
- const i = new Date(n);
135
- return Number.isNaN(i.getTime()) ? void 0 : i;
136
- }
137
- function p(e, t) {
138
- const n = new Date(e);
139
- return n.setMilliseconds(0), t === "second" || (n.setSeconds(0), t === "minute") || (n.setMinutes(0), t === "hour") || n.setHours(0), n;
140
- }
141
- function fe(e) {
142
- return e == null ? "" : e instanceof Date ? String(e.getTime()) : `${e.from?.getTime() ?? ""}-${e.to?.getTime() ?? ""}`;
143
- }
144
- function L(e, t) {
145
- const n = new Date(e);
146
- return t && n.setHours(t.getHours(), t.getMinutes(), t.getSeconds(), 0), n;
147
- }
148
- var We = (e) => new Date(e.getFullYear(), e.getMonth(), 1), Xe = (e) => new Date(e.getFullYear(), e.getMonth() + 1, 0), et = (e) => new Date(e.getFullYear(), e.getMonth(), e.getDate()), me = (e) => new Date(e.getFullYear(), e.getMonth(), e.getDate(), 23, 59, 59, 999), he = (e, t) => e && e > t ? e : t, pe = (e, t) => e && e < t ? e : t;
149
- function tt(e) {
150
- if (e?.hidden != null) return null;
151
- let t, n;
152
- const s = e?.disabled == null ? [] : Array.isArray(e.disabled) ? e.disabled : [e.disabled];
153
- for (const i of s) {
154
- if (i == null || typeof i != "object" || i instanceof Date || Object.keys(i).length !== 1) return null;
155
- if ("before" in i && i.before instanceof Date) t = he(t, et(i.before));
156
- else if ("after" in i && i.after instanceof Date) n = pe(n, me(i.after));
157
- else return null;
158
- }
159
- return e?.startMonth && (t = he(t, We(e.startMonth))), e?.endMonth && (n = pe(n, me(Xe(e.endMonth)))), {
160
- min: t,
161
- max: n
162
- };
163
- }
164
- var ge = "(pointer: coarse)";
165
- function nt() {
166
- const e = _e((t) => {
167
- if (typeof window > "u" || !window.matchMedia) return () => {
168
- };
169
- const n = window.matchMedia(ge);
170
- return n.addEventListener("change", t), () => n.removeEventListener("change", t);
171
- }, []);
172
- return Le(e, () => typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia(ge).matches, () => !1);
173
- }
174
- function Z({ label: e, value: t, time: n, disabled: s, onChange: i }) {
175
- return /* @__PURE__ */ b(J, { children: [/* @__PURE__ */ l("span", {
176
- className: "text-pho-description text-xs",
177
- children: e
178
- }), /* @__PURE__ */ l("label", {
179
- className: h("bg-pho-primary ring-pho-primary rounded-sm px-2 py-1 ring-1 ring-inset", "focus-within:ring-pho-brand transition-shadow duration-100 ease-linear focus-within:ring-2"),
180
- children: /* @__PURE__ */ l("input", {
181
- type: "time",
182
- step: ve[n],
183
- disabled: s,
184
- "aria-label": e,
185
- value: t ? De(t, n) : "",
186
- onChange: (u) => i(u.target.value),
187
- className: h("text-pho-primary w-full bg-transparent text-base tabular-nums outline-none", "[&::-webkit-calendar-picker-indicator]:hidden")
188
- })
189
- })] });
190
- }
191
- function ot(e) {
192
- const { mode: t = "single", defaultValue: n, onValueChange: s, label: i, hint: u, placeholder: f, invalid: d, disabled: m, required: C, size: R = "md", time: r, locales: G, calendarProps: k, id: Me, className: Q } = e, j = e.presets, W = "value" in e, [Ne, Ce] = w(n), O = W ? e.value : Ne, [M, N] = w(!1), E = B(0), X = f ?? (t === "range" ? "Pick a date range" : Ze(G, r)), ke = Ve(), T = Me ?? ke, z = u ? `${T}-hint` : void 0, ee = `${T}-calendar`, [te, ne] = w(!1), Y = (o = !1) => {
193
- M || (E.current = 0, S(void 0), ne(o), N(!0));
194
- }, g = (o) => {
195
- W || Ce(o), s?.(o);
196
- }, v = t === "single" ? O : void 0, c = t === "range" ? O : void 0, Ee = v ?? c?.from, [Te, y] = w(null), [q, Se] = w(null), H = q && q.key === fe(O) ? q.label : null, P = Te ?? H ?? Je(O, G, r), $e = (o) => {
197
- const a = typeof o.value == "function" ? o.value() : o.value;
198
- Se({
199
- label: o.label,
200
- key: fe(a)
201
- }), y(null), g(a), N(!1);
202
- }, [Fe, S] = w(void 0), [Ie] = w(() => k?.today ?? /* @__PURE__ */ new Date()), oe = Fe ?? k?.defaultMonth ?? Ee ?? Ie, K = B(null), re = B(null), Re = nt(), x = tt(k), Oe = Re && t === "single" && x != null && !j?.length, Pe = /* @__PURE__ */ b(J, { children: [/* @__PURE__ */ l(se, { className: "text-pho-secondary size-4 shrink-0" }), /* @__PURE__ */ l("span", {
203
- className: h("min-w-0 flex-1 truncate", P === "" && "text-pho-placeholder"),
204
- children: P === "" ? X : P
205
- })] });
206
- return /* @__PURE__ */ b("div", {
207
- className: "flex w-full flex-col gap-1.5",
208
- children: [
209
- i ? /* @__PURE__ */ b("label", {
210
- htmlFor: T,
211
- className: "text-pho-secondary flex w-fit cursor-default items-center gap-0.5 text-base font-medium",
212
- children: [i, C ? /* @__PURE__ */ l("span", {
213
- className: "text-pho-brand",
214
- children: "*"
215
- }) : null]
216
- }) : null,
217
- Oe ? /* @__PURE__ */ b("div", {
218
- "data-invalid": d || void 0,
219
- className: h(ce, ze, le[R], ue[R], Q),
220
- children: [Pe, /* @__PURE__ */ l("input", {
221
- id: T,
222
- type: r ? "datetime-local" : "date",
223
- step: r ? ve[r] : void 0,
224
- min: x?.min ? r ? U(p(x.min, r), r) : D(x.min) : void 0,
225
- max: x?.max ? r ? U(p(x.max, r), r) : D(x.max) : void 0,
226
- required: C,
227
- disabled: m,
228
- "aria-describedby": z,
229
- value: v ? r ? U(v, r) : D(v) : "",
230
- onChange: (o) => {
231
- const a = V(o.target.value);
232
- g(a ? p(a, r) : void 0);
233
- },
234
- className: "absolute inset-0 size-full cursor-pointer opacity-0"
235
- })]
236
- }) : /* @__PURE__ */ b(_.Root, {
237
- open: M,
238
- onOpenChange: (o, a) => {
239
- !o && a.reason === "outside-press" && a.event.target instanceof Node && K.current?.contains(a.event.target) || (o ? (E.current = 0, S(void 0)) : (y(null), ne(!1)), N(o));
240
- },
241
- children: [/* @__PURE__ */ b("div", {
242
- ref: K,
243
- "data-invalid": d || void 0,
244
- "data-popup-open": M || void 0,
245
- className: h(ce, je, le[R], ue[R], Q),
246
- children: [/* @__PURE__ */ l(se, { className: "text-pho-secondary size-4 shrink-0" }), /* @__PURE__ */ l("input", {
247
- id: T,
248
- type: "text",
249
- readOnly: t === "range",
250
- disabled: m,
251
- required: C,
252
- placeholder: X,
253
- "aria-describedby": z,
254
- role: "combobox",
255
- "aria-haspopup": "dialog",
256
- "aria-expanded": M,
257
- "aria-controls": M ? ee : void 0,
258
- autoComplete: "off",
259
- spellCheck: !1,
260
- value: P,
261
- onFocus: () => Y(),
262
- onMouseDown: () => Y(),
263
- onChange: (o) => {
264
- const a = o.target.value;
265
- if (y(a), a.trim() === "") {
266
- g(void 0);
267
- return;
268
- }
269
- const $ = Qe(a, G);
270
- $ && (g(p($, r)), S($));
271
- },
272
- onBlur: () => y(null),
273
- onKeyDown: (o) => {
274
- if (o.key === "Escape" && M) {
275
- o.preventDefault(), y(null), N(!1);
276
- return;
277
- }
278
- if (o.key === "ArrowDown") {
279
- o.preventDefault();
280
- const a = re.current?.querySelector("td[data-day] button[tabindex='0']");
281
- if (a) {
282
- a.focus();
283
- return;
284
- }
285
- Y(!0);
286
- }
287
- },
288
- className: h("text-pho-primary placeholder:text-pho-placeholder min-w-0 flex-1 bg-transparent outline-none", t === "range" && "cursor-pointer")
289
- })]
290
- }), /* @__PURE__ */ l(_.Portal, { children: /* @__PURE__ */ l(_.Positioner, {
291
- anchor: K,
292
- align: "start",
293
- sideOffset: 6,
294
- children: /* @__PURE__ */ l(_.Popup, {
295
- ref: re,
296
- id: ee,
297
- initialFocus: !1,
298
- finalFocus: !1,
299
- className: "max-h-[var(--available-height)] overflow-y-auto p-3",
300
- children: /* @__PURE__ */ b("div", {
301
- className: "flex flex-col gap-3 sm:flex-row",
302
- children: [j?.length ? /* @__PURE__ */ l("div", {
303
- role: "group",
304
- "aria-label": "Presets",
305
- className: h("flex shrink-0 gap-1 overflow-x-auto", "sm:border-pho-secondary sm:w-36 sm:flex-col sm:gap-0.5 sm:overflow-visible sm:border-r sm:pr-3"),
306
- children: j.map((o) => /* @__PURE__ */ l("button", {
307
- type: "button",
308
- "aria-pressed": o.label === H,
309
- onClick: () => $e(o),
310
- className: h(Ye, o.label === H && qe),
311
- children: o.label
312
- }, o.label))
313
- }) : null, /* @__PURE__ */ b("div", { children: [t === "range" ? /* @__PURE__ */ l(ie, {
314
- ...k,
315
- mode: "range",
316
- month: oe,
317
- onMonthChange: S,
318
- autoFocus: te,
319
- selected: c,
320
- onSelect: (o, a) => {
321
- const $ = E.current === 0;
322
- if (E.current += 1, $ && c?.to) {
323
- const ae = p(L(a, r ? c.from : void 0), r);
324
- g({
325
- from: ae,
326
- to: new Date(ae)
327
- }), y(null);
328
- return;
329
- }
330
- const A = o && {
331
- from: o.from && p(L(o.from, r ? c?.from : void 0), r),
332
- to: o.to && p(L(o.to, r ? c?.to : void 0), r)
333
- };
334
- g(A), y(null), !r && E.current >= 2 && (!A || A.from && A.to) && N(!1);
335
- }
336
- }) : /* @__PURE__ */ l(ie, {
337
- ...k,
338
- mode: "single",
339
- month: oe,
340
- onMonthChange: S,
341
- autoFocus: te,
342
- selected: v,
343
- onSelect: (o) => {
344
- g(o && p(L(o, r ? v : void 0), r)), y(null), r || N(!1);
345
- }
346
- }), r ? /* @__PURE__ */ l("div", {
347
- className: "border-pho-secondary mt-3 grid grid-cols-[auto_1fr] items-center gap-x-3 gap-y-2 border-t pt-3",
348
- children: t === "range" ? /* @__PURE__ */ b(J, { children: [/* @__PURE__ */ l(Z, {
349
- label: "From",
350
- value: c?.from,
351
- time: r,
352
- onChange: (o) => {
353
- if (!c?.from) return;
354
- const a = V(`${D(c.from)}T${o}`);
355
- a && g({
356
- ...c,
357
- from: p(a, r)
358
- });
359
- },
360
- disabled: !c?.from
361
- }), /* @__PURE__ */ l(Z, {
362
- label: "To",
363
- value: c?.to,
364
- time: r,
365
- onChange: (o) => {
366
- if (!c?.to) return;
367
- const a = V(`${D(c.to)}T${o}`);
368
- a && g({
369
- ...c,
370
- to: p(a, r)
371
- });
372
- },
373
- disabled: !c?.to
374
- })] }) : /* @__PURE__ */ l(Z, {
375
- label: "Time",
376
- value: v,
377
- time: r,
378
- onChange: (o) => {
379
- if (!v) return;
380
- const a = V(`${D(v)}T${o}`);
381
- a && g(p(a, r));
382
- },
383
- disabled: !v
384
- })
385
- }) : null] })]
386
- })
387
- })
388
- }) })]
389
- }),
390
- u ? /* @__PURE__ */ l("p", {
391
- id: z,
392
- className: h("text-pho-description text-base", d && "text-pho-error"),
393
- children: u
394
- }) : null
395
- ]
396
- });
397
- }
398
- ot.displayName = "DatePicker";
399
- export {
400
- Je as n,
401
- ot as t
402
- };
403
-
404
- //# sourceMappingURL=date-picker-DnQuw-B1.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"date-picker-DnQuw-B1.js","names":[],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconCalendar.mjs","../../src/components/date-picker/date-picker.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M4 7a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M16 3v4\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M8 3v4\", \"key\": \"svg-2\" }], [\"path\", { \"d\": \"M4 11h16\", \"key\": \"svg-3\" }], [\"path\", { \"d\": \"M11 15h1\", \"key\": \"svg-4\" }], [\"path\", { \"d\": \"M12 15v3\", \"key\": \"svg-5\" }]];\nconst IconCalendar = createReactComponent(\"outline\", \"calendar\", \"Calendar\", __iconNode);\n\nexport { __iconNode, IconCalendar as default };\n//# sourceMappingURL=IconCalendar.mjs.map\n","import {\n useCallback,\n useId,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from \"react\";\nimport { IconCalendar } from \"@tabler/icons-react\";\nimport type { DateRange, Matcher, PropsBase } from \"react-day-picker\";\nimport { Calendar } from \"../calendar\";\nimport { Popover } from \"../popover\";\nimport type { InputSize } from \"../input\";\nimport { cn } from \"../../utils/cn\";\n\n/** The trigger wears Input's sizes so the two line up in one form. */\nexport type DatePickerSize = InputSize;\n\n/**\n * How fine the time is asked for, and read back. Omit it for a date alone.\n * The value is always a `Date`; the granularity says which of its parts the\n * viewer sets, and everything below is zeroed.\n */\nexport type DatePickerTime = \"hour\" | \"minute\" | \"second\";\n\n/** `step` for a native time field — the unit it moves and shows. */\nconst TIME_STEP: Record<DatePickerTime, number> = {\n hour: 3600,\n minute: 60,\n second: 1,\n};\n\n// Effective padding matches Input's (12/8px, lg 14/10px); Input reaches it\n// through a 2px wrapper inset it has to compensate for, the trigger directly.\nconst SIZE_PAD: Record<DatePickerSize, string> = {\n // 16px until there is room — a 14px control next to a 16px field looks shrunk.\n sm: \"px-3 py-2 text-md md:text-base\",\n md: \"px-3 py-2 text-md\",\n lg: \"px-3.5 py-2.5 text-md\",\n};\n\nconst SIZE_RADIUS: Record<DatePickerSize, string> = {\n sm: \"rounded-base\",\n md: \"rounded-base\",\n lg: \"squircle rounded-base\",\n};\n\nconst TRIGGER_BASE = cn(\n \"bg-pho-primary ring-pho-primary text-pho-primary relative flex w-full cursor-pointer items-center gap-2 text-left ring-1 ring-inset\",\n \"transition-shadow duration-100 ease-linear focus-visible:outline-none\",\n // Invalid is mid-weight — thicker than the rest hairline, thinner than focus.\n \"data-[invalid]:ring-pho-error-subtle data-[invalid]:ring-[1.5px]\",\n);\n\n// Open or focused, the edge is Input's: the brand ring at 2px in place of the\n// hairline. The popover path focuses the button itself; the native path puts a\n// system field over it, so the ring follows the field inside.\nconst TRIGGER_FIELD = cn(\n \"has-[input:focus-visible]:ring-pho-brand data-[popup-open]:ring-pho-brand has-[input:focus-visible]:ring-2 data-[popup-open]:ring-2\",\n \"data-[invalid]:has-[input:focus-visible]:ring-pho-error data-[invalid]:data-[popup-open]:ring-pho-error\",\n \"has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50\",\n);\n\nconst TRIGGER_NATIVE = cn(\n \"has-[input:focus-visible]:ring-pho-brand has-[input:focus-visible]:ring-2\",\n \"data-[invalid]:has-[input:focus-visible]:ring-pho-error\",\n \"has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50\",\n);\n\n/**\n * A named window in the rail beside the calendar — the Menu row's manners,\n * since that is what a list of choices is.\n */\nconst PRESET = cn(\n \"flex shrink-0 cursor-pointer items-center rounded-sm px-2.5 py-1.5 text-left text-base whitespace-nowrap select-none\",\n \"text-pho-secondary transition-[color,background-color] duration-150 ease-out\",\n \"hover:bg-pho-ghost-hover hover:text-pho-primary\",\n \"outline-pho-brand focus-visible:outline-2 focus-visible:-outline-offset-1\",\n \"sm:w-full\",\n);\n\n/** The one in play. Quiet, like a highlighted menu row — not an action fill. */\nconst PRESET_ON = \"bg-pho-ghost-hover text-pho-primary font-medium\";\n\n/* ------------------------------------------------------------------ words */\n\n/**\n * ICU disagrees with itself about which space belongs before `AM` and around\n * a range dash: Node sends a narrow no-break space and a thin space where\n * Chrome sends ordinary ones. The two strings look identical and are not, so\n * a server-rendered label would fail to hydrate. Flattening every space\n * separator to the ordinary one makes the words the same on both sides.\n */\nconst SPACE_SEPARATORS = /[\\u00a0\\u2000-\\u200a\\u202f\\u205f\\u3000]/g;\nconst flattenSpaces = (words: string) => words.replace(SPACE_SEPARATORS, \" \");\n\n/** The date's parts, all in figures — the shape that is quickest to type. */\nconst NUMERIC_DATE = {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n} as const;\n\n/** The clock, on a 24-hour dial: `15:04` is fewer keystrokes than `3:04 PM`. */\nconst NUMERIC_CLOCK: Record<DatePickerTime, Intl.DateTimeFormatOptions> = {\n hour: { hour: \"2-digit\", minute: \"2-digit\", hourCycle: \"h23\" },\n minute: { hour: \"2-digit\", minute: \"2-digit\", hourCycle: \"h23\" },\n second: {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hourCycle: \"h23\",\n },\n};\n\n/** A day whose parts are all different, so the locale's order reads clearly. */\nconst SAMPLE = new Date(2026, 8, 12, 15, 4, 5);\n\nfunction numericFormat(\n locales: Intl.LocalesArgument,\n time: DatePickerTime | undefined,\n) {\n return new Intl.DateTimeFormat(locales, {\n ...NUMERIC_DATE,\n ...(time ? NUMERIC_CLOCK[time] : {}),\n });\n}\n\ntype DatePart = \"year\" | \"month\" | \"day\";\nconst isDatePart = (type: string): type is DatePart =>\n type === \"year\" || type === \"month\" || type === \"day\";\n\n/** Which of year, month and day comes first here, and which comes last. */\nfunction numericOrder(locales: Intl.LocalesArgument): DatePart[] {\n return new Intl.DateTimeFormat(locales, NUMERIC_DATE)\n .formatToParts(SAMPLE)\n .map((part) => part.type)\n .filter(isDatePart);\n}\n\nconst MASK: Record<DatePart, string> = {\n year: \"yyyy\",\n month: \"mm\",\n day: \"dd\",\n};\n\n/**\n * The shape to type, in this locale's own order — `mm/dd/yyyy`,\n * `yyyy-mm-dd`, `dd.mm.yyyy`. Lowercase, the way a browser's own date field\n * writes it, so the two paths read alike.\n */\nexport function dateFieldMask(\n locales?: Intl.LocalesArgument,\n time?: DatePickerTime,\n): string {\n return flattenSpaces(\n numericFormat(locales, time)\n .formatToParts(SAMPLE)\n .map((part) =>\n isDatePart(part.type)\n ? MASK[part.type]\n : part.type === \"hour\"\n ? \"hh\"\n : part.type === \"minute\"\n ? \"mm\"\n : part.type === \"second\"\n ? \"ss\"\n : part.value,\n )\n .join(\"\"),\n );\n}\n\n/**\n * The figures in the field — `09/12/2026`, or `09/10/2026 – 09/13/2026` for a\n * span, in the viewer's locale. An empty or half-finished range prints just\n * the day that is settled; nothing selected prints nothing. Pass `time` to\n * print the clock too, at the precision that was asked for.\n *\n * Figures rather than words (`Sep 12, 2026`) because the field is typed into:\n * a month's name is the one part of a date nobody wants to spell.\n */\nexport function formatDateLabel(\n value: Date | DateRange | undefined,\n locales?: Intl.LocalesArgument,\n time?: DatePickerTime,\n): string {\n if (value == null) return \"\";\n const format = numericFormat(locales, time);\n if (value instanceof Date) return flattenSpaces(format.format(value));\n if (value.from == null) return \"\";\n if (value.to == null) return flattenSpaces(format.format(value.from));\n // A span of one day is a day: printing it twice says nothing the once did\n // not, and the first click of a range makes exactly that shape.\n if (\n time == null &&\n value.from.getFullYear() === value.to.getFullYear() &&\n value.from.getMonth() === value.to.getMonth() &&\n value.from.getDate() === value.to.getDate()\n ) {\n return flattenSpaces(format.format(value.from));\n }\n // Both ends in full, joined here rather than by `formatRange`: ICU collapses\n // a span into `9/1 – 8/2026`, which is not a shape anyone can read back,\n // and pads the figures differently from one engine to the next.\n return flattenSpaces(\n `${format.format(value.from)} – ${format.format(value.to)}`,\n );\n}\n\n/* ------------------------------------------------------- date arithmetic */\n\nconst pad = (n: number) => String(n).padStart(2, \"0\");\n\n/** `YYYY-MM-DD` in the viewer's own zone — never `toISOString`, which is UTC. */\nfunction toDateValue(date: Date): string {\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;\n}\n\nfunction toClockValue(date: Date, time: DatePickerTime): string {\n const hm = `${pad(date.getHours())}:${pad(date.getMinutes())}`;\n return time === \"second\" ? `${hm}:${pad(date.getSeconds())}` : hm;\n}\n\n/** The `datetime-local` spelling of an instant, at the asked-for precision. */\nfunction toDateTimeValue(date: Date, time: DatePickerTime): string {\n return `${toDateValue(date)}T${toClockValue(date, time)}`;\n}\n\n/**\n * Read back a `date` or `datetime-local` field. Parsed part by part rather\n * than handed to `new Date(string)`, which reads a bare `YYYY-MM-DD` as UTC\n * midnight and lands on the day before west of Greenwich.\n */\nfunction fromInputValue(value: string): Date | undefined {\n const match =\n /^(\\d{4})-(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2}))?)?$/.exec(value);\n if (!match) return undefined;\n const [, y, m, d, hh, mm, ss] = match;\n const date = new Date(\n Number(y),\n Number(m) - 1,\n Number(d),\n Number(hh ?? 0),\n Number(mm ?? 0),\n Number(ss ?? 0),\n 0,\n );\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\n/** A date the calendar could actually show — `Feb 31` rolled over, so no. */\nfunction makeLocalDate(\n shortYear: number,\n month: number,\n day: number,\n clock: number[],\n): Date | undefined {\n // `12/25/26` means 2026, not the year 26 — and `new Date(26, …)` would say\n // 1926. Two figures are this century.\n const year = shortYear < 100 ? 2000 + shortYear : shortYear;\n if (month < 1 || month > 12 || day < 1 || day > 31) return undefined;\n const [hh = 0, mm = 0, ss = 0] = clock;\n if (hh > 23 || mm > 59 || ss > 59) return undefined;\n const date = new Date(year, month - 1, day, hh, mm, ss, 0);\n return date.getMonth() === month - 1 && date.getDate() === day\n ? date\n : undefined;\n}\n\n/**\n * A date out of whatever the viewer typed, read in the same order the field\n * writes it — so what it shows is what it takes back. `yyyy-mm-dd` is read as\n * itself wherever it turns up, since nothing else starts with four figures,\n * and a date spelled out in words still parses so a paste of `Sep 12, 2026`\n * lands. Three numbers at least: the field must not flicker through\n * Decembers on the way to one date.\n */\nfunction parseDateText(\n text: string,\n locales: Intl.LocalesArgument,\n): Date | undefined {\n const trimmed = text.trim();\n if (trimmed === \"\") return undefined;\n\n const numbers = (trimmed.match(/\\d+/g) ?? []).map(Number);\n if (numbers.length >= 3) {\n const clock = numbers.slice(3);\n // `3:04 pm` is not the shape the field writes, but it is a shape people\n // type; move it onto the 24-hour dial the rest of this speaks.\n if (/\\bpm\\b/i.test(trimmed) && clock[0] !== undefined && clock[0] < 12) {\n clock[0] += 12;\n } else if (/\\bam\\b/i.test(trimmed) && clock[0] === 12) {\n clock[0] = 0;\n }\n\n // Four figures up front can only be a year; no locale puts a day or a\n // month there.\n if (/^\\d{4}\\D/.test(trimmed)) {\n const [year, month, day] = numbers;\n return makeLocalDate(year!, month!, day!, clock);\n }\n\n const slots: Partial<Record<DatePart, number>> = {};\n numericOrder(locales).forEach((part, at) => {\n slots[part] = numbers[at];\n });\n if (slots.year != null && slots.month != null && slots.day != null) {\n const made = makeLocalDate(slots.year, slots.month, slots.day, clock);\n if (made) return made;\n }\n }\n\n // Words — a pasted `Sep 12, 2026`. Only worth trying with letters in it and\n // a four-figure year to go with them: `new Date` turns a bare `Sep 12` into\n // this year's, which is a guess the field should not make.\n if (!/[a-z]/i.test(trimmed)) return undefined;\n if (numbers.length < 2 || !/\\b\\d{4}\\b/.test(trimmed)) return undefined;\n const spelled = new Date(trimmed);\n return Number.isNaN(spelled.getTime()) ? undefined : spelled;\n}\n\n/** Zero everything finer than the granularity, so the value means what it says. */\nfunction clampTime(date: Date, time: DatePickerTime | undefined): Date {\n const next = new Date(date);\n next.setMilliseconds(0);\n if (time === \"second\") return next;\n next.setSeconds(0);\n if (time === \"minute\") return next;\n next.setMinutes(0);\n if (time === \"hour\") return next;\n next.setHours(0);\n return next;\n}\n\n/**\n * A value's identity, for telling whether the window on screen is still the\n * one a preset put there. Instants, so a re-render cannot change the answer.\n */\nfunction valueKey(value: Date | DateRange | undefined): string {\n if (value == null) return \"\";\n if (value instanceof Date) return String(value.getTime());\n return `${value.from?.getTime() ?? \"\"}-${value.to?.getTime() ?? \"\"}`;\n}\n\n/** A day from the calendar, wearing the clock the value already carried. */\nfunction withDay(day: Date, keepTimeFrom: Date | undefined): Date {\n const next = new Date(day);\n if (keepTimeFrom) {\n next.setHours(\n keepTimeFrom.getHours(),\n keepTimeFrom.getMinutes(),\n keepTimeFrom.getSeconds(),\n 0,\n );\n }\n return next;\n}\n\nconst startOfMonth = (d: Date) => new Date(d.getFullYear(), d.getMonth(), 1);\nconst endOfMonth = (d: Date) => new Date(d.getFullYear(), d.getMonth() + 1, 0);\n// DayPicker's matchers count calendar days, so a bound carrying a time of day\n// disables nothing extra on the calendar. Widen each to its whole day before\n// handing it to a system picker, which would otherwise enforce the clock too.\nconst startOfDay = (d: Date) =>\n new Date(d.getFullYear(), d.getMonth(), d.getDate());\nconst endOfDay = (d: Date) =>\n new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59, 999);\nconst later = (a: Date | undefined, b: Date) => (a && a > b ? a : b);\nconst earlier = (a: Date | undefined, b: Date) => (a && a < b ? a : b);\n\n/**\n * The only rules a system picker enforces are its first and last day. Returns\n * them, or `null` when the page asked for something the OS cannot express — a\n * weekday rule, a predicate, a hidden set — in which case the calendar, which\n * can enforce it, stays on every device.\n */\nfunction nativeBounds(\n calendarProps: PropsBase | undefined,\n): { min?: Date; max?: Date } | null {\n if (calendarProps?.hidden != null) return null;\n\n let min: Date | undefined;\n let max: Date | undefined;\n const rules: Matcher[] =\n calendarProps?.disabled == null\n ? []\n : Array.isArray(calendarProps.disabled)\n ? calendarProps.disabled\n : [calendarProps.disabled];\n\n for (const rule of rules) {\n if (rule == null || typeof rule !== \"object\" || rule instanceof Date) {\n return null;\n }\n const keys = Object.keys(rule);\n // `{ before }` and `{ after }` alone are the two the OS understands; the\n // pair of them is DayPicker's *interval*, which means the opposite.\n if (keys.length !== 1) return null;\n if (\"before\" in rule && rule.before instanceof Date) {\n min = later(min, startOfDay(rule.before));\n } else if (\"after\" in rule && rule.after instanceof Date) {\n max = earlier(max, endOfDay(rule.after));\n } else {\n return null;\n }\n }\n\n if (calendarProps?.startMonth) {\n min = later(min, startOfMonth(calendarProps.startMonth));\n }\n if (calendarProps?.endMonth) {\n max = earlier(max, endOfDay(endOfMonth(calendarProps.endMonth)));\n }\n return { min, max };\n}\n\n/* --------------------------------------------------------------- devices */\n\nconst COARSE_POINTER = \"(pointer: coarse)\";\n\n/**\n * True where the primary input is a finger. `useSyncExternalStore` so the\n * server and the first client render agree (no match) and the swap happens in\n * the same commit as hydration, rather than as a mismatch.\n */\nfunction useCoarsePointer(): boolean {\n const subscribe = useCallback((notify: () => void) => {\n if (typeof window === \"undefined\" || !window.matchMedia) return () => {};\n const query = window.matchMedia(COARSE_POINTER);\n query.addEventListener(\"change\", notify);\n return () => query.removeEventListener(\"change\", notify);\n }, []);\n\n return useSyncExternalStore(\n subscribe,\n () =>\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(COARSE_POINTER).matches,\n () => false,\n );\n}\n\n/* ------------------------------------------------------------------ props */\n\n/**\n * A window the page offers by name — `Last 7 days` — beside the calendar.\n * Pass a function for anything measured from now, so it is resolved at the\n * click rather than at render.\n */\nexport interface DatePickerPreset<T> {\n label: string;\n value: T | (() => T);\n}\n\ninterface DatePickerBaseProps {\n /** Field label (associated for accessibility). */\n label?: ReactNode;\n /** Helper text below the field; rendered in the error color when `invalid`. */\n hint?: ReactNode;\n /**\n * What the field shows until something is chosen.\n * @default the shape to type, in this locale's order (`mm/dd/yyyy`)\n */\n placeholder?: string;\n /** Render the invalid state (error ring + error-colored hint). */\n invalid?: boolean;\n disabled?: boolean;\n /** Marks the label with the required asterisk. */\n required?: boolean;\n /** Size variant. @default \"md\" */\n size?: DatePickerSize;\n /**\n * Ask for a time as well as a day, this fine. `hour` sets the hour and\n * zeroes the rest, `minute` the hour and minute, `second` all three. Omit\n * it and the value is midnight on the chosen day.\n */\n time?: DatePickerTime;\n /** Locale for the trigger's words. Defaults to the viewer's. */\n locales?: Intl.LocalesArgument;\n /**\n * Everything else React DayPicker takes — `disabled` days, `startMonth` /\n * `endMonth`, `numberOfMonths`, `weekStartsOn`, `captionLayout`.\n */\n calendarProps?: PropsBase;\n /** Id for the trigger, if the page needs its own. */\n id?: string;\n /** Class applied to the trigger. */\n className?: string;\n}\n\nexport interface DatePickerSingleProps extends DatePickerBaseProps {\n /** @default \"single\" */\n mode?: \"single\";\n value?: Date;\n defaultValue?: Date;\n onValueChange?: (value: Date | undefined) => void;\n /** Named days offered beside the calendar. */\n presets?: DatePickerPreset<Date>[];\n}\n\nexport interface DatePickerRangeProps extends DatePickerBaseProps {\n mode: \"range\";\n value?: DateRange;\n defaultValue?: DateRange;\n onValueChange?: (value: DateRange | undefined) => void;\n /** Named windows offered beside the calendar — `Last 7 days`, and so on. */\n presets?: DatePickerPreset<DateRange>[];\n}\n\nexport type DatePickerProps = DatePickerSingleProps | DatePickerRangeProps;\n\n/* ------------------------------------------------------------- the clock */\n\n/** One labelled time field — the popover's way of asking for the clock. */\nfunction ClockField({\n label,\n value,\n time,\n disabled,\n onChange,\n}: {\n label: string;\n value: Date | undefined;\n time: DatePickerTime;\n disabled?: boolean;\n onChange: (next: string) => void;\n}) {\n return (\n <>\n <span className=\"text-pho-description text-xs\">{label}</span>\n <label\n className={cn(\n \"bg-pho-primary ring-pho-primary rounded-sm px-2 py-1 ring-1 ring-inset\",\n \"focus-within:ring-pho-brand transition-shadow duration-100 ease-linear focus-within:ring-2\",\n )}\n >\n <input\n type=\"time\"\n step={TIME_STEP[time]}\n disabled={disabled}\n aria-label={label}\n value={value ? toClockValue(value, time) : \"\"}\n onChange={(event) => onChange(event.target.value)}\n className={cn(\n \"text-pho-primary w-full bg-transparent text-base tabular-nums outline-none\",\n // The browser's own clock glyph is off-brand and unstyleable;\n // the field's words are the control.\n \"[&::-webkit-calendar-picker-indicator]:hidden\",\n )}\n />\n </label>\n </>\n );\n}\n\n/* ------------------------------------------------------------ the picker */\n\n/**\n * Date Picker — a field that shows the chosen date and opens a `Calendar` to\n * change it. `mode=\"range\"` picks a span instead of a day; the popover stays\n * open until both ends are down.\n *\n * The value is a `Date` (or a `{ from, to }` range), never a string: pass\n * `value` to control it, `defaultValue` to let it keep its own. Clearing is\n * built in — clicking the chosen day again unsets it.\n *\n * `time` asks for the clock as well, to the hour, the minute, or the second.\n *\n * On a touch device the field hands off to the system picker — the OS wheel or\n * dialog, which people already know — as long as the rules the page set are\n * ones it can enforce. A weekday rule or a predicate keeps the calendar, which\n * can; so does `mode=\"range\"`, which no system picker offers.\n */\nexport function DatePicker(props: DatePickerProps) {\n const {\n mode = \"single\",\n defaultValue,\n onValueChange,\n label,\n hint,\n placeholder,\n invalid,\n disabled,\n required,\n size = \"md\",\n time,\n locales,\n calendarProps,\n id,\n className,\n } = props;\n const presets = props.presets as\n DatePickerPreset<Date | DateRange>[] | undefined;\n\n // Presence of the prop, not its value: an empty controlled picker is the\n // normal starting state, so `value === undefined` cannot mean \"uncontrolled\".\n const controlled = \"value\" in props;\n const [ownValue, setOwnValue] = useState<Date | DateRange | undefined>(\n defaultValue,\n );\n const value = controlled ? props.value : ownValue;\n const [open, setOpen] = useState(false);\n // A range takes two clicks, and the first one already reads as a complete\n // one-day range ({ from, to } both set), so the value alone can't say when\n // the question is answered. Count the picks in this opening instead.\n const picks = useRef(0);\n\n // Empty, the field shows the shape to type. A span cannot be typed, so it\n // asks in words instead.\n const fieldPlaceholder =\n placeholder ??\n (mode === \"range\" ? \"Pick a date range\" : dateFieldMask(locales, time));\n\n const generatedId = useId();\n const triggerId = id ?? generatedId;\n const hintId = hint ? `${triggerId}-hint` : undefined;\n const calendarId = `${triggerId}-calendar`;\n\n // Whether the calendar should take the caret as it appears — true only when\n // a key asked for it, so a click leaves the caret in the field.\n const [gridFocus, setGridFocus] = useState(false);\n\n // The field is not a `Popover.Trigger`, so Base UI never routes its own\n // opening through `onOpenChange`: a controlled `open` is written straight\n // into the store. Every way in goes through here instead, or the reset an\n // opening owes — the pick count, the month on screen — silently never runs.\n const openPicker = (focusGrid = false) => {\n if (open) return;\n picks.current = 0;\n setMonth(undefined);\n setGridFocus(focusGrid);\n setOpen(true);\n };\n\n const commit = (next: Date | DateRange | undefined) => {\n if (!controlled) setOwnValue(next);\n // The two modes have disjoint value types, and the union's callback is\n // only ever handed the shape its own mode produces.\n (\n onValueChange as ((v: Date | DateRange | undefined) => void) | undefined\n )?.(next);\n };\n\n const single = mode === \"single\" ? (value as Date | undefined) : undefined;\n const range = mode === \"range\" ? (value as DateRange | undefined) : undefined;\n // Reopen where the value lives, not on today's month.\n const anchor = single ?? range?.from;\n\n // The field is a text input, so the words in it are the viewer's until they\n // leave: `null` means \"whatever the value says\", anything else is what they\n // typed. Blur, a pick, and closing all hand the field back to the value.\n const [draft, setDraft] = useState<string | null>(null);\n // A preset names the window it set; the name stands only while the value is\n // still the one it produced, so a day picked afterwards drops the name with\n // no bookkeeping.\n const [chosen, setChosen] = useState<{ label: string; key: string } | null>(\n null,\n );\n const presetLabel =\n chosen && chosen.key === valueKey(value) ? chosen.label : null;\n\n const text = draft ?? presetLabel ?? formatDateLabel(value, locales, time);\n\n const pickPreset = (preset: DatePickerPreset<Date | DateRange>) => {\n const next =\n typeof preset.value === \"function\" ? preset.value() : preset.value;\n setChosen({ label: preset.label, key: valueKey(next) });\n setDraft(null);\n commit(next);\n // A named window is the whole answer, clock included.\n setOpen(false);\n };\n\n // The month on screen follows what is typed, and resets to the value's own\n // month each time the calendar opens. Held from the first render rather than\n // handed over later: DayPicker keeps its own month until the prop arrives,\n // and a calendar that starts uncontrolled would ignore the first jump.\n const [month, setMonth] = useState<Date | undefined>(undefined);\n const [thisMonth] = useState(() => calendarProps?.today ?? new Date());\n const shownMonth =\n month ?? calendarProps?.defaultMonth ?? anchor ?? thisMonth;\n\n const fieldRef = useRef<HTMLDivElement>(null);\n const popupRef = useRef<HTMLDivElement>(null);\n\n const coarse = useCoarsePointer();\n const bounds = nativeBounds(calendarProps);\n // No system picker offers a range, so that mode keeps the calendar; so does\n // a rule the OS cannot enforce.\n const native =\n coarse && mode === \"single\" && bounds != null && !presets?.length;\n\n const face = (\n <>\n <IconCalendar className=\"text-pho-secondary size-4 shrink-0\" />\n <span\n className={cn(\n \"min-w-0 flex-1 truncate\",\n text === \"\" && \"text-pho-placeholder\",\n )}\n >\n {text === \"\" ? fieldPlaceholder : text}\n </span>\n </>\n );\n\n return (\n <div className=\"flex w-full flex-col gap-1.5\">\n {label ? (\n <label\n htmlFor={triggerId}\n className=\"text-pho-secondary flex w-fit cursor-default items-center gap-0.5 text-base font-medium\"\n >\n {label}\n {required ? <span className=\"text-pho-brand\">*</span> : null}\n </label>\n ) : null}\n\n {native ? (\n <div\n data-invalid={invalid || undefined}\n className={cn(\n TRIGGER_BASE,\n TRIGGER_NATIVE,\n SIZE_PAD[size],\n SIZE_RADIUS[size],\n className,\n )}\n >\n {face}\n {/* The system field lies over the whole control at zero opacity:\n the tap opens the OS picker, the words underneath stay Pho's. */}\n <input\n id={triggerId}\n type={time ? \"datetime-local\" : \"date\"}\n step={time ? TIME_STEP[time] : undefined}\n min={\n bounds?.min\n ? time\n ? toDateTimeValue(clampTime(bounds.min, time), time)\n : toDateValue(bounds.min)\n : undefined\n }\n max={\n bounds?.max\n ? time\n ? toDateTimeValue(clampTime(bounds.max, time), time)\n : toDateValue(bounds.max)\n : undefined\n }\n required={required}\n disabled={disabled}\n aria-describedby={hintId}\n value={\n single\n ? time\n ? toDateTimeValue(single, time)\n : toDateValue(single)\n : \"\"\n }\n onChange={(event) => {\n const next = fromInputValue(event.target.value);\n commit(next ? clampTime(next, time) : undefined);\n }}\n className=\"absolute inset-0 size-full cursor-pointer opacity-0\"\n />\n </div>\n ) : (\n <Popover.Root\n open={open}\n onOpenChange={(next, details) => {\n // Clicking in the field is how the viewer reaches the caret, so it\n // opens the calendar and never takes it away again — the field is\n // not a trigger Base UI knows about, so its own presses arrive\n // here as presses from outside.\n if (\n !next &&\n details.reason === \"outside-press\" &&\n details.event.target instanceof Node &&\n fieldRef.current?.contains(details.event.target)\n ) {\n return;\n }\n // Opening is `openPicker`'s job; this only ever hears about\n // closes (Escape, a click outside) and the odd programmatic open.\n if (next) {\n picks.current = 0;\n setMonth(undefined);\n } else {\n setDraft(null);\n setGridFocus(false);\n }\n setOpen(next);\n }}\n >\n <div\n ref={fieldRef}\n data-invalid={invalid || undefined}\n data-popup-open={open || undefined}\n className={cn(\n TRIGGER_BASE,\n TRIGGER_FIELD,\n SIZE_PAD[size],\n SIZE_RADIUS[size],\n className,\n )}\n >\n <IconCalendar className=\"text-pho-secondary size-4 shrink-0\" />\n <input\n id={triggerId}\n type=\"text\"\n // A span is two dates and a separator; there is nothing\n // sensible to type, so the field only opens the calendar.\n readOnly={mode === \"range\"}\n disabled={disabled}\n required={required}\n placeholder={fieldPlaceholder}\n aria-describedby={hintId}\n // The APG's date-picker combobox: a text field that also says\n // what it opens. `textbox` alone does not support `aria-expanded`.\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={open ? calendarId : undefined}\n autoComplete=\"off\"\n spellCheck={false}\n value={text}\n onFocus={() => openPicker()}\n onMouseDown={() => openPicker()}\n onChange={(event) => {\n const typed = event.target.value;\n setDraft(typed);\n if (typed.trim() === \"\") {\n commit(undefined);\n return;\n }\n const parsed = parseDateText(typed, locales);\n if (parsed) {\n commit(clampTime(parsed, time));\n // Follow the words: the calendar shows what was typed.\n setMonth(parsed);\n }\n }}\n onBlur={() => setDraft(null)}\n onKeyDown={(event) => {\n if (event.key === \"Escape\" && open) {\n event.preventDefault();\n setDraft(null);\n setOpen(false);\n return;\n }\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n // Hand the caret to the grid, where the arrows mean days.\n const grid = popupRef.current?.querySelector<HTMLElement>(\n \"td[data-day] button[tabindex='0']\",\n );\n if (grid) {\n grid.focus();\n return;\n }\n // Closed: the grid is not mounted yet, so the calendar takes\n // the caret itself as it appears — one press, not two.\n openPicker(true);\n }\n }}\n className={cn(\n \"text-pho-primary placeholder:text-pho-placeholder min-w-0 flex-1 bg-transparent outline-none\",\n mode === \"range\" && \"cursor-pointer\",\n )}\n />\n </div>\n\n <Popover.Portal>\n <Popover.Positioner anchor={fieldRef} align=\"start\" sideOffset={6}>\n {/* Two months on a phone are taller than the room under the\n field; cap the popup at what Base UI measured and let it\n scroll rather than running off the screen. */}\n <Popover.Popup\n ref={popupRef}\n id={calendarId}\n // The field keeps the caret: the viewer is mid-word, and the\n // calendar is a second way to answer, not a takeover.\n initialFocus={false}\n finalFocus={false}\n className=\"max-h-[var(--available-height)] overflow-y-auto p-3\"\n >\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n {presets?.length ? (\n // Beside the calendar where there is room, above it on a\n // phone, where a row that scrolls sideways costs no height.\n <div\n // A labelled set of buttons, not a form section.\n // oxlint-disable-next-line jsx-a11y/prefer-tag-over-role\n role=\"group\"\n aria-label=\"Presets\"\n className={cn(\n \"flex shrink-0 gap-1 overflow-x-auto\",\n \"sm:border-pho-secondary sm:w-36 sm:flex-col sm:gap-0.5 sm:overflow-visible sm:border-r sm:pr-3\",\n )}\n >\n {presets.map((preset) => (\n <button\n key={preset.label}\n type=\"button\"\n aria-pressed={preset.label === presetLabel}\n onClick={() => pickPreset(preset)}\n className={cn(\n PRESET,\n preset.label === presetLabel && PRESET_ON,\n )}\n >\n {preset.label}\n </button>\n ))}\n </div>\n ) : null}\n\n <div>\n {mode === \"range\" ? (\n <Calendar\n {...calendarProps}\n mode=\"range\"\n month={shownMonth}\n onMonthChange={setMonth}\n // DayPicker's own prop, not the DOM attribute.\n // oxlint-disable-next-line jsx-a11y/no-autofocus\n autoFocus={gridFocus}\n selected={range}\n onSelect={(next, clicked) => {\n const first = picks.current === 0;\n picks.current += 1;\n // Reopened on a span that is already settled: the first\n // click starts a new one. DayPicker would otherwise drag\n // the nearer end over, so asking for Sep 20 – 25 on top\n // of Sep 1 – 8 would land on Sep 1 – 25.\n if (first && range?.to) {\n const day = clampTime(\n withDay(clicked, time ? range.from : undefined),\n time,\n );\n commit({ from: day, to: new Date(day) });\n setDraft(null);\n return;\n }\n const kept = next && {\n from:\n next.from &&\n clampTime(\n withDay(\n next.from,\n time ? range?.from : undefined,\n ),\n time,\n ),\n to:\n next.to &&\n clampTime(\n withDay(next.to, time ? range?.to : undefined),\n time,\n ),\n };\n commit(kept);\n setDraft(null);\n // Second pick, and the question is answered either way:\n // both ends down, or the same day twice, which DayPicker\n // reads as clearing the span. Unless a time is still to\n // be set, which lives below.\n if (\n !time &&\n picks.current >= 2 &&\n (!kept || (kept.from && kept.to))\n ) {\n setOpen(false);\n }\n }}\n />\n ) : (\n <Calendar\n {...calendarProps}\n mode=\"single\"\n month={shownMonth}\n onMonthChange={setMonth}\n // oxlint-disable-next-line jsx-a11y/no-autofocus\n autoFocus={gridFocus}\n selected={single}\n onSelect={(next) => {\n commit(\n next &&\n clampTime(\n withDay(next, time ? single : undefined),\n time,\n ),\n );\n setDraft(null);\n // The clock is still to be set, and it is below.\n if (!time) setOpen(false);\n }}\n />\n )}\n\n {time ? (\n <div className=\"border-pho-secondary mt-3 grid grid-cols-[auto_1fr] items-center gap-x-3 gap-y-2 border-t pt-3\">\n {mode === \"range\" ? (\n <>\n <ClockField\n label=\"From\"\n value={range?.from}\n time={time}\n onChange={(clock) => {\n if (!range?.from) return;\n const next = fromInputValue(\n `${toDateValue(range.from)}T${clock}`,\n );\n if (next) {\n commit({\n ...range,\n from: clampTime(next, time),\n });\n }\n }}\n disabled={!range?.from}\n />\n <ClockField\n label=\"To\"\n value={range?.to}\n time={time}\n onChange={(clock) => {\n if (!range?.to) return;\n const next = fromInputValue(\n `${toDateValue(range.to)}T${clock}`,\n );\n if (next) {\n commit({\n ...range,\n to: clampTime(next, time),\n });\n }\n }}\n disabled={!range?.to}\n />\n </>\n ) : (\n <ClockField\n label=\"Time\"\n value={single}\n time={time}\n onChange={(clock) => {\n if (!single) return;\n const next = fromInputValue(\n `${toDateValue(single)}T${clock}`,\n );\n if (next) commit(clampTime(next, time));\n }}\n disabled={!single}\n />\n )}\n </div>\n ) : null}\n </div>\n </div>\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n </Popover.Root>\n )}\n\n {hint ? (\n <p\n id={hintId}\n className={cn(\n \"text-pho-description text-base\",\n invalid && \"text-pho-error\",\n )}\n >\n {hint}\n </p>\n ) : null}\n </div>\n );\n}\n\nDatePicker.displayName = \"DatePicker\";\n"],"x_google_ignoreList":[0],"mappings":"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"}