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

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 (163) hide show
  1. package/README.md +856 -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 +2 -1
  8. package/dist/components/alert/alert-close-button.svelte +18 -20
  9. package/dist/components/alert/alert-content.svelte +2 -1
  10. package/dist/components/alert/alert-description.svelte +2 -1
  11. package/dist/components/alert/alert-icon.svelte +2 -1
  12. package/dist/components/alert/alert-root.svelte +3 -2
  13. package/dist/components/alert/alert-title.svelte +2 -1
  14. package/dist/components/alert/alert.stories.svelte +401 -40
  15. package/dist/components/alert/alert.stories.svelte.d.ts +2 -5
  16. package/dist/components/atom/html-atom.svelte +205 -201
  17. package/dist/components/atom/snippet-renderer.svelte +5 -0
  18. package/dist/components/atom/snippet-renderer.svelte.d.ts +5 -0
  19. package/dist/components/avatar/avatar.stories.svelte.d.ts +1 -1
  20. package/dist/components/badge/badge.stories.svelte.d.ts +1 -1
  21. package/dist/components/breadcrumb/breadcrumb.stories.svelte.d.ts +1 -1
  22. package/dist/components/button/button.stories.svelte +60 -57
  23. package/dist/components/calendar/atoms.d.ts +5 -0
  24. package/dist/components/calendar/atoms.js +5 -0
  25. package/dist/components/calendar/bond.svelte.d.ts +72 -0
  26. package/dist/components/calendar/bond.svelte.js +132 -0
  27. package/dist/components/calendar/calendar-body.svelte +107 -0
  28. package/dist/components/calendar/calendar-body.svelte.d.ts +8 -0
  29. package/dist/components/calendar/calendar-day.svelte +97 -0
  30. package/dist/components/calendar/calendar-day.svelte.d.ts +4 -0
  31. package/dist/components/calendar/calendar-header.svelte +33 -0
  32. package/dist/components/calendar/calendar-header.svelte.d.ts +7 -0
  33. package/dist/components/calendar/calendar-root.svelte +208 -0
  34. package/dist/components/calendar/calendar-root.svelte.d.ts +8 -0
  35. package/dist/components/calendar/calendar-week-day.svelte +34 -0
  36. package/dist/components/calendar/calendar-week-day.svelte.d.ts +9 -0
  37. package/dist/components/calendar/calendar.css +26 -0
  38. package/dist/components/calendar/calendar.stories.svelte +36 -0
  39. package/dist/components/calendar/calendar.stories.svelte.d.ts +6 -0
  40. package/dist/components/calendar/index.d.ts +4 -0
  41. package/dist/components/calendar/index.js +4 -0
  42. package/dist/components/calendar/runes.svelte.d.ts +3 -0
  43. package/dist/components/calendar/runes.svelte.js +25 -0
  44. package/dist/components/calendar/types.d.ts +62 -0
  45. package/dist/components/calendar/types.js +1 -0
  46. package/dist/components/card/card-body.svelte +39 -39
  47. package/dist/components/card/card-description.svelte +41 -41
  48. package/dist/components/card/card-footer.svelte +41 -41
  49. package/dist/components/card/card-header.svelte +41 -41
  50. package/dist/components/card/card-media.svelte +41 -41
  51. package/dist/components/card/card-root.svelte +91 -91
  52. package/dist/components/card/card-subtitle.svelte +41 -41
  53. package/dist/components/card/card-title.svelte +45 -45
  54. package/dist/components/collapsible/collapsible-body.svelte +39 -39
  55. package/dist/components/collapsible/collapsible-header.svelte +39 -39
  56. package/dist/components/collapsible/collapsible-indicator.svelte +50 -50
  57. package/dist/components/collapsible/collapsible-root.svelte +66 -66
  58. package/dist/components/combobox/combobox-root.svelte +65 -65
  59. package/dist/components/container/container.stories.svelte.d.ts +1 -1
  60. package/dist/components/contextmenu/contextmenu-trigger.svelte.d.ts +1 -1
  61. package/dist/components/datagrid/bond.svelte.d.ts +2 -2
  62. package/dist/components/datagrid/datagrid-body.svelte +37 -37
  63. package/dist/components/datagrid/datagrid-checkbox.svelte +101 -101
  64. package/dist/components/datagrid/datagrid-footer.svelte +34 -34
  65. package/dist/components/datagrid/datagrid-header.svelte +49 -49
  66. package/dist/components/datagrid/datagrid-root.svelte +59 -59
  67. package/dist/components/datagrid/td/datagrid-td.svelte +66 -66
  68. package/dist/components/datagrid/th/datagrid-th.svelte +106 -106
  69. package/dist/components/datagrid/tr/datagrid-tr.svelte +88 -88
  70. package/dist/components/date-picker/atoms.d.ts +7 -0
  71. package/dist/components/date-picker/atoms.js +7 -0
  72. package/dist/components/date-picker/bond.svelte.d.ts +67 -0
  73. package/dist/components/date-picker/bond.svelte.js +174 -0
  74. package/dist/components/date-picker/date-picker-calendar.svelte +42 -0
  75. package/dist/components/date-picker/date-picker-calendar.svelte.d.ts +7 -0
  76. package/dist/components/date-picker/date-picker-header.svelte +105 -0
  77. package/dist/components/date-picker/date-picker-header.svelte.d.ts +7 -0
  78. package/dist/components/date-picker/date-picker-months.svelte +150 -0
  79. package/dist/components/date-picker/date-picker-months.svelte.d.ts +7 -0
  80. package/dist/components/date-picker/date-picker-root.svelte +94 -0
  81. package/dist/components/date-picker/date-picker-root.svelte.d.ts +17 -0
  82. package/dist/components/date-picker/date-picker-years.svelte +214 -0
  83. package/dist/components/date-picker/date-picker-years.svelte.d.ts +7 -0
  84. package/dist/components/date-picker/date-picker.stories.svelte +51 -0
  85. package/dist/components/date-picker/date-picker.stories.svelte.d.ts +3 -0
  86. package/dist/components/date-picker/index.d.ts +3 -0
  87. package/dist/components/date-picker/index.js +3 -0
  88. package/dist/components/date-picker/types.d.ts +1 -0
  89. package/dist/components/date-picker/types.js +1 -0
  90. package/dist/components/dialog/dialog-body.svelte +39 -39
  91. package/dist/components/dialog/dialog-close-button.svelte +58 -58
  92. package/dist/components/dialog/dialog-content.svelte +62 -62
  93. package/dist/components/dialog/dialog-description.svelte +40 -40
  94. package/dist/components/dialog/dialog-footer.svelte +39 -39
  95. package/dist/components/dialog/dialog-header.svelte +39 -39
  96. package/dist/components/dialog/dialog-root.svelte +110 -110
  97. package/dist/components/dialog/dialog-title.svelte +41 -41
  98. package/dist/components/drawer/drawer-backdrop.svelte +38 -38
  99. package/dist/components/drawer/drawer-body.svelte +42 -42
  100. package/dist/components/drawer/drawer-content.svelte +42 -42
  101. package/dist/components/drawer/drawer-description.svelte +44 -44
  102. package/dist/components/drawer/drawer-footer.svelte +41 -41
  103. package/dist/components/drawer/drawer-header.svelte +43 -43
  104. package/dist/components/drawer/drawer-root.svelte +93 -93
  105. package/dist/components/drawer/drawer-title.svelte +44 -44
  106. package/dist/components/dropdown/dropdown-query.svelte +54 -54
  107. package/dist/components/dropdown/dropdown-root.svelte +59 -59
  108. package/dist/components/dropdown/dropdown-trigger.svelte +41 -41
  109. package/dist/components/dropdown/dropdown-value.svelte +60 -60
  110. package/dist/components/element/html-element.svelte +85 -85
  111. package/dist/components/form/bond.svelte.d.ts +1 -1
  112. package/dist/components/form/field/field-control.svelte +48 -48
  113. package/dist/components/form/field/field-label.svelte +24 -24
  114. package/dist/components/form/field/field-root.svelte +59 -59
  115. package/dist/components/icon/icon.svelte +44 -44
  116. package/dist/components/image/image.stories.svelte.d.ts +1 -1
  117. package/dist/components/index.d.ts +3 -0
  118. package/dist/components/index.js +3 -0
  119. package/dist/components/input/input-control.svelte +103 -103
  120. package/dist/components/label/label.svelte +25 -25
  121. package/dist/components/popover/popover-arrow.svelte +111 -111
  122. package/dist/components/popover/popover-content.svelte +46 -7
  123. package/dist/components/popover/popover-root.svelte +48 -49
  124. package/dist/components/popover/popover.stories.svelte +52 -67
  125. package/dist/components/portal/portal-root.svelte +83 -83
  126. package/dist/components/portal/teleport.svelte +50 -50
  127. package/dist/components/qr-code/index.d.ts +1 -0
  128. package/dist/components/qr-code/index.js +1 -0
  129. package/dist/components/qr-code/qr-code.stories.svelte +24 -0
  130. package/dist/components/qr-code/qr-code.stories.svelte.d.ts +26 -0
  131. package/dist/components/qr-code/qr-code.svelte +25 -0
  132. package/dist/components/qr-code/qr-code.svelte.d.ts +6 -0
  133. package/dist/components/radio/radio.svelte +109 -109
  134. package/dist/components/radio/types.svelte.d.ts +1 -1
  135. package/dist/components/scrollable/scrollable-container.svelte +82 -82
  136. package/dist/components/scrollable/scrollable-content.svelte +41 -41
  137. package/dist/components/scrollable/scrollable-root.svelte +100 -100
  138. package/dist/components/scrollable/scrollable-thumb.svelte +75 -75
  139. package/dist/components/scrollable/scrollable-track.svelte +59 -59
  140. package/dist/components/scrollable/scrollable.stories.svelte.d.ts +1 -1
  141. package/dist/components/tabs/tab/tab-body.svelte +52 -52
  142. package/dist/components/tabs/tab/tab-description.svelte +41 -41
  143. package/dist/components/tabs/tab/tab-header.svelte +71 -71
  144. package/dist/components/tabs/tab/tab-root.svelte +86 -86
  145. package/dist/components/toast/toast-description.svelte +38 -38
  146. package/dist/components/toast/toast-root.svelte +61 -61
  147. package/dist/components/toast/toast-title.svelte +35 -35
  148. package/dist/components/tree/tree-body.svelte +39 -39
  149. package/dist/components/tree/tree-header.svelte +54 -54
  150. package/dist/components/tree/tree-indicator.svelte +40 -40
  151. package/dist/components/tree/tree-root.svelte +65 -65
  152. package/dist/components/virtual/virtual-root.svelte +239 -239
  153. package/dist/context/preset.svelte.d.ts +1 -1
  154. package/dist/icons/icon-arrow-down.svelte.d.ts +1 -1
  155. package/dist/icons/icon-checkmark.svelte.d.ts +1 -1
  156. package/dist/icons/icon-close.svelte.d.ts +1 -1
  157. package/dist/icons/icon-more-vert.svelte.d.ts +1 -1
  158. package/dist/runes/container.svelte.d.ts +2 -2
  159. package/dist/shared/bond.svelte.d.ts +1 -1
  160. package/dist/utils/state.d.ts +1 -1
  161. package/dist/utils/state.js +2 -1
  162. package/llm/variants.md +1261 -712
  163. package/package.json +464 -437
