@svelte-atoms/core 1.0.0-alpha.28 → 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 (74) hide show
  1. package/README.md +1 -5
  2. package/dist/components/alert/alert-actions.svelte +43 -43
  3. package/dist/components/alert/alert-close-button.svelte +70 -70
  4. package/dist/components/alert/alert-content.svelte +43 -43
  5. package/dist/components/alert/alert-description.svelte +42 -42
  6. package/dist/components/alert/alert-icon.svelte +47 -47
  7. package/dist/components/alert/alert-root.svelte +103 -103
  8. package/dist/components/alert/alert-title.svelte +42 -42
  9. package/dist/components/alert/alert.stories.svelte +401 -401
  10. package/dist/components/atom/html-atom.svelte +6 -4
  11. package/dist/components/atom/html-atom.svelte.d.ts +1 -1
  12. package/dist/components/atom/snippet-renderer.svelte +5 -5
  13. package/dist/components/button/button.stories.svelte +60 -60
  14. package/dist/components/calendar/calendar-body.svelte +107 -107
  15. package/dist/components/calendar/calendar-day.svelte +0 -1
  16. package/dist/components/calendar/calendar-header.svelte +2 -6
  17. package/dist/components/calendar/calendar-header.svelte.d.ts +0 -1
  18. package/dist/components/calendar/calendar-root.svelte +0 -2
  19. package/dist/components/calendar/calendar-week-day.svelte +34 -34
  20. package/dist/components/calendar/calendar.css +26 -26
  21. package/dist/components/calendar/calendar.stories.svelte +0 -5
  22. package/dist/components/calendar/calendar.stories.svelte.d.ts +24 -4
  23. package/dist/components/datagrid/datagrid-root.svelte +59 -59
  24. package/dist/components/datagrid/datagrid.css +5 -47
  25. package/dist/components/datagrid/types.d.ts +1 -1
  26. package/dist/components/date-picker/atoms.d.ts +0 -4
  27. package/dist/components/date-picker/atoms.js +0 -4
  28. package/dist/components/date-picker/date-picker-calendar.svelte +34 -9
  29. package/dist/components/date-picker/date-picker-calendar.svelte.d.ts +2 -5
  30. package/dist/components/date-picker/date-picker-header.svelte +59 -64
  31. package/dist/components/date-picker/date-picker-header.svelte.d.ts +2 -5
  32. package/dist/components/date-picker/date-picker-months.svelte +36 -44
  33. package/dist/components/date-picker/date-picker-months.svelte.d.ts +2 -5
  34. package/dist/components/date-picker/date-picker-root.svelte +3 -2
  35. package/dist/components/date-picker/date-picker-root.svelte.d.ts +2 -15
  36. package/dist/components/date-picker/date-picker-years.svelte +88 -97
  37. package/dist/components/date-picker/date-picker-years.svelte.d.ts +2 -5
  38. package/dist/components/date-picker/date-picker.stories.svelte +6 -15
  39. package/dist/components/date-picker/types.d.ts +53 -1
  40. package/dist/components/dialog/dialog-content.svelte +62 -62
  41. package/dist/components/element/html-element.svelte +85 -85
  42. package/dist/components/element/types.d.ts +1 -1
  43. package/dist/components/index.d.ts +1 -0
  44. package/dist/components/index.js +1 -0
  45. package/dist/components/lazy/index.d.ts +1 -0
  46. package/dist/components/lazy/index.js +1 -0
  47. package/dist/components/lazy/lazy.stories.svelte +35 -0
  48. package/dist/components/lazy/lazy.stories.svelte.d.ts +19 -0
  49. package/dist/components/lazy/lazy.svelte +28 -0
  50. package/dist/components/lazy/lazy.svelte.d.ts +5 -0
  51. package/dist/components/lazy/types.d.ts +10 -0
  52. package/dist/components/lazy/types.js +1 -0
  53. package/dist/components/menu/menu-list.svelte +40 -39
  54. package/dist/components/menu/menu-list.svelte.d.ts +1 -0
  55. package/dist/components/popover/popover-content.svelte +178 -178
  56. package/dist/components/popover/popover-root.svelte +48 -48
  57. package/dist/components/popover/popover.stories.svelte +52 -52
  58. package/dist/components/qr-code/index.d.ts +1 -0
  59. package/dist/components/qr-code/index.js +1 -0
  60. package/dist/components/qr-code/qr-code.stories.svelte +4 -1
  61. package/dist/components/qr-code/qr-code.svelte +65 -15
  62. package/dist/components/qr-code/qr-code.svelte.d.ts +2 -4
  63. package/dist/components/qr-code/types.d.ts +14 -0
  64. package/dist/components/qr-code/types.js +1 -0
  65. package/dist/components/sidebar/bond.svelte.d.ts +0 -5
  66. package/dist/components/sidebar/bond.svelte.js +1 -12
  67. package/dist/components/sidebar/sidebar-content.svelte +39 -39
  68. package/dist/components/sidebar/sidebar-content.svelte.d.ts +2 -2
  69. package/dist/components/sidebar/sidebar-root.svelte +41 -68
  70. package/dist/components/sidebar/sidebar-root.svelte.d.ts +2 -2
  71. package/dist/components/sidebar/sidebar.stories.svelte +54 -52
  72. package/dist/components/sidebar/types.d.ts +6 -6
  73. package/llm/variants.md +1259 -1261
  74. package/package.json +2 -1
