@human-kit/svelte-components 1.0.0-alpha.2 → 1.0.0-alpha.4

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 (217) hide show
  1. package/dist/FOCUS_STATE_CONTRACT.md +63 -0
  2. package/dist/FOCUS_STATE_REVIEW_TEMPLATE.md +70 -0
  3. package/dist/calendar/README.md +2 -1
  4. package/dist/calendar/TODO.md +21 -107
  5. package/dist/calendar/body-cell/README.md +15 -0
  6. package/dist/calendar/body-cell/calendar-body-cell.svelte +116 -41
  7. package/dist/calendar/grid/README.md +13 -0
  8. package/dist/calendar/grid-body/README.md +13 -0
  9. package/dist/calendar/grid-header/README.md +13 -0
  10. package/dist/calendar/header-cell/README.md +14 -0
  11. package/dist/calendar/heading/README.md +13 -0
  12. package/dist/calendar/root/README.md +24 -0
  13. package/dist/calendar/root/calendar-root-test.svelte +4 -0
  14. package/dist/calendar/root/calendar-root-test.svelte.d.ts +1 -0
  15. package/dist/calendar/root/calendar-root.svelte +3 -0
  16. package/dist/calendar/root/calendar-root.svelte.d.ts +1 -0
  17. package/dist/calendar/root/context.d.ts +4 -0
  18. package/dist/calendar/root/context.js +28 -25
  19. package/dist/calendar/root/date-utils.d.ts +1 -1
  20. package/dist/calendar/root/date-utils.js +16 -26
  21. package/dist/calendar/trigger-next/README.md +14 -0
  22. package/dist/calendar/trigger-previous/README.md +14 -0
  23. package/dist/clock/README.md +75 -0
  24. package/dist/clock/axis/README.md +24 -0
  25. package/dist/clock/axis/clock-axis.svelte +37 -0
  26. package/dist/clock/axis/clock-axis.svelte.d.ts +8 -0
  27. package/dist/clock/hooks/use-wheel-scroll.svelte.d.ts +16 -0
  28. package/dist/clock/hooks/use-wheel-scroll.svelte.js +336 -0
  29. package/dist/clock/index.d.ts +10 -0
  30. package/dist/clock/index.js +10 -0
  31. package/dist/clock/index.parts.d.ts +4 -0
  32. package/dist/clock/index.parts.js +4 -0
  33. package/dist/clock/root/README.md +38 -0
  34. package/dist/clock/root/clock-root-test.svelte +62 -0
  35. package/dist/clock/root/clock-root-test.svelte.d.ts +14 -0
  36. package/dist/clock/root/clock-root.svelte +329 -0
  37. package/dist/clock/root/clock-root.svelte.d.ts +25 -0
  38. package/dist/clock/root/context.d.ts +22 -0
  39. package/dist/clock/root/context.js +15 -0
  40. package/dist/clock/root/resolve-visible-columns.d.ts +7 -0
  41. package/dist/clock/root/resolve-visible-columns.js +16 -0
  42. package/dist/clock/root/time-utils.d.ts +48 -0
  43. package/dist/clock/root/time-utils.js +314 -0
  44. package/dist/clock/root/wheel-options.d.ts +17 -0
  45. package/dist/clock/root/wheel-options.js +63 -0
  46. package/dist/clock/wheel-column/README.md +25 -0
  47. package/dist/clock/wheel-column/clock-wheel-column-bindable-test.svelte +16 -0
  48. package/dist/clock/wheel-column/clock-wheel-column-bindable-test.svelte.d.ts +3 -0
  49. package/dist/clock/wheel-column/clock-wheel-column-custom-snippet-test.svelte +29 -0
  50. package/dist/clock/wheel-column/clock-wheel-column-custom-snippet-test.svelte.d.ts +6 -0
  51. package/dist/clock/wheel-column/clock-wheel-column-default-height-test.svelte +11 -0
  52. package/dist/clock/wheel-column/clock-wheel-column-default-height-test.svelte.d.ts +3 -0
  53. package/dist/clock/wheel-column/clock-wheel-column-test.svelte +38 -0
  54. package/dist/clock/wheel-column/clock-wheel-column-test.svelte.d.ts +12 -0
  55. package/dist/clock/wheel-column/clock-wheel-column-tp-test.svelte +38 -0
  56. package/dist/clock/wheel-column/clock-wheel-column-tp-test.svelte.d.ts +12 -0
  57. package/dist/clock/wheel-column/clock-wheel-column-untagged-snippet-test.svelte +29 -0
  58. package/dist/clock/wheel-column/clock-wheel-column-untagged-snippet-test.svelte.d.ts +6 -0
  59. package/dist/clock/wheel-column/clock-wheel-column.svelte +499 -0
  60. package/dist/clock/wheel-column/clock-wheel-column.svelte.d.ts +17 -0
  61. package/dist/clock/wheel-item/README.md +17 -0
  62. package/dist/clock/wheel-item/clock-wheel-item.svelte +49 -0
  63. package/dist/clock/wheel-item/clock-wheel-item.svelte.d.ts +17 -0
  64. package/dist/combobox/TODO.md +28 -175
  65. package/dist/combobox/button/combobox-button.svelte +2 -0
  66. package/dist/combobox/root/combobox.svelte +30 -0
  67. package/dist/datepicker/README.md +100 -0
  68. package/dist/datepicker/TODO.md +28 -0
  69. package/dist/datepicker/calendar/README.md +19 -0
  70. package/dist/datepicker/calendar/date-picker-calendar-unsafe-props-test.svelte +60 -0
  71. package/dist/datepicker/calendar/date-picker-calendar-unsafe-props-test.svelte.d.ts +3 -0
  72. package/dist/datepicker/calendar/date-picker-calendar.svelte +65 -0
  73. package/dist/datepicker/calendar/date-picker-calendar.svelte.d.ts +10 -0
  74. package/dist/datepicker/index.d.ts +18 -0
  75. package/dist/datepicker/index.js +18 -0
  76. package/dist/datepicker/index.parts.d.ts +14 -0
  77. package/dist/datepicker/index.parts.js +14 -0
  78. package/dist/datepicker/input/README.md +15 -0
  79. package/dist/datepicker/input/date-picker-input.svelte +108 -0
  80. package/dist/datepicker/input/date-picker-input.svelte.d.ts +11 -0
  81. package/dist/datepicker/internal/strict-props.d.ts +2 -0
  82. package/dist/datepicker/internal/strict-props.js +28 -0
  83. package/dist/datepicker/popover/README.md +20 -0
  84. package/dist/datepicker/popover/date-picker-popover-handler-test.svelte +57 -0
  85. package/dist/datepicker/popover/date-picker-popover-handler-test.svelte.d.ts +3 -0
  86. package/dist/datepicker/popover/date-picker-popover-unsafe-props-test.svelte +45 -0
  87. package/dist/datepicker/popover/date-picker-popover-unsafe-props-test.svelte.d.ts +18 -0
  88. package/dist/datepicker/popover/date-picker-popover.svelte +87 -0
  89. package/dist/datepicker/popover/date-picker-popover.svelte.d.ts +7 -0
  90. package/dist/datepicker/root/README.md +38 -0
  91. package/dist/datepicker/root/context.d.ts +43 -0
  92. package/dist/datepicker/root/context.js +15 -0
  93. package/dist/datepicker/root/date-picker-bindable-empty-test.svelte +24 -0
  94. package/dist/datepicker/root/date-picker-bindable-empty-test.svelte.d.ts +3 -0
  95. package/dist/datepicker/root/date-picker-bindable-test.svelte +41 -0
  96. package/dist/datepicker/root/date-picker-bindable-test.svelte.d.ts +3 -0
  97. package/dist/datepicker/root/date-picker-empty-test.svelte +47 -0
  98. package/dist/datepicker/root/date-picker-empty-test.svelte.d.ts +3 -0
  99. package/dist/datepicker/root/date-picker-locale-typing-test.svelte +47 -0
  100. package/dist/datepicker/root/date-picker-locale-typing-test.svelte.d.ts +3 -0
  101. package/dist/datepicker/root/date-picker-open-cancel-test.svelte +54 -0
  102. package/dist/datepicker/root/date-picker-open-cancel-test.svelte.d.ts +8 -0
  103. package/dist/datepicker/root/date-picker-root.svelte +495 -0
  104. package/dist/datepicker/root/date-picker-root.svelte.d.ts +24 -0
  105. package/dist/datepicker/root/date-picker-test.svelte +86 -0
  106. package/dist/datepicker/root/date-picker-test.svelte.d.ts +13 -0
  107. package/dist/datepicker/root/date-utils.d.ts +17 -0
  108. package/dist/datepicker/root/date-utils.js +138 -0
  109. package/dist/datepicker/root/draft-evaluation.d.ts +13 -0
  110. package/dist/datepicker/root/draft-evaluation.js +56 -0
  111. package/dist/datepicker/root/focus-controller.d.ts +3 -0
  112. package/dist/datepicker/root/focus-controller.js +15 -0
  113. package/dist/datepicker/root/open-change.d.ts +5 -0
  114. package/dist/datepicker/root/open-change.js +13 -0
  115. package/dist/datepicker/root/open-controller.d.ts +7 -0
  116. package/dist/datepicker/root/open-controller.js +15 -0
  117. package/dist/datepicker/root/segment-controller.d.ts +8 -0
  118. package/dist/datepicker/root/segment-controller.js +53 -0
  119. package/dist/datepicker/root/segment-state.d.ts +18 -0
  120. package/dist/datepicker/root/segment-state.js +134 -0
  121. package/dist/datepicker/root/value-commit.d.ts +4 -0
  122. package/dist/datepicker/root/value-commit.js +8 -0
  123. package/dist/datepicker/segment/README.md +14 -0
  124. package/dist/datepicker/segment/date-picker-segment.svelte +319 -0
  125. package/dist/datepicker/segment/date-picker-segment.svelte.d.ts +9 -0
  126. package/dist/datepicker/trigger/README.md +14 -0
  127. package/dist/datepicker/trigger/date-picker-trigger.svelte +110 -0
  128. package/dist/datepicker/trigger/date-picker-trigger.svelte.d.ts +9 -0
  129. package/dist/dialog/content/dialog-content.svelte +6 -6
  130. package/dist/dialog/root/context.d.ts +2 -1
  131. package/dist/dialog/root/dialog-root.svelte +9 -2
  132. package/dist/index.d.ts +8 -0
  133. package/dist/index.js +8 -0
  134. package/dist/listbox/root/listbox.svelte +44 -0
  135. package/dist/popover/README.md +10 -0
  136. package/dist/popover/content/popover-content-standalone-test.svelte +28 -0
  137. package/dist/popover/content/popover-content-standalone-test.svelte.d.ts +6 -0
  138. package/dist/popover/content/popover-content-test.svelte +2 -1
  139. package/dist/popover/content/popover-content-test.svelte.d.ts +2 -1
  140. package/dist/popover/content/popover-content.svelte +91 -18
  141. package/dist/popover/content/popover-content.svelte.d.ts +5 -1
  142. package/dist/popover/index.d.ts +1 -1
  143. package/dist/popover/index.js +1 -3
  144. package/dist/popover/root/README.md +10 -15
  145. package/dist/popover/root/context.d.ts +16 -7
  146. package/dist/popover/root/context.js +0 -2
  147. package/dist/popover/root/focus-state.d.ts +4 -0
  148. package/dist/popover/root/focus-state.js +33 -0
  149. package/dist/popover/root/popover-root.svelte +90 -17
  150. package/dist/popover/root/popover-root.svelte.d.ts +2 -1
  151. package/dist/popover/root/popover-test.svelte +2 -1
  152. package/dist/popover/root/popover-test.svelte.d.ts +2 -1
  153. package/dist/popover/trigger/popover-trigger-button.svelte +4 -4
  154. package/dist/popover/trigger/popover-trigger.svelte +1 -1
  155. package/dist/portal/portal.svelte +3 -1
  156. package/dist/primitives/click-outside.d.ts +1 -1
  157. package/dist/primitives/click-outside.js +1 -1
  158. package/dist/primitives/focus-trap.d.ts +7 -2
  159. package/dist/primitives/focus-trap.js +50 -17
  160. package/dist/primitives/index.d.ts +1 -0
  161. package/dist/primitives/index.js +1 -0
  162. package/dist/primitives/input-modality.d.ts +7 -0
  163. package/dist/primitives/input-modality.js +125 -0
  164. package/dist/test-utils/focus-contract.d.ts +3 -0
  165. package/dist/test-utils/focus-contract.js +26 -0
  166. package/dist/timepicker/IMPLEMENTATION_PLAN.md +254 -0
  167. package/dist/timepicker/README.md +97 -0
  168. package/dist/timepicker/TODO.md +86 -0
  169. package/dist/timepicker/clock/README.md +14 -0
  170. package/dist/timepicker/clock/time-picker-clock-test.svelte +45 -0
  171. package/dist/timepicker/clock/time-picker-clock-test.svelte.d.ts +11 -0
  172. package/dist/timepicker/clock/time-picker-clock.svelte +65 -0
  173. package/dist/timepicker/clock/time-picker-clock.svelte.d.ts +10 -0
  174. package/dist/timepicker/index.d.ts +14 -0
  175. package/dist/timepicker/index.js +14 -0
  176. package/dist/timepicker/index.parts.d.ts +8 -0
  177. package/dist/timepicker/index.parts.js +8 -0
  178. package/dist/timepicker/input/README.md +15 -0
  179. package/dist/timepicker/input/time-picker-input-forwarding-test.svelte +40 -0
  180. package/dist/timepicker/input/time-picker-input-forwarding-test.svelte.d.ts +3 -0
  181. package/dist/timepicker/input/time-picker-input.svelte +109 -0
  182. package/dist/timepicker/input/time-picker-input.svelte.d.ts +11 -0
  183. package/dist/timepicker/internal/strict-props.d.ts +4 -0
  184. package/dist/timepicker/internal/strict-props.js +51 -0
  185. package/dist/timepicker/popover/README.md +20 -0
  186. package/dist/timepicker/popover/time-picker-popover-unsafe-props-test.svelte +22 -0
  187. package/dist/timepicker/popover/time-picker-popover-unsafe-props-test.svelte.d.ts +3 -0
  188. package/dist/timepicker/popover/time-picker-popover.svelte +89 -0
  189. package/dist/timepicker/popover/time-picker-popover.svelte.d.ts +7 -0
  190. package/dist/timepicker/root/README.md +42 -0
  191. package/dist/timepicker/root/context.d.ts +51 -0
  192. package/dist/timepicker/root/context.js +15 -0
  193. package/dist/timepicker/root/time-picker-12h-test.svelte +22 -0
  194. package/dist/timepicker/root/time-picker-12h-test.svelte.d.ts +3 -0
  195. package/dist/timepicker/root/time-picker-bindable-test.svelte +25 -0
  196. package/dist/timepicker/root/time-picker-bindable-test.svelte.d.ts +3 -0
  197. package/dist/timepicker/root/time-picker-empty-test.svelte +20 -0
  198. package/dist/timepicker/root/time-picker-empty-test.svelte.d.ts +3 -0
  199. package/dist/timepicker/root/time-picker-root.svelte +625 -0
  200. package/dist/timepicker/root/time-picker-root.svelte.d.ts +28 -0
  201. package/dist/timepicker/root/time-picker-test.svelte +72 -0
  202. package/dist/timepicker/root/time-picker-test.svelte.d.ts +15 -0
  203. package/dist/timepicker/root/time-utils.d.ts +1 -0
  204. package/dist/timepicker/root/time-utils.js +3 -0
  205. package/dist/timepicker/segment/README.md +14 -0
  206. package/dist/timepicker/segment/time-picker-segment.svelte +365 -0
  207. package/dist/timepicker/segment/time-picker-segment.svelte.d.ts +9 -0
  208. package/dist/timepicker/trigger/README.md +14 -0
  209. package/dist/timepicker/trigger/time-picker-trigger-forwarding-test.svelte +35 -0
  210. package/dist/timepicker/trigger/time-picker-trigger-forwarding-test.svelte.d.ts +3 -0
  211. package/dist/timepicker/trigger/time-picker-trigger.svelte +122 -0
  212. package/dist/timepicker/trigger/time-picker-trigger.svelte.d.ts +9 -0
  213. package/dist/utils/date-only.d.ts +11 -0
  214. package/dist/utils/date-only.js +53 -0
  215. package/dist/utils/index.d.ts +1 -0
  216. package/dist/utils/index.js +1 -0
  217. package/package.json +16 -1
