@k2b/ui 0.44.0 → 0.45.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 (123) hide show
  1. package/dist/browser/actions/Tabs.js +3 -4
  2. package/dist/browser/actions/Tabs.js.map +1 -1
  3. package/dist/browser/actions/menu-sheet.js +2 -3
  4. package/dist/browser/actions/menu-sheet.js.map +1 -1
  5. package/dist/browser/actions/phone-sheet.js +4 -0
  6. package/dist/browser/actions/phone-sheet.js.map +1 -0
  7. package/dist/browser/content/DataTable.js +47 -51
  8. package/dist/browser/content/DataTable.js.map +1 -1
  9. package/dist/browser/feedback/dialog-core.js +5 -1
  10. package/dist/browser/feedback/dialog-core.js.map +1 -1
  11. package/dist/browser/feedback/dialog-tone.js +26 -0
  12. package/dist/browser/feedback/dialog-tone.js.map +1 -0
  13. package/dist/browser/feedback/index.js.map +1 -1
  14. package/dist/browser/feedback/prompt-confirm.js +223 -0
  15. package/dist/browser/feedback/prompt-confirm.js.map +1 -0
  16. package/dist/browser/feedback/prompts.js +195 -343
  17. package/dist/browser/feedback/prompts.js.map +1 -1
  18. package/dist/browser/inputs/ChoiceList.js +45 -17
  19. package/dist/browser/inputs/ChoiceList.js.map +1 -1
  20. package/dist/browser/inputs/DatePicker.js +1647 -334
  21. package/dist/browser/inputs/DatePicker.js.map +1 -1
  22. package/dist/browser/inputs/TextInput.js +5 -4
  23. package/dist/browser/inputs/TextInput.js.map +1 -1
  24. package/dist/browser/inputs/date-input-messages.js +128 -0
  25. package/dist/browser/inputs/date-input-messages.js.map +1 -0
  26. package/dist/browser/inputs/date-input-status.js +132 -0
  27. package/dist/browser/inputs/date-input-status.js.map +1 -0
  28. package/dist/browser/inputs/date-input.js +334 -0
  29. package/dist/browser/inputs/date-input.js.map +1 -0
  30. package/dist/browser/inputs/date-sheet.js +49 -0
  31. package/dist/browser/inputs/date-sheet.js.map +1 -0
  32. package/dist/browser/internal/reveal-in-scroller.js +28 -0
  33. package/dist/browser/internal/reveal-in-scroller.js.map +1 -0
  34. package/dist/browser/intl/messages.js +6 -0
  35. package/dist/browser/intl/messages.js.map +1 -1
  36. package/dist/browser/layout/AppWorkspace.js +536 -512
  37. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  38. package/dist/browser/layout/BottomSheet.js +3 -0
  39. package/dist/browser/layout/BottomSheet.js.map +1 -1
  40. package/dist/browser/layout/PanelDialog.js +167 -132
  41. package/dist/browser/layout/PanelDialog.js.map +1 -1
  42. package/dist/browser/layout/Settings.js +175 -139
  43. package/dist/browser/layout/Settings.js.map +1 -1
  44. package/dist/browser/layout/SettingsModal.js +2 -4
  45. package/dist/browser/layout/SettingsModal.js.map +1 -1
  46. package/dist/browser/layout/index.js.map +1 -1
  47. package/dist/browser/surfaces/StatusBadge.js +47 -14
  48. package/dist/browser/surfaces/StatusBadge.js.map +1 -1
  49. package/dist/browser/text-editor/TextEditor.js +7 -0
  50. package/dist/browser/text-editor/TextEditor.js.map +1 -1
  51. package/dist/ssr/actions/Tabs.js +3 -4
  52. package/dist/ssr/actions/Tabs.js.map +1 -1
  53. package/dist/ssr/actions/menu-sheet.js +2 -3
  54. package/dist/ssr/actions/menu-sheet.js.map +1 -1
  55. package/dist/ssr/actions/phone-sheet.js +4 -0
  56. package/dist/ssr/actions/phone-sheet.js.map +1 -0
  57. package/dist/ssr/content/DataTable.js +1 -2
  58. package/dist/ssr/content/DataTable.js.map +1 -1
  59. package/dist/ssr/feedback/dialog-core.js +5 -1
  60. package/dist/ssr/feedback/dialog-core.js.map +1 -1
  61. package/dist/ssr/feedback/dialog-tone.js +26 -0
  62. package/dist/ssr/feedback/dialog-tone.js.map +1 -0
  63. package/dist/ssr/feedback/index.js.map +1 -1
  64. package/dist/ssr/feedback/prompt-confirm.js +123 -0
  65. package/dist/ssr/feedback/prompt-confirm.js.map +1 -0
  66. package/dist/ssr/feedback/prompts.js +60 -132
  67. package/dist/ssr/feedback/prompts.js.map +1 -1
  68. package/dist/ssr/inputs/ChoiceList.js +29 -9
  69. package/dist/ssr/inputs/ChoiceList.js.map +1 -1
  70. package/dist/ssr/inputs/DatePicker.js +1183 -166
  71. package/dist/ssr/inputs/DatePicker.js.map +1 -1
  72. package/dist/ssr/inputs/TextInput.js +5 -4
  73. package/dist/ssr/inputs/TextInput.js.map +1 -1
  74. package/dist/ssr/inputs/date-input-messages.js +128 -0
  75. package/dist/ssr/inputs/date-input-messages.js.map +1 -0
  76. package/dist/ssr/inputs/date-input-status.js +132 -0
  77. package/dist/ssr/inputs/date-input-status.js.map +1 -0
  78. package/dist/ssr/inputs/date-input.js +334 -0
  79. package/dist/ssr/inputs/date-input.js.map +1 -0
  80. package/dist/ssr/inputs/date-sheet.js +44 -0
  81. package/dist/ssr/inputs/date-sheet.js.map +1 -0
  82. package/dist/ssr/internal/reveal-in-scroller.js +28 -0
  83. package/dist/ssr/internal/reveal-in-scroller.js.map +1 -0
  84. package/dist/ssr/intl/messages.js +6 -0
  85. package/dist/ssr/intl/messages.js.map +1 -1
  86. package/dist/ssr/layout/AppWorkspace.js +44 -23
  87. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  88. package/dist/ssr/layout/BottomSheet.js +3 -0
  89. package/dist/ssr/layout/BottomSheet.js.map +1 -1
  90. package/dist/ssr/layout/PanelDialog.js +48 -30
  91. package/dist/ssr/layout/PanelDialog.js.map +1 -1
  92. package/dist/ssr/layout/Settings.js +34 -18
  93. package/dist/ssr/layout/Settings.js.map +1 -1
  94. package/dist/ssr/layout/SettingsModal.js +2 -4
  95. package/dist/ssr/layout/SettingsModal.js.map +1 -1
  96. package/dist/ssr/layout/index.js.map +1 -1
  97. package/dist/ssr/surfaces/StatusBadge.js +26 -8
  98. package/dist/ssr/surfaces/StatusBadge.js.map +1 -1
  99. package/dist/ssr/text-editor/TextEditor.js +7 -0
  100. package/dist/ssr/text-editor/TextEditor.js.map +1 -1
  101. package/dist/styles.css +1 -1
  102. package/dist/types/actions/menu-sheet.d.ts +1 -3
  103. package/dist/types/actions/phone-sheet.d.ts +3 -0
  104. package/dist/types/feedback/dialog-tone.d.ts +10 -0
  105. package/dist/types/feedback/index.d.ts +1 -0
  106. package/dist/types/feedback/prompt-confirm.d.ts +19 -0
  107. package/dist/types/feedback/prompts.d.ts +4 -8
  108. package/dist/types/inputs/ChoiceList.d.ts +7 -3
  109. package/dist/types/inputs/DatePicker.d.ts +13 -3
  110. package/dist/types/inputs/TextInput.d.ts +1 -1
  111. package/dist/types/inputs/date-input-messages.d.ts +64 -0
  112. package/dist/types/inputs/date-input-status.d.ts +35 -0
  113. package/dist/types/inputs/date-input.d.ts +90 -0
  114. package/dist/types/inputs/date-sheet.d.ts +14 -0
  115. package/dist/types/internal/reveal-in-scroller.d.ts +6 -0
  116. package/dist/types/intl/messages.d.ts +3 -0
  117. package/dist/types/layout/AppWorkspace.d.ts +14 -0
  118. package/dist/types/layout/BottomSheet.d.ts +3 -0
  119. package/dist/types/layout/PanelDialog.d.ts +3 -0
  120. package/dist/types/layout/Settings.d.ts +17 -1
  121. package/dist/types/layout/index.d.ts +1 -1
  122. package/dist/types/surfaces/StatusBadge.d.ts +5 -0
  123. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import { template as _$template } from "solid-js/web";
2
2
  import { delegateEvents as _$delegateEvents } from "solid-js/web";
3
- import { setProperty as _$setProperty } from "solid-js/web";
4
3
  import { setStyleProperty as _$setStyleProperty } from "solid-js/web";
4
+ import { setProperty as _$setProperty } from "solid-js/web";
5
5
  import { className as _$className } from "solid-js/web";
6
6
  import { getNextMarker as _$getNextMarker } from "solid-js/web";
7
7
  import { setAttribute as _$setAttribute } from "solid-js/web";