@@ -1,33 +1,36 @@
1
1
  <script lang="ts">
2
- import { HtmlAtom } from '../atom';
3
- import { PopoverBond } from '../popover';
4
- import { Icon } from '../icon';
5
- import { DatePickerBond } from './bond.svelte';
2
+ import { animate } from 'motion';
6
3
  import { getYear, setYear } from 'date-fns';
7
4
  import { cn } from '../../utils';
8
- import { animate } from 'motion';
5
+ import { DatePickerBond } from './bond.svelte';
6
+ import type { DatePickerYearsProps } from './types';
7
+ import { HtmlAtom } from '../atom';
8
+ import { Icon } from '../icon';
9
9
 
10
- const popover = PopoverBond.get();
11
10
  const datePicker = DatePickerBond.get();
12
- const calendar = datePicker.calendar;
13
11
 
14
12
  const pivote = $derived(datePicker?.state.props.pivote ?? new Date());
15
13
 
16
- let yearPivote = $state(pivote.getFullYear());
14
+ let pivoteYear = $derived(pivote.getFullYear());
17
15
 
18
16
  const currentYear = $derived(getYear(pivote));
19
17
 
20
18
  // Generate array of years to display (12 years: current ±5)
21
19
  const yearsGrid = $derived.by(() => {
22
20
  const years = [];
23
- const startYear = yearPivote - 5;
21
+ const startYear = pivoteYear - 5;
24
22
  for (let i = 0; i < 12; i++) {
25
23
  years.push(startYear + i);
26
24
  }
27
25
  return years;
28
26
  });
29
27
 
30
- let { class: klass = '', preset = 'datepicker.years', children, ...restProps } = $props();
28
+ let {
29
+ class: klass = '',
30
+ preset = 'datepicker.years',
31
+ children,
32
+ ...restProps
33
+ }: DatePickerYearsProps = $props();
31
34
 
32
35
  let scrollTimeout: NodeJS.Timeout | undefined = undefined;
33
36
 
@@ -58,11 +61,11 @@
58
61
  }
59
62
 
60
63
  function handlePreviousYear() {
61
- yearPivote = yearPivote - 1;
64
+ pivoteYear = pivoteYear - 1;
62
65
  }
63
66
 
64
67
  function handleNextYear() {
65
- yearPivote = yearPivote + 1;
68
+ pivoteYear = pivoteYear + 1;
66
69
  }
67
70
 
68
71
  function handleYearSelect(year: number) {
@@ -84,7 +87,7 @@
84
87
  // Debounce the scroll event to avoid rapid year changes
85
88
  scrollTimeout = setTimeout(() => {
86
89
  const direction = event.deltaY > 0 ? 1 : -1; // Positive = scroll down = next year
87
- yearPivote = yearPivote + direction;
90
+ pivoteYear = pivoteYear + direction;
88
91
  }, 50);
89
92
  }
90
93
  </script>
@@ -120,95 +123,83 @@
120
123
  {preset}
121
124
  {...restProps}
122
125
  >
