ajo-ui 0.1.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.
Files changed (103) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +126 -0
  3. package/dist/accordion.js +130 -0
  4. package/dist/avatar.js +54 -0
  5. package/dist/calendar.js +2 -0
  6. package/dist/carousel.js +239 -0
  7. package/dist/chart.js +790 -0
  8. package/dist/checkbox-group.js +70 -0
  9. package/dist/checkbox.js +77 -0
  10. package/dist/chunks/bar-CVafh6C1.js +99 -0
  11. package/dist/chunks/calendar-q8jZ8Cxr.js +1923 -0
  12. package/dist/chunks/collection-DtRB63U4.js +111 -0
  13. package/dist/chunks/data-table-DpkWv4y4.js +1039 -0
  14. package/dist/chunks/menu-B45IyHHC.js +704 -0
  15. package/dist/chunks/native-BJdhd9XJ.js +20 -0
  16. package/dist/chunks/popup-C8Bb3l_g.js +459 -0
  17. package/dist/chunks/popup-surface-BDCgtVU0.js +18 -0
  18. package/dist/chunks/position-D6_i_SRn.js +434 -0
  19. package/dist/chunks/virtual-list-B7hjGkjk.js +413 -0
  20. package/dist/collapsible.js +106 -0
  21. package/dist/command.js +263 -0
  22. package/dist/context-menu.js +112 -0
  23. package/dist/data-table.js +5 -0
  24. package/dist/dialog.js +207 -0
  25. package/dist/direction.js +22 -0
  26. package/dist/drawer.js +139 -0
  27. package/dist/field.js +26 -0
  28. package/dist/index.js +38 -0
  29. package/dist/input-date.js +994 -0
  30. package/dist/input-group.js +52 -0
  31. package/dist/input-otp.js +179 -0
  32. package/dist/menu.js +2 -0
  33. package/dist/menubar.js +236 -0
  34. package/dist/message-scroller.js +446 -0
  35. package/dist/navigation-menu.js +330 -0
  36. package/dist/popover.js +307 -0
  37. package/dist/progress.js +39 -0
  38. package/dist/radio-group.js +107 -0
  39. package/dist/resizable.js +172 -0
  40. package/dist/select.js +961 -0
  41. package/dist/sidebar.js +343 -0
  42. package/dist/slider.js +259 -0
  43. package/dist/switch.js +53 -0
  44. package/dist/tabs.js +182 -0
  45. package/dist/toast.js +492 -0
  46. package/dist/toggle-group.js +111 -0
  47. package/dist/toggle.js +52 -0
  48. package/dist/toolbar.js +127 -0
  49. package/dist/tooltip.js +196 -0
  50. package/dist/utils.js +104 -0
  51. package/dist/virtual-list.js +2 -0
  52. package/package.json +250 -0
  53. package/src/accordion.tsx +261 -0
  54. package/src/availability.ts +261 -0
  55. package/src/avatar.tsx +99 -0
  56. package/src/bar.ts +156 -0
  57. package/src/calendar.tsx +1441 -0
  58. package/src/carousel.tsx +424 -0
  59. package/src/chart.tsx +1194 -0
  60. package/src/checkbox-group.tsx +132 -0
  61. package/src/checkbox.tsx +130 -0
  62. package/src/collapsible.tsx +188 -0
  63. package/src/collection.ts +154 -0
  64. package/src/command.tsx +511 -0
  65. package/src/context-menu.tsx +233 -0
  66. package/src/data-table-contract.ts +143 -0
  67. package/src/data-table-model.ts +760 -0
  68. package/src/data-table.tsx +475 -0
  69. package/src/dialog.tsx +393 -0
  70. package/src/direction.tsx +45 -0
  71. package/src/drawer.tsx +251 -0
  72. package/src/field.tsx +61 -0
  73. package/src/index.ts +37 -0
  74. package/src/input-date.tsx +1539 -0
  75. package/src/input-group.tsx +142 -0
  76. package/src/input-otp.tsx +324 -0
  77. package/src/menu-cluster.ts +124 -0
  78. package/src/menu.tsx +1095 -0
  79. package/src/menubar.tsx +459 -0
  80. package/src/message-scroller.tsx +732 -0
  81. package/src/native.ts +26 -0
  82. package/src/navigation-menu.tsx +578 -0
  83. package/src/popover.tsx +519 -0
  84. package/src/popup-surface.tsx +31 -0
  85. package/src/popup.ts +569 -0
  86. package/src/position.ts +523 -0
  87. package/src/progress.tsx +70 -0
  88. package/src/radio-group.tsx +186 -0
  89. package/src/resizable.tsx +310 -0
  90. package/src/segments.ts +922 -0
  91. package/src/select.tsx +1501 -0
  92. package/src/sidebar.tsx +683 -0
  93. package/src/slider.tsx +424 -0
  94. package/src/switch.tsx +104 -0
  95. package/src/tabs.tsx +314 -0
  96. package/src/toast.tsx +923 -0
  97. package/src/toggle-group.tsx +249 -0
  98. package/src/toggle.tsx +91 -0
  99. package/src/toolbar.tsx +212 -0
  100. package/src/tooltip.tsx +359 -0
  101. package/src/utils.ts +204 -0
  102. package/src/virtual-list.tsx +205 -0
  103. package/src/virtual.ts +385 -0