@@ -23,30 +23,42 @@ var _tmpl$ = /*#__PURE__*/_$template(`<button type=button class="k2b-date-trigge
23
23
  _tmpl$7 = /*#__PURE__*/_$template(`<button type=button>`),
24
24
  _tmpl$8 = /*#__PURE__*/_$template(`<div class=k2b-date-weekdays aria-hidden=true><!$><!/><!$><!/>`),
25
25
  _tmpl$9 = /*#__PURE__*/_$template(`<div class=k2b-date-grid role=grid><!$><!/><!$><!/>`),
26
- _tmpl$0 = /*#__PURE__*/_$template(`<section class=k2b-date-calendar><header class=k2b-date-calendar__header><button type=button class=k2b-date-calendar__nav><i class="ti ti-chevron-left"aria-hidden=true></i></button><button type=button class=k2b-date-calendar__title></button><button type=button class=k2b-date-calendar__nav><i class="ti ti-chevron-right"aria-hidden=true></i></button></header><!$><!/>`),
27
- _tmpl$1 = /*#__PURE__*/_$template(`<div class=k2b-date-months role=group>`),
28
- _tmpl$10 = /*#__PURE__*/_$template(`<span class=k2b-date-weekend>`),
29
- _tmpl$11 = /*#__PURE__*/_$template(`<span>`),
30
- _tmpl$12 = /*#__PURE__*/_$template(`<span class=k2b-date-weekend aria-hidden=true>`),
31
- _tmpl$13 = /*#__PURE__*/_$template(`<div class=k2b-date-week role=row>`),
32
- _tmpl$14 = /*#__PURE__*/_$template(`<button type=button role=gridcell>`),
33
- _tmpl$15 = /*#__PURE__*/_$template(`<label class=k2b-date-time><!$><!/><span class=k2b-date-time__control><input type=text inputmode=numeric placeholder=09:00><i class="ti ti-clock"aria-hidden=true>`),
34
- _tmpl$16 = /*#__PURE__*/_$template(`<div class=k2b-date-popover__body><!$><!/><!$><!/>`),
35
- _tmpl$17 = /*#__PURE__*/_$template(`<button type=button class=k2b-date-optional-time__remove><i class="ti ti-x"aria-hidden=true>`),
36
- _tmpl$18 = /*#__PURE__*/_$template(`<div class=k2b-date-optional-time>`),
37
- _tmpl$19 = /*#__PURE__*/_$template(`<div class=k2b-date-actions><!$><!/><button type=button class=k2b-date-apply>`),
38
- _tmpl$20 = /*#__PURE__*/_$template(`<button type=button class=k2b-date-optional-time__add><i class="ti ti-clock-plus"aria-hidden=true></i><!$><!/>`),
39
- _tmpl$21 = /*#__PURE__*/_$template(`<span class=k2b-date-range-value><span></span><i class="ti ti-arrow-narrow-right"aria-hidden=true></i><span>`),
40
- _tmpl$22 = /*#__PURE__*/_$template(`<span class=k2b-date-duration><i class="ti ti-hourglass-low"aria-hidden=true></i><!$><!/>`),
41
- _tmpl$23 = /*#__PURE__*/_$template(`<div class=k2b-date-range-times><!$><!/><!$><!/>`),
42
- _tmpl$24 = /*#__PURE__*/_$template(`<div class=k2b-date-durations role=group>`);
26
+ _tmpl$0 = /*#__PURE__*/_$template(`<footer class=k2b-date-calendar__limits><span></span><span>`),
27
+ _tmpl$1 = /*#__PURE__*/_$template(`<section class=k2b-date-calendar><header class=k2b-date-calendar__header><button type=button class=k2b-date-calendar__nav><i class="ti ti-chevron-left"aria-hidden=true></i></button><button type=button class=k2b-date-calendar__title></button><button type=button class=k2b-date-calendar__nav><i class="ti ti-chevron-right"aria-hidden=true></i></button></header><!$><!/><!$><!/>`),
28
+ _tmpl$10 = /*#__PURE__*/_$template(`<div class=k2b-date-months role=group>`),
29
+ _tmpl$11 = /*#__PURE__*/_$template(`<span class=k2b-date-weekend>`),
30
+ _tmpl$12 = /*#__PURE__*/_$template(`<span>`),
31
+ _tmpl$13 = /*#__PURE__*/_$template(`<span class=k2b-date-weekend aria-hidden=true>`),
32
+ _tmpl$14 = /*#__PURE__*/_$template(`<div class=k2b-date-week role=row>`),
33
+ _tmpl$15 = /*#__PURE__*/_$template(`<button type=button role=gridcell>`),
34
+ _tmpl$16 = /*#__PURE__*/_$template(`<label class=k2b-date-time><!$><!/><span class=k2b-date-time__control><input type=text inputmode=numeric placeholder=09:00><i class="ti ti-clock"aria-hidden=true>`),
35
+ _tmpl$17 = /*#__PURE__*/_$template(`<p class=k2b-date-status>`),
36
+ _tmpl$18 = /*#__PURE__*/_$template(`<span class=k2b-sr-only aria-live=polite>`),
37
+ _tmpl$19 = /*#__PURE__*/_$template(`<button type=button class="k2b-input-shell__clear k2b-input-clear-action k2b-date-field__clear"><i class="ti ti-x"aria-hidden=true>`),
38
+ _tmpl$20 = /*#__PURE__*/_$template(`<button type=button class=k2b-date-field__toggle tabindex=-1><i class="ti ti-chevron-down"aria-hidden=true>`),
39
+ _tmpl$21 = /*#__PURE__*/_$template(`<div class=k2b-date-popover__body><!$><!/><!$><!/>`),
40
+ _tmpl$22 = /*#__PURE__*/_$template(`<div class="k2b-date-picker k2b-date-field"><div class=k2b-input-shell><span class="k2b-input-shell__icon k2b-date-field__icon"aria-hidden=true><i class="ti ti-calendar"></i></span><input><!$><!/><!$><!/><div class=k2b-date-popover popover=manual role=dialog></div></div><!$><!/>`),
41
+ _tmpl$23 = /*#__PURE__*/_$template(`<span class=k2b-date-field__lock aria-hidden=true><i class="ti ti-lock">`),
42
+ _tmpl$24 = /*#__PURE__*/_$template(`<div class=k2b-date-actions><!$><!/><button type=button class=k2b-date-apply>`),
43
+ _tmpl$25 = /*#__PURE__*/_$template(`<span class=k2b-date-duration><i class="ti ti-hourglass-low"aria-hidden=true></i><!$><!/>`),
44
+ _tmpl$26 = /*#__PURE__*/_$template(`<div class="k2b-date-picker k2b-date-field"data-range=true><div class=k2b-input-shell role=group><span class="k2b-input-shell__icon k2b-date-field__icon"aria-hidden=true><i class="ti ti-calendar-stats"></i></span><input><i class="ti ti-arrow-narrow-right k2b-date-field__arrow"aria-hidden=true></i><input><span class=k2b-date-field__spacer></span><!$><!/><!$><!/><div class=k2b-date-popover popover=manual role=dialog></div></div><!$><!/>`),
45
+ _tmpl$27 = /*#__PURE__*/_$template(`<button type=button class=k2b-date-optional-time__remove><i class="ti ti-x"aria-hidden=true>`),
46
+ _tmpl$28 = /*#__PURE__*/_$template(`<div class=k2b-date-optional-time>`),
47
+ _tmpl$29 = /*#__PURE__*/_$template(`<button type=button class=k2b-date-optional-time__add><i class="ti ti-clock-plus"aria-hidden=true></i><!$><!/>`),
48
+ _tmpl$30 = /*#__PURE__*/_$template(`<span class=k2b-date-range-value><span></span><i class="ti ti-arrow-narrow-right"aria-hidden=true></i><span>`),
49
+ _tmpl$31 = /*#__PURE__*/_$template(`<div class=k2b-date-range-times><!$><!/><!$><!/>`),
50
+ _tmpl$32 = /*#__PURE__*/_$template(`<div class=k2b-date-durations role=group>`);
43
51
  import { dates } from "@k2b/stdlib";
44
- import { createEffect, createMemo, createSignal, For, onCleanup, onMount, Show } from "solid-js";
52
+ import { batch, createEffect, createMemo, createSignal, For, on, onCleanup, onMount, Show } from "solid-js";
53
+ import { prefersMenuSheet } from "../actions/phone-sheet";
45
54
  import { createFieldMeta, Field, fieldControlAria, fieldDescribedBy } from "../internal/field";
46
55
  import { returnFocus, ringOnReturn } from "../internal/focus-return";
47
56
  import { useDateConfigLocale } from "../intl/locale";
48
57
  import { resolveUiMessages, useUiMessages } from "../intl/messages";
49
58
  import { isWeekendKey } from "../intl/weekend";
59
+ import { dateInputPattern, formatDateInput, parseDateInput } from "./date-input";
60
+ import { resolveDateInputMessages } from "./date-input-messages";
61
+ import { draftStatusText, errorText, formatDateLong, limitErrorText, rangeStatusText, restStatusText, spokenDateText, typingStatusText } from "./date-input-status";
50
62
  import { dateKey, displayDate, filterTimeInput, formatDateOnlyRangeDuration, formatDateTimeValue, inRange, isCompleteTime, isDateKey, isRangeEdge, monthDate, monthNames, msUntilNextDay, normalizeTimeInput, parseDateValue, pickerContext, pickRangeDay, previewRange, rangeAnchor, resolveFocusDay, splitDateTime, toDateTimeValue, weekendBands, yearMonth } from "./date-picker";
51
63
  import { commitFieldValue, resolveMaybeAccessor } from "./field-contract";
52
64
  const popoverIsOpen = popover => {
@@ -57,10 +69,18 @@ const popoverIsOpen = popover => {
57
69
  return false;
58
70
  }
59
71
  };
60
- export const placeDatePopover = (trigger, popover, wide) => {
72
+
73
+ /** `below` is a line under the trigger that the panel must not cover, such as a typed field's status line. */
74
+ export const placeDatePopover = (trigger, popover, wide, below) => {
61
75
  const margin = 8;
62
76
  const gap = 4;
63
- const rect = trigger.getBoundingClientRect();
77
+ const triggerRect = trigger.getBoundingClientRect();
78
+ const belowRect = below?.getBoundingClientRect();
79
+ const rect = {
80
+ left: triggerRect.left,
81
+ top: triggerRect.top,
82
+ bottom: Math.max(triggerRect.bottom, belowRect?.height ? belowRect.bottom : 0)
83
+ };
64
84
  // Keep the panel at its designed width instead of stretching to a full-width
65
85
  // trigger; it only ever shrinks to fit a narrow viewport.
66
86
  const preferredWidth = wide ? 440 : 336;
@@ -331,7 +351,19 @@ function DatePickerPanel(props) {
331
351
  const [view, setView] = createSignal("days");
332
352
  const context = createMemo(() => pickerContext(props.dateConfig));
333
353
  const month = createMemo(() => yearMonth(props.visibleMonth(), context()));
334
- const weeks = createMemo(() => dates.getMonthGrid(month().year, month().month, context()));
354
+ // Always six weeks: typing moves an open calendar between months, and a month with fewer weeks would resize it.
355
+ const weeks = createMemo(() => {
356
+ const grid = [...dates.getMonthGrid(month().year, month().month, context())];
357
+ while (grid.length < 6) {
358
+ const last = grid[grid.length - 1].at(-1);
359
+ grid.push(Array.from({
360
+ length: 7
361
+ }, (_, index) => dates.addDays(last, index + 1, context())));
362
+ }
363
+ return grid;
364
+ });
365
+ const blocked = key => Boolean(props.min && key < props.min || props.max && key > props.max);
366
+ const inputMessages = createMemo(() => resolveDateInputMessages(context().locale));
335
367
  const weekdays = createMemo(() => dates.weekdays(context()));
336
368
  const months = createMemo(() => monthNames(context()));
337
369
  const dayNameFormatter = createMemo(() => new Intl.DateTimeFormat(context().locale, {
@@ -388,7 +420,7 @@ function DatePickerPanel(props) {
388
420
  let calendar;
389
421
  // Days that belong to the visible month; the roving tabindex must land on one
390
422
  // of them or the grid becomes unreachable by keyboard after month navigation.
391
- const monthDayKeys = createMemo(() => dayRows().flat().filter(day => !day.outside).map(day => day.key));
423
+ const monthDayKeys = createMemo(() => dayRows().flat().filter(day => !day.outside && !blocked(day.key)).map(day => day.key));
392
424
  // Remembers where arrow-key navigation left off so Tab returns to that day.
393
425
  const [focusedKey, setFocusedKey] = createSignal();
394
426
  const defaultFocus = createMemo(() => resolveFocusDay(monthDayKeys(), focusedKey() || props.focusDate?.() || props.selected?.() || todayKey()));
@@ -396,8 +428,18 @@ function DatePickerPanel(props) {
396
428
  const moveYear = delta => props.setVisibleMonth(monthDate(month().year + delta, month().month, context()));
397
429
  const previousLabel = () => view() === "days" ? messages().previousMonth : messages().previousYear;
398
430
  const nextLabel = () => view() === "days" ? messages().nextMonth : messages().nextYear;
431
+ // A step whose whole month (or year) lies outside min/max is not offered.
432
+ const stepBlocked = delta => {
433
+ if (view() === "days") {
434
+ const target = dateKey(dates.addMonths(props.visibleMonth(), delta, context()), context()).slice(0, 7);
435
+ return Boolean(props.min && target < props.min.slice(0, 7) || props.max && target > props.max.slice(0, 7));
436
+ }
437
+ const year = String(month().year + delta);
438
+ return Boolean(props.min && year < props.min.slice(0, 4) || props.max && year > props.max.slice(0, 4));
439
+ };
399
440
  const focusDate = date => {
400
441
  const targetKey = dateKey(date, context());
442
+ if (blocked(targetKey)) return;
401
443
  if (!dates.isSameMonth(date, props.visibleMonth(), context())) props.setVisibleMonth(date);
402
444
  queueMicrotask(() => calendar?.querySelector(`[data-date-day="${targetKey}"]`)?.focus());
403
445
  };
@@ -428,13 +470,15 @@ function DatePickerPanel(props) {
428
470
  }
429
471
  };
430
472
  return (() => {
431
- var _el$27 = _$getNextElement(_tmpl$0),
473
+ var _el$27 = _$getNextElement(_tmpl$1),
432
474
  _el$28 = _el$27.firstChild,
433
475
  _el$29 = _el$28.firstChild,
434
476
  _el$30 = _el$29.nextSibling,
435
477
  _el$31 = _el$30.nextSibling,
436
- _el$42 = _el$28.nextSibling,
437
- [_el$43, _co$10] = _$getNextMarker(_el$42.nextSibling);
478
+ _el$45 = _el$28.nextSibling,
479
+ [_el$46, _co$10] = _$getNextMarker(_el$45.nextSibling),
480
+ _el$47 = _el$46.nextSibling,
481
+ [_el$48, _co$11] = _$getNextMarker(_el$47.nextSibling);
438
482
  var _ref$3 = calendar;
439
483
  typeof _ref$3 === "function" ? _$use(_ref$3, _el$27) : calendar = _el$27;
440
484
  _el$29.$$click = () => view() === "days" ? moveMonth(-1) : moveYear(-1);
@@ -457,34 +501,34 @@ function DatePickerPanel(props) {
457
501
  },
458
502
  get fallback() {
459
503
  return (() => {
460
- var _el$44 = _$getNextElement(_tmpl$1);
461
- _$insert(_el$44, _$createComponent(For, {
504
+ var _el$49 = _$getNextElement(_tmpl$10);
505
+ _$insert(_el$49, _$createComponent(For, {
462
506
  get each() {
463
507
  return months();
464
508
  },
465
509
  children: (name, index) => (() => {
466
- var _el$45 = _$getNextElement(_tmpl$7);
467
- _el$45.$$click = () => {
510
+ var _el$50 = _$getNextElement(_tmpl$7);
511
+ _el$50.$$click = () => {
468
512
  props.setVisibleMonth(monthDate(month().year, index(), context()));
469
513
  setView("days");
470
514
  };
471
- _$insert(_el$45, name);
515
+ _$insert(_el$50, name);
472
516
  _$effect(_p$ => {
473
- var _v$0 = index() === month().month,
474
- _v$1 = index() === month().month ? "true" : undefined;
475
- _v$0 !== _p$.e && _$setAttribute(_el$45, "aria-pressed", _p$.e = _v$0);
476
- _v$1 !== _p$.t && _$setAttribute(_el$45, "data-selected", _p$.t = _v$1);
517
+ var _v$10 = index() === month().month,
518
+ _v$11 = index() === month().month ? "true" : undefined;
519
+ _v$10 !== _p$.e && _$setAttribute(_el$50, "aria-pressed", _p$.e = _v$10);
520
+ _v$11 !== _p$.t && _$setAttribute(_el$50, "data-selected", _p$.t = _v$11);
477
521
  return _p$;
478
522
  }, {
479
523
  e: undefined,
480
524
  t: undefined
481
525
  });
482
526
  _$runHydrationEvents();
483
- return _el$45;
527
+ return _el$50;
484
528
  })()
485
529
  }));
486
- _$effect(() => _$setAttribute(_el$44, "aria-label", `Months in ${month().year}`));
487
- return _el$44;
530
+ _$effect(() => _$setAttribute(_el$49, "aria-label", `Months in ${month().year}`));
531
+ return _el$49;
488
532
  })();
489
533
  },
490
534
  get children() {
@@ -499,9 +543,9 @@ function DatePickerPanel(props) {
499
543
  return bands();
500
544
  },
501
545
  children: band => (() => {
502
- var _el$46 = _$getNextElement(_tmpl$10);
503
- _$effect(_$p => _$setStyleProperty(_el$46, "grid-column", `${band.start + 1} / span ${band.span}`));
504
- return _el$46;
546
+ var _el$51 = _$getNextElement(_tmpl$11);
547
+ _$effect(_$p => _$setStyleProperty(_el$51, "grid-column", `${band.start + 1} / span ${band.span}`));
548
+ return _el$51;
505
549
  })()
506
550
  }), _el$34, _co$8);
507
551
  _$insert(_el$32, _$createComponent(For, {
@@ -509,10 +553,10 @@ function DatePickerPanel(props) {
509
553
  return weekdays();
510
554
  },
511
555
  children: (day, index) => (() => {
512
- var _el$47 = _$getNextElement(_tmpl$11);
513
- _$insert(_el$47, day);
514
- _$effect(() => _$setAttribute(_el$47, "data-weekend", weekendColumns()[index()] ? "true" : undefined));
515
- return _el$47;
556
+ var _el$52 = _$getNextElement(_tmpl$12);
557
+ _$insert(_el$52, day);
558
+ _$effect(() => _$setAttribute(_el$52, "data-weekend", weekendColumns()[index()] ? "true" : undefined));
559
+ return _el$52;
516
560
  })()
517
561
  }), _el$36, _co$9);
518
562
  return _el$32;
@@ -527,18 +571,18 @@ function DatePickerPanel(props) {
527
571
  return bands();
528
572
  },
529
573
  children: band => (() => {
530
- var _el$48 = _$getNextElement(_tmpl$12);
574
+ var _el$53 = _$getNextElement(_tmpl$13);
531
575
  _$effect(_p$ => {
532
- var _v$10 = `${band.start + 1} / span ${band.span}`,
533
- _v$11 = `1 / span ${dayRows().length}`;
534
- _v$10 !== _p$.e && _$setStyleProperty(_el$48, "grid-column", _p$.e = _v$10);
535
- _v$11 !== _p$.t && _$setStyleProperty(_el$48, "grid-row", _p$.t = _v$11);
576
+ var _v$12 = `${band.start + 1} / span ${band.span}`,
577
+ _v$13 = `1 / span ${dayRows().length}`;
578
+ _v$12 !== _p$.e && _$setStyleProperty(_el$53, "grid-column", _p$.e = _v$12);
579
+ _v$13 !== _p$.t && _$setStyleProperty(_el$53, "grid-row", _p$.t = _v$13);
536
580
  return _p$;
537
581
  }, {
538
582
  e: undefined,
539
583
  t: undefined
540
584
  });
541
- return _el$48;
585
+ return _el$53;
542
586
  })()
543
587
  }), _el$39, _co$0);
544
588
  _$insert(_el$37, _$createComponent(For, {
@@ -546,8 +590,8 @@ function DatePickerPanel(props) {
546
590
  return dayRows();
547
591
  },
548
592
  children: week => (() => {
549
- var _el$49 = _$getNextElement(_tmpl$13);
550
- _$insert(_el$49, _$createComponent(For, {
593
+ var _el$54 = _$getNextElement(_tmpl$14);
594
+ _$insert(_el$54, _$createComponent(For, {
551
595
  each: week,
552
596
  children: (cell, cellIndex) => {
553
597
  const selected = () => props.selected?.() === cell.key;
@@ -558,39 +602,47 @@ function DatePickerPanel(props) {
558
602
  const active = () => selected() || isRangeEdge(cell.key, range());
559
603
  const focusable = () => cell.key === defaultFocus();
560
604
  const today = () => cell.key === todayKey();
605
+ const label = () => {
606
+ const name = today() ? todayLabel(cell.label) : cell.label;
607
+ return blocked(cell.key) ? inputMessages().notSelectable({
608
+ date: name
609
+ }) : name;
610
+ };
561
611
  return (() => {
562
- var _el$50 = _$getNextElement(_tmpl$14);
563
- _el$50.addEventListener("pointerleave", () => props.onDayPreview?.(null));
564
- _el$50.addEventListener("pointerenter", () => props.onDayPreview?.(cell.key));
565
- _el$50.addEventListener("focus", () => {
612
+ var _el$55 = _$getNextElement(_tmpl$15);
613
+ _el$55.addEventListener("pointerleave", () => props.onDayPreview?.(null));
614
+ _el$55.addEventListener("pointerenter", () => props.onDayPreview?.(cell.key));
615
+ _el$55.addEventListener("focus", () => {
566
616
  setFocusedKey(cell.key);
567
617
  props.onDayPreview?.(cell.key);
568
618
  });
569
- _el$50.addEventListener("blur", () => props.onDayPreview?.(null));
570
- _el$50.$$keydown = event => handleDayKeyDown(event, cell.day);
571
- _el$50.$$click = () => props.onSelect(cell.key);
572
- _$insert(_el$50, () => cell.number);
619
+ _el$55.addEventListener("blur", () => props.onDayPreview?.(null));
620
+ _el$55.$$keydown = event => handleDayKeyDown(event, cell.day);
621
+ _el$55.$$click = () => props.onSelect(cell.key);
622
+ _$insert(_el$55, () => cell.number);
573
623
  _$effect(_p$ => {
574
- var _v$12 = cell.key,
575
- _v$13 = focusable() ? "true" : undefined,
576
- _v$14 = cell.outside ? "true" : undefined,
577
- _v$15 = weekendColumns()[cellIndex()] ? "true" : undefined,
578
- _v$16 = inRange(cell.key, range()) && !active() ? "true" : undefined,
579
- _v$17 = today() ? "true" : undefined,
580
- _v$18 = today() ? "date" : undefined,
581
- _v$19 = today() ? todayLabel(cell.label) : cell.label,
582
- _v$20 = active(),
583
- _v$21 = focusable() ? 0 : -1;
584
- _v$12 !== _p$.e && _$setAttribute(_el$50, "data-date-day", _p$.e = _v$12);
585
- _v$13 !== _p$.t && _$setAttribute(_el$50, "data-date-focus", _p$.t = _v$13);
586
- _v$14 !== _p$.a && _$setAttribute(_el$50, "data-outside", _p$.a = _v$14);
587
- _v$15 !== _p$.o && _$setAttribute(_el$50, "data-weekend", _p$.o = _v$15);
588
- _v$16 !== _p$.i && _$setAttribute(_el$50, "data-in-range", _p$.i = _v$16);
589
- _v$17 !== _p$.n && _$setAttribute(_el$50, "data-today", _p$.n = _v$17);
590
- _v$18 !== _p$.s && _$setAttribute(_el$50, "aria-current", _p$.s = _v$18);
591
- _v$19 !== _p$.h && _$setAttribute(_el$50, "aria-label", _p$.h = _v$19);
592
- _v$20 !== _p$.r && _$setAttribute(_el$50, "aria-selected", _p$.r = _v$20);
593
- _v$21 !== _p$.d && _$setAttribute(_el$50, "tabindex", _p$.d = _v$21);
624
+ var _v$14 = cell.key,
625
+ _v$15 = focusable() ? "true" : undefined,
626
+ _v$16 = cell.outside ? "true" : undefined,
627
+ _v$17 = weekendColumns()[cellIndex()] ? "true" : undefined,
628
+ _v$18 = inRange(cell.key, range()) && !active() ? "true" : undefined,
629
+ _v$19 = today() ? "true" : undefined,
630
+ _v$20 = today() ? "date" : undefined,
631
+ _v$21 = label(),
632
+ _v$22 = active(),
633
+ _v$23 = blocked(cell.key),
634
+ _v$24 = focusable() ? 0 : -1;
635
+ _v$14 !== _p$.e && _$setAttribute(_el$55, "data-date-day", _p$.e = _v$14);
636
+ _v$15 !== _p$.t && _$setAttribute(_el$55, "data-date-focus", _p$.t = _v$15);
637
+ _v$16 !== _p$.a && _$setAttribute(_el$55, "data-outside", _p$.a = _v$16);
638
+ _v$17 !== _p$.o && _$setAttribute(_el$55, "data-weekend", _p$.o = _v$17);
639
+ _v$18 !== _p$.i && _$setAttribute(_el$55, "data-in-range", _p$.i = _v$18);
640
+ _v$19 !== _p$.n && _$setAttribute(_el$55, "data-today", _p$.n = _v$19);
641
+ _v$20 !== _p$.s && _$setAttribute(_el$55, "aria-current", _p$.s = _v$20);
642
+ _v$21 !== _p$.h && _$setAttribute(_el$55, "aria-label", _p$.h = _v$21);
643
+ _v$22 !== _p$.r && _$setAttribute(_el$55, "aria-selected", _p$.r = _v$22);
644
+ _v$23 !== _p$.d && _$setProperty(_el$55, "disabled", _p$.d = _v$23);
645
+ _v$24 !== _p$.l && _$setAttribute(_el$55, "tabindex", _p$.l = _v$24);
594
646
  return _p$;
595
647
  }, {
596
648
  e: undefined,
@@ -602,32 +654,62 @@ function DatePickerPanel(props) {
602
654
  s: undefined,
603
655
  h: undefined,
604
656
  r: undefined,
605
- d: undefined
657
+ d: undefined,
658
+ l: undefined
606
659
  });
607
660
  _$runHydrationEvents();
608
- return _el$50;
661
+ return _el$55;
609
662
  })();
610
663
  }
611
664
  }));
612
- return _el$49;
665
+ return _el$54;
613
666
  })()
614
667
  }), _el$41, _co$1);
615
668
  return _el$37;
616
669
  })()];
617
670
  }
618
- }), _el$43, _co$10);
671
+ }), _el$46, _co$10);
672
+ _$insert(_el$27, _$createComponent(Show, {
673
+ get when() {
674
+ return props.min || props.max;
675
+ },
676
+ get children() {
677
+ var _el$42 = _$getNextElement(_tmpl$0),
678
+ _el$43 = _el$42.firstChild,
679
+ _el$44 = _el$43.nextSibling;
680
+ _$insert(_el$43, (() => {
681
+ var _c$ = _$memo(() => !!props.min);
682
+ return () => _c$() ? inputMessages().limitFrom({
683
+ date: formatDateInput(props.min, context().locale)
684
+ }) : "";
685
+ })());
686
+ _$insert(_el$44, (() => {
687
+ var _c$2 = _$memo(() => !!props.max);
688
+ return () => _c$2() ? inputMessages().limitUntil({
689
+ date: formatDateInput(props.max, context().locale)
690
+ }) : "";
691
+ })());
692
+ return _el$42;
693
+ }
694
+ }), _el$48, _co$11);
619
695
  _$effect(_p$ => {
620
696
  var _v$7 = messages().calendar,
621
- _v$8 = previousLabel(),
622
- _v$9 = nextLabel();
697
+ _v$8 = stepBlocked(-1),
698
+ _v$9 = previousLabel(),
699
+ _v$0 = stepBlocked(1),
700
+ _v$1 = nextLabel();
623
701
  _v$7 !== _p$.e && _$setAttribute(_el$27, "aria-label", _p$.e = _v$7);
624
- _v$8 !== _p$.t && _$setAttribute(_el$29, "aria-label", _p$.t = _v$8);
625
- _v$9 !== _p$.a && _$setAttribute(_el$31, "aria-label", _p$.a = _v$9);
702
+ _v$8 !== _p$.t && _$setProperty(_el$29, "disabled", _p$.t = _v$8);
703
+ _v$9 !== _p$.a && _$setAttribute(_el$29, "aria-label", _p$.a = _v$9);
704
+ _v$0 !== _p$.o && _$setProperty(_el$31, "disabled", _p$.o = _v$0);
705
+ _v$1 !== _p$.i && _$setAttribute(_el$31, "aria-label", _p$.i = _v$1);
626
706
  return _p$;
627
707
  }, {
628
708
  e: undefined,
629
709
  t: undefined,
630
- a: undefined
710
+ a: undefined,
711
+ o: undefined,
712
+ i: undefined
631
713
  });
632
714
  _$runHydrationEvents();
633
715
  return _el$27;
@@ -636,78 +718,1277 @@ function DatePickerPanel(props) {
636
718
  function TimeInput(props) {
637
719
  const messages = useUiMessages();
638
720
  return (() => {
639
- var _el$51 = _$getNextElement(_tmpl$15),
640
- _el$55 = _el$51.firstChild,
641
- [_el$56, _co$11] = _$getNextMarker(_el$55.nextSibling),
642
- _el$53 = _el$56.nextSibling,
643
- _el$54 = _el$53.firstChild;
644
- _$insert(_el$51, _$createComponent(Show, {
721
+ var _el$56 = _$getNextElement(_tmpl$16),
722
+ _el$60 = _el$56.firstChild,
723
+ [_el$61, _co$12] = _$getNextMarker(_el$60.nextSibling),
724
+ _el$58 = _el$61.nextSibling,
725
+ _el$59 = _el$58.firstChild;
726
+ _$insert(_el$56, _$createComponent(Show, {
645
727
  get when() {
646
728
  return props.label;
647
729
  },
648
730
  get children() {
649
- var _el$52 = _$getNextElement(_tmpl$11);
650
- _$insert(_el$52, () => props.label);
651
- return _el$52;
731
+ var _el$57 = _$getNextElement(_tmpl$12);
732
+ _$insert(_el$57, () => props.label);
733
+ return _el$57;
652
734
  }
653
- }), _el$56, _co$11);
654
- _el$54.addEventListener("blur", () => props.onChange(normalizeTimeInput(props.time)));
655
- _el$54.$$input = event => props.onChange(filterTimeInput(event.currentTarget.value));
656
- _$effect(() => _$setAttribute(_el$54, "aria-label", props.label ? messages().timeLabel({
735
+ }), _el$61, _co$12);
736
+ _el$59.addEventListener("blur", () => props.onChange(normalizeTimeInput(props.time)));
737
+ _el$59.$$input = event => props.onChange(filterTimeInput(event.currentTarget.value));
738
+ _$effect(() => _$setAttribute(_el$59, "aria-label", props.label ? messages().timeLabel({
657
739
  label: props.label
658
740
  }) : messages().time));
659
- _$effect(() => _$setProperty(_el$54, "value", props.time));
741
+ _$effect(() => _$setProperty(_el$59, "value", props.time));
660
742
  _$runHydrationEvents();
661
- return _el$51;
743
+ return _el$56;
662
744
  })();
663
745
  }
746
+
747
+ /** The calendar popover of a typed field: it lives inside the field's shell, so focus in the calendar keeps the field's focus edge. */
748
+ function createCalendarPopover(options) {
749
+ const [open, setOpen] = createSignal(false);
750
+ let popover;
751
+ const place = () => {
752
+ const anchor = options.anchor();
753
+ if (anchor && popover && open()) placeDatePopover(anchor, popover, options.wide(), options.below());
754
+ };
755
+ const show = () => {
756
+ if (!popover || popoverIsOpen(popover)) return;
757
+ setOpen(true);
758
+ popover.showPopover();
759
+ place();
760
+ };
761
+ const close = () => {
762
+ if (popoverIsOpen(popover)) popover?.hidePopover();
763
+ setOpen(false);
764
+ };
765
+ createEffect(() => {
766
+ if (!open()) return;
767
+ window.addEventListener("resize", place);
768
+ window.addEventListener("scroll", place, true);
769
+ onCleanup(() => {
770
+ window.removeEventListener("resize", place);
771
+ window.removeEventListener("scroll", place, true);
772
+ });
773
+ });
774
+ onCleanup(close);
775
+ return {
776
+ open,
777
+ show,
778
+ close,
779
+ place,
780
+ ref: element => {
781
+ popover = element;
782
+ // The browser also hides a popover itself, for example when it leaves the top layer.
783
+ element.addEventListener("toggle", () => setOpen(popoverIsOpen(element)));
784
+ },
785
+ element: () => popover,
786
+ focusDay: () => queueMicrotask(() => popover?.querySelector('[data-date-focus="true"]')?.focus())
787
+ };
788
+ }
789
+
790
+ /** The day an empty calendar opens on: today, moved inside min/max, so a limited field never opens on locked months only. */
791
+ const openingDay = (value, limits, context) => {
792
+ if (value) return value;
793
+ const today = dateKey(new Date(), context);
794
+ if (limits.min && today < limits.min) return limits.min;
795
+ if (limits.max && today > limits.max) return limits.max;
796
+ return today;
797
+ };
798
+ const fieldName = owner => typeof owner.label === "string" ? owner.label : owner["aria-label"];
799
+
800
+ /** Clicks on the calendar's empty space keep focus where it is, so the draft and caret stay in the text. */
801
+ const keepFocus = event => {
802
+ if (!event.target.closest("button")) event.preventDefault();
803
+ };
804
+ const caretToEnd = input => {
805
+ input?.focus();
806
+ input?.setSelectionRange(input.value.length, input.value.length);
807
+ };
808
+ function DateStatusLine(props) {
809
+ return [(() => {
810
+ var _el$62 = _$getNextElement(_tmpl$17);
811
+ var _ref$4 = props.ref;
812
+ typeof _ref$4 === "function" ? _$use(_ref$4, _el$62) : props.ref = _el$62;
813
+ _$insert(_el$62, () => props.text);
814
+ _$effect(_p$ => {
815
+ var _v$25 = props.id,
816
+ _v$26 = props.tone,
817
+ _v$27 = typeof props.text === "string" && props.text ? props.text : undefined;
818
+ _v$25 !== _p$.e && _$setAttribute(_el$62, "id", _p$.e = _v$25);
819
+ _v$26 !== _p$.t && _$setAttribute(_el$62, "data-tone", _p$.t = _v$26);
820
+ _v$27 !== _p$.a && _$setAttribute(_el$62, "title", _p$.a = _v$27);
821
+ return _p$;
822
+ }, {
823
+ e: undefined,
824
+ t: undefined,
825
+ a: undefined
826
+ });
827
+ return _el$62;
828
+ })(), (() => {
829
+ var _el$63 = _$getNextElement(_tmpl$18);
830
+ _$insert(_el$63, () => props.announcement);
831
+ return _el$63;
832
+ })()];
833
+ }
834
+
835
+ /**
836
+ * The typed date field. The text and the calendar always show the same day: typing moves the calendar, picking a day
837
+ * fills the text, and the status line says which day the text means before it is committed.
838
+ */
839
+ function DateTextField(props) {
840
+ const uiMessages = useUiMessages();
841
+ const meta = createFieldMeta(props.owner.id);
842
+ const locale = () => props.dateConfig().locale;
843
+ const t = createMemo(() => resolveDateInputMessages(locale()));
844
+ const today = () => dateKey(new Date(), props.dateConfig());
845
+ const format = key => key ? formatDateInput(key, locale()) : "";
846
+ const limits = () => ({
847
+ min: props.owner.min,
848
+ max: props.owner.max
849
+ });
850
+ const interactive = () => !props.owner.disabled && !props.owner.readOnly;
851
+ const [text, setText] = createSignal(format(props.value()));
852
+ const [dirty, setDirty] = createSignal(false);
853
+ const [failure, setFailure] = createSignal();
854
+ const [announcement, setAnnouncement] = createSignal("");
855
+ const [visibleMonth, setVisibleMonth] = createSignal(parseDateValue(openingDay(props.value(), limits(), props.dateConfig()), props.dateConfig()));
856
+ let shell;
857
+ let input;
858
+ let toggle;
859
+ let statusLine;
860
+ const [sheetOpen, setSheetOpen] = createSignal(false);
861
+ let announceTimer;
862
+ const calendar = createCalendarPopover({
863
+ anchor: () => shell,
864
+ below: () => statusLine,
865
+ wide: () => Boolean(props.owner.presets?.length)
866
+ });
867
+ const popoverId = `${meta.controlId}-calendar`;
868
+ const sheetId = `${meta.controlId}-sheet`;
869
+ // The status line holds the field's message slot, so it carries the `<id>-error` every field family uses.
870
+ const statusId = meta.errorId;
871
+ const parse = value => parseDateInput(value, {
872
+ today: today(),
873
+ locale: locale()
874
+ });
875
+ const parsed = createMemo(() => dirty() ? parse(text()) : undefined);
876
+ const draftKey = () => {
877
+ const result = parsed();
878
+ if (!result) return props.value();
879
+ return result.kind === "date" ? result.date : null;
880
+ };
881
+
882
+ // A value set from outside replaces the text, unless someone is typing.
883
+ createEffect(on([props.value, locale], () => {
884
+ if (dirty()) return;
885
+ setText(format(props.value()));
886
+ setFailure(undefined);
887
+ setVisibleMonth(parseDateValue(openingDay(props.value(), limits(), props.dateConfig()), props.dateConfig()));
888
+ }));
889
+ // The calendar follows the typed day, and a refused text stops being red once it means an allowed day.
890
+ createEffect(on(parsed, result => {
891
+ if (result?.kind === "date") {
892
+ setVisibleMonth(parseDateValue(result.date, props.dateConfig()));
893
+ if (!limitErrorText(result.date, limits(), locale(), t())) setFailure(undefined);
894
+ } else if (result?.kind === "empty") setFailure(undefined);
895
+ }));
896
+ onCleanup(() => clearTimeout(announceTimer));
897
+ const externalError = () => resolveMaybeAccessor(props.owner.error);
898
+ const invalid = () => Boolean(failure() || externalError());
899
+ const status = createMemo(() => {
900
+ const failed = failure();
901
+ if (failed) return {
902
+ tone: "error",
903
+ text: failed
904
+ };
905
+ const result = parsed();
906
+ if (result?.kind === "date") {
907
+ const limit = limitErrorText(result.date, limits(), locale(), t());
908
+ return limit ? {
909
+ tone: "rest",
910
+ text: limit
911
+ } : {
912
+ tone: "draft",
913
+ text: draftStatusText(result.date, result.note, locale(), t())
914
+ };
915
+ }
916
+ if (result?.kind === "error") return {
917
+ tone: "rest",
918
+ text: typingStatusText(result.error, locale(), t(), today())
919
+ };
920
+ const external = externalError();
921
+ if (external) return {
922
+ tone: "error",
923
+ text: external
924
+ };
925
+ const value = props.value();
926
+ if (!value || result) return {
927
+ tone: "rest",
928
+ text: ""
929
+ };
930
+ return {
931
+ tone: "rest",
932
+ text: props.owner.renderValue?.(value) ?? restStatusText(value, today(), locale())
933
+ };
934
+ });
935
+ const save = next => {
936
+ if (next !== props.value()) commitFieldValue(props.owner, next);
937
+ };
938
+ const fail = message => {
939
+ setFailure(message);
940
+ setAnnouncement(message);
941
+ };
942
+ /** Enter, leaving the field and a picked day commit; a refused text stays for correction and the value is kept. */
943
+ const commit = () => {
944
+ const result = parse(text());
945
+ setDirty(false);
946
+ if (result.kind === "empty") {
947
+ if (props.owner.required) return fail(t().required);
948
+ setFailure(undefined);
949
+ return save(null);
950
+ }
951
+ if (result.kind === "error") return fail(errorText(result.error, locale(), t(), today()));
952
+ const limit = limitErrorText(result.date, limits(), locale(), t());
953
+ if (limit) return fail(limit);
954
+ setFailure(undefined);
955
+ setText(format(result.date));
956
+ save(result.date);
957
+ };
958
+ const restore = () => {
959
+ setText(format(props.value()));
960
+ setDirty(false);
961
+ setFailure(undefined);
962
+ setVisibleMonth(parseDateValue(openingDay(props.value(), limits(), props.dateConfig()), props.dateConfig()));
963
+ calendar.close();
964
+ };
965
+ const pick = key => {
966
+ setText(format(key));
967
+ setDirty(false);
968
+ setFailure(undefined);
969
+ save(key);
970
+ calendar.close();
971
+ };
972
+ const openSheet = async () => {
973
+ setSheetOpen(true);
974
+ calendar.close();
975
+ const {
976
+ openDateSheet
977
+ } = await import("./date-sheet");
978
+ await openDateSheet({
979
+ title: props.owner.label ?? props.owner["aria-label"],
980
+ subtitle: props.value() ? formatDateLong(props.value(), locale()) : t().noDate,
981
+ ariaLabel: fieldName(props.owner),
982
+ id: sheetId,
983
+ locale: locale() ?? "en",
984
+ content: close => _$createComponent(DatePickerPanel, {
985
+ visibleMonth: visibleMonth,
986
+ setVisibleMonth: setVisibleMonth,
987
+ selected: draftKey,
988
+ focusDate: draftKey,
989
+ onSelect: key => {
990
+ // Saved at once: the sheet's promise settles only after its history entry has gone.
991
+ pick(key);
992
+ close(key);
993
+ },
994
+ get dateConfig() {
995
+ return props.dateConfig();
996
+ },
997
+ get min() {
998
+ return props.owner.min;
999
+ },
1000
+ get max() {
1001
+ return props.owner.max;
1002
+ }
1003
+ })
1004
+ });
1005
+ setSheetOpen(false);
1006
+ toggle?.focus({
1007
+ preventScroll: true
1008
+ });
1009
+ };
1010
+ /** Phones open the calendar as a sheet; there the text only brings up the keypad. */
1011
+ const openCalendar = focusDay => {
1012
+ if (!interactive()) return;
1013
+ if (prefersMenuSheet()) return void openSheet();
1014
+ if (!dirty()) setVisibleMonth(parseDateValue(openingDay(props.value(), limits(), props.dateConfig()), props.dateConfig()));
1015
+ calendar.show();
1016
+ if (focusDay) calendar.focusDay();
1017
+ };
1018
+ const onPointerDown = event => {
1019
+ const target = event.target;
1020
+ if (!interactive() || calendar.element()?.contains(target) || target.closest(".k2b-date-field__clear")) return;
1021
+ const onIcon = target.closest(".k2b-date-field__toggle, .k2b-date-field__icon");
1022
+ if (prefersMenuSheet()) {
1023
+ if (onIcon) {
1024
+ event.preventDefault();
1025
+ void openSheet();
1026
+ }
1027
+ return;
1028
+ }
1029
+ if (onIcon) {
1030
+ event.preventDefault();
1031
+ input?.focus();
1032
+ if (calendar.open()) calendar.close();else openCalendar(false);
1033
+ return;
1034
+ }
1035
+ // A pointer in the text opens the calendar and keeps the caret; Tab focus never opens it.
1036
+ if (event.button === 0 && !calendar.open()) setTimeout(() => openCalendar(false));
1037
+ };
1038
+ const onKeyDown = event => {
1039
+ // A refused text keeps Enter too, so it does not submit the form around it.
1040
+ if (event.key === "Enter" && (dirty() || calendar.open() || failure())) {
1041
+ event.preventDefault();
1042
+ commit();
1043
+ calendar.close();
1044
+ } else if (event.key === "Escape" && (dirty() || calendar.open() || failure())) {
1045
+ event.preventDefault();
1046
+ event.stopPropagation();
1047
+ restore();
1048
+ } else if (event.key === "ArrowDown") {
1049
+ event.preventDefault();
1050
+ openCalendar(true);
1051
+ } else if (event.key === "ArrowUp" && event.altKey) {
1052
+ event.preventDefault();
1053
+ calendar.close();
1054
+ }
1055
+ };
1056
+ const onFocusOut = event => {
1057
+ const next = event.relatedTarget;
1058
+ if (sheetOpen() || next === input || next && calendar.element()?.contains(next)) return;
1059
+ if (dirty()) commit();
1060
+ calendar.close();
1061
+ };
1062
+ return _$createComponent(Field, {
1063
+ get ["class"]() {
1064
+ return props.owner.class;
1065
+ },
1066
+ get label() {
1067
+ return props.owner.label;
1068
+ },
1069
+ get description() {
1070
+ return props.owner.description;
1071
+ },
1072
+ get required() {
1073
+ return props.owner.required;
1074
+ },
1075
+ get disabled() {
1076
+ return props.owner.disabled;
1077
+ },
1078
+ meta: meta,
1079
+ get children() {
1080
+ var _el$64 = _$getNextElement(_tmpl$22),
1081
+ _el$65 = _el$64.firstChild,
1082
+ _el$66 = _el$65.firstChild,
1083
+ _el$67 = _el$66.nextSibling,
1084
+ _el$76 = _el$67.nextSibling,
1085
+ [_el$77, _co$15] = _$getNextMarker(_el$76.nextSibling),
1086
+ _el$78 = _el$77.nextSibling,
1087
+ [_el$79, _co$16] = _$getNextMarker(_el$78.nextSibling),
1088
+ _el$70 = _el$79.nextSibling,
1089
+ _el$80 = _el$65.nextSibling,
1090
+ [_el$81, _co$17] = _$getNextMarker(_el$80.nextSibling);
1091
+ _el$64.$$focusout = onFocusOut;
1092
+ _el$65.$$pointerdown = onPointerDown;
1093
+ var _ref$5 = shell;
1094
+ typeof _ref$5 === "function" ? _$use(_ref$5, _el$65) : shell = _el$65;
1095
+ var _ref$6 = input;
1096
+ typeof _ref$6 === "function" ? _$use(_ref$6, _el$67) : input = _el$67;
1097
+ _$spread(_el$67, _$mergeProps(() => fieldControlAria(meta, props.owner), {
1098
+ get id() {
1099
+ return meta.controlId;
1100
+ },
1101
+ "class": "k2b-input",
1102
+ "type": "text",
1103
+ "inputMode": "numeric",
1104
+ "autocomplete": "off",
1105
+ "spellcheck": false,
1106
+ "role": "combobox",
1107
+ "aria-haspopup": "dialog",
1108
+ get ["aria-expanded"]() {
1109
+ return calendar.open() || sheetOpen();
1110
+ },
1111
+ get ["aria-controls"]() {
1112
+ return sheetOpen() ? sheetId : popoverId;
1113
+ },
1114
+ get ["aria-describedby"]() {
1115
+ return [props.owner["aria-describedby"], props.owner.description ? meta.descriptionId : undefined, statusId].filter(Boolean).join(" ");
1116
+ },
1117
+ get ["aria-invalid"]() {
1118
+ return invalid() ? "true" : undefined;
1119
+ },
1120
+ get placeholder() {
1121
+ return props.owner.placeholder ?? datePattern(locale(), t());
1122
+ },
1123
+ get value() {
1124
+ return text();
1125
+ },
1126
+ get disabled() {
1127
+ return props.owner.disabled;
1128
+ },
1129
+ get readOnly() {
1130
+ return props.owner.readOnly;
1131
+ },
1132
+ "onInput": event => {
1133
+ setText(event.currentTarget.value);
1134
+ setDirty(true);
1135
+ clearTimeout(announceTimer);
1136
+ announceTimer = setTimeout(() => {
1137
+ const result = parsed();
1138
+ setAnnouncement(result?.kind === "date" ? spokenDateText(result.date, result.note, locale(), t()) : "");
1139
+ }, 500);
1140
+ },
1141
+ "onKeyDown": onKeyDown
1142
+ }), false, false);
1143
+ _$insert(_el$65, _$createComponent(Show, {
1144
+ get when() {
1145
+ return _$memo(() => !!props.owner.clearable)() && interactive();
1146
+ },
1147
+ get children() {
1148
+ var _el$68 = _$getNextElement(_tmpl$19);
1149
+ _el$68.$$click = () => {
1150
+ pick(null);
1151
+ input?.focus();
1152
+ };
1153
+ _$effect(_p$ => {
1154
+ var _v$28 = text() ? undefined : "true",
1155
+ _v$29 = uiMessages().clearDate;
1156
+ _v$28 !== _p$.e && _$setAttribute(_el$68, "data-hidden", _p$.e = _v$28);
1157
+ _v$29 !== _p$.t && _$setAttribute(_el$68, "aria-label", _p$.t = _v$29);
1158
+ return _p$;
1159
+ }, {
1160
+ e: undefined,
1161
+ t: undefined
1162
+ });
1163
+ _$runHydrationEvents();
1164
+ return _el$68;
1165
+ }
1166
+ }), _el$77, _co$15);
1167
+ _$insert(_el$65, _$createComponent(Show, {
1168
+ get when() {
1169
+ return !props.owner.readOnly;
1170
+ },
1171
+ get fallback() {
1172
+ return _$getNextElement(_tmpl$23);
1173
+ },
1174
+ get children() {
1175
+ var _el$69 = _$getNextElement(_tmpl$20);
1176
+ _el$69.$$click = event => {
1177
+ // Pointers are handled on pointerdown; this is activation by assistive technology.
1178
+ if (event.detail === 0) openCalendar(true);
1179
+ };
1180
+ var _ref$7 = toggle;
1181
+ typeof _ref$7 === "function" ? _$use(_ref$7, _el$69) : toggle = _el$69;
1182
+ _$effect(_p$ => {
1183
+ var _v$30 = props.owner.disabled,
1184
+ _v$31 = calendar.open() ? t().closeCalendar : t().openCalendar,
1185
+ _v$32 = calendar.open() || sheetOpen(),
1186
+ _v$33 = sheetOpen() ? sheetId : popoverId;
1187
+ _v$30 !== _p$.e && _$setProperty(_el$69, "disabled", _p$.e = _v$30);
1188
+ _v$31 !== _p$.t && _$setAttribute(_el$69, "aria-label", _p$.t = _v$31);
1189
+ _v$32 !== _p$.a && _$setAttribute(_el$69, "aria-expanded", _p$.a = _v$32);
1190
+ _v$33 !== _p$.o && _$setAttribute(_el$69, "aria-controls", _p$.o = _v$33);
1191
+ return _p$;
1192
+ }, {
1193
+ e: undefined,
1194
+ t: undefined,
1195
+ a: undefined,
1196
+ o: undefined
1197
+ });
1198
+ _$runHydrationEvents();
1199
+ return _el$69;
1200
+ }
1201
+ }), _el$79, _co$16);
1202
+ _el$70.$$keydown = event => {
1203
+ if (event.key !== "Escape" && !(event.key === "ArrowUp" && event.altKey)) return;
1204
+ event.preventDefault();
1205
+ event.stopPropagation();
1206
+ calendar.close();
1207
+ input?.focus();
1208
+ };
1209
+ _el$70.$$pointerdown = keepFocus;
1210
+ var _ref$8 = calendar.ref;
1211
+ typeof _ref$8 === "function" ? _$use(_ref$8, _el$70) : calendar.ref = _el$70;
1212
+ _$setAttribute(_el$70, "id", popoverId);
1213
+ _$insert(_el$70, _$createComponent(Show, {
1214
+ get when() {
1215
+ return calendar.open();
1216
+ },
1217
+ get children() {
1218
+ var _el$71 = _$getNextElement(_tmpl$21),
1219
+ _el$72 = _el$71.firstChild,
1220
+ [_el$73, _co$13] = _$getNextMarker(_el$72.nextSibling),
1221
+ _el$74 = _el$73.nextSibling,
1222
+ [_el$75, _co$14] = _$getNextMarker(_el$74.nextSibling);
1223
+ _$insert(_el$71, _$createComponent(PresetRail, {
1224
+ get presets() {
1225
+ return props.owner.presets;
1226
+ },
1227
+ onSelect: value => {
1228
+ pick(value);
1229
+ caretToEnd(input);
1230
+ }
1231
+ }), _el$73, _co$13);
1232
+ _$insert(_el$71, _$createComponent(DatePickerPanel, {
1233
+ visibleMonth: visibleMonth,
1234
+ setVisibleMonth: setVisibleMonth,
1235
+ selected: draftKey,
1236
+ focusDate: draftKey,
1237
+ onSelect: key => {
1238
+ pick(key);
1239
+ caretToEnd(input);
1240
+ },
1241
+ get dateConfig() {
1242
+ return props.dateConfig();
1243
+ },
1244
+ get min() {
1245
+ return props.owner.min;
1246
+ },
1247
+ get max() {
1248
+ return props.owner.max;
1249
+ }
1250
+ }), _el$75, _co$14);
1251
+ return _el$71;
1252
+ }
1253
+ }));
1254
+ _$insert(_el$64, _$createComponent(DateStatusLine, {
1255
+ ref: element => {
1256
+ statusLine = element;
1257
+ },
1258
+ id: statusId,
1259
+ get tone() {
1260
+ return status().tone;
1261
+ },
1262
+ get text() {
1263
+ return status().text;
1264
+ },
1265
+ get announcement() {
1266
+ return announcement();
1267
+ }
1268
+ }), _el$81, _co$17);
1269
+ _$effect(_p$ => {
1270
+ var _v$34 = calendar.open() ? "true" : undefined,
1271
+ _v$35 = props.owner.readOnly ? "true" : undefined,
1272
+ _v$36 = invalid() ? "true" : undefined,
1273
+ _v$37 = fieldName(props.owner) ?? uiMessages().datePicker;
1274
+ _v$34 !== _p$.e && _$setAttribute(_el$64, "data-open", _p$.e = _v$34);
1275
+ _v$35 !== _p$.t && _$setAttribute(_el$64, "data-readonly", _p$.t = _v$35);
1276
+ _v$36 !== _p$.a && _$setAttribute(_el$65, "data-invalid", _p$.a = _v$36);
1277
+ _v$37 !== _p$.o && _$setAttribute(_el$70, "aria-label", _p$.o = _v$37);
1278
+ return _p$;
1279
+ }, {
1280
+ e: undefined,
1281
+ t: undefined,
1282
+ a: undefined,
1283
+ o: undefined
1284
+ });
1285
+ _$runHydrationEvents();
1286
+ return _el$64;
1287
+ }
1288
+ });
1289
+ }
1290
+ const datePattern = (locale, t) => dateInputPattern(locale, {
1291
+ day: t.dayLetters,
1292
+ month: t.monthLetters,
1293
+ year: t.yearLetters
1294
+ });
1295
+
1296
+ /** "11.11.2026 – 14.11.2026", "11.11. bis 14.11." or "Nov 11 to Nov 14" pasted into either half fills both. */
1297
+ const splitPastedRange = text => {
1298
+ const parts = text.trim().split(/\s*[–—]\s*|\s+-\s+|\s+(?:bis|to|until)\s+/i);
1299
+ return parts.length === 2 && parts[0] && parts[1] ? [parts[0], parts[1]] : undefined;
1300
+ };
1301
+
1302
+ /** A date-only range as two typed halves in one field; the calendar keeps two clicks and Apply. */
1303
+ function DateRangeTextField(props) {
1304
+ const uiMessages = useUiMessages();
1305
+ const meta = createFieldMeta(props.owner.id);
1306
+ const locale = () => props.dateConfig().locale;
1307
+ const t = createMemo(() => resolveDateInputMessages(locale()));
1308
+ const today = () => dateKey(new Date(), props.dateConfig());
1309
+ const format = key => key ? formatDateInput(key, locale()) : "";
1310
+ const limits = () => ({
1311
+ min: props.owner.min,
1312
+ max: props.owner.max
1313
+ });
1314
+ const interactive = () => !props.owner.disabled && !props.owner.readOnly;
1315
+ const [startText, setStartText] = createSignal(format(props.value().start));
1316
+ const [endText, setEndText] = createSignal(format(props.value().end));
1317
+ const [dirty, setDirty] = createSignal(false);
1318
+ const [failure, setFailure] = createSignal();
1319
+ const [announcement, setAnnouncement] = createSignal("");
1320
+ const [visibleMonth, setVisibleMonth] = createSignal(parseDateValue(openingDay(props.value().start || props.value().end, limits(), props.dateConfig()), props.dateConfig()));
1321
+ // The calendar's own draft: two clicks pick a range, Apply commits it.
1322
+ const [picked, setPicked] = createSignal(props.value());
1323
+ const [anchor, setAnchor] = createSignal(null);
1324
+ const [previewDate, setPreviewDate] = createSignal(null);
1325
+ let shell;
1326
+ let startInput;
1327
+ let endInput;
1328
+ let toggle;
1329
+ let statusLine;
1330
+ const [sheetOpen, setSheetOpen] = createSignal(false);
1331
+ let announceTimer;
1332
+ const wide = () => Boolean(props.owner.datePresets?.length || props.owner.presets?.length);
1333
+ const calendar = createCalendarPopover({
1334
+ anchor: () => shell,
1335
+ below: () => statusLine,
1336
+ wide
1337
+ });
1338
+ const popoverId = `${meta.controlId}-calendar`;
1339
+ const sheetId = `${meta.controlId}-sheet`;
1340
+ // The status line holds the field's message slot, so it carries the `<id>-error` every field family uses.
1341
+ const statusId = meta.errorId;
1342
+ const name = () => fieldName(props.owner);
1343
+ const parse = value => parseDateInput(value, {
1344
+ today: today(),
1345
+ locale: locale()
1346
+ });
1347
+ const halves = createMemo(() => dirty() ? [parse(startText()), parse(endText())] : undefined);
1348
+ const draft = createMemo(() => {
1349
+ const current = halves();
1350
+ if (!current) return props.value();
1351
+ const [start, end] = current;
1352
+ return {
1353
+ start: start.kind === "date" ? start.date : null,
1354
+ end: end.kind === "date" ? end.date : null
1355
+ };
1356
+ });
1357
+ const shownRange = createMemo(() => previewRange(picked(), anchor(), previewDate()));
1358
+ const fill = range => {
1359
+ setStartText(format(range.start));
1360
+ setEndText(format(range.end));
1361
+ };
1362
+ createEffect(on([props.value, locale], () => {
1363
+ if (dirty()) return;
1364
+ fill(props.value());
1365
+ setPicked(props.value());
1366
+ setFailure(undefined);
1367
+ }));
1368
+ createEffect(on(draft, range => {
1369
+ // A day picked in the calendar wrote this text itself; its half-picked range keeps going.
1370
+ if (!dirty() || range.start === picked().start && range.end === picked().end) return;
1371
+ setPicked(range);
1372
+ setAnchor(null);
1373
+ if (range.start || range.end) setVisibleMonth(parseDateValue(range.start || range.end, props.dateConfig()));
1374
+ setFailure(undefined);
1375
+ }));
1376
+ onCleanup(() => clearTimeout(announceTimer));
1377
+ const externalError = () => resolveMaybeAccessor(props.owner.error);
1378
+ const invalid = () => Boolean(failure() || externalError());
1379
+ const status = createMemo(() => {
1380
+ const failed = failure();
1381
+ if (failed) return {
1382
+ tone: "error",
1383
+ text: failed
1384
+ };
1385
+ const current = halves();
1386
+ if (current) {
1387
+ const mistake = current.find(half => half.kind === "error");
1388
+ if (mistake) return {
1389
+ tone: "rest",
1390
+ text: typingStatusText(mistake.error, locale(), t(), today())
1391
+ };
1392
+ const range = draft();
1393
+ const limit = [range.start, range.end].map(key => key && limitErrorText(key, limits(), locale(), t())).find(Boolean);
1394
+ if (limit) return {
1395
+ tone: "rest",
1396
+ text: limit
1397
+ };
1398
+ const text = rangeStatusText(range, locale(), t());
1399
+ return {
1400
+ tone: text ? "draft" : "rest",
1401
+ text: text ? `→ ${text}` : ""
1402
+ };
1403
+ }
1404
+ const external = externalError();
1405
+ if (external) return {
1406
+ tone: "error",
1407
+ text: external
1408
+ };
1409
+ return {
1410
+ tone: "rest",
1411
+ text: rangeStatusText(props.value(), locale(), t())
1412
+ };
1413
+ });
1414
+ const save = next => {
1415
+ if (next.start !== props.value().start || next.end !== props.value().end) commitFieldValue(props.owner, next);
1416
+ };
1417
+ const fail = message => {
1418
+ setFailure(message);
1419
+ setAnnouncement(message);
1420
+ };
1421
+ const commitRange = range => {
1422
+ setDirty(false);
1423
+ const limit = [range.start, range.end].map(key => key && limitErrorText(key, limits(), locale(), t())).find(Boolean);
1424
+ if (limit) return fail(limit);
1425
+ if (range.start && range.end && range.end < range.start) return fail(t().endBeforeStart);
1426
+ if (range.start && !range.end) return fail(t().missingEnd);
1427
+ if (range.end && !range.start) return fail(t().missingStart);
1428
+ if (!range.start && props.owner.required) return fail(t().required);
1429
+ setFailure(undefined);
1430
+ fill(range);
1431
+ setPicked(range);
1432
+ save(range);
1433
+ };
1434
+ const commit = () => {
1435
+ const [start, end] = [parse(startText()), parse(endText())];
1436
+ const mistake = [start, end].find(half => half.kind === "error");
1437
+ if (mistake) {
1438
+ setDirty(false);
1439
+ return fail(errorText(mistake.error, locale(), t(), today()));
1440
+ }
1441
+ commitRange({
1442
+ start: start.kind === "date" ? start.date : null,
1443
+ end: end.kind === "date" ? end.date : null
1444
+ });
1445
+ };
1446
+ const restore = () => {
1447
+ fill(props.value());
1448
+ setPicked(props.value());
1449
+ setAnchor(null);
1450
+ setDirty(false);
1451
+ setFailure(undefined);
1452
+ calendar.close();
1453
+ };
1454
+ /** Calendar clicks fill both halves at once, so the text, the status line and the calendar show the same range. */
1455
+ const pickDay = key => {
1456
+ const next = pickRangeDay(picked(), anchor(), key);
1457
+ // One update: the start alone would read as a typed range and reset the anchor of the next click.
1458
+ batch(() => {
1459
+ setPicked(next.range);
1460
+ setAnchor(next.anchor);
1461
+ setPreviewDate(null);
1462
+ fill(next.range);
1463
+ setDirty(true);
1464
+ });
1465
+ };
1466
+ const apply = range => {
1467
+ commitRange(range);
1468
+ calendar.close();
1469
+ };
1470
+ const canApply = () => Boolean(picked().start) === Boolean(picked().end);
1471
+ const rangeCalendar = onApply => [(() => {
1472
+ var _el$83 = _$getNextElement(_tmpl$21),
1473
+ _el$84 = _el$83.firstChild,
1474
+ [_el$85, _co$18] = _$getNextMarker(_el$84.nextSibling),
1475
+ _el$86 = _el$85.nextSibling,
1476
+ [_el$87, _co$19] = _$getNextMarker(_el$86.nextSibling);
1477
+ _$insert(_el$83, _$createComponent(Show, {
1478
+ get when() {
1479
+ return props.owner.datePresets?.length;
1480
+ },
1481
+ get fallback() {
1482
+ return _$createComponent(PresetRail, {
1483
+ get presets() {
1484
+ return props.owner.presets;
1485
+ },
1486
+ onSelect: onApply
1487
+ });
1488
+ },
1489
+ get children() {
1490
+ return _$createComponent(PresetRail, {
1491
+ get presets() {
1492
+ return props.owner.datePresets;
1493
+ },
1494
+ onSelect: value => {
1495
+ const next = value ? {
1496
+ start: value,
1497
+ end: value
1498
+ } : {
1499
+ start: null,
1500
+ end: null
1501
+ };
1502
+ batch(() => {
1503
+ setPicked(next);
1504
+ setAnchor(null);
1505
+ fill(next);
1506
+ setDirty(true);
1507
+ });
1508
+ if (value) setVisibleMonth(parseDateValue(value, props.dateConfig()));
1509
+ }
1510
+ });
1511
+ }
1512
+ }), _el$85, _co$18);
1513
+ _$insert(_el$83, _$createComponent(DatePickerPanel, {
1514
+ visibleMonth: visibleMonth,
1515
+ setVisibleMonth: setVisibleMonth,
1516
+ range: shownRange,
1517
+ focusDate: () => picked().start,
1518
+ onSelect: pickDay,
1519
+ onDayPreview: key => setPreviewDate(rangeAnchor(picked(), anchor()) ? key : null),
1520
+ get dateConfig() {
1521
+ return props.dateConfig();
1522
+ },
1523
+ get min() {
1524
+ return props.owner.min;
1525
+ },
1526
+ get max() {
1527
+ return props.owner.max;
1528
+ }
1529
+ }), _el$87, _co$19);
1530
+ return _el$83;
1531
+ })(), (() => {
1532
+ var _el$88 = _$getNextElement(_tmpl$24),
1533
+ _el$90 = _el$88.firstChild,
1534
+ [_el$91, _co$20] = _$getNextMarker(_el$90.nextSibling),
1535
+ _el$89 = _el$91.nextSibling;
1536
+ _$insert(_el$88, _$createComponent(Show, {
1537
+ get when() {
1538
+ return formatDateOnlyRangeDuration(shownRange(), props.dateConfig());
1539
+ },
1540
+ children: duration => (() => {
1541
+ var _el$92 = _$getNextElement(_tmpl$25),
1542
+ _el$93 = _el$92.firstChild,
1543
+ _el$94 = _el$93.nextSibling,
1544
+ [_el$95, _co$21] = _$getNextMarker(_el$94.nextSibling);
1545
+ _$insert(_el$92, duration, _el$95, _co$21);
1546
+ return _el$92;
1547
+ })()
1548
+ }), _el$91, _co$20);
1549
+ _el$89.$$click = () => onApply(picked());
1550
+ _$insert(_el$89, () => uiMessages().apply);
1551
+ _$effect(() => _$setProperty(_el$89, "disabled", !canApply()));
1552
+ _$runHydrationEvents();
1553
+ return _el$88;
1554
+ })()];
1555
+ const openSheet = async () => {
1556
+ setSheetOpen(true);
1557
+ calendar.close();
1558
+ const before = {
1559
+ start: startText(),
1560
+ end: endText(),
1561
+ dirty: dirty()
1562
+ };
1563
+ // Every opening starts from the text, also after a dismissed sheet left other days picked.
1564
+ batch(() => {
1565
+ setPicked(draft());
1566
+ setAnchor(null);
1567
+ setPreviewDate(null);
1568
+ });
1569
+ const {
1570
+ openDateSheet
1571
+ } = await import("./date-sheet");
1572
+ const range = await openDateSheet({
1573
+ title: props.owner.label ?? props.owner["aria-label"],
1574
+ subtitle: rangeStatusText(props.value(), locale(), t()) || t().noDate,
1575
+ ariaLabel: name(),
1576
+ id: sheetId,
1577
+ locale: locale() ?? "en",
1578
+ content: close => rangeCalendar(next => {
1579
+ // Saved at once, as in the single date sheet.
1580
+ commitRange(next);
1581
+ close(next);
1582
+ })
1583
+ });
1584
+ setSheetOpen(false);
1585
+ // A dismissed sheet saves nothing and leaves the text as it was before the sheet opened.
1586
+ if (!range) batch(() => {
1587
+ setStartText(before.start);
1588
+ setEndText(before.end);
1589
+ setDirty(before.dirty);
1590
+ setAnchor(null);
1591
+ });
1592
+ toggle?.focus({
1593
+ preventScroll: true
1594
+ });
1595
+ };
1596
+ const openCalendar = focusDay => {
1597
+ if (!interactive()) return;
1598
+ setAnchor(null);
1599
+ setPreviewDate(null);
1600
+ setPicked(draft());
1601
+ if (prefersMenuSheet()) return void openSheet();
1602
+ const range = draft();
1603
+ setVisibleMonth(parseDateValue(openingDay(range.start || range.end, limits(), props.dateConfig()), props.dateConfig()));
1604
+ calendar.show();
1605
+ if (focusDay) calendar.focusDay();
1606
+ };
1607
+ const onPointerDown = event => {
1608
+ const target = event.target;
1609
+ if (!interactive() || calendar.element()?.contains(target) || target.closest(".k2b-date-field__clear")) return;
1610
+ const onIcon = target.closest(".k2b-date-field__toggle, .k2b-date-field__icon");
1611
+ if (prefersMenuSheet()) {
1612
+ if (onIcon) {
1613
+ event.preventDefault();
1614
+ void openSheet();
1615
+ }
1616
+ return;
1617
+ }
1618
+ if (onIcon) {
1619
+ event.preventDefault();
1620
+ if (!shell?.contains(document.activeElement)) startInput?.focus();
1621
+ if (calendar.open()) calendar.close();else openCalendar(false);
1622
+ return;
1623
+ }
1624
+ if (event.button === 0 && !calendar.open()) setTimeout(() => openCalendar(false));
1625
+ };
1626
+ const onKeyDown = event => {
1627
+ // A refused text keeps Enter too, so it does not submit the form around it.
1628
+ if (event.key === "Enter" && (dirty() || calendar.open() || failure())) {
1629
+ event.preventDefault();
1630
+ commit();
1631
+ calendar.close();
1632
+ } else if (event.key === "Escape" && (dirty() || calendar.open() || failure())) {
1633
+ event.preventDefault();
1634
+ event.stopPropagation();
1635
+ restore();
1636
+ } else if (event.key === "ArrowDown") {
1637
+ event.preventDefault();
1638
+ openCalendar(true);
1639
+ } else if (event.key === "ArrowUp" && event.altKey) {
1640
+ event.preventDefault();
1641
+ calendar.close();
1642
+ }
1643
+ };
1644
+ const onInput = setter => event => {
1645
+ setter(event.currentTarget.value);
1646
+ setDirty(true);
1647
+ clearTimeout(announceTimer);
1648
+ announceTimer = setTimeout(() => {
1649
+ const range = draft();
1650
+ setAnnouncement(range.start || range.end ? rangeStatusText(range, locale(), t()) : "");
1651
+ }, 500);
1652
+ };
1653
+ const onPaste = event => {
1654
+ const parts = splitPastedRange(event.clipboardData?.getData("text") ?? "");
1655
+ if (!parts) return;
1656
+ event.preventDefault();
1657
+ setStartText(parts[0]);
1658
+ setEndText(parts[1]);
1659
+ setDirty(true);
1660
+ };
1661
+ const onFocusOut = event => {
1662
+ const next = event.relatedTarget;
1663
+ if (sheetOpen() || next && shell?.contains(next)) return;
1664
+ if (dirty()) commit();
1665
+ calendar.close();
1666
+ };
1667
+ const inputProps = {
1668
+ class: "k2b-input",
1669
+ type: "text",
1670
+ inputMode: "numeric",
1671
+ autocomplete: "off",
1672
+ spellcheck: false,
1673
+ "aria-haspopup": "dialog",
1674
+ onKeyDown,
1675
+ onPaste
1676
+ };
1677
+ const describedBy = () => [props.owner["aria-describedby"], props.owner.description ? meta.descriptionId : undefined, statusId].filter(Boolean).join(" ");
1678
+ return _$createComponent(Field, {
1679
+ get ["class"]() {
1680
+ return props.owner.class;
1681
+ },
1682
+ get label() {
1683
+ return props.owner.label;
1684
+ },
1685
+ get description() {
1686
+ return props.owner.description;
1687
+ },
1688
+ get required() {
1689
+ return props.owner.required;
1690
+ },
1691
+ get disabled() {
1692
+ return props.owner.disabled;
1693
+ },
1694
+ meta: meta,
1695
+ get children() {
1696
+ var _el$96 = _$getNextElement(_tmpl$26),
1697
+ _el$97 = _el$96.firstChild,
1698
+ _el$98 = _el$97.firstChild,
1699
+ _el$99 = _el$98.nextSibling,
1700
+ _el$100 = _el$99.nextSibling,
1701
+ _el$101 = _el$100.nextSibling,
1702
+ _el$102 = _el$101.nextSibling,
1703
+ _el$106 = _el$102.nextSibling,
1704
+ [_el$107, _co$22] = _$getNextMarker(_el$106.nextSibling),
1705
+ _el$108 = _el$107.nextSibling,
1706
+ [_el$109, _co$23] = _$getNextMarker(_el$108.nextSibling),
1707
+ _el$105 = _el$109.nextSibling,
1708
+ _el$110 = _el$97.nextSibling,
1709
+ [_el$111, _co$24] = _$getNextMarker(_el$110.nextSibling);
1710
+ _el$96.$$focusout = onFocusOut;
1711
+ _el$97.$$pointerdown = onPointerDown;
1712
+ var _ref$9 = shell;
1713
+ typeof _ref$9 === "function" ? _$use(_ref$9, _el$97) : shell = _el$97;
1714
+ var _ref$0 = startInput;
1715
+ typeof _ref$0 === "function" ? _$use(_ref$0, _el$99) : startInput = _el$99;
1716
+ _$spread(_el$99, _$mergeProps(inputProps, {
1717
+ "role": "combobox",
1718
+ get ["aria-controls"]() {
1719
+ return sheetOpen() ? sheetId : popoverId;
1720
+ },
1721
+ get id() {
1722
+ return meta.controlId;
1723
+ },
1724
+ get ["aria-label"]() {
1725
+ return _$memo(() => !!name())() ? t().startOf({
1726
+ label: name()
1727
+ }) : t().start;
1728
+ },
1729
+ get ["aria-expanded"]() {
1730
+ return calendar.open() || sheetOpen();
1731
+ },
1732
+ get ["aria-describedby"]() {
1733
+ return describedBy();
1734
+ },
1735
+ get ["aria-invalid"]() {
1736
+ return invalid() ? "true" : undefined;
1737
+ },
1738
+ get ["aria-required"]() {
1739
+ return props.owner.required || undefined;
1740
+ },
1741
+ get placeholder() {
1742
+ return t().start;
1743
+ },
1744
+ get value() {
1745
+ return startText();
1746
+ },
1747
+ get disabled() {
1748
+ return props.owner.disabled;
1749
+ },
1750
+ get readOnly() {
1751
+ return props.owner.readOnly;
1752
+ },
1753
+ get onInput() {
1754
+ return onInput(setStartText);
1755
+ }
1756
+ }), false, false);
1757
+ var _ref$1 = endInput;
1758
+ typeof _ref$1 === "function" ? _$use(_ref$1, _el$101) : endInput = _el$101;
1759
+ _$spread(_el$101, _$mergeProps(inputProps, {
1760
+ "role": "combobox",
1761
+ get ["aria-controls"]() {
1762
+ return sheetOpen() ? sheetId : popoverId;
1763
+ },
1764
+ get ["aria-label"]() {
1765
+ return _$memo(() => !!name())() ? t().endOf({
1766
+ label: name()
1767
+ }) : t().end;
1768
+ },
1769
+ get ["aria-expanded"]() {
1770
+ return calendar.open() || sheetOpen();
1771
+ },
1772
+ get ["aria-describedby"]() {
1773
+ return describedBy();
1774
+ },
1775
+ get ["aria-invalid"]() {
1776
+ return invalid() ? "true" : undefined;
1777
+ },
1778
+ get ["aria-required"]() {
1779
+ return props.owner.required || undefined;
1780
+ },
1781
+ get placeholder() {
1782
+ return t().end;
1783
+ },
1784
+ get value() {
1785
+ return endText();
1786
+ },
1787
+ get disabled() {
1788
+ return props.owner.disabled;
1789
+ },
1790
+ get readOnly() {
1791
+ return props.owner.readOnly;
1792
+ },
1793
+ get onInput() {
1794
+ return onInput(setEndText);
1795
+ }
1796
+ }), false, false);
1797
+ _$insert(_el$97, _$createComponent(Show, {
1798
+ get when() {
1799
+ return _$memo(() => !!props.owner.clearable)() && interactive();
1800
+ },
1801
+ get children() {
1802
+ var _el$103 = _$getNextElement(_tmpl$19);
1803
+ _el$103.$$click = () => {
1804
+ commitRange({
1805
+ start: null,
1806
+ end: null
1807
+ });
1808
+ startInput?.focus();
1809
+ };
1810
+ _$effect(_p$ => {
1811
+ var _v$38 = startText() || endText() ? undefined : "true",
1812
+ _v$39 = uiMessages().clearDate;
1813
+ _v$38 !== _p$.e && _$setAttribute(_el$103, "data-hidden", _p$.e = _v$38);
1814
+ _v$39 !== _p$.t && _$setAttribute(_el$103, "aria-label", _p$.t = _v$39);
1815
+ return _p$;
1816
+ }, {
1817
+ e: undefined,
1818
+ t: undefined
1819
+ });
1820
+ _$runHydrationEvents();
1821
+ return _el$103;
1822
+ }
1823
+ }), _el$107, _co$22);
1824
+ _$insert(_el$97, _$createComponent(Show, {
1825
+ get when() {
1826
+ return !props.owner.readOnly;
1827
+ },
1828
+ get fallback() {
1829
+ return _$getNextElement(_tmpl$23);
1830
+ },
1831
+ get children() {
1832
+ var _el$104 = _$getNextElement(_tmpl$20);
1833
+ _el$104.$$click = event => {
1834
+ if (event.detail === 0) openCalendar(true);
1835
+ };
1836
+ var _ref$10 = toggle;
1837
+ typeof _ref$10 === "function" ? _$use(_ref$10, _el$104) : toggle = _el$104;
1838
+ _$effect(_p$ => {
1839
+ var _v$40 = props.owner.disabled,
1840
+ _v$41 = calendar.open() ? t().closeCalendar : t().openCalendar,
1841
+ _v$42 = calendar.open() || sheetOpen(),
1842
+ _v$43 = sheetOpen() ? sheetId : popoverId;
1843
+ _v$40 !== _p$.e && _$setProperty(_el$104, "disabled", _p$.e = _v$40);
1844
+ _v$41 !== _p$.t && _$setAttribute(_el$104, "aria-label", _p$.t = _v$41);
1845
+ _v$42 !== _p$.a && _$setAttribute(_el$104, "aria-expanded", _p$.a = _v$42);
1846
+ _v$43 !== _p$.o && _$setAttribute(_el$104, "aria-controls", _p$.o = _v$43);
1847
+ return _p$;
1848
+ }, {
1849
+ e: undefined,
1850
+ t: undefined,
1851
+ a: undefined,
1852
+ o: undefined
1853
+ });
1854
+ _$runHydrationEvents();
1855
+ return _el$104;
1856
+ }
1857
+ }), _el$109, _co$23);
1858
+ _el$105.$$keydown = event => {
1859
+ if (event.key !== "Escape" && !(event.key === "ArrowUp" && event.altKey)) return;
1860
+ event.preventDefault();
1861
+ event.stopPropagation();
1862
+ calendar.close();
1863
+ startInput?.focus();
1864
+ };
1865
+ _el$105.$$pointerdown = keepFocus;
1866
+ var _ref$11 = calendar.ref;
1867
+ typeof _ref$11 === "function" ? _$use(_ref$11, _el$105) : calendar.ref = _el$105;
1868
+ _$setAttribute(_el$105, "id", popoverId);
1869
+ _$insert(_el$105, _$createComponent(Show, {
1870
+ get when() {
1871
+ return calendar.open();
1872
+ },
1873
+ get children() {
1874
+ return rangeCalendar(range => {
1875
+ apply(range);
1876
+ caretToEnd(endInput);
1877
+ });
1878
+ }
1879
+ }));
1880
+ _$insert(_el$96, _$createComponent(DateStatusLine, {
1881
+ ref: element => {
1882
+ statusLine = element;
1883
+ },
1884
+ id: statusId,
1885
+ get tone() {
1886
+ return status().tone;
1887
+ },
1888
+ get text() {
1889
+ return status().text;
1890
+ },
1891
+ get announcement() {
1892
+ return announcement();
1893
+ }
1894
+ }), _el$111, _co$24);
1895
+ _$effect(_p$ => {
1896
+ var _v$44 = calendar.open() ? "true" : undefined,
1897
+ _v$45 = props.owner.readOnly ? "true" : undefined,
1898
+ _v$46 = props.owner.label ? meta.labelId : undefined,
1899
+ _v$47 = props.owner.label ? undefined : props.owner["aria-label"],
1900
+ _v$48 = invalid() ? "true" : undefined,
1901
+ _v$49 = name() ?? uiMessages().datePicker;
1902
+ _v$44 !== _p$.e && _$setAttribute(_el$96, "data-open", _p$.e = _v$44);
1903
+ _v$45 !== _p$.t && _$setAttribute(_el$96, "data-readonly", _p$.t = _v$45);
1904
+ _v$46 !== _p$.a && _$setAttribute(_el$97, "aria-labelledby", _p$.a = _v$46);
1905
+ _v$47 !== _p$.o && _$setAttribute(_el$97, "aria-label", _p$.o = _v$47);
1906
+ _v$48 !== _p$.i && _$setAttribute(_el$97, "data-invalid", _p$.i = _v$48);
1907
+ _v$49 !== _p$.n && _$setAttribute(_el$105, "aria-label", _p$.n = _v$49);
1908
+ return _p$;
1909
+ }, {
1910
+ e: undefined,
1911
+ t: undefined,
1912
+ a: undefined,
1913
+ o: undefined,
1914
+ i: undefined,
1915
+ n: undefined
1916
+ });
1917
+ _$runHydrationEvents();
1918
+ return _el$96;
1919
+ }
1920
+ });
1921
+ }
664
1922
  export function DatePicker(props) {
665
1923
  const value = () => resolveMaybeAccessor(props.value);
666
1924
  const dateConfig = useDateConfigLocale(() => props.dateConfig);
667
1925
  const [visibleMonth, setVisibleMonth] = createSignal(parseDateValue(value(), dateConfig()));
668
1926
  const valueLabel = () => displayDate(value(), dateConfig());
669
- return _$createComponent(PickerShell, {
670
- owner: props,
671
- icon: "ti ti-calendar",
672
- valueLabel: valueLabel,
673
- get valueContent() {
674
- return props.renderValue ? () => props.renderValue(value()) : undefined;
1927
+ return _$createComponent(Show, {
1928
+ get when() {
1929
+ return props.appearance === "plain";
675
1930
  },
676
- clearValue: null,
677
- onOpen: () => setVisibleMonth(parseDateValue(value(), dateConfig())),
678
- get wide() {
679
- return Boolean(props.presets?.length);
1931
+ get fallback() {
1932
+ return _$createComponent(DateTextField, {
1933
+ owner: props,
1934
+ value: value,
1935
+ dateConfig: dateConfig
1936
+ });
680
1937
  },
681
- children: close => (() => {
682
- var _el$57 = _$getNextElement(_tmpl$16),
683
- _el$58 = _el$57.firstChild,
684
- [_el$59, _co$12] = _$getNextMarker(_el$58.nextSibling),
685
- _el$60 = _el$59.nextSibling,
686
- [_el$61, _co$13] = _$getNextMarker(_el$60.nextSibling);
687
- _$insert(_el$57, _$createComponent(PresetRail, {
688
- get presets() {
689
- return props.presets;
1938
+ get children() {
1939
+ return _$createComponent(PickerShell, {
1940
+ owner: props,
1941
+ icon: "ti ti-calendar",
1942
+ valueLabel: valueLabel,
1943
+ get valueContent() {
1944
+ return props.renderValue ? () => props.renderValue(value()) : undefined;
690
1945
  },
691
- onSelect: value => {
692
- close();
693
- commitFieldValue(props, value);
694
- }
695
- }), _el$59, _co$12);
696
- _$insert(_el$57, _$createComponent(DatePickerPanel, {
697
- visibleMonth: visibleMonth,
698
- setVisibleMonth: setVisibleMonth,
699
- selected: value,
700
- focusDate: value,
701
- onSelect: value => {
702
- close();
703
- commitFieldValue(props, value);
1946
+ clearValue: null,
1947
+ onOpen: () => setVisibleMonth(parseDateValue(openingDay(value(), {
1948
+ min: props.min,
1949
+ max: props.max
1950
+ }, dateConfig()), dateConfig())),
1951
+ get wide() {
1952
+ return Boolean(props.presets?.length);
704
1953
  },
705
- get dateConfig() {
706
- return dateConfig();
707
- }
708
- }), _el$61, _co$13);
709
- return _el$57;
710
- })()
1954
+ children: close => (() => {
1955
+ var _el$113 = _$getNextElement(_tmpl$21),
1956
+ _el$114 = _el$113.firstChild,
1957
+ [_el$115, _co$25] = _$getNextMarker(_el$114.nextSibling),
1958
+ _el$116 = _el$115.nextSibling,
1959
+ [_el$117, _co$26] = _$getNextMarker(_el$116.nextSibling);
1960
+ _$insert(_el$113, _$createComponent(PresetRail, {
1961
+ get presets() {
1962
+ return props.presets;
1963
+ },
1964
+ onSelect: value => {
1965
+ close();
1966
+ commitFieldValue(props, value);
1967
+ }
1968
+ }), _el$115, _co$25);
1969
+ _$insert(_el$113, _$createComponent(DatePickerPanel, {
1970
+ visibleMonth: visibleMonth,
1971
+ setVisibleMonth: setVisibleMonth,
1972
+ selected: value,
1973
+ focusDate: value,
1974
+ onSelect: value => {
1975
+ close();
1976
+ commitFieldValue(props, value);
1977
+ },
1978
+ get dateConfig() {
1979
+ return dateConfig();
1980
+ },
1981
+ get min() {
1982
+ return props.min;
1983
+ },
1984
+ get max() {
1985
+ return props.max;
1986
+ }
1987
+ }), _el$117, _co$26);
1988
+ return _el$113;
1989
+ })()
1990
+ });
1991
+ }
711
1992
  });
712
1993
  }
713
1994
  export function DateTimePicker(props) {
@@ -730,7 +2011,10 @@ export function DateTimePicker(props) {
730
2011
  setDraftDate(next.date);
731
2012
  setDraftTime(next.time || defaultTime());
732
2013
  setWithTime(valueHasTime());
733
- setVisibleMonth(parseDateValue(next.date, dateConfig()));
2014
+ setVisibleMonth(parseDateValue(openingDay(next.date, {
2015
+ min: props.min,
2016
+ max: props.max
2017
+ }, dateConfig()), dateConfig()));
734
2018
  };
735
2019
  const canApply = () => Boolean(draftDate()) && (!withTime() || isCompleteTime(draftTime()));
736
2020
  const draftValue = () => withTime() ? toDateTimeValue(draftDate(), draftTime(), dateConfig()) : draftDate() || null;
@@ -767,12 +2051,12 @@ export function DateTimePicker(props) {
767
2051
  commitFieldValue(props, next);
768
2052
  };
769
2053
  return [(() => {
770
- var _el$62 = _$getNextElement(_tmpl$16),
771
- _el$63 = _el$62.firstChild,
772
- [_el$64, _co$14] = _$getNextMarker(_el$63.nextSibling),
773
- _el$65 = _el$64.nextSibling,
774
- [_el$66, _co$15] = _$getNextMarker(_el$65.nextSibling);
775
- _$insert(_el$62, _$createComponent(PresetRail, {
2054
+ var _el$118 = _$getNextElement(_tmpl$21),
2055
+ _el$119 = _el$118.firstChild,
2056
+ [_el$120, _co$27] = _$getNextMarker(_el$119.nextSibling),
2057
+ _el$121 = _el$120.nextSibling,
2058
+ [_el$122, _co$28] = _$getNextMarker(_el$121.nextSibling);
2059
+ _$insert(_el$118, _$createComponent(PresetRail, {
776
2060
  get presets() {
777
2061
  return props.presets;
778
2062
  },
@@ -780,8 +2064,8 @@ export function DateTimePicker(props) {
780
2064
  close();
781
2065
  commitFieldValue(props, value);
782
2066
  }
783
- }), _el$64, _co$14);
784
- _$insert(_el$62, _$createComponent(DatePickerPanel, {
2067
+ }), _el$120, _co$27);
2068
+ _$insert(_el$118, _$createComponent(DatePickerPanel, {
785
2069
  visibleMonth: visibleMonth,
786
2070
  setVisibleMonth: setVisibleMonth,
787
2071
  selected: draftDate,
@@ -794,15 +2078,21 @@ export function DateTimePicker(props) {
794
2078
  },
795
2079
  get dateConfig() {
796
2080
  return dateConfig();
2081
+ },
2082
+ get min() {
2083
+ return props.min;
2084
+ },
2085
+ get max() {
2086
+ return props.max;
797
2087
  }
798
- }), _el$66, _co$15);
799
- return _el$62;
2088
+ }), _el$122, _co$28);
2089
+ return _el$118;
800
2090
  })(), (() => {
801
- var _el$67 = _$getNextElement(_tmpl$19),
802
- _el$71 = _el$67.firstChild,
803
- [_el$72, _co$16] = _$getNextMarker(_el$71.nextSibling),
804
- _el$70 = _el$72.nextSibling;
805
- _$insert(_el$67, _$createComponent(Show, {
2091
+ var _el$123 = _$getNextElement(_tmpl$24),
2092
+ _el$127 = _el$123.firstChild,
2093
+ [_el$128, _co$29] = _$getNextMarker(_el$127.nextSibling),
2094
+ _el$126 = _el$128.nextSibling;
2095
+ _$insert(_el$123, _$createComponent(Show, {
806
2096
  get when() {
807
2097
  return props.optionalTime;
808
2098
  },
@@ -815,25 +2105,25 @@ export function DateTimePicker(props) {
815
2105
  });
816
2106
  },
817
2107
  get children() {
818
- var _el$68 = _$getNextElement(_tmpl$18);
819
- var _ref$4 = timeField;
820
- typeof _ref$4 === "function" ? _$use(_ref$4, _el$68) : timeField = _el$68;
821
- _$insert(_el$68, _$createComponent(Show, {
2108
+ var _el$124 = _$getNextElement(_tmpl$28);
2109
+ var _ref$12 = timeField;
2110
+ typeof _ref$12 === "function" ? _$use(_ref$12, _el$124) : timeField = _el$124;
2111
+ _$insert(_el$124, _$createComponent(Show, {
822
2112
  get when() {
823
2113
  return withTime();
824
2114
  },
825
2115
  get fallback() {
826
2116
  return (() => {
827
- var _el$73 = _$getNextElement(_tmpl$20),
828
- _el$74 = _el$73.firstChild,
829
- _el$75 = _el$74.nextSibling,
830
- [_el$76, _co$17] = _$getNextMarker(_el$75.nextSibling);
831
- _el$73.$$click = addTime;
832
- var _ref$5 = addTimeButton;
833
- typeof _ref$5 === "function" ? _$use(_ref$5, _el$73) : addTimeButton = _el$73;
834
- _$insert(_el$73, () => messages().addTime, _el$76, _co$17);
2117
+ var _el$129 = _$getNextElement(_tmpl$29),
2118
+ _el$130 = _el$129.firstChild,
2119
+ _el$131 = _el$130.nextSibling,
2120
+ [_el$132, _co$30] = _$getNextMarker(_el$131.nextSibling);
2121
+ _el$129.$$click = addTime;
2122
+ var _ref$13 = addTimeButton;
2123
+ typeof _ref$13 === "function" ? _$use(_ref$13, _el$129) : addTimeButton = _el$129;
2124
+ _$insert(_el$129, () => messages().addTime, _el$132, _co$30);
835
2125
  _$runHydrationEvents();
836
- return _el$73;
2126
+ return _el$129;
837
2127
  })();
838
2128
  },
839
2129
  get children() {
@@ -843,32 +2133,32 @@ export function DateTimePicker(props) {
843
2133
  },
844
2134
  onChange: setDraftTime
845
2135
  }), (() => {
846
- var _el$69 = _$getNextElement(_tmpl$17);
847
- _el$69.$$click = removeTime;
2136
+ var _el$125 = _$getNextElement(_tmpl$27);
2137
+ _el$125.$$click = removeTime;
848
2138
  _$effect(_p$ => {
849
- var _v$22 = messages().removeTime,
850
- _v$23 = messages().removeTime;
851
- _v$22 !== _p$.e && _$setAttribute(_el$69, "aria-label", _p$.e = _v$22);
852
- _v$23 !== _p$.t && _$setAttribute(_el$69, "title", _p$.t = _v$23);
2139
+ var _v$50 = messages().removeTime,
2140
+ _v$51 = messages().removeTime;
2141
+ _v$50 !== _p$.e && _$setAttribute(_el$125, "aria-label", _p$.e = _v$50);
2142
+ _v$51 !== _p$.t && _$setAttribute(_el$125, "title", _p$.t = _v$51);
853
2143
  return _p$;
854
2144
  }, {
855
2145
  e: undefined,
856
2146
  t: undefined
857
2147
  });
858
2148
  _$runHydrationEvents();
859
- return _el$69;
2149
+ return _el$125;
860
2150
  })()];
861
2151
  }
862
2152
  }));
863
- _$effect(() => _$setAttribute(_el$68, "data-with-time", withTime() ? "true" : undefined));
864
- return _el$68;
2153
+ _$effect(() => _$setAttribute(_el$124, "data-with-time", withTime() ? "true" : undefined));
2154
+ return _el$124;
865
2155
  }
866
- }), _el$72, _co$16);
867
- _el$70.$$click = apply;
868
- _$insert(_el$70, () => messages().apply);
869
- _$effect(() => _$setProperty(_el$70, "disabled", !canApply()));
2156
+ }), _el$128, _co$29);
2157
+ _el$126.$$click = apply;
2158
+ _$insert(_el$126, () => messages().apply);
2159
+ _$effect(() => _$setProperty(_el$126, "disabled", !canApply()));
870
2160
  _$runHydrationEvents();
871
- return _el$67;
2161
+ return _el$123;
872
2162
  })()];
873
2163
  }
874
2164
  });
@@ -909,7 +2199,10 @@ export function DateRangePicker(props) {
909
2199
  setPreviewDate(null);
910
2200
  setStartTime(next.start.time || "09:00");
911
2201
  setEndTime(next.end.time || "10:00");
912
- setVisibleMonth(parseDateValue(next.start.date || next.end.date, dateConfig()));
2202
+ setVisibleMonth(parseDateValue(openingDay(next.start.date || next.end.date, {
2203
+ min: props.min,
2204
+ max: props.max
2205
+ }, dateConfig()), dateConfig()));
913
2206
  };
914
2207
  const valueLabel = () => {
915
2208
  if (!value().start && !value().end) return "";
@@ -919,19 +2212,19 @@ export function DateRangePicker(props) {
919
2212
  const valueContent = () => {
920
2213
  const format = withTime() ? formatDateTimeValue : displayDate;
921
2214
  return (() => {
922
- var _el$77 = _$getNextElement(_tmpl$21),
923
- _el$78 = _el$77.firstChild,
924
- _el$79 = _el$78.nextSibling,
925
- _el$80 = _el$79.nextSibling;
926
- _$insert(_el$78, (() => {
927
- var _c$ = _$memo(() => !!value().start);
928
- return () => _c$() ? format(value().start, dateConfig()) : messages().start;
2215
+ var _el$133 = _$getNextElement(_tmpl$30),
2216
+ _el$134 = _el$133.firstChild,
2217
+ _el$135 = _el$134.nextSibling,
2218
+ _el$136 = _el$135.nextSibling;
2219
+ _$insert(_el$134, (() => {
2220
+ var _c$3 = _$memo(() => !!value().start);
2221
+ return () => _c$3() ? format(value().start, dateConfig()) : messages().start;
929
2222
  })());
930
- _$insert(_el$80, (() => {
931
- var _c$2 = _$memo(() => !!value().end);
932
- return () => _c$2() ? format(value().end, dateConfig()) : "End";
2223
+ _$insert(_el$136, (() => {
2224
+ var _c$4 = _$memo(() => !!value().end);
2225
+ return () => _c$4() ? format(value().end, dateConfig()) : "End";
933
2226
  })());
934
- return _el$77;
2227
+ return _el$133;
935
2228
  })();
936
2229
  };
937
2230
  const selectDate = value => {
@@ -985,151 +2278,171 @@ export function DateRangePicker(props) {
985
2278
  close();
986
2279
  commitFieldValue(props, value);
987
2280
  };
988
- return _$createComponent(PickerShell, {
989
- owner: props,
990
- icon: "ti ti-calendar-stats",
991
- valueLabel: valueLabel,
992
- valueContent: valueContent,
993
- clearValue: {
994
- start: null,
995
- end: null
996
- },
997
- get timezone() {
998
- return _$memo(() => !!withTime())() ? dateConfig().timeZone : undefined;
2281
+ return _$createComponent(Show, {
2282
+ get when() {
2283
+ return props.appearance === "plain" || withTime();
999
2284
  },
1000
- footerMeta: () => _$createComponent(Show, {
1001
- get when() {
1002
- return durationLabel();
1003
- },
1004
- get children() {
1005
- var _el$81 = _$getNextElement(_tmpl$22),
1006
- _el$82 = _el$81.firstChild,
1007
- _el$83 = _el$82.nextSibling,
1008
- [_el$84, _co$18] = _$getNextMarker(_el$83.nextSibling);
1009
- _$insert(_el$81, durationLabel, _el$84, _co$18);
1010
- return _el$81;
1011
- }
1012
- }),
1013
- onOpen: syncDraft,
1014
- get wide() {
1015
- return Boolean(props.datePresets?.length || props.presets?.length);
2285
+ get fallback() {
2286
+ return _$createComponent(DateRangeTextField, {
2287
+ owner: props,
2288
+ value: value,
2289
+ dateConfig: dateConfig
2290
+ });
1016
2291
  },
1017
- children: close => [(() => {
1018
- var _el$85 = _$getNextElement(_tmpl$16),
1019
- _el$86 = _el$85.firstChild,
1020
- [_el$87, _co$19] = _$getNextMarker(_el$86.nextSibling),
1021
- _el$88 = _el$87.nextSibling,
1022
- [_el$89, _co$20] = _$getNextMarker(_el$88.nextSibling);
1023
- _$insert(_el$85, _$createComponent(Show, {
1024
- get when() {
1025
- return props.datePresets?.length;
2292
+ get children() {
2293
+ return _$createComponent(PickerShell, {
2294
+ owner: props,
2295
+ icon: "ti ti-calendar-stats",
2296
+ valueLabel: valueLabel,
2297
+ valueContent: valueContent,
2298
+ clearValue: {
2299
+ start: null,
2300
+ end: null
1026
2301
  },
1027
- get fallback() {
1028
- return _$createComponent(PresetRail, {
1029
- get presets() {
1030
- return props.presets;
1031
- },
1032
- onSelect: value => {
1033
- close();
1034
- commitFieldValue(props, value);
1035
- }
1036
- });
2302
+ get timezone() {
2303
+ return _$memo(() => !!withTime())() ? dateConfig().timeZone : undefined;
1037
2304
  },
1038
- get children() {
1039
- return _$createComponent(PresetRail, {
1040
- get presets() {
1041
- return props.datePresets;
2305
+ footerMeta: () => _$createComponent(Show, {
2306
+ get when() {
2307
+ return durationLabel();
2308
+ },
2309
+ get children() {
2310
+ var _el$137 = _$getNextElement(_tmpl$25),
2311
+ _el$138 = _el$137.firstChild,
2312
+ _el$139 = _el$138.nextSibling,
2313
+ [_el$140, _co$31] = _$getNextMarker(_el$139.nextSibling);
2314
+ _$insert(_el$137, durationLabel, _el$140, _co$31);
2315
+ return _el$137;
2316
+ }
2317
+ }),
2318
+ onOpen: syncDraft,
2319
+ get wide() {
2320
+ return Boolean(props.datePresets?.length || props.presets?.length);
2321
+ },
2322
+ children: close => [(() => {
2323
+ var _el$141 = _$getNextElement(_tmpl$21),
2324
+ _el$142 = _el$141.firstChild,
2325
+ [_el$143, _co$32] = _$getNextMarker(_el$142.nextSibling),
2326
+ _el$144 = _el$143.nextSibling,
2327
+ [_el$145, _co$33] = _$getNextMarker(_el$144.nextSibling);
2328
+ _$insert(_el$141, _$createComponent(Show, {
2329
+ get when() {
2330
+ return props.datePresets?.length;
1042
2331
  },
1043
- onSelect: value => {
1044
- setDraftRange(value ? {
1045
- start: value,
1046
- end: value
1047
- } : {
1048
- start: null,
1049
- end: null
2332
+ get fallback() {
2333
+ return _$createComponent(PresetRail, {
2334
+ get presets() {
2335
+ return props.presets;
2336
+ },
2337
+ onSelect: value => {
2338
+ close();
2339
+ commitFieldValue(props, value);
2340
+ }
2341
+ });
2342
+ },
2343
+ get children() {
2344
+ return _$createComponent(PresetRail, {
2345
+ get presets() {
2346
+ return props.datePresets;
2347
+ },
2348
+ onSelect: value => {
2349
+ setDraftRange(value ? {
2350
+ start: value,
2351
+ end: value
2352
+ } : {
2353
+ start: null,
2354
+ end: null
2355
+ });
2356
+ if (value) setVisibleMonth(parseDateValue(value, dateConfig()));
2357
+ }
1050
2358
  });
1051
- if (value) setVisibleMonth(parseDateValue(value, dateConfig()));
1052
2359
  }
1053
- });
1054
- }
1055
- }), _el$87, _co$19);
1056
- _$insert(_el$85, _$createComponent(DatePickerPanel, {
1057
- visibleMonth: visibleMonth,
1058
- setVisibleMonth: setVisibleMonth,
1059
- range: displayRange,
1060
- focusDate: () => draftRange().start,
1061
- onSelect: selectDate,
1062
- onDayPreview: value => setPreviewDate(rangeAnchor(draftRange(), anchor()) ? value : null),
1063
- get dateConfig() {
1064
- return dateConfig();
1065
- }
1066
- }), _el$89, _co$20);
1067
- return _el$85;
1068
- })(), _$createComponent(Show, {
1069
- get when() {
1070
- return withTime();
1071
- },
1072
- get children() {
1073
- var _el$90 = _$getNextElement(_tmpl$23),
1074
- _el$91 = _el$90.firstChild,
1075
- [_el$92, _co$21] = _$getNextMarker(_el$91.nextSibling),
1076
- _el$93 = _el$92.nextSibling,
1077
- [_el$94, _co$22] = _$getNextMarker(_el$93.nextSibling);
1078
- _$insert(_el$90, _$createComponent(TimeInput, {
1079
- get label() {
1080
- return messages().start;
1081
- },
1082
- get time() {
1083
- return startTime();
1084
- },
1085
- onChange: setStartTime
1086
- }), _el$92, _co$21);
1087
- _$insert(_el$90, _$createComponent(TimeInput, {
1088
- get label() {
1089
- return messages().end;
1090
- },
1091
- get time() {
1092
- return endTime();
2360
+ }), _el$143, _co$32);
2361
+ _$insert(_el$141, _$createComponent(DatePickerPanel, {
2362
+ visibleMonth: visibleMonth,
2363
+ setVisibleMonth: setVisibleMonth,
2364
+ range: displayRange,
2365
+ focusDate: () => draftRange().start,
2366
+ onSelect: selectDate,
2367
+ onDayPreview: value => setPreviewDate(rangeAnchor(draftRange(), anchor()) ? value : null),
2368
+ get dateConfig() {
2369
+ return dateConfig();
2370
+ },
2371
+ get min() {
2372
+ return props.min;
2373
+ },
2374
+ get max() {
2375
+ return props.max;
2376
+ }
2377
+ }), _el$145, _co$33);
2378
+ return _el$141;
2379
+ })(), _$createComponent(Show, {
2380
+ get when() {
2381
+ return withTime();
1093
2382
  },
1094
- onChange: setEndTime
1095
- }), _el$94, _co$22);
1096
- return _el$90;
1097
- }
1098
- }), (() => {
1099
- var _el$95 = _$getNextElement(_tmpl$19),
1100
- _el$98 = _el$95.firstChild,
1101
- [_el$99, _co$23] = _$getNextMarker(_el$98.nextSibling),
1102
- _el$97 = _el$99.nextSibling;
1103
- _$insert(_el$95, _$createComponent(Show, {
1104
- get when() {
1105
- return _$memo(() => !!withTime())() && props.durationPresets?.length;
1106
- },
1107
- get children() {
1108
- var _el$96 = _$getNextElement(_tmpl$24);
1109
- _$insert(_el$96, _$createComponent(For, {
1110
- get each() {
1111
- return props.durationPresets;
2383
+ get children() {
2384
+ var _el$146 = _$getNextElement(_tmpl$31),
2385
+ _el$147 = _el$146.firstChild,
2386
+ [_el$148, _co$34] = _$getNextMarker(_el$147.nextSibling),
2387
+ _el$149 = _el$148.nextSibling,
2388
+ [_el$150, _co$35] = _$getNextMarker(_el$149.nextSibling);
2389
+ _$insert(_el$146, _$createComponent(TimeInput, {
2390
+ get label() {
2391
+ return messages().start;
2392
+ },
2393
+ get time() {
2394
+ return startTime();
2395
+ },
2396
+ onChange: setStartTime
2397
+ }), _el$148, _co$34);
2398
+ _$insert(_el$146, _$createComponent(TimeInput, {
2399
+ get label() {
2400
+ return messages().end;
2401
+ },
2402
+ get time() {
2403
+ return endTime();
2404
+ },
2405
+ onChange: setEndTime
2406
+ }), _el$150, _co$35);
2407
+ return _el$146;
2408
+ }
2409
+ }), (() => {
2410
+ var _el$151 = _$getNextElement(_tmpl$24),
2411
+ _el$154 = _el$151.firstChild,
2412
+ [_el$155, _co$36] = _$getNextMarker(_el$154.nextSibling),
2413
+ _el$153 = _el$155.nextSibling;
2414
+ _$insert(_el$151, _$createComponent(Show, {
2415
+ get when() {
2416
+ return _$memo(() => !!withTime())() && props.durationPresets?.length;
1112
2417
  },
1113
- children: preset => (() => {
1114
- var _el$100 = _$getNextElement(_tmpl$7);
1115
- _el$100.$$click = () => applyDuration(preset.minutes);
1116
- _$insert(_el$100, () => preset.label);
1117
- _$effect(() => _$setAttribute(_el$100, "aria-pressed", durationMinutes() === preset.minutes));
1118
- _$runHydrationEvents();
1119
- return _el$100;
1120
- })()
1121
- }));
1122
- _$effect(() => _$setAttribute(_el$96, "aria-label", messages().durationPresets));
1123
- return _el$96;
1124
- }
1125
- }), _el$99, _co$23);
1126
- _el$97.$$click = () => commit(close);
1127
- _$insert(_el$97, () => messages().apply);
1128
- _$effect(() => _$setProperty(_el$97, "disabled", Boolean(draftRange().start) !== Boolean(draftRange().end) || Boolean(withTime() && draftRange().start && draftRange().end && (!isCompleteTime(startTime()) || !isCompleteTime(endTime())))));
1129
- _$runHydrationEvents();
1130
- return _el$95;
1131
- })()]
2418
+ get children() {
2419
+ var _el$152 = _$getNextElement(_tmpl$32);
2420
+ _$insert(_el$152, _$createComponent(For, {
2421
+ get each() {
2422
+ return props.durationPresets;
2423
+ },
2424
+ children: preset => (() => {
2425
+ var _el$156 = _$getNextElement(_tmpl$7);
2426
+ _el$156.$$click = () => applyDuration(preset.minutes);
2427
+ _$insert(_el$156, () => preset.label);
2428
+ _$effect(() => _$setAttribute(_el$156, "aria-pressed", durationMinutes() === preset.minutes));
2429
+ _$runHydrationEvents();
2430
+ return _el$156;
2431
+ })()
2432
+ }));
2433
+ _$effect(() => _$setAttribute(_el$152, "aria-label", messages().durationPresets));
2434
+ return _el$152;
2435
+ }
2436
+ }), _el$155, _co$36);
2437
+ _el$153.$$click = () => commit(close);
2438
+ _$insert(_el$153, () => messages().apply);
2439
+ _$effect(() => _$setProperty(_el$153, "disabled", Boolean(draftRange().start) !== Boolean(draftRange().end) || Boolean(withTime() && draftRange().start && draftRange().end && (!isCompleteTime(startTime()) || !isCompleteTime(endTime())))));
2440
+ _$runHydrationEvents();
2441
+ return _el$151;
2442
+ })()]
2443
+ });
2444
+ }
1132
2445
  });
1133
2446
  }
1134
- _$delegateEvents(["click", "keydown", "input"]);
2447
+ _$delegateEvents(["click", "keydown", "input", "focusout", "pointerdown"]);
1135
2448
  //# sourceMappingURL=DatePicker.js.map