@@ -1,44 +1,44 @@
1
- <script
2
- lang="ts"
3
- generics="Src extends Component = Component, E extends HtmlElementTagName = 'div', B extends Base = Base"
4
- >
5
- import type { Component } from 'svelte';
6
- import type { HTMLAttributes } from 'svelte/elements';
7
- import { HtmlAtom, type Base } from '../atom';
8
- import type { HtmlElementTagName, HtmlElementType } from '../element';
9
- import type { IconProps } from './types';
10
-
11
- type Element = HtmlElementType<'div'>;
12
-
13
- let {
14
- class: klass = '',
15
- src = undefined,
16
- preset = 'icon',
17
- children = undefined,
18
- ...restProps
19
- }: IconProps<Src, E, B> & HTMLAttributes<Element> = $props();
20
- </script>
21
-
22
- <HtmlAtom
23
- {preset}
24
- class={[
25
- 'icon inline-flex aspect-square h-6 items-center justify-center leading-none text-current',
26
- '$preset',
27
- klass
28
- ]}
29
- {...restProps}
30
- >
31
- {#if src}
32
- {@const Src = src}
33
- <Src />
34
- {:else}
35
- {@render children?.()}
36
- {/if}
37
- </HtmlAtom>
38
-
39
- <style>
40
- :global(.icon > *) {
41
- width: 100%;
42
- height: 100%;
43
- }
44
- </style>
1
+ <script
2
+ lang="ts"
3
+ generics="Src extends Component = Component, E extends HtmlElementTagName = 'div', B extends Base = Base"
4
+ >
5
+ import type { Component } from 'svelte';
6
+ import type { HTMLAttributes } from 'svelte/elements';
7
+ import { HtmlAtom, type Base } from '../atom';
8
+ import type { HtmlElementTagName, HtmlElementType } from '../element';
9
+ import type { IconProps } from './types';
10
+
11
+ type Element = HtmlElementType<'div'>;
12
+
13
+ let {
14
+ class: klass = '',
15
+ src = undefined,
16
+ preset = 'icon',
17
+ children = undefined,
18
+ ...restProps
19
+ }: IconProps<Src, E, B> & HTMLAttributes<Element> = $props();
20
+ </script>
21
+
22
+ <HtmlAtom
23
+ {preset}
24
+ class={[
25
+ 'icon inline-flex aspect-square h-6 items-center justify-center leading-none text-current',
26
+ '$preset',
27
+ klass
28
+ ]}
29
+ {...restProps}
30
+ >
31
+ {#if src}
32
+ {@const Src = src}
33
+ <Src />
34
+ {:else}
35
+ {@render children?.()}
36
+ {/if}
37
+ </HtmlAtom>
38
+
39
+ <style>
40
+ :global(.icon > *) {
41
+ width: 100%;
42
+ height: 100%;
43
+ }
44
+ </style>
@@ -4,7 +4,7 @@ type Image = SvelteComponent<{
4
4
  }, {
5
5
  [evt: string]: CustomEvent<any>;
6
6
  }, {}> & {
7
- $$bindings?: string | undefined;
7
+ $$bindings?: string;
8
8
  };
9
9
  declare const Image: $$__sveltets_2_IsomorphicComponent<{
10
10
  [x: string]: never;
@@ -35,3 +35,6 @@ export * from './stack';
35
35
  export * from './element';
36
36
  export * from './atom';
37
37
  export * from './container';
38
+ export * from './calendar';
39
+ export * from './date-picker';
40
+ export * from './qr-code';
@@ -35,3 +35,6 @@ export * from './stack';
35
35
  export * from './element';
36
36
  export * from './atom';
37
37
  export * from './container';
38
+ export * from './calendar';
39
+ export * from './date-picker';
40
+ export * from './qr-code';
@@ -1,103 +1,103 @@
1
- <script lang="ts" generics="B extends Base = Base">
2
- import { on } from '../../attachments/event.svelte';
3
- import { getPreset } from '../../context';
4
- import { cn, toClassValue } from '../../utils';
5
- import type { PresetModuleName } from '../../context/preset.svelte';
6
- import type { Base } from '../atom';
7
- import { InputBond } from './bond.svelte';
8
- import type { InputControlProps } from './types';
9
-
10
- const bond = InputBond.get();
11
-
12
- let {
13
- value = $bindable(),
14
- files = $bindable(),
15
- date = $bindable(),
16
- number = $bindable(),
17
- checked = $bindable(),
18
- class: klass = '',
19
- type = 'text',
20
- preset: presetKey = 'input.control',
21
- onchange = undefined,
22
- oninput = undefined,
23
- ...restProps
24
- }: InputControlProps<B> = $props();
25
-
26
- const preset = getPreset(presetKey as PresetModuleName)?.apply(bond, [bond]);
27
-
28
- const valueProps = $derived({
29
- ...(bond?.input?.() ?? {}),
30
- ...restProps
31
- });
32
-
33
- function handleChange(ev: CustomEvent) {
34
- if (!onchange) return;
35
-
36
- onchange?.(ev, {
37
- value: value,
38
- files: files,
39
- date: date,
40
- number: number,
41
- checked: checked,
42
- event: ev
43
- });
44
- }
45
-
46
- function handleInput(ev: InputEvent) {
47
- if (!oninput) return;
48
-
49
- const currentTarget = ev.currentTarget as HTMLInputElement;
50
-
51
- if (type === 'number') {
52
- number = currentTarget.valueAsNumber;
53
- }
54
-
55
- if (type === 'date' || type == 'time' || type === 'datetime-local' || type === 'date-local') {
56
- date = currentTarget.valueAsDate;
57
- }
58
-
59
- oninput?.(ev, {
60
- value: value,
61
- files: files,
62
- date: date,
63
- number: number,
64
- checked: checked,
65
- event: ev
66
- });
67
- }
68
-
69
- function toFileList(files: File[]) {
70
- const dataTransfer = new DataTransfer();
71
- files.forEach((file) => dataTransfer.items.add(file));
72
- return dataTransfer.files;
73
- }
74
- </script>
75
-
76
- <input
77
- bind:value={
78
- () => value,
79
- (v) => {
80
- value = v;
81
- if (bond) {
82
- bond.state.props.value = v;
83
- }
84
- }
85
- }
86
- class={cn(
87
- 'text-foreground placeholder:text-muted-foreground h-full w-full flex-1 bg-transparent px-2 leading-1 outline-none',
88
- preset?.class,
89
- toClassValue(klass, bond)
90
- )}
91
- type={type ?? 'text'}
92
- onchange={handleChange}
93
- oninput={handleInput}
94
- {...valueProps}
95
- {@attach (node) => {
96
- if (type === 'file') {
97
- return on('input', () => {
98
- files = Array.from(node.files || []);
99
- bond!.state.props.files = files;
100
- })(node);
101
- }
102
- }}
103
- />
1
+ <script lang="ts" generics="B extends Base = Base">
2
+ import { on } from '../../attachments/event.svelte';
3
+ import { getPreset } from '../../context';
4
+ import { cn, toClassValue } from '../../utils';
5
+ import type { PresetModuleName } from '../../context/preset.svelte';
6
+ import type { Base } from '../atom';
7
+ import { InputBond } from './bond.svelte';
8
+ import type { InputControlProps } from './types';
9
+
10
+ const bond = InputBond.get();
11
+
12
+ let {
13
+ value = $bindable(),
14
+ files = $bindable(),
15
+ date = $bindable(),
16
+ number = $bindable(),
17
+ checked = $bindable(),
18
+ class: klass = '',
19
+ type = 'text',
20
+ preset: presetKey = 'input.control',
21
+ onchange = undefined,
22
+ oninput = undefined,
23
+ ...restProps
24
+ }: InputControlProps<B> = $props();
25
+
26
+ const preset = getPreset(presetKey as PresetModuleName)?.apply(bond, [bond]);
27
+
28
+ const valueProps = $derived({
29
+ ...(bond?.input?.() ?? {}),
30
+ ...restProps
31
+ });
32
+
33
+ function handleChange(ev: CustomEvent) {
34
+ if (!onchange) return;
35
+
36
+ onchange?.(ev, {
37
+ value: value,
38
+ files: files,
39
+ date: date,
40
+ number: number,
41
+ checked: checked,
42
+ event: ev
43
+ });
44
+ }
45
+
46
+ function handleInput(ev: InputEvent) {
47
+ if (!oninput) return;
48
+
49
+ const currentTarget = ev.currentTarget as HTMLInputElement;
50
+
51
+ if (type === 'number') {
52
+ number = currentTarget.valueAsNumber;
53
+ }
54
+
55
+ if (type === 'date' || type == 'time' || type === 'datetime-local' || type === 'date-local') {
56
+ date = currentTarget.valueAsDate;
57
+ }
58
+
59
+ oninput?.(ev, {
60
+ value: value,
61
+ files: files,
62
+ date: date,
63
+ number: number,
64
+ checked: checked,
65
+ event: ev
66
+ });
67
+ }
68
+
69
+ function toFileList(files: File[]) {
70
+ const dataTransfer = new DataTransfer();
71
+ files.forEach((file) => dataTransfer.items.add(file));
72
+ return dataTransfer.files;
73
+ }
74
+ </script>
75
+
76
+ <input
77
+ bind:value={
78
+ () => value,
79
+ (v) => {
80
+ value = v;
81
+ if (bond) {
82
+ bond.state.props.value = v;
83
+ }
84
+ }
85
+ }
86
+ class={cn(
87
+ 'text-foreground placeholder:text-muted-foreground h-full w-full flex-1 bg-transparent px-2 leading-1 outline-none',
88
+ preset?.class,
89
+ toClassValue(klass, bond)
90
+ )}
91
+ type={type ?? 'text'}
92
+ onchange={handleChange}
93
+ oninput={handleInput}
94
+ {...valueProps}
95
+ {@attach (node) => {
96
+ if (type === 'file') {
97
+ return on('input', () => {
98
+ files = Array.from(node.files || []);
99
+ bond!.state.props.files = files;
100
+ })(node);
101
+ }
102
+ }}
103
+ />
@@ -1,25 +1,25 @@
1
- <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'label', B extends Base = Base">
2
- import type { HTMLAttributes } from 'svelte/elements';
3
- import { HtmlAtom, type ElementType, type Base } from '../atom';
4
- import type { LabelProps } from './types';
5
-
6
- type Element = ElementType<E>;
7
-
8
- let {
9
- class: klass = '',
10
- as = 'label' as E,
11
- for: labelfor = null,
12
- children,
13
- ...restProps
14
- }: LabelProps<E, B> & HTMLAttributes<Element> = $props();
15
- </script>
16
-
17
- <HtmlAtom
18
- {as}
19
- preset="label"
20
- class={['font-medium', '$preset', klass]}
21
- for={labelfor}
22
- {...restProps}
23
- >
24
- {@render children?.()}
25
- </HtmlAtom>
1
+ <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'label', B extends Base = Base">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { HtmlAtom, type ElementType, type Base } from '../atom';
4
+ import type { LabelProps } from './types';
5
+
6
+ type Element = ElementType<E>;
7
+
8
+ let {
9
+ class: klass = '',
10
+ as = 'label' as E,
11
+ for: labelfor = null,
12
+ children,
13
+ ...restProps
14
+ }: LabelProps<E, B> & HTMLAttributes<Element> = $props();
15
+ </script>
16
+
17
+ <HtmlAtom
18
+ {as}
19
+ preset="label"
20
+ class={['font-medium', '$preset', klass]}
21
+ for={labelfor}
22
+ {...restProps}
23
+ >
24
+ {@render children?.()}
25
+ </HtmlAtom>
@@ -1,111 +1,111 @@
1
- <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
- import type { HTMLAttributes } from 'svelte/elements';
3
- import { animate as motion } from 'motion';
4
- import { HtmlAtom, type Base } from '../atom';
5
- import { PopoverBond } from './bond.svelte';
6
- import type { PopoverArrowProps } from './types';
7
-
8
- type Element = HTMLElementTagNameMap[E];
9
-
10
- const bond = PopoverBond.get();
11
-
12
- if (!bond) {
13
- throw new Error('');
14
- }
15
-
16
- let {
17
- class: klass = '',
18
- children = undefined,
19
- onmount = undefined,
20
- ondestroy = undefined,
21
- animate = _animate,
22
- enter = undefined,
23
- exit = undefined,
24
- initial = undefined,
25
- ...restProps
26
- }: PopoverArrowProps<E, B> & HTMLAttributes<Element> = $props();
27
-
28
- const position = $derived(bond.position);
29
- const middlewareArrowData = $derived(position?.middlewareData?.arrow);
30
- const isReady = $derived(!!middlewareArrowData);
31
- const side = $derived(position?.placement?.split('-')[0] ?? 'top');
32
-
33
- const arrowProps = $derived({
34
- ...bond.arrow(),
35
- ...restProps
36
- });
37
-
38
- // Rotation based on placement side
39
- const rotation = $derived.by(() => {
40
- switch (side) {
41
- case 'top':
42
- return 180;
43
- case 'bottom':
44
- return 0;
45
- case 'left':
46
- return 90;
47
- case 'right':
48
- return -90;
49
- default:
50
- return 0;
51
- }
52
- });
53
-
54
- function _animate(node: HTMLElement) {
55
- if (!middlewareArrowData) {
56
- return;
57
- }
58
-
59
- const { x, y } = middlewareArrowData;
60
-
61
- const isMainAxis = side === 'top' || side === 'bottom';
62
-
63
- const crossAxisStyle = isMainAxis
64
- ? {
65
- left: 0
66
- }
67
- : {
68
- top: 0
69
- };
70
-
71
- motion(
72
- node,
73
- {
74
- x: x ?? 0,
75
- y: y ?? 0,
76
- opacity: 1,
77
- ...crossAxisStyle
78
- },
79
- { duration: 0 }
80
- );
81
- }
82
- </script>
83
-
84
- <HtmlAtom
85
- {bond}
86
- preset="popover.arrow"
87
- class={['text-border border-border pointer-events-none absolute opacity-0', '$preset', klass]}
88
- onmount={onmount?.bind(bond.state)}
89
- ondestroy={ondestroy?.bind(bond.state)}
90
- animate={animate?.bind(bond.state)}
91
- enter={enter?.bind(bond.state)}
92
- exit={exit?.bind(bond.state)}
93
- initial={initial?.bind(bond.state)}
94
- style="{side}: 100%;"
95
- {...arrowProps}
96
- >
97
- {#if children}
98
- {@render children({ popover: bond })}
99
- {:else}
100
- <svg
101
- width="12"
102
- height="12"
103
- viewBox="0 0 12 12"
104
- fill="none"
105
- xmlns="http://www.w3.org/2000/svg"
106
- style="transform: rotate({rotation}deg);"
107
- >
108
- <path d="M0 12L6 6L12 12H0Z" fill="currentColor" stroke="none" />
109
- </svg>
110
- {/if}
111
- </HtmlAtom>
1
+ <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { animate as motion } from 'motion';
4
+ import { HtmlAtom, type Base } from '../atom';
5
+ import { PopoverBond } from './bond.svelte';
6
+ import type { PopoverArrowProps } from './types';
7
+
8
+ type Element = HTMLElementTagNameMap[E];
9
+
10
+ const bond = PopoverBond.get();
11
+
12
+ if (!bond) {
13
+ throw new Error('');
14
+ }
15
+
16
+ let {
17
+ class: klass = '',
18
+ children = undefined,
19
+ onmount = undefined,
20
+ ondestroy = undefined,
21
+ animate = _animate,
22
+ enter = undefined,
23
+ exit = undefined,
24
+ initial = undefined,
25
+ ...restProps
26
+ }: PopoverArrowProps<E, B> & HTMLAttributes<Element> = $props();
27
+
28
+ const position = $derived(bond.position);
29
+ const middlewareArrowData = $derived(position?.middlewareData?.arrow);
30
+ const isReady = $derived(!!middlewareArrowData);
31
+ const side = $derived(position?.placement?.split('-')[0] ?? 'top');
32
+
33
+ const arrowProps = $derived({
34
+ ...bond.arrow(),
35
+ ...restProps
36
+ });
37
+
38
+ // Rotation based on placement side
39
+ const rotation = $derived.by(() => {
40
+ switch (side) {
41
+ case 'top':
42
+ return 180;
43
+ case 'bottom':
44
+ return 0;
45
+ case 'left':
46
+ return 90;
47
+ case 'right':
48
+ return -90;
49
+ default:
50
+ return 0;
51
+ }
52
+ });
53
+
54
+ function _animate(node: HTMLElement) {
55
+ if (!middlewareArrowData) {
56
+ return;
57
+ }
58
+
59
+ const { x, y } = middlewareArrowData;
60
+
61
+ const isMainAxis = side === 'top' || side === 'bottom';
62
+
63
+ const crossAxisStyle = isMainAxis
64
+ ? {
65
+ left: 0
66
+ }
67
+ : {
68
+ top: 0
69
+ };
70
+
71
+ motion(
72
+ node,
73
+ {
74
+ x: x ?? 0,
75
+ y: y ?? 0,
76
+ opacity: 1,
77
+ ...crossAxisStyle
78
+ },
79
+ { duration: 0 }
80
+ );
81
+ }
82
+ </script>
83
+
84
+ <HtmlAtom
85
+ {bond}
86
+ preset="popover.arrow"
87
+ class={['text-border border-border pointer-events-none absolute opacity-0', '$preset', klass]}
88
+ onmount={onmount?.bind(bond.state)}
89
+ ondestroy={ondestroy?.bind(bond.state)}
90
+ animate={animate?.bind(bond.state)}
91
+ enter={enter?.bind(bond.state)}
92
+ exit={exit?.bind(bond.state)}
93
+ initial={initial?.bind(bond.state)}
94
+ style="{side}: 100%;"
95
+ {...arrowProps}
96
+ >
97
+ {#if children}
98
+ {@render children({ popover: bond })}
99
+ {:else}
100
+ <svg
101
+ width="12"
102
+ height="12"
103
+ viewBox="0 0 12 12"
104
+ fill="none"
105
+ xmlns="http://www.w3.org/2000/svg"
106
+ style="transform: rotate({rotation}deg);"
107
+ >
108
+ <path d="M0 12L6 6L12 12H0Z" fill="currentColor" stroke="none" />
109
+ </svg>
110
+ {/if}
111
+ </HtmlAtom>
@@ -59,12 +59,12 @@
59
59
  const xOffset = $derived(dx * offset);
60
60
  const yOffset = $derived(dy * offset);
61
61
 
62
+ const openAsNumber = $derived(+isOpen);
63
+ const deltaArrow = $derived(position?.middlewareData?.arrow ? 1 : 0);
64
+
62
65
  let isInitialized = false;
63
66
 
64
67
  function _containerInitial(this: typeof bond.state, node: Element) {
65
- const openAsNumber = +this.isOpen;
66
-
67
- const deltaArrow = position?.middlewareData?.arrow ? 1 : 0;
68
68
  const arrowClientWidth = bond?.elements.arrow?.clientWidth ?? 0;
69
69
  const arrowClientHeight = bond?.elements.arrow?.clientHeight ?? 0;
70
70
 
@@ -81,8 +81,6 @@
81
81
  return;
82
82
  }
83
83
 
84
- const openAsNumber = +this.isOpen;
85
-
86
84
  const deltaArrow = position?.middlewareData?.arrow ? 1 : 0;
87
85
  const arrowClientWidth = bond?.elements.arrow?.clientWidth ?? 0;
88
86
  const arrowClientHeight = bond?.elements.arrow?.clientHeight ?? 0;
@@ -93,17 +91,58 @@
93
91
  node.style.transform = `translate3d(${_x}px, ${_y}px, 1px)`;
94
92
  }
95
93
 
94
+ let isOpened = false;
95
+
96
96
  function _animate(this: typeof bond.state, node: Element) {
97
97
  const isOpen = this.isOpen;
98
98
 
99
+ const arrowClientWidth = bond?.elements.arrow?.clientWidth ?? 0;
100
+ const arrowClientHeight = bond?.elements.arrow?.clientHeight ?? 0;
101
+
102
+ const _x = openAsNumber * dx;
103
+ const _y = openAsNumber * dy;
104
+
105
+ const getTransformOrigin = () => {
106
+ switch (placement) {
107
+ case 'top':
108
+ case 'top-start':
109
+ case 'top-end':
110
+ return 'bottom';
111
+ case 'bottom':
112
+ case 'bottom-start':
113
+ case 'bottom-end':
114
+ return 'top';
115
+ case 'left':
116
+ case 'left-start':
117
+ case 'left-end':
118
+ return 'right';
119
+ case 'right':
120
+ case 'right-start':
121
+ case 'right-end':
122
+ return 'left';
123
+ default:
124
+ return 'center';
125
+ }
126
+ };
127
+
128
+ const transformOrigin = getTransformOrigin();
129
+
130
+ const from = isOpened ? 1 : 0.95;
131
+
99
132
  motion(
100
133
  node,
101
134
  {
102
- opacity: +isOpen,
103
- y: (isOpen ? 0 : -1) * dy * 8
135
+ opacity: openAsNumber,
136
+ y: _y + dy * (!isOpen ? -1 : 0) * (arrowClientHeight + yOffset),
137
+ x: _x + dx * (!isOpen ? -1 : 0) * (arrowClientWidth + xOffset),
138
+ scaleY: dy ? (isOpen ? [from, 1] : [1, 0.8]) : undefined,
139
+ scaleX: dx ? (isOpen ? [from, 1] : [1, 0.8]) : undefined,
140
+ transformOrigin
104
141
  },
105
142
  { duration: DURATION.fast / 1000 }
106
143
  );
144
+
145
+ isOpened = isOpen;
107
146
  }
108
147
  </script>
109
148