@svelte-atoms/core 1.0.0-alpha.29 → 1.0.0-alpha.30
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.
- package/README.md +852 -852
- package/dist/attachments/clickout.svelte.d.ts +1 -1
- package/dist/attachments/clickout.svelte.js +2 -2
- package/dist/components/accordion/accordion-root.svelte +61 -61
- package/dist/components/accordion/accordion-root.svelte.d.ts +1 -1
- package/dist/components/accordion/accordion.stories.svelte +145 -134
- package/dist/components/alert/alert.stories.svelte +400 -401
- package/dist/components/atom/html-atom.svelte +71 -17
- package/dist/components/avatar/avatar.stories.svelte +22 -27
- package/dist/components/badge/badge.stories.svelte +12 -17
- package/dist/components/badge/badge.svelte +19 -19
- package/dist/components/breadcrumb/breadcrumb.stories.svelte +16 -21
- package/dist/components/button/button.stories.svelte +27 -60
- package/dist/components/calendar/calendar-day.svelte +96 -96
- package/dist/components/calendar/calendar-header.svelte +29 -29
- package/dist/components/calendar/calendar-root.svelte +206 -206
- package/dist/components/calendar/calendar.stories.svelte +10 -15
- package/dist/components/card/card-body.svelte +39 -39
- package/dist/components/card/card-footer.svelte +41 -41
- package/dist/components/card/card-root.svelte +91 -91
- package/dist/components/card/card.stories.svelte +133 -145
- package/dist/components/checkbox/checkbox.stories.svelte +22 -27
- package/dist/components/checkbox/checkbox.svelte +155 -157
- package/dist/components/collapsible/collapsible.stories.svelte +172 -173
- package/dist/components/combobox/combobox-root.svelte +65 -65
- package/dist/components/combobox/compobox.stories.svelte +51 -54
- package/dist/components/container/container.stories.svelte +20 -23
- package/dist/components/datagrid/datagrid-root.svelte +59 -59
- package/dist/components/datagrid/datagrid.css +5 -5
- package/dist/components/datagrid/datagrid.stories.svelte +72 -75
- package/dist/components/date-picker/date-picker-calendar.svelte +67 -67
- package/dist/components/date-picker/date-picker-header.svelte +100 -100
- package/dist/components/date-picker/date-picker-months.svelte +142 -142
- package/dist/components/date-picker/date-picker-root.svelte +1 -1
- package/dist/components/date-picker/date-picker-years.svelte +205 -205
- package/dist/components/date-picker/date-picker.stories.svelte +11 -18
- package/dist/components/dialog/dialog-content.svelte +62 -62
- package/dist/components/dialog/dialog.stories.svelte +64 -67
- package/dist/components/drawer/attachments.svelte.js +8 -9
- package/dist/components/drawer/drawer-content.svelte +57 -42
- package/dist/components/drawer/drawer.stories.svelte +212 -224
- package/dist/components/dropdown/dropdown-root.svelte +59 -59
- package/dist/components/dropdown/dropdown.stories.svelte +80 -83
- package/dist/components/form/form.stories.svelte +96 -99
- package/dist/components/image/image.stories.svelte +20 -23
- package/dist/components/input/input.stories.svelte +35 -38
- package/dist/components/label/label.stories.svelte +15 -26
- package/dist/components/label/label.stories.svelte.d.ts +24 -4
- package/dist/components/lazy/lazy.stories.svelte +9 -16
- package/dist/components/lazy/lazy.svelte +28 -28
- package/dist/components/link/link.stories.svelte +15 -26
- package/dist/components/link/link.stories.svelte.d.ts +24 -4
- package/dist/components/menu/menu-list.svelte +40 -40
- package/dist/components/menu/menu.stories.svelte +33 -36
- package/dist/components/popover/bond.svelte.js +31 -25
- package/dist/components/popover/popover-arrow.svelte +111 -111
- package/dist/components/popover/popover-content.svelte +175 -178
- package/dist/components/popover/popover-indicator.svelte +44 -43
- package/dist/components/popover/popover-root.svelte +48 -48
- package/dist/components/popover/popover.stories.svelte +49 -52
- package/dist/components/qr-code/qr-code.stories.svelte +4 -13
- package/dist/components/qr-code/qr-code.svelte +75 -75
- package/dist/components/radio/radio-group.stories.svelte +41 -50
- package/dist/components/radio/radio.stories.svelte +17 -26
- package/dist/components/radio/radio.svelte +109 -109
- package/dist/components/root/root.svelte +121 -121
- package/dist/components/root/root.svelte.d.ts +1 -1
- package/dist/components/scrollable/scrollable.stories.svelte +116 -126
- package/dist/components/sidebar/sidebar-content.svelte +13 -2
- package/dist/components/sidebar/sidebar-root.svelte +10 -12
- package/dist/components/sidebar/sidebar.stories.svelte +8 -19
- package/dist/components/sidebar/types.d.ts +1 -0
- package/dist/components/tabs/tab/bond.svelte.d.ts +4 -1
- package/dist/components/tabs/tab/bond.svelte.js +4 -1
- package/dist/components/tabs/tabs.stories.svelte +56 -59
- package/dist/components/tooltip/tooltip-trigger.svelte +39 -37
- package/dist/components/tooltip/tooltip.stories.svelte +32 -35
- package/dist/components/tree/tree.stories.svelte +142 -134
- package/dist/context/preset.svelte.d.ts +3 -3
- package/dist/utils/function.d.ts +2 -0
- package/dist/utils/function.js +6 -0
- package/package.json +6 -9
- package/dist/actions/animation.svelte.d.ts +0 -6
- package/dist/actions/animation.svelte.js +0 -14
- package/dist/actions/clickout.svelte.d.ts +0 -2
- package/dist/actions/clickout.svelte.js +0 -15
- package/dist/actions/popover.svelte.d.ts +0 -19
- package/dist/actions/popover.svelte.js +0 -81
- package/dist/actions/portal.svelte.d.ts +0 -8
- package/dist/actions/portal.svelte.js +0 -32
- package/dist/attachments/gsap.svelte.d.ts +0 -2
- package/dist/attachments/gsap.svelte.js +0 -26
|
@@ -1,67 +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>
|
|
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>
|
|
@@ -1,100 +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>
|
|
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>
|
|
@@ -1,142 +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}
|
|
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}
|