123
- {#if children}
124
- {@render children?.({
125
- calendar,
126
- popover,
127
- currentYear,
128
- yearsGrid,
129
- onPrevious: handlePreviousYear,
130
- onNext: handleNextYear,
131
- onYearSelect: handleYearSelect
132
- })}
133
- {:else}
134
- <HtmlAtom class="flex flex-1 flex-col" {enter} {exit}>
135
- <!-- Navigation Bar -->
136
- <nav
137
- class="border-border text-foreground flex h-12 items-center justify-between gap-2 border-b px-2 py-2"
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"
138
137
  >
139
- <!-- Previous Year Button -->
140
- <button
141
- type="button"
142
- class="hover:bg-foreground/10 active:bg-foreground/20 flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors"
143
- onclick={handlePreviousYear}
144
- aria-label="Previous year"
145
- >
146
- <Icon class="size-5">
147
- <svg
148
- xmlns="http://www.w3.org/2000/svg"
149
- class="size-full"
150
- viewBox="0 0 24 24"
151
- fill="none"
152
- stroke="currentColor"
153
- stroke-width="2"
154
- stroke-linecap="round"
155
- stroke-linejoin="round"
156
- >
157
- <path d="M15 18l-6-6 6-6" />
158
- </svg>
159
- </Icon>
160
- </button>
161
-
162
- <!-- Year Display -->
163
- <div class="text-foreground flex-1 text-center text-sm font-semibold">
164
- {currentYear}
165
- </div>
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>
166
158
 
167
- <!-- Next Year Button -->
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}
168
188
  <button
169
189
  type="button"
170
- class="hover:bg-foreground/10 active:bg-foreground/20 flex size-8 cursor-pointer items-center justify-center rounded-md transition-colors"
171
- onclick={handleNextYear}
172
- aria-label="Next year"
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}
173
198
  >
174
- <Icon class="size-5">
175
- <svg
176
- xmlns="http://www.w3.org/2000/svg"
177
- class="size-full"
178
- viewBox="0 0 24 24"
179
- fill="none"
180
- stroke="currentColor"
181
- stroke-width="2"
182
- stroke-linecap="round"
183
- stroke-linejoin="round"
184
- >
185
- <path d="M9 18l6-6-6-6" />
186
- </svg>
187
- </Icon>
199
+ {year}
188
200
  </button>