@@ -0,0 +1,994 @@
1
+ import { flag, triggerAttrs } from "./utils.js";
2
+ import { a as field, c as isReversed, i as defaultMessage, l as timeRun, o as formatValue, r as compile, s as fromISO, t as Calendar, u as unitLabel } from "./chunks/calendar-q8jZ8Cxr.js";
3
+ import { n as popup, t as contentAttrs } from "./chunks/popup-C8Bb3l_g.js";
4
+ import { FieldContext } from "./field.js";
5
+ import { callHandler, callRef, controlled, dom, id, listen, restore, roving, spin, statefulRootAttrs } from "ajo-cloves";
6
+ import { context } from "ajo/context";
7
+ import { Fragment, jsx, jsxs } from "ajo/jsx-runtime";
8
+ //#region packages/ajo-ui/src/input-date.tsx
9
+ var InputDateContext = context(null);
10
+ var resolveLocale = (locale) => {
11
+ const code = typeof locale === "string" ? locale : locale?.code;
12
+ if (code) return code;
13
+ if (typeof document !== "undefined" && document.documentElement.lang) return document.documentElement.lang;
14
+ return "en-US";
15
+ };
16
+ var InputDateRoot = function* (initial) {
17
+ let kind = initial.kind;
18
+ const rootId = id("input-date");
19
+ const domReady = dom(this);
20
+ const ownerDocument = domReady ? this.ownerDocument : null;
21
+ const node = (value) => {
22
+ const view = ownerDocument?.defaultView;
23
+ return Boolean(view && value instanceof view.Node);
24
+ };
25
+ const ios = domReady && typeof navigator !== "undefined" && (/iP(ad|hone|od)/.test(navigator.userAgent) || navigator.userAgent.includes("Mac") && navigator.maxTouchPoints > 1);
26
+ const warned = /* @__PURE__ */ new Set();
27
+ const timeSurfaces = /* @__PURE__ */ new Set();
28
+ let closeOnSelect;
29
+ let composing = null;
30
+ let controlId = `${rootId}-control`;
31
+ let availabilitySource = initial.unavailable;
32
+ let availability = compile(initial.unavailable);
33
+ let boundsSource;
34
+ let boundsAvailability;
35
+ let calendarUserSource;
36
+ let calendarUserAvailability;
37
+ let allowNonContiguous = Boolean(initial.allowNonContiguous);
38
+ let disabled = Boolean(initial.disabled);
39
+ let isRange = Boolean(initial.range);
40
+ let locale = resolveLocale(initial.locale);
41
+ let onOpenChange;
42
+ let onValueChange;
43
+ let pendingFocus = false;
44
+ let pendingReference = null;
45
+ let closingInside = false;
46
+ let pop;
47
+ let presets = [];
48
+ let readOnly = Boolean(initial.readOnly);
49
+ let required = Boolean(initial.required);
50
+ let visibleMonth;
51
+ const unavailableValue = (value) => availability?.value(kind, value) ?? false;
52
+ const sideDefault = (value, side) => {
53
+ if (value == null) return void 0;
54
+ if (typeof value === "string") return side === "from" ? value : void 0;
55
+ return value[side] ?? void 0;
56
+ };
57
+ const optionsFor = (side, args) => ({
58
+ kind,
59
+ locale,
60
+ granularity: args.granularity,
61
+ hourCycle: args.hourCycle,
62
+ step: args.step,
63
+ placeholderValue: args.placeholderValue,
64
+ defaultValue: sideDefault(args.defaultValue, side),
65
+ min: args.min,
66
+ max: args.max,
67
+ unavailable: availability ? unavailableValue : void 0,
68
+ errorMessage: args.errorMessage
69
+ });
70
+ const fields = {
71
+ from: field(optionsFor("from", initial)),
72
+ to: field(optionsFor("to", initial))
73
+ };
74
+ const composeValue = () => {
75
+ const from = fields.from.value();
76
+ if (!isRange) return from;
77
+ const to = fields.to.value();
78
+ return from == null && to == null ? null : {
79
+ from,
80
+ to
81
+ };
82
+ };
83
+ const valueState = controlled(this, {
84
+ fallback: initial.defaultValue ?? null,
85
+ onChange: (next, event) => onValueChange?.(next, event)
86
+ });
87
+ const sideValue = (side) => {
88
+ if (!valueState.controlled) return void 0;
89
+ const value = valueState.value;
90
+ if (value == null) return null;
91
+ if (typeof value === "string") return side === "from" ? value : null;
92
+ return value[side];
93
+ };
94
+ const emitIfChanged = (results, event) => {
95
+ if (results.every((result) => result.emit === void 0)) return;
96
+ valueState.set(composeValue(), event);
97
+ };
98
+ const segmentsOf = (surface = "field", rendered = true) => domReady ? Array.from(this.querySelectorAll("[data-segment]")).filter((item) => item.dataset.surface === surface && (!rendered || item.offsetParent !== null)) : [];
99
+ const segmentOf = (event) => event.target instanceof Element ? event.target.closest("[data-segment]") : null;
100
+ const sideOf = (segment) => segment.dataset.side ?? "from";
101
+ const surfaceOf = (segment) => segment.dataset.surface === "popover" ? "popover" : "field";
102
+ const unitOf = (segment) => segment.dataset.segment;
103
+ const moveFocus = (from, step) => {
104
+ const list = segmentsOf(surfaceOf(from));
105
+ list[list.indexOf(from) + step]?.focus();
106
+ };
107
+ const apply = (result, event, segment) => {
108
+ if (!result.handled) return false;
109
+ emitIfChanged([result], event);
110
+ if (result.advance) moveFocus(segment, 1);
111
+ if (result.retreat) moveFocus(segment, -1);
112
+ this.next();
113
+ return true;
114
+ };
115
+ const focusMemory = restore(this);
116
+ const clearFocusIntent = () => {
117
+ pendingFocus = false;
118
+ pendingReference = null;
119
+ };
120
+ const restoreAfterClose = () => {
121
+ clearFocusIntent();
122
+ const active = ownerDocument?.activeElement;
123
+ if (dom(active) && pop.content?.contains(active) && !closingInside) focusMemory.restore();
124
+ else focusMemory.capture(null);
125
+ closingInside = false;
126
+ };
127
+ pop = popup(this, {
128
+ prefix: "input-date",
129
+ profile: "date",
130
+ initialOpen: Boolean(initial.open ?? initial.defaultOpen),
131
+ disabled: () => disabled,
132
+ onOpenChange: (next, event) => onOpenChange?.(next, event),
133
+ reference: (view) => view.reference,
134
+ source: (view) => view.trigger,
135
+ referenceHidden: "close",
136
+ dismiss: {
137
+ escape: false,
138
+ outside: true,
139
+ inside: (view) => [
140
+ dom(view.reference) ? view.reference : null,
141
+ view.trigger,
142
+ view.content
143
+ ],
144
+ onDismiss: (event) => setOpen(false, event)
145
+ },
146
+ onPosition: () => {
147
+ if (!pendingFocus || pop.reference !== pendingReference) return;
148
+ clearFocusIntent();
149
+ if (!pop.content) return;
150
+ (pop.content.querySelector("[data-slot=\"calendar-day-button\"][data-state=\"selected\"]:not(:disabled)") ?? pop.content.querySelector("[data-slot=\"calendar-day-button\"][data-today]:not(:disabled)") ?? pop.content.querySelector("[data-slot=\"calendar-day-button\"]:not(:disabled)") ?? pop.content).focus();
151
+ },
152
+ onSync: (opened) => {
153
+ if (!opened) restoreAfterClose();
154
+ }
155
+ });
156
+ pop.setReference(this);
157
+ const setOpen = (next, event) => {
158
+ if (disabled && next) return;
159
+ if (next === pop.open) return;
160
+ if (next) {
161
+ visibleMonth = void 0;
162
+ pendingFocus = true;
163
+ pendingReference = pop.reference;
164
+ } else {
165
+ clearFocusIntent();
166
+ closingInside = event?.type === "pointerdown" && node(event.target) && this.contains(event.target);
167
+ }
168
+ pop.setOpen(next, event);
169
+ };
170
+ const toggleOpen = (event) => {
171
+ const next = !pop.open;
172
+ if (next) focusMemory.capture(pop.trigger);
173
+ setOpen(next, event);
174
+ };
175
+ const popupPart = (part) => {
176
+ if (kind !== "time") return true;
177
+ if (!warned.has(part)) {
178
+ warned.add(part);
179
+ console.warn(`[input-date] <${part}> has no effect under InputTime; popup parts require a date family root.`);
180
+ }
181
+ return false;
182
+ };
183
+ const timeSurface = (part) => {
184
+ if (kind === "datetime") return true;
185
+ if (!warned.has(part)) {
186
+ warned.add(part);
187
+ console.warn(`[input-date] <${part}> has no effect outside InputDateTime.`);
188
+ }
189
+ return false;
190
+ };
191
+ const hasTimeSurface = () => timeSurfaces.size > 0;
192
+ const dateOfValue = (side) => {
193
+ const units = fields[side].units;
194
+ return units.year != null && units.month != null && units.day != null ? new Date(units.year, units.month - 1, units.day, 12) : void 0;
195
+ };
196
+ const daySelected = () => dateOfValue("from") ?? null;
197
+ const rangeSelected = () => {
198
+ const from = dateOfValue("from");
199
+ const to = dateOfValue("to");
200
+ return from || to ? {
201
+ from,
202
+ to
203
+ } : null;
204
+ };
205
+ const monthOf = () => visibleMonth ?? dateOfValue("from");
206
+ const onMonthChange = (month, event) => {
207
+ const slot = event?.target instanceof Element ? event.target.closest("[data-slot]")?.dataset.slot : void 0;
208
+ this.next(() => visibleMonth = month);
209
+ if (!domReady || !slot) return;
210
+ const active = document.activeElement;
211
+ if (active && active !== document.body) return;
212
+ pop.content?.querySelector(`[data-slot="${slot}"]`)?.focus();
213
+ };
214
+ const dayOfBound = (value) => {
215
+ if (!value) return void 0;
216
+ const units = fromISO(kind, value);
217
+ return units && units.year != null && units.month != null && units.day != null ? new Date(units.year, units.month - 1, units.day, 12) : void 0;
218
+ };
219
+ const syncAvailability = (args) => {
220
+ if (args.unavailable !== availabilitySource) {
221
+ availabilitySource = args.unavailable;
222
+ availability = compile(args.unavailable);
223
+ }
224
+ const bounds = `${args.min ?? ""}\0${args.max ?? ""}`;
225
+ if (bounds !== boundsSource) {
226
+ boundsSource = bounds;
227
+ const matcher = [];
228
+ const before = dayOfBound(args.min);
229
+ const after = dayOfBound(args.max);
230
+ if (before) matcher.push({ before });
231
+ if (after) matcher.push({ after });
232
+ boundsAvailability = compile(matcher);
233
+ }
234
+ };
235
+ const hardDisabled = (date) => Boolean(calendarUserAvailability?.day(date) || boundsAvailability?.day(date));
236
+ const hardDisabledMatcher = [hardDisabled];
237
+ const calendarDisabled = (user) => {
238
+ if (user !== calendarUserSource) {
239
+ calendarUserSource = user;
240
+ calendarUserAvailability = compile(user);
241
+ }
242
+ return calendarUserAvailability || boundsAvailability ? hardDisabledMatcher : void 0;
243
+ };
244
+ const datePatch = (editor, date) => {
245
+ const patch = {
246
+ year: date.getFullYear(),
247
+ month: date.getMonth() + 1,
248
+ day: date.getDate()
249
+ };
250
+ if (kind === "datetime") {
251
+ const units = editor.units;
252
+ const seeded = editor.placeholder();
253
+ if (units.hour == null) patch.hour = seeded.hour;
254
+ if (units.minute == null) patch.minute = seeded.minute;
255
+ if (units.second == null && editor.segments.some((segment) => segment.type === "second")) patch.second = seeded.second;
256
+ if (units.dayPeriod == null && editor.hourCycle === "h12") patch.dayPeriod = seeded.dayPeriod;
257
+ }
258
+ return patch;
259
+ };
260
+ const emptyDate = {
261
+ year: null,
262
+ month: null,
263
+ day: null
264
+ };
265
+ const pickDay = (next, event) => {
266
+ if (disabled || readOnly) return;
267
+ emitIfChanged([fields.from.merge(next ? datePatch(fields.from, next) : emptyDate)], event);
268
+ if (closeOnSelect ?? (Boolean(next) && !hasTimeSurface())) setOpen(false, event);
269
+ this.next();
270
+ };
271
+ const pickRange = (next, event) => {
272
+ if (disabled || readOnly) return;
273
+ const patchFor = (editor, date) => date ? datePatch(editor, date) : emptyDate;
274
+ emitIfChanged([fields.from.merge(patchFor(fields.from, next?.from)), fields.to.merge(patchFor(fields.to, next?.to))], event);
275
+ if (closeOnSelect ?? (Boolean(next?.from && next?.to) && !hasTimeSurface())) setOpen(false, event);
276
+ this.next();
277
+ };
278
+ const applyPreset = (value, event) => {
279
+ if (disabled || readOnly) return;
280
+ const mergeSide = (side, next) => {
281
+ if (next == null) return fields[side].clear();
282
+ const units = fromISO(kind, next, fields[side].hourCycle);
283
+ if (!units) {
284
+ console.warn(`[input-date] invalid ${kind} preset value: "${next}"`);
285
+ return { handled: false };
286
+ }
287
+ return fields[side].merge(units);
288
+ };
289
+ emitIfChanged(typeof value === "string" ? [mergeSide("from", value)] : [mergeSide("from", value.from), mergeSide("to", value.to)], event);
290
+ setOpen(false, event);
291
+ this.next();
292
+ };
293
+ const clearValue = (event) => {
294
+ if (disabled || readOnly) return;
295
+ const results = [fields.from.clear()];
296
+ if (isRange) results.push(fields.to.clear());
297
+ emitIfChanged(results, event);
298
+ if (domReady) queueMicrotask(() => segmentsOf("field")[0]?.focus());
299
+ this.next();
300
+ };
301
+ const relocateFocus = () => {
302
+ const active = document.activeElement;
303
+ if (!(active instanceof HTMLElement) || !active.dataset.segment || !this.contains(active)) return;
304
+ const survives = (item) => fields[sideOf(item)].segments.some((segment) => segment.type === unitOf(item));
305
+ if (survives(active)) return;
306
+ const surface = surfaceOf(active);
307
+ const list = segmentsOf(surface, false);
308
+ const index = list.indexOf(active);
309
+ const target = list.slice(0, Math.max(index, 0)).reverse().find(survives) ?? list.slice(index + 1).find(survives);
310
+ if (!target) return;
311
+ const side = sideOf(target);
312
+ const unit = unitOf(target);
313
+ queueMicrotask(() => {
314
+ const current = document.activeElement;
315
+ if (current instanceof HTMLElement && current !== document.body && this.contains(current)) return;
316
+ segmentsOf(surface).find((item) => sideOf(item) === side && unitOf(item) === unit)?.focus();
317
+ });
318
+ };
319
+ const stepper = spin(this, { onMove: (move, event) => {
320
+ const segment = segmentOf(event);
321
+ if (!segment || readOnly || disabled) return;
322
+ apply(fields[sideOf(segment)].spin(unitOf(segment), move), event, segment);
323
+ } });
324
+ const nav = roving(this, {
325
+ items: () => {
326
+ const active = document.activeElement;
327
+ return segmentsOf(active instanceof HTMLElement && active.dataset.segment ? surfaceOf(active) : "field");
328
+ },
329
+ orientation: () => "horizontal",
330
+ dir: () => domReady && getComputedStyle(this).direction === "rtl" ? "rtl" : "ltr",
331
+ loop: () => false,
332
+ onMove: (target) => target.focus()
333
+ });
334
+ listen(this, "keydown", (event) => {
335
+ if (event.key === "Escape") {
336
+ if (!pop.open) return;
337
+ event.preventDefault();
338
+ setOpen(false, event);
339
+ return;
340
+ }
341
+ const segment = segmentOf(event);
342
+ if (!segment) return;
343
+ const side = sideOf(segment);
344
+ const unit = unitOf(segment);
345
+ if (event.altKey && event.key.startsWith("Arrow")) {
346
+ if (event.key === "ArrowDown" && pop.content) {
347
+ event.preventDefault();
348
+ focusMemory.capture(segment);
349
+ setOpen(true, event);
350
+ }
351
+ return;
352
+ }
353
+ if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "a") {
354
+ event.preventDefault();
355
+ return;
356
+ }
357
+ if (event.key === "Backspace" || event.key === "Delete") {
358
+ event.preventDefault();
359
+ if (!readOnly && !disabled) apply(fields[side].erase(unit), event, segment);
360
+ return;
361
+ }
362
+ if (event.key === "Enter") {
363
+ event.preventDefault();
364
+ moveFocus(segment, 1);
365
+ return;
366
+ }
367
+ if (!readOnly && stepper.handle(event)) return;
368
+ if (!readOnly && (event.key === "+" || event.key === "-")) {
369
+ event.preventDefault();
370
+ apply(fields[side].spin(unit, { step: event.key === "+" ? 1 : -1 }), event, segment);
371
+ return;
372
+ }
373
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight") nav.handle(event);
374
+ });
375
+ listen(this, "beforeinput", (event) => {
376
+ const segment = segmentOf(event);
377
+ if (!segment) return;
378
+ if (event.cancelable) event.preventDefault();
379
+ if (disabled || readOnly) return;
380
+ const side = sideOf(segment);
381
+ const unit = unitOf(segment);
382
+ if (event.inputType === "insertCompositionText") {
383
+ composing ??= {
384
+ side,
385
+ unit,
386
+ element: segment,
387
+ text: segment.textContent ?? ""
388
+ };
389
+ return;
390
+ }
391
+ if (event.inputType === "deleteContentBackward" || event.inputType === "deleteContentForward") {
392
+ apply(fields[side].erase(unit), event, segment);
393
+ return;
394
+ }
395
+ if (event.inputType === "insertText" && event.data) for (const key of event.data) apply(fields[side].type(unit, key), event, segment);
396
+ });
397
+ listen(this, "input", (event) => {
398
+ if (!composing) return;
399
+ const segment = segmentOf(event);
400
+ if (segment !== composing.element) return;
401
+ segment.textContent = composing.text;
402
+ this.next();
403
+ });
404
+ listen(this, "compositionend", (event) => {
405
+ if (!composing) return;
406
+ const { side, unit, element } = composing;
407
+ composing = null;
408
+ if (!disabled && !readOnly && event.data) for (const key of event.data) apply(fields[side].type(unit, key), event, element);
409
+ this.next();
410
+ });
411
+ listen(this, "paste", (event) => {
412
+ if (segmentOf(event)) event.preventDefault();
413
+ });
414
+ listen(this, "pointerdown", (event) => {
415
+ if (event.button) return;
416
+ const target = event.target instanceof Element ? event.target : null;
417
+ if (!target) return;
418
+ if (pop.open && !pop.content?.contains(target) && !pop.trigger?.contains(target)) setOpen(false, event);
419
+ const segment = target.closest("[data-segment]");
420
+ if (segment) {
421
+ event.preventDefault();
422
+ if (!disabled) segment.focus();
423
+ return;
424
+ }
425
+ const group = target.closest("[data-slot=\"input-date-field\"]");
426
+ if (!group || !this.contains(group)) return;
427
+ if (target.closest("[data-slot=\"input-date-trigger\"], a, button, input, select, textarea")) return;
428
+ event.preventDefault();
429
+ if (disabled) return;
430
+ const list = Array.from(group.querySelectorAll("[data-segment]"));
431
+ ([...list].reverse().find((item) => item.dataset.placeholder !== "true") ?? list[0])?.focus();
432
+ });
433
+ listen(this, "focusout", (event) => {
434
+ const segment = segmentOf(event);
435
+ if (!segment) return;
436
+ fields[sideOf(segment)].blur();
437
+ this.next();
438
+ });
439
+ if (domReady) {
440
+ document.addEventListener("selectionchange", () => {
441
+ const selection = document.getSelection();
442
+ if (!selection || selection.isCollapsed || !selection.anchorNode) return;
443
+ const anchor = selection.anchorNode instanceof Element ? selection.anchorNode : selection.anchorNode.parentElement;
444
+ if (anchor?.closest("[data-segment]") && this.contains(anchor)) selection.collapseToEnd();
445
+ }, { signal: this.signal });
446
+ document.addEventListener("click", (event) => {
447
+ const label = event.target instanceof Element ? event.target.closest("label") : null;
448
+ if (!label || label.getAttribute("for") !== controlId) return;
449
+ segmentsOf("field")[0]?.focus();
450
+ }, { signal: this.signal });
451
+ document.addEventListener("reset", (event) => {
452
+ if (!(event.target instanceof HTMLFormElement) || !event.target.contains(this)) return;
453
+ if (valueState.controlled) return;
454
+ fields.from.reset();
455
+ if (isRange) fields.to.reset();
456
+ valueState.init(composeValue());
457
+ this.next();
458
+ }, { signal: this.signal });
459
+ }
460
+ for (const args of this) {
461
+ const kindChanged = args.kind !== kind;
462
+ kind = args.kind;
463
+ syncAvailability(args);
464
+ allowNonContiguous = Boolean(args.allowNonContiguous);
465
+ closeOnSelect = args.closeOnSelect;
466
+ disabled = Boolean(args.disabled);
467
+ isRange = Boolean(args.range);
468
+ locale = resolveLocale(args.locale);
469
+ const emptyLabel = args.emptyLabel ?? "Empty";
470
+ onOpenChange = args.onOpenChange;
471
+ onValueChange = args.onValueChange;
472
+ presets = args.presets ?? [];
473
+ readOnly = Boolean(args.readOnly);
474
+ required = Boolean(args.required);
475
+ valueState.sync(args.value);
476
+ if (!pop.sync(args.open == null ? void 0 : Boolean(args.open), {
477
+ placement: args.placement,
478
+ gap: args.gap
479
+ })) clearFocusIntent();
480
+ else closingInside = false;
481
+ if (kindChanged && args.value === void 0) {
482
+ fields.from.sync(sideDefault(args.defaultValue, "from") ?? null, optionsFor("from", args));
483
+ fields.to.sync(sideDefault(args.defaultValue, "to") ?? null, optionsFor("to", args));
484
+ valueState.init(composeValue());
485
+ } else {
486
+ fields.from.sync(sideValue("from"), optionsFor("from", args));
487
+ if (isRange) fields.to.sync(sideValue("to"), optionsFor("to", args));
488
+ }
489
+ if (domReady) relocateFocus();
490
+ const fieldCtx = FieldContext();
491
+ controlId = fieldCtx?.ids.control ?? `${rootId}-control`;
492
+ const externalDescribedby = fieldCtx?.groupAttrs["aria-describedby"];
493
+ const reasonFrom = fields.from.reason();
494
+ const reasonTo = isRange ? fields.to.reason() : null;
495
+ const reversed = isRange && isReversed(fields.from.value(), fields.to.value());
496
+ const rangeFrom = isRange ? dateOfValue("from") : void 0;
497
+ const rangeTo = isRange ? dateOfValue("to") : void 0;
498
+ const unavailableRange = !allowNonContiguous && Boolean(rangeFrom && rangeTo && availability?.crosses(rangeFrom, rangeTo));
499
+ const rangeReason = reversed ? { code: "reversed" } : unavailableRange ? { code: "unavailableRange" } : null;
500
+ const invalidOf = (side) => (side === "from" ? reasonFrom : reasonTo) != null || rangeReason != null;
501
+ const hourCycle = fields.from.hourCycle;
502
+ const message = fields.from.message() ?? (isRange ? fields.to.message() : null) ?? (rangeReason ? args.errorMessage?.(rangeReason) ?? defaultMessage(rangeReason, {
503
+ kind,
504
+ locale,
505
+ hourCycle
506
+ }) : null);
507
+ const descriptionId = `${rootId}-description`;
508
+ const messageId = `${rootId}-message`;
509
+ const human = (side) => {
510
+ const committed = fields[side].value();
511
+ return committed == null ? null : formatValue(committed, {
512
+ kind,
513
+ locale,
514
+ hourCycle
515
+ });
516
+ };
517
+ const formatted = isRange ? [human("from"), human("to")].filter(Boolean).join(" – ") : human("from");
518
+ const descriptionText = formatted ? `${kind === "time" ? "Selected time" : "Selected date"}: ${formatted}` : null;
519
+ const value = composeValue();
520
+ const firstUnit = fields.from.segments.find((segment) => segment.editable)?.type;
521
+ const sideLabel = (side, override) => override ?? (kind === "time" ? side === "from" ? "Start time" : "End time" : side === "from" ? "Start date" : "End date");
522
+ const describedbyOf = (side, first) => {
523
+ const parts = [];
524
+ if ((first || invalidOf(side)) && typeof externalDescribedby === "string") parts.push(externalDescribedby);
525
+ if (first && descriptionText) parts.push(descriptionId);
526
+ if (invalidOf(side) && message) parts.push(messageId);
527
+ return parts.join(" ") || void 0;
528
+ };
529
+ const valuetextOf = (side, unit) => {
530
+ const editor = fields[side];
531
+ const current = editor.units[unit];
532
+ if (current == null) return emptyLabel;
533
+ if (unit === "month" && editor.monthNames.length) return `${current} – ${editor.monthNames[current - 1]}`;
534
+ if (unit === "hour" && editor.hourCycle === "h12" && editor.units.dayPeriod != null) return `${current} ${editor.periods[editor.units.dayPeriod]}`;
535
+ return editor.text(unit);
536
+ };
537
+ const groupAttrs = (side, label, surface = "field") => {
538
+ const invalid = invalidOf(side);
539
+ const record = {
540
+ "aria-disabled": flag(disabled),
541
+ "aria-invalid": flag(invalid),
542
+ "data-disabled": flag(disabled),
543
+ "data-invalid": flag(invalid),
544
+ "data-readonly": flag(readOnly),
545
+ "data-side": side,
546
+ "data-slot": surface === "field" ? "input-date-field" : "input-date-time-field",
547
+ "data-surface": surface,
548
+ role: "group"
549
+ };
550
+ if (surface === "popover") record["aria-label"] = label;
551
+ else if (isRange) record["aria-label"] = sideLabel(side, label);
552
+ else {
553
+ if (label) record["aria-label"] = label;
554
+ if (fieldCtx) {
555
+ record["aria-labelledby"] = fieldCtx.groupAttrs["aria-labelledby"];
556
+ record["aria-describedby"] = fieldCtx.groupAttrs["aria-describedby"];
557
+ }
558
+ }
559
+ return record;
560
+ };
561
+ const segmentAttrs = (side, segment, label, surface = "field") => {
562
+ const unit = segment.type;
563
+ const editor = fields[side];
564
+ const first = surface === "field" && side === "from" && unit === firstUnit;
565
+ const filled = editor.units[unit] != null;
566
+ const bounds = editor.bounds(unit);
567
+ const unitName = unitLabel(locale, unit);
568
+ const segmentId = first ? controlId : `${rootId}-${surface}-${side}-${unit}`;
569
+ const labelId = fieldCtx?.ids.label;
570
+ const surfaceLabel = surface === "popover" ? label : isRange ? sideLabel(side, label) : label;
571
+ const record = {
572
+ "aria-describedby": describedbyOf(side, first),
573
+ "aria-invalid": flag(invalidOf(side)),
574
+ "aria-label": surfaceLabel ? `${unitName}, ${surfaceLabel}` : unitName,
575
+ "aria-labelledby": surface === "field" && labelId ? `${segmentId} ${labelId}` : void 0,
576
+ "aria-readonly": readOnly ? "true" : void 0,
577
+ "aria-required": first && required ? "true" : void 0,
578
+ autocapitalize: "off",
579
+ autocorrect: "off",
580
+ "data-placeholder": flag(!editor.text(unit)),
581
+ "data-side": side,
582
+ "data-segment": unit,
583
+ "data-slot": "input-date-segment",
584
+ "data-surface": surface,
585
+ enterkeyhint: "next",
586
+ id: segmentId,
587
+ role: ios ? "textbox" : "spinbutton",
588
+ spellcheck: "false",
589
+ style: "caret-color:transparent",
590
+ tabindex: disabled ? void 0 : "0"
591
+ };
592
+ if (!ios) if (unit === "dayPeriod") record["aria-valuetext"] = filled ? editor.text(unit) : emptyLabel;
593
+ else {
594
+ record["aria-valuemin"] = bounds.min;
595
+ record["aria-valuemax"] = bounds.max;
596
+ if (filled) record["aria-valuenow"] = editor.units[unit];
597
+ record["aria-valuetext"] = valuetextOf(side, unit);
598
+ }
599
+ if (domReady && !disabled && !readOnly) {
600
+ record.contenteditable = "true";
601
+ if (unit !== "dayPeriod") record.inputmode = "numeric";
602
+ }
603
+ return record;
604
+ };
605
+ const segmentText = (side, segment, surface = "field") => {
606
+ const unit = segment.type;
607
+ if (composing && composing.side === side && composing.unit === unit && surfaceOf(composing.element) === surface) return composing.text;
608
+ return fields[side].text(unit) || segment.placeholder;
609
+ };
610
+ InputDateContext({
611
+ allowNonContiguous,
612
+ applyPreset,
613
+ calendarDisabled,
614
+ calendarUnavailable: availabilitySource,
615
+ clear: clearValue,
616
+ contentId: pop.contentId,
617
+ contentStyle: pop.contentStyle,
618
+ daySelected,
619
+ disabled,
620
+ field: (side) => fields[side],
621
+ groupAttrs,
622
+ hasValue: value != null,
623
+ kind,
624
+ locale,
625
+ message,
626
+ monthOf,
627
+ onMonthChange,
628
+ open: pop.open,
629
+ pickDay,
630
+ pickRange,
631
+ popup: popupPart,
632
+ presets,
633
+ range: isRange,
634
+ rangeSelected,
635
+ readOnly,
636
+ registerTimeSurface: (element) => timeSurfaces.add(element),
637
+ segmentAttrs,
638
+ segmentText,
639
+ setContent: pop.setContent,
640
+ setTrigger: pop.setTrigger,
641
+ timeSurface,
642
+ toggleOpen,
643
+ triggerId: pop.triggerId,
644
+ unregisterTimeSurface: (element) => timeSurfaces.delete(element)
645
+ });
646
+ yield /* @__PURE__ */ jsxs(Fragment, { children: [
647
+ args.name && !isRange ? /* @__PURE__ */ jsx("input", {
648
+ "data-slot": "input-date-hidden",
649
+ disabled,
650
+ name: args.name,
651
+ "set:value": fields.from.value() ?? "",
652
+ type: "hidden",
653
+ value: fields.from.value() ?? ""
654
+ }) : null,
655
+ args.name && isRange ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
656
+ "data-slot": "input-date-hidden",
657
+ disabled,
658
+ name: `${args.name}[from]`,
659
+ "set:value": fields.from.value() ?? "",
660
+ type: "hidden",
661
+ value: fields.from.value() ?? ""
662
+ }), /* @__PURE__ */ jsx("input", {
663
+ "data-slot": "input-date-hidden",
664
+ disabled,
665
+ name: `${args.name}[to]`,
666
+ "set:value": fields.to.value() ?? "",
667
+ type: "hidden",
668
+ value: fields.to.value() ?? ""
669
+ })] }) : null,
670
+ args.children ?? /* @__PURE__ */ jsxs(Fragment, { children: [isRange ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(InputDateField, { side: "from" }), /* @__PURE__ */ jsx(InputDateField, { side: "to" })] }) : /* @__PURE__ */ jsx(InputDateField, {}), args.calendar && kind !== "time" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(InputDateTrigger, {}), /* @__PURE__ */ jsxs(InputDateContent, { children: [
671
+ /* @__PURE__ */ jsx(InputDateCalendar, { ...typeof args.calendar === "object" ? args.calendar : {} }),
672
+ kind === "datetime" ? isRange ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(InputDateTimeField, { side: "from" }), /* @__PURE__ */ jsx(InputDateTimeField, { side: "to" })] }) : /* @__PURE__ */ jsx(InputDateTimeField, {}) : null,
673
+ presets.length ? /* @__PURE__ */ jsx(InputDatePresets, {}) : null
674
+ ] })] }) : null] }),
675
+ descriptionText ? /* @__PURE__ */ jsx("span", {
676
+ "data-slot": "input-date-description",
677
+ hidden: true,
678
+ id: descriptionId,
679
+ children: descriptionText
680
+ }) : null,
681
+ message ? /* @__PURE__ */ jsx("span", {
682
+ "data-slot": "input-date-message",
683
+ hidden: true,
684
+ id: messageId,
685
+ children: message
686
+ }) : null
687
+ ] });
688
+ }
689
+ };
690
+ /** Segment-based date field; the calendar popover is an optional part. */
691
+ var InputDate = ({ allowNonContiguous, calendar, children, class: classes, closeOnSelect, defaultOpen, defaultValue, disabled, emptyLabel, errorMessage, gap, locale, max, min, name, onOpenChange, onValueChange, open, placement, placeholderValue, presets, range, readOnly, required, unavailable, value, ...attrs }) => {
692
+ const fieldCtx = FieldContext();
693
+ return /* @__PURE__ */ jsx(InputDateRoot, {
694
+ ...statefulRootAttrs(attrs),
695
+ ...range ? {
696
+ "attr:role": "group",
697
+ "attr:aria-describedby": fieldCtx?.groupAttrs["aria-describedby"],
698
+ "attr:aria-labelledby": fieldCtx?.groupAttrs["aria-labelledby"]
699
+ } : {},
700
+ allowNonContiguous,
701
+ calendar,
702
+ closeOnSelect,
703
+ defaultOpen,
704
+ defaultValue,
705
+ disabled,
706
+ emptyLabel,
707
+ errorMessage,
708
+ gap,
709
+ kind: "date",
710
+ locale,
711
+ max,
712
+ min,
713
+ name,
714
+ onOpenChange,
715
+ onValueChange,
716
+ open,
717
+ placement,
718
+ placeholderValue,
719
+ presets,
720
+ range,
721
+ readOnly,
722
+ required,
723
+ unavailable,
724
+ value,
725
+ "attr:class": classes,
726
+ "attr:data-slot": "input-date",
727
+ children
728
+ });
729
+ };
730
+ /** Segment-based time field; canonical 24h values regardless of display cycle. */
731
+ var InputTime = ({ allowNonContiguous, children, class: classes, defaultValue, disabled, emptyLabel, errorMessage, granularity, hourCycle, locale, max, min, name, onValueChange, placeholderValue, range, readOnly, required, step, unavailable, value, ...attrs }) => {
732
+ const fieldCtx = FieldContext();
733
+ return /* @__PURE__ */ jsx(InputDateRoot, {
734
+ ...statefulRootAttrs(attrs),
735
+ ...range ? {
736
+ "attr:role": "group",
737
+ "attr:aria-describedby": fieldCtx?.groupAttrs["aria-describedby"],
738
+ "attr:aria-labelledby": fieldCtx?.groupAttrs["aria-labelledby"]
739
+ } : {},
740
+ allowNonContiguous,
741
+ defaultValue,
742
+ disabled,
743
+ emptyLabel,
744
+ errorMessage,
745
+ granularity,
746
+ hourCycle,
747
+ kind: "time",
748
+ locale,
749
+ max,
750
+ min,
751
+ name,
752
+ onValueChange,
753
+ placeholderValue,
754
+ range,
755
+ readOnly,
756
+ required,
757
+ step,
758
+ unavailable,
759
+ value,
760
+ "attr:class": classes,
761
+ "attr:data-slot": "input-time",
762
+ children
763
+ });
764
+ };
765
+ /** Segment-based date-time field; the calendar merges picked days with entered time. */
766
+ var InputDateTime = ({ allowNonContiguous, calendar, children, class: classes, closeOnSelect, defaultOpen, defaultValue, disabled, emptyLabel, errorMessage, gap, granularity, hourCycle, locale, max, min, name, onOpenChange, onValueChange, open, placement, placeholderValue, presets, range, readOnly, required, step, unavailable, value, ...attrs }) => {
767
+ const fieldCtx = FieldContext();
768
+ return /* @__PURE__ */ jsx(InputDateRoot, {
769
+ ...statefulRootAttrs(attrs),
770
+ ...range ? {
771
+ "attr:role": "group",
772
+ "attr:aria-describedby": fieldCtx?.groupAttrs["aria-describedby"],
773
+ "attr:aria-labelledby": fieldCtx?.groupAttrs["aria-labelledby"]
774
+ } : {},
775
+ allowNonContiguous,
776
+ calendar,
777
+ closeOnSelect,
778
+ defaultOpen,
779
+ defaultValue,
780
+ disabled,
781
+ emptyLabel,
782
+ errorMessage,
783
+ gap,
784
+ granularity,
785
+ hourCycle,
786
+ kind: "datetime",
787
+ locale,
788
+ max,
789
+ min,
790
+ name,
791
+ onOpenChange,
792
+ onValueChange,
793
+ open,
794
+ placement,
795
+ placeholderValue,
796
+ presets,
797
+ range,
798
+ readOnly,
799
+ required,
800
+ step,
801
+ unavailable,
802
+ value,
803
+ "attr:class": classes,
804
+ "attr:data-slot": "input-datetime",
805
+ children
806
+ });
807
+ };
808
+ /** Segmented group surface; renders the derived segments and literals closed. */
809
+ var InputDateField = ({ class: classes, label, literalClass, ref, segmentClass, side, ...attrs }) => {
810
+ const ctx = InputDateContext();
811
+ if (!ctx) throw new Error("InputDateField must be used within an InputDate family root.");
812
+ if (ctx.range && !side) console.warn("[input-date] <InputDateField side> is required in range mode.");
813
+ const current = ctx.range ? side ?? "from" : "from";
814
+ const editor = ctx.field(current);
815
+ return /* @__PURE__ */ jsx("div", {
816
+ ...attrs,
817
+ ...ctx.groupAttrs(current, label),
818
+ class: classes,
819
+ ref,
820
+ children: editor.segments.map((segment, index) => segment.editable ? /* @__PURE__ */ jsx("div", {
821
+ ...ctx.segmentAttrs(current, segment, label),
822
+ class: segmentClass,
823
+ children: ctx.segmentText(current, segment)
824
+ }, segment.type) : /* @__PURE__ */ jsx("div", {
825
+ "aria-hidden": "true",
826
+ class: literalClass,
827
+ "data-slot": "input-date-literal",
828
+ children: segment.text
829
+ }, `literal-${index}`))
830
+ });
831
+ };
832
+ /** Time run of the bound datetime field, rendered as a second popover surface. */
833
+ var InputDateTimeField = ({ class: classes, label, literalClass, ref, segmentClass, side, ...attrs }) => {
834
+ const ctx = InputDateContext();
835
+ if (!ctx || !ctx.timeSurface("InputDateTimeField")) return null;
836
+ if (ctx.range && !side) console.warn("[input-date] <InputDateTimeField side> is required in range mode.");
837
+ const current = ctx.range ? side ?? "from" : "from";
838
+ const resolvedLabel = label ?? (ctx.range ? current === "from" ? "Start time" : "End time" : "Time");
839
+ const editor = ctx.field(current);
840
+ let registered = null;
841
+ const reference = (element) => {
842
+ if (registered && registered !== element) ctx.unregisterTimeSurface(registered);
843
+ if (element && registered !== element) ctx.registerTimeSurface(element);
844
+ registered = element;
845
+ callRef(ref, element);
846
+ };
847
+ return /* @__PURE__ */ jsx("div", {
848
+ ...attrs,
849
+ ...ctx.groupAttrs(current, resolvedLabel, "popover"),
850
+ class: classes,
851
+ ref: reference,
852
+ children: timeRun(editor.segments).map((segment, index) => segment.editable ? /* @__PURE__ */ jsx("div", {
853
+ ...ctx.segmentAttrs(current, segment, resolvedLabel, "popover"),
854
+ class: segmentClass,
855
+ children: ctx.segmentText(current, segment, "popover")
856
+ }, segment.type) : /* @__PURE__ */ jsx("div", {
857
+ "aria-hidden": "true",
858
+ class: literalClass,
859
+ "data-slot": "input-date-time-literal",
860
+ children: segment.text
861
+ }, `literal-${index}`))
862
+ });
863
+ };
864
+ /** Optional calendar button; the popover still anchors to the field group. */
865
+ var InputDateTrigger = ({ children, class: classes, disabled, iconClass, id: idArg, ref, type = "button", "set:onclick": onClick, ...attrs }) => {
866
+ const ctx = InputDateContext();
867
+ if (ctx && !ctx.popup("InputDateTrigger")) return null;
868
+ const disabledFlag = Boolean(disabled ?? ctx?.disabled);
869
+ return /* @__PURE__ */ jsx("button", {
870
+ ...attrs,
871
+ ...triggerAttrs({
872
+ controls: ctx?.contentId,
873
+ expanded: Boolean(ctx?.open),
874
+ haspopup: "dialog",
875
+ id: idArg,
876
+ open: Boolean(ctx?.open),
877
+ ref,
878
+ setTrigger: ctx?.setTrigger,
879
+ triggerId: ctx?.triggerId
880
+ }),
881
+ "aria-label": attrs["aria-label"] ?? "Show calendar",
882
+ class: classes,
883
+ "data-slot": "input-date-trigger",
884
+ disabled: disabledFlag,
885
+ "set:onclick": (event) => {
886
+ callHandler(onClick, event);
887
+ if (event.defaultPrevented) return;
888
+ ctx?.toggleOpen(event);
889
+ },
890
+ type,
891
+ children: children ?? /* @__PURE__ */ jsx("span", {
892
+ "aria-hidden": "true",
893
+ class: iconClass,
894
+ "data-slot": "input-date-trigger-icon"
895
+ })
896
+ });
897
+ };
898
+ /** Popover panel for the calendar; a dialog anchored to the field group. */
899
+ var InputDateContent = ({ children, class: classes, ref, style, ...attrs }) => {
900
+ const ctx = InputDateContext();
901
+ if (ctx && !ctx.popup("InputDateContent")) return null;
902
+ return /* @__PURE__ */ jsx("div", {
903
+ ...attrs,
904
+ ...contentAttrs({
905
+ id: ctx?.contentId,
906
+ open: Boolean(ctx?.open),
907
+ ref,
908
+ setContent: ctx?.setContent,
909
+ style: ctx?.contentStyle(style),
910
+ tabindex: "-1"
911
+ }),
912
+ "aria-label": attrs["aria-label"] ?? "Calendar",
913
+ class: classes,
914
+ "data-slot": "input-date-content",
915
+ role: "dialog",
916
+ children
917
+ });
918
+ };
919
+ /** Calendar wired to the field: picked days fill the date units and commit. */
920
+ var InputDateCalendar = ({ component, ...attrs }) => {
921
+ const ctx = InputDateContext();
922
+ const CurrentCalendar = component ?? Calendar;
923
+ if (!ctx) return /* @__PURE__ */ jsx(CurrentCalendar, { ...attrs });
924
+ if (!ctx.popup("InputDateCalendar")) return null;
925
+ const common = {
926
+ ...attrs,
927
+ allowNonContiguous: ctx.allowNonContiguous,
928
+ disabled: ctx.calendarDisabled(attrs.disabled),
929
+ locale: attrs.locale ?? ctx.locale,
930
+ month: attrs.month ?? ctx.monthOf(),
931
+ onMonthChange: (month, event) => {
932
+ attrs.onMonthChange?.(month, event);
933
+ ctx.onMonthChange(month, event);
934
+ },
935
+ unavailable: ctx.calendarUnavailable
936
+ };
937
+ if (ctx.range) return /* @__PURE__ */ jsx(CurrentCalendar, {
938
+ ...common,
939
+ mode: "range",
940
+ selected: ctx.rangeSelected(),
941
+ onSelect: (next, event) => ctx.pickRange(next, event)
942
+ });
943
+ return /* @__PURE__ */ jsx(CurrentCalendar, {
944
+ ...common,
945
+ mode: "single",
946
+ selected: ctx.daySelected(),
947
+ onSelect: (next, event) => ctx.pickDay(next, event)
948
+ });
949
+ };
950
+ /** Clear button; renders only while a value exists and emits null. */
951
+ var InputDateClear = ({ children, class: classes, disabled, iconClass, type = "button", "set:onclick": onClick, ...attrs }) => {
952
+ const ctx = InputDateContext();
953
+ if (ctx && !ctx.hasValue) return null;
954
+ const disabledFlag = Boolean(disabled ?? ctx?.disabled);
955
+ return /* @__PURE__ */ jsx("button", {
956
+ ...attrs,
957
+ "aria-label": attrs["aria-label"] ?? "Clear",
958
+ class: classes,
959
+ "data-slot": "input-date-clear",
960
+ disabled: disabledFlag,
961
+ "set:onclick": (event) => {
962
+ callHandler(onClick, event);
963
+ if (event.defaultPrevented) return;
964
+ ctx?.clear(event);
965
+ },
966
+ type,
967
+ children: children ?? /* @__PURE__ */ jsx("span", {
968
+ "aria-hidden": "true",
969
+ class: iconClass,
970
+ "data-slot": "input-date-clear-icon"
971
+ })
972
+ });
973
+ };
974
+ /** Preset value buttons for the popover; a pick commits and closes. */
975
+ var InputDatePresets = ({ buttonClass, children, class: classes, ...attrs }) => {
976
+ const ctx = InputDateContext();
977
+ if (!ctx || !ctx.popup("InputDatePresets")) return null;
978
+ if (!children && !ctx.presets.length) return null;
979
+ return /* @__PURE__ */ jsx("div", {
980
+ ...attrs,
981
+ class: classes,
982
+ "data-slot": "input-date-presets",
983
+ children: children ?? ctx.presets.map((preset) => /* @__PURE__ */ jsx("button", {
984
+ class: buttonClass,
985
+ "data-slot": "input-date-preset",
986
+ disabled: ctx.disabled,
987
+ "set:onclick": (event) => ctx.applyPreset(preset.value, event),
988
+ type: "button",
989
+ children: preset.label
990
+ }, preset.label))
991
+ });
992
+ };
993
+ //#endregion
994
+ export { InputDate, InputDateCalendar, InputDateClear, InputDateContent, InputDateField, InputDatePresets, InputDateTime, InputDateTimeField, InputDateTrigger, InputTime };