@svelte-atoms/core 1.0.0-alpha.27 → 1.0.0-alpha.29

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 (186) hide show
  1. package/README.md +852 -645
  2. package/dist/components/accordion/accordion-root.svelte +61 -61
  3. package/dist/components/accordion/item/accordion-item-body.svelte +42 -42
  4. package/dist/components/accordion/item/accordion-item-header.svelte +50 -50
  5. package/dist/components/accordion/item/accordion-item-indicator.svelte +50 -50
  6. package/dist/components/accordion/item/accordion-item-root.svelte +65 -65
  7. package/dist/components/alert/alert-actions.svelte +43 -42
  8. package/dist/components/alert/alert-close-button.svelte +70 -72
  9. package/dist/components/alert/alert-content.svelte +43 -42
  10. package/dist/components/alert/alert-description.svelte +42 -41
  11. package/dist/components/alert/alert-icon.svelte +47 -46
  12. package/dist/components/alert/alert-root.svelte +103 -102
  13. package/dist/components/alert/alert-title.svelte +42 -41
  14. package/dist/components/alert/alert.stories.svelte +384 -23
  15. package/dist/components/alert/alert.stories.svelte.d.ts +2 -5
  16. package/dist/components/atom/html-atom.svelte +207 -201
  17. package/dist/components/atom/html-atom.svelte.d.ts +1 -1
  18. package/dist/components/atom/snippet-renderer.svelte +5 -0
  19. package/dist/components/atom/snippet-renderer.svelte.d.ts +5 -0
  20. package/dist/components/avatar/avatar.stories.svelte.d.ts +1 -1
  21. package/dist/components/badge/badge.stories.svelte.d.ts +1 -1
  22. package/dist/components/breadcrumb/breadcrumb.stories.svelte.d.ts +1 -1
  23. package/dist/components/button/button.stories.svelte +17 -14
  24. package/dist/components/calendar/atoms.d.ts +5 -0
  25. package/dist/components/calendar/atoms.js +5 -0
  26. package/dist/components/calendar/bond.svelte.d.ts +72 -0
  27. package/dist/components/calendar/bond.svelte.js +132 -0
  28. package/dist/components/calendar/calendar-body.svelte +107 -0
  29. package/dist/components/calendar/calendar-body.svelte.d.ts +8 -0
  30. package/dist/components/calendar/calendar-day.svelte +96 -0
  31. package/dist/components/calendar/calendar-day.svelte.d.ts +4 -0
  32. package/dist/components/calendar/calendar-header.svelte +29 -0
  33. package/dist/components/calendar/calendar-header.svelte.d.ts +6 -0
  34. package/dist/components/calendar/calendar-root.svelte +206 -0
  35. package/dist/components/calendar/calendar-root.svelte.d.ts +8 -0
  36. package/dist/components/calendar/calendar-week-day.svelte +34 -0
  37. package/dist/components/calendar/calendar-week-day.svelte.d.ts +9 -0
  38. package/dist/components/calendar/calendar.css +26 -0
  39. package/dist/components/calendar/calendar.stories.svelte +31 -0
  40. package/dist/components/calendar/calendar.stories.svelte.d.ts +26 -0
  41. package/dist/components/calendar/index.d.ts +4 -0
  42. package/dist/components/calendar/index.js +4 -0
  43. package/dist/components/calendar/runes.svelte.d.ts +3 -0
  44. package/dist/components/calendar/runes.svelte.js +25 -0
  45. package/dist/components/calendar/types.d.ts +62 -0
  46. package/dist/components/calendar/types.js +1 -0
  47. package/dist/components/card/card-body.svelte +39 -39
  48. package/dist/components/card/card-description.svelte +41 -41
  49. package/dist/components/card/card-footer.svelte +41 -41
  50. package/dist/components/card/card-header.svelte +41 -41
  51. package/dist/components/card/card-media.svelte +41 -41
  52. package/dist/components/card/card-root.svelte +91 -91
  53. package/dist/components/card/card-subtitle.svelte +41 -41
  54. package/dist/components/card/card-title.svelte +45 -45
  55. package/dist/components/collapsible/collapsible-body.svelte +39 -39
  56. package/dist/components/collapsible/collapsible-header.svelte +39 -39
  57. package/dist/components/collapsible/collapsible-indicator.svelte +50 -50
  58. package/dist/components/collapsible/collapsible-root.svelte +66 -66
  59. package/dist/components/combobox/combobox-root.svelte +65 -65
  60. package/dist/components/container/container.stories.svelte.d.ts +1 -1
  61. package/dist/components/contextmenu/contextmenu-trigger.svelte.d.ts +1 -1
  62. package/dist/components/datagrid/bond.svelte.d.ts +2 -2
  63. package/dist/components/datagrid/datagrid-body.svelte +37 -37
  64. package/dist/components/datagrid/datagrid-checkbox.svelte +101 -101
  65. package/dist/components/datagrid/datagrid-footer.svelte +34 -34
  66. package/dist/components/datagrid/datagrid-header.svelte +49 -49
  67. package/dist/components/datagrid/datagrid-root.svelte +2 -2
  68. package/dist/components/datagrid/datagrid.css +5 -47
  69. package/dist/components/datagrid/td/datagrid-td.svelte +66 -66
  70. package/dist/components/datagrid/th/datagrid-th.svelte +106 -106
  71. package/dist/components/datagrid/tr/datagrid-tr.svelte +88 -88
  72. package/dist/components/datagrid/types.d.ts +1 -1
  73. package/dist/components/date-picker/atoms.d.ts +3 -0
  74. package/dist/components/date-picker/atoms.js +3 -0
  75. package/dist/components/date-picker/bond.svelte.d.ts +67 -0
  76. package/dist/components/date-picker/bond.svelte.js +174 -0
  77. package/dist/components/date-picker/date-picker-calendar.svelte +67 -0
  78. package/dist/components/date-picker/date-picker-calendar.svelte.d.ts +4 -0
  79. package/dist/components/date-picker/date-picker-header.svelte +100 -0
  80. package/dist/components/date-picker/date-picker-header.svelte.d.ts +4 -0
  81. package/dist/components/date-picker/date-picker-months.svelte +142 -0
  82. package/dist/components/date-picker/date-picker-months.svelte.d.ts +4 -0
  83. package/dist/components/date-picker/date-picker-root.svelte +95 -0
  84. package/dist/components/date-picker/date-picker-root.svelte.d.ts +4 -0
  85. package/dist/components/date-picker/date-picker-years.svelte +205 -0
  86. package/dist/components/date-picker/date-picker-years.svelte.d.ts +4 -0
  87. package/dist/components/date-picker/date-picker.stories.svelte +42 -0
  88. package/dist/components/date-picker/date-picker.stories.svelte.d.ts +3 -0
  89. package/dist/components/date-picker/index.d.ts +3 -0
  90. package/dist/components/date-picker/index.js +3 -0
  91. package/dist/components/date-picker/types.d.ts +53 -0
  92. package/dist/components/date-picker/types.js +1 -0
  93. package/dist/components/dialog/dialog-body.svelte +39 -39
  94. package/dist/components/dialog/dialog-close-button.svelte +58 -58
  95. package/dist/components/dialog/dialog-content.svelte +1 -1
  96. package/dist/components/dialog/dialog-description.svelte +40 -40
  97. package/dist/components/dialog/dialog-footer.svelte +39 -39
  98. package/dist/components/dialog/dialog-header.svelte +39 -39
  99. package/dist/components/dialog/dialog-root.svelte +110 -110
  100. package/dist/components/dialog/dialog-title.svelte +41 -41
  101. package/dist/components/drawer/drawer-backdrop.svelte +38 -38
  102. package/dist/components/drawer/drawer-body.svelte +42 -42
  103. package/dist/components/drawer/drawer-content.svelte +42 -42
  104. package/dist/components/drawer/drawer-description.svelte +44 -44
  105. package/dist/components/drawer/drawer-footer.svelte +41 -41
  106. package/dist/components/drawer/drawer-header.svelte +43 -43
  107. package/dist/components/drawer/drawer-root.svelte +93 -93
  108. package/dist/components/drawer/drawer-title.svelte +44 -44
  109. package/dist/components/dropdown/dropdown-query.svelte +54 -54
  110. package/dist/components/dropdown/dropdown-root.svelte +59 -59
  111. package/dist/components/dropdown/dropdown-trigger.svelte +41 -41
  112. package/dist/components/dropdown/dropdown-value.svelte +60 -60
  113. package/dist/components/element/types.d.ts +1 -1
  114. package/dist/components/form/bond.svelte.d.ts +1 -1
  115. package/dist/components/form/field/field-control.svelte +48 -48
  116. package/dist/components/form/field/field-label.svelte +24 -24
  117. package/dist/components/form/field/field-root.svelte +59 -59
  118. package/dist/components/icon/icon.svelte +44 -44
  119. package/dist/components/image/image.stories.svelte.d.ts +1 -1
  120. package/dist/components/index.d.ts +4 -0
  121. package/dist/components/index.js +4 -0
  122. package/dist/components/input/input-control.svelte +103 -103
  123. package/dist/components/label/label.svelte +25 -25
  124. package/dist/components/lazy/index.d.ts +1 -0
  125. package/dist/components/lazy/index.js +1 -0
  126. package/dist/components/lazy/lazy.stories.svelte +35 -0
  127. package/dist/components/lazy/lazy.stories.svelte.d.ts +19 -0
  128. package/dist/components/lazy/lazy.svelte +28 -0
  129. package/dist/components/lazy/lazy.svelte.d.ts +5 -0
  130. package/dist/components/lazy/types.d.ts +10 -0
  131. package/dist/components/lazy/types.js +1 -0
  132. package/dist/components/menu/menu-list.svelte +40 -39
  133. package/dist/components/menu/menu-list.svelte.d.ts +1 -0
  134. package/dist/components/popover/popover-arrow.svelte +111 -111
  135. package/dist/components/popover/popover-content.svelte +178 -139
  136. package/dist/components/popover/popover-root.svelte +16 -17
  137. package/dist/components/popover/popover.stories.svelte +0 -15
  138. package/dist/components/portal/portal-root.svelte +83 -83
  139. package/dist/components/portal/teleport.svelte +50 -50
  140. package/dist/components/qr-code/index.d.ts +2 -0
  141. package/dist/components/qr-code/index.js +2 -0
  142. package/dist/components/qr-code/qr-code.stories.svelte +27 -0
  143. package/dist/components/qr-code/qr-code.stories.svelte.d.ts +26 -0
  144. package/dist/components/qr-code/qr-code.svelte +75 -0
  145. package/dist/components/qr-code/qr-code.svelte.d.ts +4 -0
  146. package/dist/components/qr-code/types.d.ts +14 -0
  147. package/dist/components/qr-code/types.js +1 -0
  148. package/dist/components/radio/radio.svelte +109 -109
  149. package/dist/components/radio/types.svelte.d.ts +1 -1
  150. package/dist/components/scrollable/scrollable-container.svelte +82 -82
  151. package/dist/components/scrollable/scrollable-content.svelte +41 -41
  152. package/dist/components/scrollable/scrollable-root.svelte +100 -100
  153. package/dist/components/scrollable/scrollable-thumb.svelte +75 -75
  154. package/dist/components/scrollable/scrollable-track.svelte +59 -59
  155. package/dist/components/scrollable/scrollable.stories.svelte.d.ts +1 -1
  156. package/dist/components/sidebar/bond.svelte.d.ts +0 -5
  157. package/dist/components/sidebar/bond.svelte.js +1 -12
  158. package/dist/components/sidebar/sidebar-content.svelte +39 -39
  159. package/dist/components/sidebar/sidebar-content.svelte.d.ts +2 -2
  160. package/dist/components/sidebar/sidebar-root.svelte +41 -68
  161. package/dist/components/sidebar/sidebar-root.svelte.d.ts +2 -2
  162. package/dist/components/sidebar/sidebar.stories.svelte +54 -52
  163. package/dist/components/sidebar/types.d.ts +6 -6
  164. package/dist/components/tabs/tab/tab-body.svelte +52 -52
  165. package/dist/components/tabs/tab/tab-description.svelte +41 -41
  166. package/dist/components/tabs/tab/tab-header.svelte +71 -71
  167. package/dist/components/tabs/tab/tab-root.svelte +86 -86
  168. package/dist/components/toast/toast-description.svelte +38 -38
  169. package/dist/components/toast/toast-root.svelte +61 -61
  170. package/dist/components/toast/toast-title.svelte +35 -35
  171. package/dist/components/tree/tree-body.svelte +39 -39
  172. package/dist/components/tree/tree-header.svelte +54 -54
  173. package/dist/components/tree/tree-indicator.svelte +40 -40
  174. package/dist/components/tree/tree-root.svelte +65 -65
  175. package/dist/components/virtual/virtual-root.svelte +239 -239
  176. package/dist/context/preset.svelte.d.ts +1 -1
  177. package/dist/icons/icon-arrow-down.svelte.d.ts +1 -1
  178. package/dist/icons/icon-checkmark.svelte.d.ts +1 -1
  179. package/dist/icons/icon-close.svelte.d.ts +1 -1
  180. package/dist/icons/icon-more-vert.svelte.d.ts +1 -1
  181. package/dist/runes/container.svelte.d.ts +2 -2
  182. package/dist/shared/bond.svelte.d.ts +1 -1
  183. package/dist/utils/state.d.ts +1 -1
  184. package/dist/utils/state.js +2 -1
  185. package/llm/variants.md +650 -103
  186. package/package.json +465 -437
