@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
@@ -1,88 +1,88 @@
1
- <script lang="ts" generics="T, E extends HtmlElementTagName, B extends Base = Base">
2
- import { untrack } from 'svelte';
3
- import { nanoid } from 'nanoid';
4
- import { defineProperty, defineState } from '../../../utils';
5
- import { HtmlAtom, type Base } from '../../atom';
6
- import type { HtmlElementTagName } from '../../element';
7
- import { DataGridTrBond, DataGridTrBondState, type DataGridTrBondProps } from './bond.svelte';
8
- import type { DatagridTrProps } from '../types';
9
- import { getDatagridHeaderContext, type DatagridContext } from '../context';
10
-
11
- import './datagrid-tr.css';
12
-
13
- const context_header = getDatagridHeaderContext();
14
-
15
- let {
16
- class: klass = '',
17
- value = nanoid(),
18
- rows = 'auto',
19
- data = undefined,
20
- header = false,
21
- factory = _factory,
22
- children = undefined,
23
- onmount = undefined,
24
- ondestroy = undefined,
25
- animate = undefined,
26
- enter = undefined,
27
- exit = undefined,
28
- initial = undefined,
29
- onclick = undefined,
30
- ...restProps
31
- }: DatagridTrProps<T, E, B> = $props();
32
-
33
- const bondProps = defineState<DataGridTrBondProps>([
34
- defineProperty('data', () => data),
35
- defineProperty('value', () => value),
36
- defineProperty('header', () => header)
37
- ]);
38
- const bond = factory(bondProps).share();
39
-
40
- const isHeader = $derived(context_header?.derived?.data?.header ?? false);
41
- const isSelected = $derived(bond.state.isSelected);
42
-
43
- const unmount = untrack(() => {
44
- if (!isHeader) {
45
- return bond.mount();
46
- }
47
- });
48
-
49
- $effect(() => unmount);
50
-
51
- function _factory(props: typeof bondProps) {
52
- const datagridTrState = new DataGridTrBondState(() => props);
53
- return new DataGridTrBond(datagridTrState);
54
- }
55
-
56
- function onclick_(ev: Event) {
57
- onclick?.(ev, { tr: bond as unknown as DatagridContext<T> });
58
-
59
- if (!ev.defaultPrevented) {
60
- //
61
- }
62
- }
63
- </script>
64
-
65
- <HtmlAtom
66
- {bond}
67
- preset="datagrid.tr"
68
- class={[
69
- 'datagrid-tr border-border items-center border-b bg-transparent',
70
- !isHeader &&
71
- 'hover:bg-foreground/2 active:bg-foreground/4 transition-colors duration-100 last:border-b-0',
72
- isHeader && 'header-tr',
73
- isSelected && 'bg-primary/2 hover:bg-primary/4 active:bg-primary/6',
74
- '$preset',
75
- klass
76
- ]}
77
- style="--rows:{rows}"
78
- enter={enter?.bind(bond.state)}
79
- exit={exit?.bind(bond.state)}
80
- initial={initial?.bind(bond.state)}
81
- animate={animate?.bind(bond.state)}
82
- onmount={onmount?.bind(bond.state)}
83
- ondestroy={ondestroy?.bind(bond.state)}
84
- onclick={onclick_}
85
- {...bond.root(restProps)}
86
- >
87
- {@render children?.({ tr: bond as unknown as DatagridContext<T> })}
88
- </HtmlAtom>
1
+ <script lang="ts" generics="T, E extends HtmlElementTagName, B extends Base = Base">
2
+ import { untrack } from 'svelte';
3
+ import { nanoid } from 'nanoid';
4
+ import { defineProperty, defineState } from '../../../utils';
5
+ import { HtmlAtom, type Base } from '../../atom';
6
+ import type { HtmlElementTagName } from '../../element';
7
+ import { DataGridTrBond, DataGridTrBondState, type DataGridTrBondProps } from './bond.svelte';
8
+ import type { DatagridTrProps } from '../types';
9
+ import { getDatagridHeaderContext, type DatagridContext } from '../context';
10
+
11
+ import './datagrid-tr.css';
12
+
13
+ const context_header = getDatagridHeaderContext();
14
+
15
+ let {
16
+ class: klass = '',
17
+ value = nanoid(),
18
+ rows = 'auto',
19
+ data = undefined,
20
+ header = false,
21
+ factory = _factory,
22
+ children = undefined,
23
+ onmount = undefined,
24
+ ondestroy = undefined,
25
+ animate = undefined,
26
+ enter = undefined,
27
+ exit = undefined,
28
+ initial = undefined,
29
+ onclick = undefined,
30
+ ...restProps
31
+ }: DatagridTrProps<T, E, B> = $props();
32
+
33
+ const bondProps = defineState<DataGridTrBondProps>([
34
+ defineProperty('data', () => data),
35
+ defineProperty('value', () => value),
36
+ defineProperty('header', () => header)
37
+ ]);
38
+ const bond = factory(bondProps).share();
39
+
40
+ const isHeader = $derived(context_header?.derived?.data?.header ?? false);
41
+ const isSelected = $derived(bond.state.isSelected);
42
+
43
+ const unmount = untrack(() => {
44
+ if (!isHeader) {
45
+ return bond.mount();
46
+ }
47
+ });
48
+
49
+ $effect(() => unmount);
50
+
51
+ function _factory(props: typeof bondProps) {
52
+ const datagridTrState = new DataGridTrBondState(() => props);
53
+ return new DataGridTrBond(datagridTrState);
54
+ }
55
+
56
+ function onclick_(ev: Event) {
57
+ onclick?.(ev, { tr: bond as unknown as DatagridContext<T> });
58
+
59
+ if (!ev.defaultPrevented) {
60
+ //
61
+ }
62
+ }
63
+ </script>
64
+
65
+ <HtmlAtom
66
+ {bond}
67
+ preset="datagrid.tr"
68
+ class={[
69
+ 'datagrid-tr border-border items-center border-b bg-transparent',
70
+ !isHeader &&
71
+ 'hover:bg-foreground/2 active:bg-foreground/4 transition-colors duration-100 last:border-b-0',
72
+ isHeader && 'header-tr',
73
+ isSelected && 'bg-primary/2 hover:bg-primary/4 active:bg-primary/6',
74
+ '$preset',
75
+ klass
76
+ ]}
77
+ style="--rows:{rows}"
78
+ enter={enter?.bind(bond.state)}
79
+ exit={exit?.bind(bond.state)}
80
+ initial={initial?.bind(bond.state)}
81
+ animate={animate?.bind(bond.state)}
82
+ onmount={onmount?.bind(bond.state)}
83
+ ondestroy={ondestroy?.bind(bond.state)}
84
+ onclick={onclick_}
85
+ {...bond.root(restProps)}
86
+ >
87
+ {@render children?.({ tr: bond as unknown as DatagridContext<T> })}
88
+ </HtmlAtom>
@@ -77,8 +77,8 @@ export interface Column {
77
77
  export interface DatagridRootProps<T> extends DatagridRootExtendProps {
78
78
  class?: string;
79
79
  template?: string;
80
+ fallbackTemplate?: string;
80
81
  values?: string[];
81
- data?: T[];
82
82
  readonly element?: HTMLElement;
83
83
  children?: Snippet<[{
84
84
  context: DatagridContext<T>;
@@ -0,0 +1,3 @@
1
+ export { Arrow, Indicator, Trigger } from '../popover/atoms';
2
+ export { default as Root } from './date-picker-root.svelte';
3
+ export { default as Calendar } from './date-picker-calendar.svelte';
@@ -0,0 +1,3 @@
1
+ export { Arrow, Indicator, Trigger } from '../popover/atoms';
2
+ export { default as Root } from './date-picker-root.svelte';
3
+ export { default as Calendar } from './date-picker-calendar.svelte';
@@ -0,0 +1,67 @@
1
+ import { PopoverBond, PopoverState, type PopoverDomElements, type PopoverStateProps } from '../popover/bond.svelte';
2
+ import type { CalendarBond, CalendarBondProps } from '../calendar/bond.svelte';
3
+ export type DatePickerBondProps = PopoverStateProps & CalendarBondProps & {
4
+ format?: string;
5
+ placeholder?: string;
6
+ };
7
+ export type DatePickerBondElements = PopoverDomElements & {
8
+ trigger: HTMLInputElement;
9
+ root: HTMLElement;
10
+ content: HTMLElement;
11
+ clearButton: HTMLElement;
12
+ };
13
+ export declare class DatePickerBond<Props extends DatePickerBondProps = DatePickerBondProps, State extends DatePickerBondState<Props> = DatePickerBondState<Props>> extends PopoverBond<Props, State, DatePickerBondElements> {
14
+ #private;
15
+ static CONTEXT_KEY: string;
16
+ constructor(state: State);
17
+ get calendar(): CalendarBond<CalendarBondProps, import("..").CalendarBondState<CalendarBondProps>> | undefined;
18
+ setCalendar(calendar: CalendarBond): void;
19
+ share(): this;
20
+ trigger(): {
21
+ [x: symbol]: (node: HTMLInputElement) => void;
22
+ id: string;
23
+ role: string;
24
+ 'aria-expanded': boolean;
25
+ 'aria-controls': string;
26
+ 'aria-label': string;
27
+ 'aria-disabled': boolean;
28
+ placeholder: string;
29
+ disabled: boolean;
30
+ readonly: boolean;
31
+ tabindex: number;
32
+ };
33
+ content(): {
34
+ [x: symbol]: (node: HTMLElement) => void;
35
+ id: string;
36
+ role: string;
37
+ 'aria-label': string;
38
+ };
39
+ clearButton(props?: Record<string, unknown>): {
40
+ onclick: (ev: Event) => void;
41
+ id: string;
42
+ type: string;
43
+ 'aria-label': string;
44
+ tabindex: number;
45
+ };
46
+ static get(): DatePickerBond;
47
+ static set(bond: DatePickerBond): DatePickerBond;
48
+ }
49
+ export declare class DatePickerBondState<Props extends DatePickerBondProps> extends PopoverState<Props> {
50
+ #private;
51
+ constructor(props: () => Props);
52
+ get formattedValue(): string;
53
+ get hasValue(): boolean;
54
+ get isYearsPickerOpen(): boolean;
55
+ get isMonthsPickerOpen(): boolean;
56
+ selectDate(date: Date): void;
57
+ selectStart(date: Date): void;
58
+ selectEnd(date: Date): void;
59
+ clear(): void;
60
+ private formatDate;
61
+ openYearsPicker(): void;
62
+ closeYearsPicker(): void;
63
+ toggleYearsPicker(): void;
64
+ openMonthsPicker(): void;
65
+ closeMonthsPicker(): void;
66
+ toggleMonthsPicker(): void;
67
+ }
@@ -0,0 +1,174 @@
1
+ import { PopoverBond, PopoverState } from '../popover/bond.svelte';
2
+ import { getContext, setContext } from 'svelte';
3
+ import { createAttachmentKey } from 'svelte/attachments';
4
+ export class DatePickerBond extends PopoverBond {
5
+ static CONTEXT_KEY = '@atoms/context/date-picker';
6
+ #calendarBond;
7
+ constructor(state) {
8
+ super(state);
9
+ }
10
+ get calendar() {
11
+ return this.#calendarBond;
12
+ }
13
+ setCalendar(calendar) {
14
+ this.#calendarBond = calendar;
15
+ }
16
+ share() {
17
+ return DatePickerBond.set(this);
18
+ }
19
+ trigger() {
20
+ const isDisabled = this.state.props.disabled ?? false;
21
+ const placeholder = this.state.props.placeholder ?? 'Select a date';
22
+ return {
23
+ id: `date-picker-input-${this.id}`,
24
+ role: 'combobox',
25
+ 'aria-expanded': this.state.props.open ?? false,
26
+ 'aria-controls': `date-picker-calendar-${this.id}`,
27
+ 'aria-label': 'Date picker',
28
+ 'aria-disabled': isDisabled,
29
+ placeholder,
30
+ disabled: isDisabled,
31
+ readonly: true,
32
+ tabindex: isDisabled ? -1 : 0,
33
+ [createAttachmentKey()]: (node) => {
34
+ this.elements.trigger = node;
35
+ }
36
+ };
37
+ }
38
+ content() {
39
+ return {
40
+ id: `date-picker-calendar-${this.id}`,
41
+ role: 'dialog',
42
+ 'aria-label': 'Choose date',
43
+ [createAttachmentKey()]: (node) => {
44
+ this.elements.content = node;
45
+ }
46
+ };
47
+ }
48
+ clearButton(props = {}) {
49
+ const hasValue = this.state.hasValue;
50
+ return {
51
+ id: `date-picker-clear-${this.id}`,
52
+ type: 'button',
53
+ 'aria-label': 'Clear date',
54
+ tabindex: hasValue ? 0 : -1,
55
+ ...props,
56
+ onclick: (ev) => {
57
+ ev.preventDefault();
58
+ ev.stopPropagation();
59
+ this.state.clear();
60
+ },
61
+ [createAttachmentKey()]: (node) => {
62
+ this.elements.clearButton = node;
63
+ }
64
+ };
65
+ }
66
+ static get() {
67
+ return getContext(this.CONTEXT_KEY);
68
+ }
69
+ static set(bond) {
70
+ return setContext(this.CONTEXT_KEY, bond);
71
+ }
72
+ }
73
+ export class DatePickerBondState extends PopoverState {
74
+ #isYearsPickerOpen = $state(false);
75
+ #isMonthsPickerOpen = $state(false);
76
+ constructor(props) {
77
+ super(props);
78
+ }
79
+ get formattedValue() {
80
+ if (this.props.range) {
81
+ if (!this.props.start)
82
+ return '';
83
+ if (!this.props.end)
84
+ return this.formatDate(this.props.start);
85
+ return `${this.formatDate(this.props.start)} - ${this.formatDate(this.props.end)}`;
86
+ }
87
+ return this.props.value ? this.formatDate(this.props.value) : '';
88
+ }
89
+ get hasValue() {
90
+ if (this.props.range) {
91
+ return !!(this.props.start || this.props.end);
92
+ }
93
+ return !!this.props.value;
94
+ }
95
+ get isYearsPickerOpen() {
96
+ return this.#isYearsPickerOpen;
97
+ }
98
+ get isMonthsPickerOpen() {
99
+ return this.#isMonthsPickerOpen;
100
+ }
101
+ selectDate(date) {
102
+ if (this.props.range) {
103
+ if (!this.props.start) {
104
+ this.props.start = date;
105
+ }
106
+ else if (!this.props.end) {
107
+ this.props.end = date;
108
+ this.close(); // Close after selecting range
109
+ }
110
+ else {
111
+ this.props.start = date;
112
+ this.props.end = undefined;
113
+ }
114
+ }
115
+ else {
116
+ this.props.value = date;
117
+ this.close(); // Close after selecting single date
118
+ }
119
+ }
120
+ selectStart(date) {
121
+ this.props.start = date;
122
+ }
123
+ selectEnd(date) {
124
+ this.props.end = date;
125
+ this.close();
126
+ }
127
+ clear() {
128
+ this.props.value = undefined;
129
+ this.props.start = undefined;
130
+ this.props.end = undefined;
131
+ }
132
+ formatDate(date) {
133
+ const format = this.props.format ?? 'MM/dd/yyyy';
134
+ // Basic formatting - can be enhanced with date-fns format later
135
+ if (format === 'MM/dd/yyyy') {
136
+ const month = String(date.getMonth() + 1).padStart(2, '0');
137
+ const day = String(date.getDate()).padStart(2, '0');
138
+ const year = date.getFullYear();
139
+ return `${month}/${day}/${year}`;
140
+ }
141
+ if (format === 'dd/MM/yyyy') {
142
+ const month = String(date.getMonth() + 1).padStart(2, '0');
143
+ const day = String(date.getDate()).padStart(2, '0');
144
+ const year = date.getFullYear();
145
+ return `${day}/${month}/${year}`;
146
+ }
147
+ if (format === 'yyyy-MM-dd') {
148
+ const month = String(date.getMonth() + 1).padStart(2, '0');
149
+ const day = String(date.getDate()).padStart(2, '0');
150
+ const year = date.getFullYear();
151
+ return `${year}-${month}-${day}`;
152
+ }
153
+ // Default fallback
154
+ return date.toLocaleDateString();
155
+ }
156
+ openYearsPicker() {
157
+ this.#isYearsPickerOpen = true;
158
+ }
159
+ closeYearsPicker() {
160
+ this.#isYearsPickerOpen = false;
161
+ }
162
+ toggleYearsPicker() {
163
+ this.#isYearsPickerOpen = !this.#isYearsPickerOpen;
164
+ }
165
+ openMonthsPicker() {
166
+ this.#isMonthsPickerOpen = true;
167
+ }
168
+ closeMonthsPicker() {
169
+ this.#isMonthsPickerOpen = false;
170
+ }
171
+ toggleMonthsPicker() {
172
+ this.#isMonthsPickerOpen = !this.#isMonthsPickerOpen;
173
+ }
174
+ }
@@ -0,0 +1,67 @@
1
+ <script lang="ts">
2
+ import { Content } from '../popover/atoms';
3
+ import {
4
+ Root,
5
+ Header as CalendarHeader,
6
+ Body as CalendarBody,
7
+ Day as CalendarDay
8
+ } from '../calendar/atoms';
9
+ import { DatePickerBond } from './bond.svelte';
10
+ import DatePickerHeader from './date-picker-header.svelte';
11
+ import DatePickerMonths from './date-picker-months.svelte';
12
+ import DatePickerYears from './date-picker-years.svelte';
13
+ import { HtmlAtom } from '../atom';
14
+ import type { CalendarRange, Day as CalendarDayType } from '../calendar/types';
15
+ import type { DatePickerCalendarProps } from './types';
16
+
17
+ const datePickerBond = DatePickerBond.get();
18
+ const datePickerBondProps = $derived(datePickerBond?.state.props);
19
+
20
+ let {
21
+ class: klass = '',
22
+ preset = 'datepicker.calendar',
23
+ children: childrenProp,
24
+ Header = DatePickerHeader,
25
+ Weekdays = CalendarHeader,
26
+ Body = CalendarBody,
27
+ Day = CalendarDay,
28
+ Months = DatePickerMonths,
29
+ Years = DatePickerYears,
30
+ ...restProps
31
+ }: DatePickerCalendarProps = $props();
32
+
33
+ const calendarProps = $derived({
34
+ ...datePickerBond?.content(),
35
+ ...datePickerBondProps,
36
+ ...restProps
37
+ });
38
+
39
+ function handleChange(_: CustomEvent, { range, pivote }: { range: CalendarRange; pivote: Date }) {
40
+ if (!datePickerBond) return;
41
+
42
+ datePickerBond.state.props.range = range;
43
+ datePickerBond.state.props.pivote = pivote;
44
+ }
45
+ </script>
46
+
47
+ <Content
48
+ class={['relative overflow-hidden p-0', klass]}
49
+ base={Root}
50
+ onchange={handleChange}
51
+ {preset}
52
+ {...calendarProps}
53
+ >
54
+ <HtmlAtom base={Header} class="col-span-full" />
55
+ <HtmlAtom base={Weekdays} />
56
+
57
+ <HtmlAtom base={Body}>
58
+ {#snippet children({ day }: { day: CalendarDayType })}
59
+ <HtmlAtom base={Day} {day} class="flex items-center justify-center">
60
+ <span class="value">{day.dayOfMonth}</span>
61
+ </HtmlAtom>
62
+ {/snippet}
63
+ </HtmlAtom>
64
+
65
+ <HtmlAtom base={Months} />
66
+ <HtmlAtom base={Years} />
67
+ </Content>
@@ -0,0 +1,4 @@
1
+ import type { DatePickerCalendarProps } from './types';
2
+ declare const DatePickerCalendar: import("svelte").Component<DatePickerCalendarProps, {}, "">;
3
+ type DatePickerCalendar = ReturnType<typeof DatePickerCalendar>;
4
+ export default DatePickerCalendar;
@@ -0,0 +1,100 @@
1
+ <script lang="ts">
2
+ import { HtmlAtom } from '../atom';
3
+ import { DatePickerBond } from './bond.svelte';
4
+ import { CalendarBond } from '../calendar/bond.svelte';
5
+ import { Icon } from '../icon';
6
+ import type { DatePickerHeaderProps } from './types';
7
+
8
+ const datePickerBond = DatePickerBond.get();
9
+ const calendarBond = CalendarBond.get();
10
+
11
+ let {
12
+ class: klass = '',
13
+ preset = 'datepicker.header',
14
+ children,
15
+ ...restProps
16
+ }: DatePickerHeaderProps = $props();
17
+
18
+ const calendarBondProps = $derived(datePickerBond?.state?.props);
19
+
20
+ const pivote = $derived(calendarBondProps?.pivote ?? new Date());
21
+
22
+ // Format month and year
23
+ const monthName = $derived(pivote.toLocaleDateString('en-US', { month: 'long' }));
24
+ const year = $derived(pivote.getFullYear());
25
+
26
+ function handlePreviousMonth() {
27
+ calendarBond?.state?.previousMonth();
28
+ }
29
+
30
+ function handleNextMonth() {
31
+ calendarBond?.state?.nextMonth();
32
+ }
33
+
34
+ function handleMonthPicker() {
35
+ if (!datePickerBond) return;
36
+ datePickerBond.state.openMonthsPicker();
37
+ }
38
+ </script>
39
+
40
+ <HtmlAtom
41
+ as="nav"
42
+ class={['border-border flex items-center justify-between gap-2 border-b p-2', '$preset', klass]}
43
+ {preset}
44
+ {...restProps}
45
+ >
46
+ <!-- Previous Month Button -->
47
+ <button
48
+ type="button"
49
+ class="hover:bg-foreground/10 active:bg-foreground/20 flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors"
50
+ onclick={handlePreviousMonth}
51
+ aria-label="Previous month"
52
+ >
53
+ <Icon class="size-5">
54
+ <svg
55
+ xmlns="http://www.w3.org/2000/svg"
56
+ class="size-full"
57
+ viewBox="0 0 24 24"
58
+ fill="none"
59
+ stroke="currentColor"
60
+ stroke-width="2"
61
+ stroke-linecap="round"
62
+ stroke-linejoin="round"
63
+ >
64
+ <path d="M15 18l-6-6 6-6" />
65
+ </svg>
66
+ </Icon>
67
+ </button>
68
+
69
+ <!-- Month and Year Display -->
70
+ <button
71
+ class="text-foreground h-full flex-1 cursor-pointer text-center text-sm font-semibold"
72
+ onclick={handleMonthPicker}
73
+ >
74
+ {monthName}
75
+ {year}
76
+ </button>
77
+
78
+ <!-- Next Month Button -->
79
+ <button
80
+ type="button"
81
+ class="hover:bg-foreground/10 active:bg-foreground/20 flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors"
82
+ onclick={handleNextMonth}
83
+ aria-label="Next month"
84
+ >
85
+ <Icon class="size-5">
86
+ <svg
87
+ xmlns="http://www.w3.org/2000/svg"
88
+ class="size-full"
89
+ viewBox="0 0 24 24"
90
+ fill="none"
91
+ stroke="currentColor"
92
+ stroke-width="2"
93
+ stroke-linecap="round"
94
+ stroke-linejoin="round"
95
+ >
96
+ <path d="M9 18l6-6-6-6" />
97
+ </svg>
98
+ </Icon>
99
+ </button>
100
+ </HtmlAtom>
@@ -0,0 +1,4 @@
1
+ import type { DatePickerHeaderProps } from './types';
2
+ declare const DatePickerHeader: import("svelte").Component<DatePickerHeaderProps, {}, "">;
3
+ type DatePickerHeader = ReturnType<typeof DatePickerHeader>;
4
+ export default DatePickerHeader;