@@ -0,0 +1,47 @@
1
+ <script lang="ts">
2
+ import { LocaleProvider } from '../../index';
3
+ import DatePicker from '../index';
4
+
5
+ let selectedValue = $state<string | null>('');
6
+ </script>
7
+
8
+ <LocaleProvider locale="es-AR">
9
+ <DatePicker.Root
10
+ onChange={(nextValue) => {
11
+ selectedValue = nextValue;
12
+ }}
13
+ >
14
+ <DatePicker.Input class="date-picker-input" aria-label="Date input">
15
+ {#snippet children(segment)}
16
+ <DatePicker.Segment class="date-picker-segment" {segment} />
17
+ {/snippet}
18
+ </DatePicker.Input>
19
+ <DatePicker.Trigger class="date-picker-trigger">Open calendar</DatePicker.Trigger>
20
+
21
+ <DatePicker.Popover class="date-picker-popover">
22
+ <DatePicker.Calendar class="date-picker-calendar">
23
+ <div class="flex items-center justify-between gap-2 p-2">
24
+ <DatePicker.TriggerPrevious />
25
+ <DatePicker.Heading />
26
+ <DatePicker.TriggerNext />
27
+ </div>
28
+ <DatePicker.Grid>
29
+ <DatePicker.GridHeader>
30
+ {#snippet children(dayLabel: string)}
31
+ <DatePicker.HeaderCell>
32
+ {dayLabel}
33
+ </DatePicker.HeaderCell>
34
+ {/snippet}
35
+ </DatePicker.GridHeader>
36
+ <DatePicker.GridBody>
37
+ {#snippet children(date: string)}
38
+ <DatePicker.BodyCell {date} />
39
+ {/snippet}
40
+ </DatePicker.GridBody>
41
+ </DatePicker.Grid>
42
+ </DatePicker.Calendar>
43
+ </DatePicker.Popover>
44
+ </DatePicker.Root>
45
+ </LocaleProvider>
46
+
47
+ <p data-testid="date-picker-value">{selectedValue}</p>
@@ -0,0 +1,3 @@
1
+ declare const DatePickerLocaleTypingTest: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type DatePickerLocaleTypingTest = ReturnType<typeof DatePickerLocaleTypingTest>;
3
+ export default DatePickerLocaleTypingTest;
@@ -0,0 +1,54 @@
1
+ <script lang="ts">
2
+ import DatePicker from '../index';
3
+
4
+ type Props = {
5
+ cancelOpen?: boolean;
6
+ cancelClose?: boolean;
7
+ defaultOpen?: boolean;
8
+ };
9
+
10
+ let { cancelOpen = false, cancelClose = false, defaultOpen = false }: Props = $props();
11
+ </script>
12
+
13
+ <DatePicker.Root
14
+ {defaultOpen}
15
+ onOpenChange={(nextOpen, details) => {
16
+ if (nextOpen && cancelOpen) {
17
+ details.cancel();
18
+ }
19
+ if (!nextOpen && cancelClose) {
20
+ details.cancel();
21
+ }
22
+ }}
23
+ >
24
+ <DatePicker.Input class="date-picker-input" aria-label="Date input">
25
+ {#snippet children(segment)}
26
+ <DatePicker.Segment class="date-picker-segment" {segment} />
27
+ {/snippet}
28
+ </DatePicker.Input>
29
+ <DatePicker.Trigger class="date-picker-trigger">Open calendar</DatePicker.Trigger>
30
+
31
+ <DatePicker.Popover class="date-picker-popover">
32
+ <DatePicker.Calendar class="date-picker-calendar">
33
+ <div class="flex items-center justify-between gap-2 p-2">
34
+ <DatePicker.TriggerPrevious />
35
+ <DatePicker.Heading />
36
+ <DatePicker.TriggerNext />
37
+ </div>
38
+ <DatePicker.Grid>
39
+ <DatePicker.GridHeader>
40
+ {#snippet children(dayLabel: string)}
41
+ <DatePicker.HeaderCell>
42
+ {dayLabel}
43
+ </DatePicker.HeaderCell>
44
+ {/snippet}
45
+ </DatePicker.GridHeader>
46
+ <DatePicker.GridBody>
47
+ {#snippet children(date: string)}
48
+ <DatePicker.BodyCell {date} />
49
+ {/snippet}
50
+ </DatePicker.GridBody>
51
+ </DatePicker.Grid>
52
+ </DatePicker.Calendar>
53
+ </DatePicker.Popover>
54
+ </DatePicker.Root>
@@ -0,0 +1,8 @@
1
+ type Props = {
2
+ cancelOpen?: boolean;
3
+ cancelClose?: boolean;
4
+ defaultOpen?: boolean;
5
+ };
6
+ declare const DatePickerOpenCancelTest: import("svelte").Component<Props, {}, "">;
7
+ type DatePickerOpenCancelTest = ReturnType<typeof DatePickerOpenCancelTest>;
8
+ export default DatePickerOpenCancelTest;
@@ -0,0 +1,495 @@
1
+ <script lang="ts">
2
+ import { untrack, type Snippet } from 'svelte';
3
+ import { useLocaleContextOptional } from '../../locale-provider/context';
4
+ import { setDatePickerContext, type DatePickerContext } from './context';
5
+ import {
6
+ buildDatePickerSegments,
7
+ compareDatePickerValues,
8
+ getDatePickerSegmentLabel,
9
+ getDatePickerSegmentOrder,
10
+ isValidDatePickerValue,
11
+ type DatePickerDateValue,
12
+ type DatePickerEditableSegmentType,
13
+ type DatePickerSegmentType
14
+ } from './date-utils';
15
+ import type { DatePickerOpenChangeDetails, DatePickerOpenChangeReason } from './context';
16
+ import {
17
+ clampSegment,
18
+ clampSegmentDraft,
19
+ createEmptySegmentDraft,
20
+ getSegmentNumericValue,
21
+ normalizeSegmentInput,
22
+ toDraftFromValue,
23
+ type DatePickerSegmentDraft,
24
+ type EditableSegmentType
25
+ } from './segment-state';
26
+ import { evaluateDatePickerDraft } from './draft-evaluation';
27
+ import {
28
+ applyTriggerSelectionCloseState,
29
+ computeDatePickerFocusWithin
30
+ } from './focus-controller';
31
+ import { getInteractionModality } from '../../primitives/input-modality';
32
+ import { resolveDatePickerOpenChangeDetails } from './open-controller';
33
+ import { normalizeBindableDatePickerValue, normalizeDatePickerValue } from './value-commit';
34
+ import {
35
+ createDatePickerSegmentRefs,
36
+ focusLastDatePickerSegment,
37
+ focusNextDatePickerSegment,
38
+ focusPreviousDatePickerSegment,
39
+ registerDatePickerSegmentRef
40
+ } from './segment-controller';
41
+
42
+ type DatePickerRootProps = {
43
+ id?: string;
44
+ value?: DatePickerDateValue | null;
45
+ defaultValue?: DatePickerDateValue | null;
46
+ onChange?: (value: DatePickerDateValue | null) => void;
47
+ isDisabled?: boolean;
48
+ isReadOnly?: boolean;
49
+ minValue?: DatePickerDateValue;
50
+ maxValue?: DatePickerDateValue;
51
+ isDateUnavailable?: (date: DatePickerDateValue) => boolean;
52
+ open?: boolean;
53
+ defaultOpen?: boolean;
54
+ onOpenChange?: (open: boolean, details: DatePickerOpenChangeDetails) => void;
55
+ closeOnSelect?: boolean;
56
+ children?: Snippet;
57
+ class?: string;
58
+ 'aria-label'?: string;
59
+ };
60
+
61
+ const generatedInstanceId = $props.id();
62
+
63
+ let {
64
+ id,
65
+ value = $bindable(),
66
+ defaultValue,
67
+ onChange,
68
+ isDisabled = false,
69
+ isReadOnly = false,
70
+ minValue,
71
+ maxValue,
72
+ isDateUnavailable,
73
+ open = $bindable(),
74
+ defaultOpen = false,
75
+ onOpenChange,
76
+ closeOnSelect = true,
77
+ children,
78
+ class: className = '',
79
+ 'aria-label': ariaLabel
80
+ }: DatePickerRootProps = $props();
81
+
82
+ const instanceId = untrack(() => id) ?? generatedInstanceId;
83
+
84
+ let triggerRef: HTMLElement | null = $state(null);
85
+ let openInternal = $state((() => defaultOpen)());
86
+ let focusVisible = $state(false);
87
+ let focusWithin = $state(false);
88
+
89
+ const initialValueProp = untrack(() => value);
90
+ const initialDefaultValue = untrack(() =>
91
+ normalizeDatePickerValue(defaultValue, isValidDatePickerValue)
92
+ );
93
+ const initialPropValue =
94
+ initialValueProp === undefined
95
+ ? initialDefaultValue
96
+ : normalizeDatePickerValue(initialValueProp, isValidDatePickerValue);
97
+
98
+ let valueInternal = $state<DatePickerDateValue | null>(initialPropValue);
99
+ let segmentDraft = $state<DatePickerSegmentDraft>(
100
+ initialPropValue ? toDraftFromValue(initialPropValue) : createEmptySegmentDraft()
101
+ );
102
+ let activeSegment = $state<Exclude<DatePickerSegmentType, 'literal'> | null>(null);
103
+ let segmentTypeBuffer = $state<DatePickerSegmentDraft>(createEmptySegmentDraft());
104
+ let segmentRefs = createDatePickerSegmentRefs();
105
+ let lastPublishedValue = $state<DatePickerDateValue | null>(initialPropValue);
106
+
107
+ if (initialValueProp === undefined) {
108
+ value = initialPropValue;
109
+ } else if (initialValueProp !== initialPropValue) {
110
+ value = initialPropValue;
111
+ }
112
+
113
+ const localeContext = useLocaleContextOptional();
114
+ const localeStore = localeContext?.locale;
115
+ const localeFromContext = $derived.by(() => {
116
+ if (!localeStore) return undefined;
117
+ return $localeStore;
118
+ });
119
+ const resolvedLocale = $derived(
120
+ localeFromContext ?? Intl.DateTimeFormat().resolvedOptions().locale
121
+ );
122
+
123
+ $effect(() => {
124
+ if (open !== undefined && open !== openInternal) {
125
+ openInternal = open;
126
+ }
127
+ });
128
+
129
+ $effect(() => {
130
+ if (value === undefined) return;
131
+ const nextValue = normalizeDatePickerValue(value, isValidDatePickerValue);
132
+ if (nextValue === lastPublishedValue) return;
133
+ lastPublishedValue = nextValue;
134
+ valueInternal = nextValue;
135
+ segmentDraft = nextValue ? toDraftFromValue(nextValue) : createEmptySegmentDraft();
136
+ segmentTypeBuffer = createEmptySegmentDraft();
137
+ });
138
+
139
+ const normalizedMinValue = $derived(isValidDatePickerValue(minValue) ? minValue : undefined);
140
+ const normalizedMaxValue = $derived(isValidDatePickerValue(maxValue) ? maxValue : undefined);
141
+ const segmentOrder = $derived(getDatePickerSegmentOrder(resolvedLocale));
142
+ const draftEvaluation = $derived.by(() =>
143
+ evaluateDatePickerDraft(segmentDraft, {
144
+ isDateOutOfRange,
145
+ isDateUnavailable: isDateUnavailableInternal
146
+ })
147
+ );
148
+ const isInvalidDraft = $derived(draftEvaluation.isInvalid);
149
+
150
+ function publishCommittedValue(
151
+ nextValue: DatePickerDateValue | null,
152
+ emitChange: boolean
153
+ ): boolean {
154
+ const normalizedBindableValue = normalizeBindableDatePickerValue(value);
155
+ const didInternalChange = valueInternal !== nextValue;
156
+ const didBindableValueChange = normalizedBindableValue !== nextValue;
157
+
158
+ if (!didInternalChange && !didBindableValueChange) return false;
159
+
160
+ valueInternal = nextValue;
161
+ if (didBindableValueChange) {
162
+ value = nextValue;
163
+ }
164
+ lastPublishedValue = nextValue;
165
+
166
+ if (emitChange && didInternalChange) {
167
+ onChange?.(nextValue);
168
+ }
169
+
170
+ return true;
171
+ }
172
+
173
+ function closeCalendarAfterSelection(selectionFocusVisible: boolean) {
174
+ setFocusVisible(selectionFocusVisible);
175
+ setOpen(false, { reason: 'close-press' });
176
+ applyTriggerSelectionCloseState(triggerRef, selectionFocusVisible ? 'keyboard' : 'pointer');
177
+ }
178
+
179
+ function isDateOutOfRange(valueToCheck: DatePickerDateValue): boolean {
180
+ if (!isValidDatePickerValue(valueToCheck)) return true;
181
+ if (normalizedMinValue && compareDatePickerValues(valueToCheck, normalizedMinValue) < 0) {
182
+ return true;
183
+ }
184
+ if (normalizedMaxValue && compareDatePickerValues(valueToCheck, normalizedMaxValue) > 0) {
185
+ return true;
186
+ }
187
+ return false;
188
+ }
189
+
190
+ function isDateUnavailableInternal(valueToCheck: DatePickerDateValue): boolean {
191
+ if (isDateOutOfRange(valueToCheck)) return true;
192
+ return isDateUnavailable?.(valueToCheck) ?? false;
193
+ }
194
+
195
+ function setOpen(
196
+ nextOpen: boolean,
197
+ details?: DatePickerOpenChangeDetails | { reason?: DatePickerOpenChangeReason; event?: Event }
198
+ ) {
199
+ if (openInternal === nextOpen) return;
200
+ const eventDetails = resolveDatePickerOpenChangeDetails(details);
201
+
202
+ onOpenChange?.(nextOpen, eventDetails);
203
+ if (eventDetails.isCanceled) return;
204
+
205
+ openInternal = nextOpen;
206
+ open = nextOpen;
207
+ }
208
+
209
+ function setValue(nextValue: DatePickerDateValue, source: 'calendar' | 'input' = 'calendar') {
210
+ if (!isValidDatePickerValue(nextValue) || isDateUnavailableInternal(nextValue)) return;
211
+ if (isDisabled || isReadOnly) return;
212
+ const selectionFocusVisible = getInteractionModality() === 'keyboard';
213
+
214
+ if (valueInternal === nextValue) {
215
+ if (source === 'calendar' && closeOnSelect) {
216
+ closeCalendarAfterSelection(selectionFocusVisible);
217
+ }
218
+ return;
219
+ }
220
+
221
+ publishCommittedValue(nextValue, true);
222
+
223
+ if (source === 'calendar') {
224
+ segmentDraft = toDraftFromValue(nextValue);
225
+ segmentTypeBuffer = createEmptySegmentDraft();
226
+ }
227
+
228
+ if (source === 'calendar' && closeOnSelect) {
229
+ closeCalendarAfterSelection(selectionFocusVisible);
230
+ }
231
+ }
232
+
233
+ function openPopover(reason: DatePickerOpenChangeReason = 'imperative-action', event?: Event) {
234
+ if (isDisabled || isReadOnly) return;
235
+ setOpen(true, { reason, event });
236
+ }
237
+
238
+ function closePopover(reason: DatePickerOpenChangeReason = 'imperative-action', event?: Event) {
239
+ setOpen(false, { reason, event });
240
+ }
241
+
242
+ function togglePopover(reason: DatePickerOpenChangeReason = 'trigger-press', event?: Event) {
243
+ if (isDisabled || isReadOnly) return;
244
+ setOpen(!openInternal, { reason, event });
245
+ }
246
+
247
+ function setTriggerRef(element: HTMLElement | null) {
248
+ if (triggerRef === element) return;
249
+ triggerRef = element;
250
+ }
251
+
252
+ function setFocusVisible(visible: boolean) {
253
+ if (focusVisible === visible) return;
254
+ focusVisible = visible;
255
+ }
256
+
257
+ function syncFocusWithin() {
258
+ const nextWithin = computeDatePickerFocusWithin(instanceId);
259
+ if (!nextWithin && focusVisible) {
260
+ focusVisible = false;
261
+ }
262
+ if (!nextWithin && activeSegment !== null) {
263
+ activeSegment = null;
264
+ segmentTypeBuffer = createEmptySegmentDraft();
265
+ }
266
+ if (focusWithin === nextWithin) return;
267
+ focusWithin = nextWithin;
268
+ }
269
+
270
+ function setActiveSegment(segment: Exclude<DatePickerSegmentType, 'literal'> | null) {
271
+ if (activeSegment === segment) return;
272
+ activeSegment = segment;
273
+ segmentTypeBuffer = createEmptySegmentDraft();
274
+ }
275
+
276
+ function getSegmentValue(type: Exclude<DatePickerSegmentType, 'literal'>): string {
277
+ if (type === 'day') return segmentDraft.day;
278
+ if (type === 'month') return segmentDraft.month;
279
+ return segmentDraft.year;
280
+ }
281
+
282
+ function setSegmentValueInternal(
283
+ type: EditableSegmentType,
284
+ nextValue: string,
285
+ fromTyping: boolean
286
+ ) {
287
+ if (isDisabled || isReadOnly) return;
288
+
289
+ const rawNumericLength = nextValue.replace(/\D/g, '').length;
290
+ const normalized = normalizeSegmentInput(type, nextValue);
291
+ const unconstrainedDraft = {
292
+ ...segmentDraft,
293
+ [type]: normalized
294
+ };
295
+ const nextDraft = clampSegmentDraft(unconstrainedDraft, type, fromTyping, rawNumericLength);
296
+ segmentDraft = nextDraft;
297
+ if (!fromTyping) {
298
+ segmentTypeBuffer = { ...segmentTypeBuffer, [type]: '' };
299
+ }
300
+
301
+ const evaluation = evaluateDatePickerDraft(nextDraft, {
302
+ isDateOutOfRange,
303
+ isDateUnavailable: isDateUnavailableInternal
304
+ });
305
+
306
+ if (evaluation.isCommitable && evaluation.value) {
307
+ setValue(evaluation.value, 'input');
308
+ return;
309
+ }
310
+
311
+ publishCommittedValue(null, true);
312
+ }
313
+
314
+ function setSegmentValue(type: Exclude<DatePickerSegmentType, 'literal'>, nextValue: string) {
315
+ setSegmentValueInternal(type, nextValue, false);
316
+ }
317
+
318
+ function registerSegmentRef(type: DatePickerEditableSegmentType, element: HTMLElement | null) {
319
+ registerDatePickerSegmentRef(segmentRefs, type, element);
320
+ }
321
+
322
+ function focusNextSegment(type: DatePickerEditableSegmentType): boolean {
323
+ return focusNextDatePickerSegment(segmentRefs, segmentOrder, type);
324
+ }
325
+
326
+ function focusPreviousSegment(type: DatePickerEditableSegmentType): boolean {
327
+ return focusPreviousDatePickerSegment(segmentRefs, segmentOrder, type);
328
+ }
329
+
330
+ function focusLastSegment(): boolean {
331
+ return focusLastDatePickerSegment(segmentRefs, segmentOrder);
332
+ }
333
+
334
+ function focusNextPlaceholderOrLastSegment(): boolean {
335
+ for (const type of segmentOrder) {
336
+ const element = segmentRefs[type];
337
+ if (!element) continue;
338
+ if (element.dataset.placeholder === 'true') {
339
+ element.focus();
340
+ return true;
341
+ }
342
+ }
343
+ return focusLastSegment();
344
+ }
345
+
346
+ function getSegmentLabel(type: DatePickerEditableSegmentType): string {
347
+ return getDatePickerSegmentLabel(resolvedLocale, type);
348
+ }
349
+
350
+ function formatSegment(
351
+ type: Exclude<DatePickerSegmentType, 'literal'>,
352
+ valueToFormat: number
353
+ ): string {
354
+ if (type === 'year') return `${valueToFormat}`;
355
+ return `${valueToFormat}`;
356
+ }
357
+
358
+ function typeSegmentDigit(
359
+ type: Exclude<DatePickerSegmentType, 'literal'>,
360
+ digit: string
361
+ ): boolean {
362
+ if (!/^\d$/.test(digit)) return false;
363
+ const maxLength = type === 'year' ? 4 : 2;
364
+ const previous = segmentTypeBuffer[type];
365
+ const next = `${previous}${digit}`.slice(-maxLength);
366
+ segmentTypeBuffer = { ...segmentTypeBuffer, [type]: next };
367
+ setSegmentValueInternal(type, next, true);
368
+
369
+ let didComplete = next.length >= maxLength;
370
+ if (!didComplete && next.length === 1) {
371
+ const firstDigit = Number(next);
372
+ if (type === 'day' && firstDigit >= 4) {
373
+ didComplete = true;
374
+ }
375
+ if (type === 'month' && firstDigit >= 2) {
376
+ didComplete = true;
377
+ }
378
+ }
379
+
380
+ if (next.length >= maxLength) {
381
+ segmentTypeBuffer = { ...segmentTypeBuffer, [type]: '' };
382
+ }
383
+ if (didComplete) {
384
+ segmentTypeBuffer = { ...segmentTypeBuffer, [type]: '' };
385
+ }
386
+ return didComplete;
387
+ }
388
+
389
+ function adjustSegmentValue(type: Exclude<DatePickerSegmentType, 'literal'>, step: number) {
390
+ if (isDisabled || isReadOnly) return;
391
+ const current = getSegmentNumericValue(type, segmentDraft, valueInternal);
392
+ const next = clampSegment(type, current + step);
393
+ setSegmentValue(type, formatSegment(type, next));
394
+ }
395
+
396
+ function getSegments() {
397
+ const baseSegments = buildDatePickerSegments(resolvedLocale, valueInternal ?? undefined);
398
+ return baseSegments.map((segment) => {
399
+ if (segment.type === 'literal') return segment;
400
+ const draftValue = segmentDraft[segment.type];
401
+ if (draftValue.length === 0) {
402
+ return {
403
+ ...segment,
404
+ value: '',
405
+ text: segment.placeholder,
406
+ isPlaceholder: true
407
+ };
408
+ }
409
+ return {
410
+ ...segment,
411
+ value: draftValue,
412
+ text: draftValue,
413
+ isPlaceholder: false
414
+ };
415
+ });
416
+ }
417
+
418
+ const context: DatePickerContext = {
419
+ get id() {
420
+ return instanceId;
421
+ },
422
+ get isDisabled() {
423
+ return isDisabled;
424
+ },
425
+ get isReadOnly() {
426
+ return isReadOnly;
427
+ },
428
+ get open() {
429
+ return openInternal;
430
+ },
431
+ get focusVisible() {
432
+ return focusVisible;
433
+ },
434
+ get focusWithin() {
435
+ return focusWithin;
436
+ },
437
+ get isInvalidDraft() {
438
+ return isInvalidDraft;
439
+ },
440
+ get activeSegment() {
441
+ return activeSegment;
442
+ },
443
+ get value() {
444
+ return valueInternal;
445
+ },
446
+ get locale() {
447
+ return resolvedLocale;
448
+ },
449
+ get triggerRef() {
450
+ return triggerRef;
451
+ },
452
+ setTriggerRef,
453
+ setFocusVisible,
454
+ syncFocusWithin,
455
+ setActiveSegment,
456
+ openPopover,
457
+ closePopover,
458
+ togglePopover,
459
+ onOpenChange: (nextOpen, details) => {
460
+ setOpen(nextOpen, details);
461
+ },
462
+ setValue,
463
+ typeSegmentDigit,
464
+ adjustSegmentValue,
465
+ isDateOutOfRange,
466
+ isDateUnavailable: isDateUnavailableInternal,
467
+ getSegments,
468
+ getSegmentValue,
469
+ setSegmentValue,
470
+ getSegmentLabel,
471
+ registerSegmentRef,
472
+ focusNextPlaceholderOrLastSegment,
473
+ focusNextSegment,
474
+ focusPreviousSegment,
475
+ focusLastSegment
476
+ };
477
+
478
+ setDatePickerContext(context);
479
+ </script>
480
+
481
+ <div
482
+ id={instanceId}
483
+ class={className}
484
+ data-disabled={isDisabled || undefined}
485
+ data-readonly={isReadOnly || undefined}
486
+ data-open={openInternal || undefined}
487
+ data-focus-visible={focusVisible || undefined}
488
+ data-focus-within={focusWithin || undefined}
489
+ data-invalid={isInvalidDraft || undefined}
490
+ aria-label={ariaLabel}
491
+ >
492
+ {#if children}
493
+ {@render children()}
494
+ {/if}
495
+ </div>
@@ -0,0 +1,24 @@
1
+ import { type Snippet } from 'svelte';
2
+ import { type DatePickerDateValue } from './date-utils';
3
+ import type { DatePickerOpenChangeDetails } from './context';
4
+ type DatePickerRootProps = {
5
+ id?: string;
6
+ value?: DatePickerDateValue | null;
7
+ defaultValue?: DatePickerDateValue | null;
8
+ onChange?: (value: DatePickerDateValue | null) => void;
9
+ isDisabled?: boolean;
10
+ isReadOnly?: boolean;
11
+ minValue?: DatePickerDateValue;
12
+ maxValue?: DatePickerDateValue;
13
+ isDateUnavailable?: (date: DatePickerDateValue) => boolean;
14
+ open?: boolean;
15
+ defaultOpen?: boolean;
16
+ onOpenChange?: (open: boolean, details: DatePickerOpenChangeDetails) => void;
17
+ closeOnSelect?: boolean;
18
+ children?: Snippet;
19
+ class?: string;
20
+ 'aria-label'?: string;
21
+ };
22
+ declare const DatePickerRoot: import("svelte").Component<DatePickerRootProps, {}, "value" | "open">;
23
+ type DatePickerRoot = ReturnType<typeof DatePickerRoot>;
24
+ export default DatePickerRoot;