@@ -0,0 +1,142 @@
1
+ <script lang="ts">
2
+ import { animate } from 'motion';
3
+ import { getYear, getMonth, setMonth } from 'date-fns';
4
+ import { cn } from '../../utils';
5
+ import { HtmlAtom } from '../atom';
6
+ import { DatePickerBond } from './bond.svelte';
7
+ import type { DatePickerMonthsProps } from './types';
8
+
9
+ const datePicker = DatePickerBond.get();
10
+
11
+ const pivote = $derived(datePicker?.state.props.pivote ?? new Date());
12
+
13
+ const currentYear = $derived(getYear(pivote));
14
+ const currentMonth = $derived(getMonth(pivote));
15
+
16
+ // Generate array of months
17
+ const monthsGrid = [
18
+ 'Jan',
19
+ 'Feb',
20
+ 'Mar',
21
+ 'Apr',
22
+ 'May',
23
+ 'Jun',
24
+ 'Jul',
25
+ 'Aug',
26
+ 'Sep',
27
+ 'Oct',
28
+ 'Nov',
29
+ 'Dec'
30
+ ];
31
+
32
+ let {
33
+ class: klass = '',
34
+ preset = 'datepicker.months',
35
+ children,
36
+ ...restProps
37
+ }: DatePickerMonthsProps = $props();
38
+
39
+ function enter(node: HTMLElement) {
40
+ animate(
41
+ node,
42
+ {
43
+ scale: [0.8, 1]
44
+ },
45
+ { duration: 100 / 1000, ease: 'circOut' }
46
+ );
47
+ return {
48
+ duration: 100
49
+ };
50
+ }
51
+
52
+ function exit(node: HTMLElement) {
53
+ animate(
54
+ node,
55
+ {
56
+ scale: 0.8
57
+ },
58
+ { duration: 100 / 1000, ease: 'circOut' }
59
+ );
60
+ return {
61
+ duration: 100
62
+ };
63
+ }
64
+
65
+ function handleMonthSelect(monthIndex: number) {
66
+ if (!datePicker?.state.props.pivote) return;
67
+ const current = datePicker.state.props.pivote;
68
+ datePicker.state.props.pivote = setMonth(current, monthIndex);
69
+
70
+ datePicker.state.closeMonthsPicker();
71
+ }
72
+
73
+ function handleYearPicker() {
74
+ if (!datePicker) return;
75
+ datePicker.state.openYearsPicker();
76
+ }
77
+ </script>
78
+
79
+ {#if datePicker.state.isMonthsPickerOpen}
80
+ <HtmlAtom
81
+ class={['absolute inset-0 z-1 flex flex-col gap-2 bg-inherit opacity-0', '$preset', klass]}
82
+ enter={(node) => {
83
+ animate(
84
+ node,
85
+ {
86
+ opacity: [0, 1]
87
+ },
88
+ { duration: 100 / 1000, ease: 'anticipate' }
89
+ );
90
+ return {
91
+ duration: 100
92
+ };
93
+ }}
94
+ exit={(node) => {
95
+ animate(
96
+ node,
97
+ {
98
+ opacity: 0
99
+ },
100
+ { duration: 100 / 1000, ease: 'anticipate' }
101
+ );
102
+ return {
103
+ duration: 100
104
+ };
105
+ }}
106
+ {preset}
107
+ {...restProps}
108
+ >
109
+ <HtmlAtom class="flex flex-1 flex-col gap-2" {enter} {exit}>
110
+ <!-- Year Display -->
111
+ <nav
112
+ class="border-border text-foreground flex h-12 items-center justify-center gap-2 border-b px-2 py-2"
113
+ >
114
+ <button
115
+ class="text-foreground cursor-pointer text-center text-sm font-semibold"
116
+ onclick={handleYearPicker}
117
+ >
118
+ {currentYear}
119
+ </button>
120
+ </nav>
121
+
122
+ <!-- Months Grid -->
123
+ <div class="grid flex-1 grid-cols-3 gap-1 px-2 pb-2">
124
+ {#each monthsGrid as month, index}
125
+ {@const isSelected = index === currentMonth}
126
+ <button
127
+ type="button"
128
+ class={cn(
129
+ 'hover:bg-foreground/10 active:bg-foreground/20 rounded-md px-3 py-2 text-sm transition-colors',
130
+ isSelected && 'bg-primary text-primary-foreground hover:bg-primary/90'
131
+ )}
132
+ onclick={() => handleMonthSelect(index)}
133
+ aria-label="Select {month}"
134
+ aria-current={isSelected ? 'date' : undefined}
135
+ >
136
+ {month}
137
+ </button>
138
+ {/each}
139
+ </div>
140
+ </HtmlAtom>
141
+ </HtmlAtom>
142
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { DatePickerMonthsProps } from './types';
2
+ declare const DatePickerMonths: import("svelte").Component<DatePickerMonthsProps, {}, "">;
3
+ type DatePickerMonths = ReturnType<typeof DatePickerMonths>;
4
+ export default DatePickerMonths;
@@ -0,0 +1,95 @@
1
+ <script lang="ts">
2
+ import { startOfDay } from 'date-fns';
3
+ import { defineProperty, defineState } from '../../utils';
4
+ import { Root } from '../popover/atoms';
5
+ import type { CalendarRange } from '../calendar/types';
6
+ import { DatePickerBond, DatePickerBondState, type DatePickerBondProps } from './bond.svelte';
7
+ import type { DatePickerRootProps } from './types';
8
+
9
+ let {
10
+ open = $bindable(false),
11
+ value = $bindable(undefined),
12
+ range = $bindable([undefined, undefined]),
13
+ pivote = $bindable(new Date()),
14
+ start = $bindable(startOfDay(new Date())),
15
+ end = $bindable(undefined),
16
+ min = undefined,
17
+ max = undefined,
18
+ type = 'single',
19
+ offset = 2,
20
+ factory = _factory,
21
+ children,
22
+ ...restProps
23
+ }: DatePickerRootProps = $props();
24
+
25
+ const seed = {};
26
+
27
+ const bondProps = defineState<DatePickerBondProps>(
28
+ [
29
+ defineProperty(
30
+ 'open',
31
+ () => open,
32
+ (v) => {
33
+ open = v;
34
+ }
35
+ ),
36
+ defineProperty(
37
+ 'range',
38
+ () => range,
39
+ (v: CalendarRange) => {
40
+ range = v;
41
+ value = v[0];
42
+ }
43
+ ),
44
+ defineProperty(
45
+ 'value',
46
+ () => range?.[0],
47
+ (v) => {
48
+ range[0] = v;
49
+ }
50
+ ),
51
+ defineProperty(
52
+ 'pivote',
53
+ () => pivote,
54
+ (v: Date) => (pivote = v)
55
+ ),
56
+ defineProperty(
57
+ 'start',
58
+ () => range[0],
59
+ (v: Date) => {
60
+ range[0] = v;
61
+ }
62
+ ),
63
+ defineProperty(
64
+ 'end',
65
+ () => range[1],
66
+ (v: Date | undefined) => {
67
+ range[1] = v;
68
+ }
69
+ ),
70
+ defineProperty(
71
+ 'min',
72
+ () => min,
73
+ (v: Date | undefined) => (min = v)
74
+ ),
75
+ defineProperty(
76
+ 'max',
77
+ () => max,
78
+ (v: Date | undefined) => (max = v)
79
+ ),
80
+ defineProperty('type', () => type ?? 'single')
81
+ ],
82
+ () => seed
83
+ );
84
+
85
+ const bond = factory().share();
86
+
87
+ function _factory() {
88
+ const bondState = new DatePickerBondState(() => bondProps);
89
+ return new DatePickerBond(bondState);
90
+ }
91
+ </script>
92
+
93
+ <Root bind:open extend={bondProps} {offset} {...restProps}>
94
+ {@render children?.({ datePicker: bond })}
95
+ </Root>
@@ -0,0 +1,4 @@
1
+ import type { DatePickerRootProps } from './types';
2
+ declare const DatePickerRoot: import("svelte").Component<DatePickerRootProps, {}, "value" | "end" | "range" | "open" | "start" | "pivote">;
3
+ type DatePickerRoot = ReturnType<typeof DatePickerRoot>;
4
+ export default DatePickerRoot;
@@ -0,0 +1,205 @@
1
+ <script lang="ts">
2
+ import { animate } from 'motion';
3
+ import { getYear, setYear } from 'date-fns';
4
+ import { cn } from '../../utils';
5
+ import { DatePickerBond } from './bond.svelte';
6
+ import type { DatePickerYearsProps } from './types';
7
+ import { HtmlAtom } from '../atom';
8
+ import { Icon } from '../icon';
9
+
10
+ const datePicker = DatePickerBond.get();
11
+
12
+ const pivote = $derived(datePicker?.state.props.pivote ?? new Date());
13
+
14
+ let pivoteYear = $derived(pivote.getFullYear());
15
+
16
+ const currentYear = $derived(getYear(pivote));
17
+
18
+ // Generate array of years to display (12 years: current ±5)
19
+ const yearsGrid = $derived.by(() => {
20
+ const years = [];
21
+ const startYear = pivoteYear - 5;
22
+ for (let i = 0; i < 12; i++) {
23
+ years.push(startYear + i);
24
+ }
25
+ return years;
26
+ });
27
+
28
+ let {
29
+ class: klass = '',
30
+ preset = 'datepicker.years',
31
+ children,
32
+ ...restProps
33
+ }: DatePickerYearsProps = $props();
34
+
35
+ let scrollTimeout: NodeJS.Timeout | undefined = undefined;
36
+
37
+ function enter(node: HTMLElement) {
38
+ animate(
39
+ node,
40
+ {
41
+ scale: [0.8, 1]
42
+ },
43
+ { duration: 100 / 1000, ease: 'circOut' }
44
+ );
45
+ return {
46
+ duration: 100
47
+ };
48
+ }
49
+
50
+ function exit(node: HTMLElement) {
51
+ animate(
52
+ node,
53
+ {
54
+ scale: 0.8
55
+ },
56
+ { duration: 100 / 1000, ease: 'circOut' }
57
+ );
58
+ return {
59
+ duration: 100
60
+ };
61
+ }
62
+
63
+ function handlePreviousYear() {
64
+ pivoteYear = pivoteYear - 1;
65
+ }
66
+
67
+ function handleNextYear() {
68
+ pivoteYear = pivoteYear + 1;
69
+ }
70
+
71
+ function handleYearSelect(year: number) {
72
+ if (!datePicker?.state.props.pivote) return;
73
+ const current = datePicker.state.props.pivote;
74
+ datePicker.state.props.pivote = setYear(current, year);
75
+
76
+ datePicker.state.closeYearsPicker();
77
+ }
78
+
79
+ function handleWheel(event: WheelEvent) {
80
+ event.preventDefault();
81
+
82
+ // Clear any existing timeout
83
+ if (scrollTimeout) {
84
+ clearTimeout(scrollTimeout);
85
+ }
86
+
87
+ // Debounce the scroll event to avoid rapid year changes
88
+ scrollTimeout = setTimeout(() => {
89
+ const direction = event.deltaY > 0 ? 1 : -1; // Positive = scroll down = next year
90
+ pivoteYear = pivoteYear + direction;
91
+ }, 50);
92
+ }
93
+ </script>
94
+
95
+ {#if datePicker.state.isYearsPickerOpen}
96
+ <HtmlAtom
97
+ class={['absolute inset-0 z-2 flex flex-col gap-2 bg-inherit opacity-0', '$preset', klass]}
98
+ enter={(node) => {
99
+ animate(
100
+ node,
101
+ {
102
+ opacity: [0, 1]
103
+ },
104
+ { duration: 100 / 1000, ease: 'anticipate' }
105
+ );
106
+ return {
107
+ duration: 100
108
+ };
109
+ }}
110
+ exit={(node) => {
111
+ animate(
112
+ node,
113
+ {
114
+ opacity: 0
115
+ },
116
+ { duration: 100 / 1000, ease: 'anticipate' }
117
+ );
118
+ return {
119
+ duration: 100
120
+ };
121
+ }}
122
+ onwheel={handleWheel}
123
+ {preset}
124
+ {...restProps}
125
+ >
126
+ <HtmlAtom class="flex flex-1 flex-col" {enter} {exit}>
127
+ <!-- Navigation Bar -->
128
+ <nav
129
+ class="border-border text-foreground flex h-12 items-center justify-between gap-2 border-b px-2 py-2"
130
+ >
131
+ <!-- Previous Year Button -->
132
+ <button
133
+ type="button"
134
+ class="hover:bg-foreground/10 active:bg-foreground/20 flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors"
135
+ onclick={handlePreviousYear}
136
+ aria-label="Previous year"
137
+ >
138
+ <Icon class="size-5">
139
+ <svg
140
+ xmlns="http://www.w3.org/2000/svg"
141
+ class="size-full"
142
+ viewBox="0 0 24 24"
143
+ fill="none"
144
+ stroke="currentColor"
145
+ stroke-width="2"
146
+ stroke-linecap="round"
147
+ stroke-linejoin="round"
148
+ >
149
+ <path d="M15 18l-6-6 6-6" />
150
+ </svg>
151
+ </Icon>
152
+ </button>
153
+
154
+ <!-- Year Display -->
155
+ <div class="flex-1">
156
+ <!-- {currentYear} -->
157
+ </div>
158
+
159
+ <!-- Next Year Button -->
160
+ <button
161
+ type="button"
162
+ class="hover:bg-foreground/10 active:bg-foreground/20 flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors"
163
+ onclick={handleNextYear}
164
+ aria-label="Next year"
165
+ >
166
+ <Icon class="size-5">
167
+ <svg
168
+ xmlns="http://www.w3.org/2000/svg"
169
+ class="size-full"
170
+ viewBox="0 0 24 24"
171
+ fill="none"
172
+ stroke="currentColor"
173
+ stroke-width="2"
174
+ stroke-linecap="round"
175
+ stroke-linejoin="round"
176
+ >
177
+ <path d="M9 18l6-6-6-6" />
178
+ </svg>
179
+ </Icon>
180
+ </button>
181
+ </nav>
182
+
183
+ <!-- Years Grid -->
184
+ <div class="grid flex-1 grid-cols-4 gap-1 px-2 py-2">
185
+ {#each yearsGrid as year}
186
+ {@const isSelected = year === pivote.getFullYear()}
187
+ {@const isCurrent = year === currentYear}
188
+ <button
189
+ type="button"
190
+ class={cn(
191
+ 'hover:bg-foreground/10 active:bg-foreground/20 rounded-md px-3 py-2 text-sm transition-colors',
192
+ isSelected && 'bg-primary text-primary-foreground hover:bg-primary/90',
193
+ isCurrent && !isSelected && 'ring-foreground/20 ring-1'
194
+ )}
195
+ onclick={() => handleYearSelect(year)}
196
+ aria-label="Select year {year}"
197
+ aria-current={isSelected ? 'date' : undefined}
198
+ >
199
+ {year}
200
+ </button>
201
+ {/each}
202
+ </div>
203
+ </HtmlAtom>
204
+ </HtmlAtom>
205
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { DatePickerYearsProps } from './types';
2
+ declare const DatePickerYears: import("svelte").Component<DatePickerYearsProps, {}, "">;
3
+ type DatePickerYears = ReturnType<typeof DatePickerYears>;
4
+ export default DatePickerYears;
@@ -0,0 +1,42 @@
1
+ <script module>
2
+ import { defineMeta } from '@storybook/addon-svelte-csf';
3
+
4
+ const { Story } = defineMeta({
5
+ title: 'Atoms/Date Picker'
6
+ });
7
+ </script>
8
+
9
+ <script lang="ts">
10
+ import { Root } from '../root';
11
+ import { DatePicker as ADatePicker } from '.';
12
+ import { Button } from '../button';
13
+ import { addDays, subDays } from 'date-fns';
14
+
15
+ let value: Date | undefined = $state(undefined);
16
+
17
+ let min = $state(subDays(new Date(), 5));
18
+ let max = $state(addDays(new Date(), 15));
19
+ </script>
20
+
21
+ <Story name="Date Picker">
22
+ {#snippet children({ args })}
23
+ <Root>
24
+ {#snippet children({})}
25
+ <div class="flex h-fit items-center justify-center">
26
+ <ADatePicker.Root bind:value {min} {max}>
27
+ <ADatePicker.Trigger base={Button} class="w-sm gap-4">
28
+ {#if value}
29
+ <div>{value.toDateString()}</div>
30
+ {:else}
31
+ <div>Open Date Picker</div>
32
+ {/if}
33
+
34
+ <ADatePicker.Indicator class="ml-auto" />
35
+ </ADatePicker.Trigger>
36
+ <ADatePicker.Calendar />
37
+ </ADatePicker.Root>
38
+ </div>
39
+ {/snippet}
40
+ </Root>
41
+ {/snippet}
42
+ </Story>
@@ -0,0 +1,3 @@
1
+ declare const DatePicker: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type DatePicker = ReturnType<typeof DatePicker>;
3
+ export default DatePicker;
@@ -0,0 +1,3 @@
1
+ export * as DatePicker from './atoms';
2
+ export * from './bond.svelte';
3
+ export * from './types';
@@ -0,0 +1,3 @@
1
+ export * as DatePicker from './atoms';
2
+ export * from './bond.svelte';
3
+ export * from './types';
@@ -0,0 +1,53 @@
1
+ import type { Component, Snippet } from 'svelte';
2
+ import type { Day, CalendarRange } from '../calendar/types';
3
+ import type { DatePickerBond } from './bond.svelte';
4
+ import type { Factory } from '../../types';
5
+ export interface DatePickerCalendarProps {
6
+ class?: string;
7
+ preset?: string;
8
+ children?: Snippet<[{
9
+ day: Day;
10
+ }]>;
11
+ Header?: Component;
12
+ Weekdays?: Component;
13
+ Body?: Component;
14
+ Day?: Component;
15
+ Months?: Component;
16
+ Years?: Component;
17
+ [key: string]: unknown;
18
+ }
19
+ export interface DatePickerHeaderProps {
20
+ class?: string;
21
+ preset?: string;
22
+ children?: Snippet;
23
+ [key: string]: unknown;
24
+ }
25
+ export interface DatePickerMonthsProps {
26
+ class?: string;
27
+ preset?: string;
28
+ children?: Snippet;
29
+ [key: string]: unknown;
30
+ }
31
+ export interface DatePickerYearsProps {
32
+ class?: string;
33
+ preset?: string;
34
+ children?: Snippet;
35
+ [key: string]: unknown;
36
+ }
37
+ export interface DatePickerRootProps {
38
+ open?: boolean;
39
+ value?: Date;
40
+ range?: CalendarRange;
41
+ pivote?: Date;
42
+ start?: Date;
43
+ end?: Date;
44
+ min?: Date;
45
+ max?: Date;
46
+ type?: 'range' | 'single';
47
+ offset?: number;
48
+ factory?: Factory<DatePickerBond>;
49
+ children?: Snippet<[{
50
+ datePicker: DatePickerBond;
51
+ }]>;
52
+ [key: string]: unknown;
53
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,39 +1,39 @@
1
- <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
- import type { DialogBodyProps } from './types';
3
- import { DialogBond } from './bond.svelte';
4
- import { HtmlAtom, type Base } from '../atom';
5
-
6
- let {
7
- class: klass,
8
- children = undefined,
9
- onmount = undefined,
10
- ondestroy = undefined,
11
- animate = undefined,
12
- enter = undefined,
13
- exit = undefined,
14
- initial = undefined,
15
- ...restProps
16
- }: DialogBodyProps<E, B> = $props();
17
-
18
- const bond = DialogBond.get();
19
-
20
- const bodyProps = $derived({
21
- ...bond?.body({}),
22
- ...restProps
23
- });
24
- </script>
25
-
26
- <HtmlAtom
27
- {bond}
28
- preset="dialog.body"
29
- class={['border-border px-4 py-2', '$preset', klass]}
30
- enter={enter?.bind(bond.state)}
31
- exit={exit?.bind(bond.state)}
32
- initial={initial?.bind(bond.state)}
33
- animate={animate?.bind(bond.state)}
34
- onmount={onmount?.bind(bond.state)}
35
- ondestroy={ondestroy?.bind(bond.state)}
36
- {...bodyProps}
37
- >
38
- {@render children?.({ dialog: bond })}
39
- </HtmlAtom>
1
+ <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
+ import type { DialogBodyProps } from './types';
3
+ import { DialogBond } from './bond.svelte';
4
+ import { HtmlAtom, type Base } from '../atom';
5
+
6
+ let {
7
+ class: klass,
8
+ children = undefined,
9
+ onmount = undefined,
10
+ ondestroy = undefined,
11
+ animate = undefined,
12
+ enter = undefined,
13
+ exit = undefined,
14
+ initial = undefined,
15
+ ...restProps
16
+ }: DialogBodyProps<E, B> = $props();
17
+
18
+ const bond = DialogBond.get();
19
+
20
+ const bodyProps = $derived({
21
+ ...bond?.body({}),
22
+ ...restProps
23
+ });
24
+ </script>
25
+
26
+ <HtmlAtom
27
+ {bond}
28
+ preset="dialog.body"
29
+ class={['border-border px-4 py-2', '$preset', klass]}
30
+ enter={enter?.bind(bond.state)}
31
+ exit={exit?.bind(bond.state)}
32
+ initial={initial?.bind(bond.state)}
33
+ animate={animate?.bind(bond.state)}
34
+ onmount={onmount?.bind(bond.state)}
35
+ ondestroy={ondestroy?.bind(bond.state)}
36
+ {...bodyProps}
37
+ >
38
+ {@render children?.({ dialog: bond })}
39
+ </HtmlAtom>