189
- </nav>
190
-
191
- <!-- Years Grid -->
192
- <div class="grid flex-1 grid-cols-4 gap-1 px-2 py-2">
193
- {#each yearsGrid as year}
194
- {@const isSelected = year === pivote.getFullYear()}
195
- {@const isCurrent = year === currentYear}
196
- <button
197
- type="button"
198
- class={cn(
199
- 'hover:bg-foreground/10 active:bg-foreground/20 rounded-md px-3 py-2 text-sm transition-colors',
200
- isSelected && 'bg-primary text-primary-foreground hover:bg-primary/90',
201
- isCurrent && !isSelected && 'ring-foreground/20 ring-1'
202
- )}
203
- onclick={() => handleYearSelect(year)}
204
- aria-label="Select year {year}"
205
- aria-current={isSelected ? 'date' : undefined}
206
- >
207
- {year}
208
- </button>
209
- {/each}
210
- </div>
211
- </HtmlAtom>
212
- {/if}
201
+ {/each}
202
+ </div>
203
+ </HtmlAtom>
213
204
  </HtmlAtom>
214
205
  {/if}
@@ -1,7 +1,4 @@
1
- declare const DatePickerYears: import("svelte").Component<{
2
- class?: string;
3
- preset?: string;
4
- children: any;
5
- } & Record<string, any>, {}, "">;
1
+ import type { DatePickerYearsProps } from './types';
2
+ declare const DatePickerYears: import("svelte").Component<DatePickerYearsProps, {}, "">;
6
3
  type DatePickerYears = ReturnType<typeof DatePickerYears>;
7
4
  export default DatePickerYears;
@@ -10,10 +10,12 @@
10
10
  import { Root } from '../root';
11
11
  import { DatePicker as ADatePicker } from '.';
12
12
  import { Button } from '../button';
13
- import { addDays, set, subDays } from 'date-fns';
14
- import { date } from 'zod';
13
+ import { addDays, subDays } from 'date-fns';
15
14
 
16
15
  let value: Date | undefined = $state(undefined);
16
+
17
+ let min = $state(subDays(new Date(), 5));
18
+ let max = $state(addDays(new Date(), 15));
17
19
  </script>
18
20
 
19
21
  <Story name="Date Picker">
@@ -21,7 +23,7 @@
21
23
  <Root>
22
24
  {#snippet children({})}
23
25
  <div class="flex h-fit items-center justify-center">
24
- <ADatePicker.Root bind:value min={subDays(new Date(), 5)} max={addDays(new Date(), 15)}>
26
+ <ADatePicker.Root bind:value {min} {max}>
25
27
  <ADatePicker.Trigger base={Button} class="w-sm gap-4">
26
28
  {#if value}
27
29
  <div>{value.toDateString()}</div>
@@ -31,18 +33,7 @@
31
33
 
32
34
  <ADatePicker.Indicator class="ml-auto" />
33
35
  </ADatePicker.Trigger>
34
- <ADatePicker.Calendar>
35
- <ADatePicker.Header class="col-span-full"></ADatePicker.Header>
36
- <ADatePicker.WeekDays></ADatePicker.WeekDays>
37
- <ADatePicker.Body>
38
- {#snippet children({ day })}
39
- <ADatePicker.Day {day} class=""></ADatePicker.Day>
40
- {/snippet}
41
- </ADatePicker.Body>
42
-
43
- <ADatePicker.Years></ADatePicker.Years>
44
- <ADatePicker.Months></ADatePicker.Months>
45
- </ADatePicker.Calendar>
36
+ <ADatePicker.Calendar />
46
37
  </ADatePicker.Root>
47
38
  </div>
48
39
  {/snippet}
@@ -1 +1,53 @@
1
- export {};
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
+ }
@@ -1,62 +1,62 @@
1
- <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
- import { animate as motion } from 'motion';
3
- import { DURATION } from '../../shared';
4
- import { HtmlAtom, type Base } from '../atom';
5
- import { DialogBond } from './bond.svelte';
6
- import type { DialogContentProps } from './types';
7
-
8
- const bond = DialogBond.get();
9
-
10
- let {
11
- class: klass = '',
12
- children = undefined,
13
- onmount = undefined,
14
- ondestroy = undefined,
15
- animate = _animate,
16
- enter = undefined,
17
- exit = undefined,
18
- initial = undefined,
19
- ...restProps
20
- }: DialogContentProps<E, B> = $props();
21
-
22
- const dialogProps = $derived({
23
- ...bond?.content({}),
24
- ...restProps
25
- });
26
-
27
- const open = $derived(bond?.state?.props?.open ?? false);
28
-
29
- function _animate(node: HTMLElement) {
30
- if (open) {
31
- bond?.elements.root?.show?.();
32
- }
33
-
34
- motion(
35
- node,
36
- { scale: 0.9 + 0.1 * +open, opacity: +open },
37
- {
38
- duration: DURATION.normal / 1000,
39
- ease: 'anticipate'
40
- }
41
- );
42
- }
43
- </script>
44
-
45
- <HtmlAtom
46
- preset="dialog.content"
47
- class={[
48
- 'bg-card text-foreground border-border flex h-fit w-full max-w-[90svw] flex-col rounded-md border py-4 shadow-sm md:min-w-sm lg:max-w-xl lg:min-w-md',
49
- '$preset',
50
- klass
51
- ]}
52
- {bond}
53
- enter={enter?.bind(bond.state)}
54
- exit={exit?.bind(bond.state)}
55
- initial={initial?.bind(bond.state)}
56
- animate={animate?.bind(bond.state)}
57
- onmount={onmount?.bind(bond.state)}
58
- ondestroy={ondestroy?.bind(bond.state)}
59
- {...dialogProps}
60
- >
61
- {@render children?.({ dialog: bond })}
62
- </HtmlAtom>
1
+ <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
+ import { animate as motion } from 'motion';
3
+ import { DURATION } from '../../shared';
4
+ import { HtmlAtom, type Base } from '../atom';
5
+ import { DialogBond } from './bond.svelte';
6
+ import type { DialogContentProps } from './types';
7
+
8
+ const bond = DialogBond.get();
9
+
10
+ let {
11
+ class: klass = '',
12
+ children = undefined,
13
+ onmount = undefined,
14
+ ondestroy = undefined,
15
+ animate = _animate,
16
+ enter = undefined,
17
+ exit = undefined,
18
+ initial = undefined,
19
+ ...restProps
20
+ }: DialogContentProps<E, B> = $props();
21
+
22
+ const dialogProps = $derived({
23
+ ...bond?.content({}),
24
+ ...restProps
25
+ });
26
+
27
+ const open = $derived(bond?.state?.props?.open ?? false);
28
+
29
+ function _animate(node: HTMLElement) {
30
+ if (open) {
31
+ bond?.elements.root?.show?.();
32
+ }
33
+
34
+ motion(
35
+ node,
36
+ { scale: 0.9 + 0.1 * +open, opacity: +open },
37
+ {
38
+ duration: DURATION.normal / 1000,
39
+ ease: 'anticipate'
40
+ }
41
+ );
42
+ }
43
+ </script>
44
+
45
+ <HtmlAtom
46
+ preset="dialog.content"
47
+ class={[
48
+ 'bg-card text-foreground border-border flex h-fit w-full max-w-[90svw] flex-col rounded-md border py-4 shadow-sm',
49
+ '$preset',
50
+ klass
51
+ ]}
52
+ {bond}
53
+ enter={enter?.bind(bond.state)}
54
+ exit={exit?.bind(bond.state)}
55
+ initial={initial?.bind(bond.state)}
56
+ animate={animate?.bind(bond.state)}
57
+ onmount={onmount?.bind(bond.state)}
58
+ ondestroy={ondestroy?.bind(bond.state)}
59
+ {...dialogProps}
60
+ >
61
+ {@render children?.({ dialog: bond })}
62
+ </HtmlAtom>
@@ -1,85 +1,85 @@
1
- <script lang="ts" generics="T extends HtmlElementTagName">
2
- import { untrack } from 'svelte';
3
- import type { HTMLAttributes } from 'svelte/elements';
4
- import { createAttachmentKey } from 'svelte/attachments';
5
- import { cn, toClassValue } from '../../utils';
6
- import type { ElementType, HtmlElementProps, HtmlElementTagName } from './types';
7
-
8
- type Element = ElementType<T>;
9
-
10
- let {
11
- class: klass = '',
12
- as = 'div' as T,
13
- global = true,
14
- initial = undefined,
15
- enter = undefined,
16
- exit = undefined,
17
- animate = undefined,
18
- onmount = undefined,
19
- ondestroy = undefined,
20
- children = undefined,
21
- ...restProps
22
- }: HtmlElementProps<T> & Omit<HTMLAttributes<Element>, keyof HtmlElementProps<T>> = $props();
23
-
24
- let node = $state<Element>();
25
-
26
- let skipFirstAnimate = $state(!!enter);
27
-
28
- $effect(() => {
29
- if (!node) return;
30
-
31
- const unmount = untrack(() => onmount?.(node!));
32
-
33
- return () => {
34
- if (typeof unmount === 'function') unmount(node!);
35
- ondestroy?.(node!);
36
- };
37
- });
38
-
39
- $effect(() => {
40
- const fn = animate;
41
-
42
- if (!node) return;
43
- const shouldSkip = untrack(() => skipFirstAnimate);
44
-
45
- if (shouldSkip) {
46
- skipFirstAnimate = false;
47
- return;
48
- }
49
-
50
- fn?.(node);
51
- });
52
-
53
- const elementProps = $derived({
54
- [createAttachmentKey()]: (n: Element) => {
55
- node = n;
56
- },
57
- class: cn(toClassValue(klass)),
58
- ...restProps
59
- });
60
-
61
- function _enter(node: Element) {
62
- initial?.(node);
63
- return () => {
64
- const { duration = 0, delay = 0, easing = undefined } = enter?.(node) ?? {};
65
- return { duration, delay, easing };
66
- };
67
- }
68
-
69
- function _exit(node: Element) {
70
- return () => {
71
- const { duration = 0, delay = 0, easing = undefined } = exit?.(node) ?? {};
72
- return { duration, delay, easing };
73
- };
74
- }
75
- </script>
76
-
77
- {#if global}
78
- <svelte:element this={as} in:_enter|global out:_exit|global {...elementProps}>
79
- {@render children?.()}
80
- </svelte:element>
81
- {:else}
82
- <svelte:element this={as} in:_enter out:_exit {...elementProps}>
83
- {@render children?.()}
84
- </svelte:element>
85
- {/if}
1
+ <script lang="ts" generics="T extends HtmlElementTagName">
2
+ import { untrack } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { createAttachmentKey } from 'svelte/attachments';
5
+ import { cn, toClassValue } from '../../utils';
6
+ import type { ElementType, HtmlElementProps, HtmlElementTagName } from './types';
7
+
8
+ type Element = ElementType<T>;
9
+
10
+ let {
11
+ class: klass = '',
12
+ as = 'div' as T,
13
+ global = true,
14
+ initial = undefined,
15
+ enter = undefined,
16
+ exit = undefined,
17
+ animate = undefined,
18
+ onmount = undefined,
19
+ ondestroy = undefined,
20
+ children = undefined,
21
+ ...restProps
22
+ }: HtmlElementProps<T> & Omit<HTMLAttributes<Element>, keyof HtmlElementProps<T>> = $props();
23
+
24
+ let node = $state<Element>();
25
+
26
+ let skipFirstAnimate = $state(!!enter);
27
+
28
+ $effect(() => {
29
+ if (!node) return;
30
+
31
+ const unmount = untrack(() => onmount?.(node!));
32
+
33
+ return () => {
34
+ if (typeof unmount === 'function') unmount(node!);
35
+ ondestroy?.(node!);
36
+ };
37
+ });
38
+
39
+ $effect(() => {
40
+ const fn = animate;
41
+
42
+ if (!node) return;
43
+ const shouldSkip = untrack(() => skipFirstAnimate);
44
+
45
+ if (shouldSkip) {
46
+ skipFirstAnimate = false;
47
+ return;
48
+ }
49
+
50
+ fn?.(node);
51
+ });
52
+
53
+ const elementProps = $derived({
54
+ [createAttachmentKey()]: (n: Element) => {
55
+ node = n;
56
+ },
57
+ class: cn(toClassValue(klass)),
58
+ ...restProps
59
+ });
60
+
61
+ function _enter(node: Element) {
62
+ initial?.(node);
63
+ return () => {
64
+ const { duration = 0, delay = 0, easing = undefined } = enter?.(node) ?? {};
65
+ return { duration, delay, easing };
66
+ };
67
+ }
68
+
69
+ function _exit(node: Element) {
70
+ return () => {
71
+ const { duration = 0, delay = 0, easing = undefined } = exit?.(node) ?? {};
72
+ return { duration, delay, easing };
73
+ };
74
+ }
75
+ </script>
76
+
77
+ {#if global}
78
+ <svelte:element this={as} in:_enter|global out:_exit|global {...elementProps}>
79
+ {@render children?.()}
80
+ </svelte:element>
81
+ {:else}
82
+ <svelte:element this={as} in:_enter out:_exit {...elementProps}>
83
+ {@render children?.()}
84
+ </svelte:element>
85
+ {/if}
@@ -12,7 +12,7 @@ export interface ElementProps<T extends ElementTagName> extends Record<string, u
12
12
  animate?: NodeFunction<T>;
13
13
  onmount?: NodeFunction<T>;
14
14
  ondestroy?: NodeFunction<T>;
15
- children?: Snippet;
15
+ children?: Snippet<unknown[]>;
16
16
  [key: string]: unknown;
17
17
  }
18
18
  export type HtmlElementTagName = keyof HTMLElementTagNameMap;
@@ -38,3 +38,4 @@ export * from './container';
38
38
  export * from './calendar';
39
39
  export * from './date-picker';
40
40
  export * from './qr-code';
41
+ export * from './lazy';
@@ -38,3 +38,4 @@ export * from './container';
38
38
  export * from './calendar';
39
39
  export * from './date-picker';
40
40
  export * from './qr-code';
41
+ export * from './lazy';
@@ -0,0 +1 @@
1
+ export { default as Lazy } from './lazy.svelte';
@@ -0,0 +1 @@
1
+ export { default as Lazy } from './lazy.svelte';