@svelte-atoms/core 1.0.0-alpha.44 → 1.0.0-alpha.46

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 (178) hide show
  1. package/README.md +13 -0
  2. package/dist/components/accordion/item/accordion-item-body.svelte +5 -8
  3. package/dist/components/accordion/item/accordion-item-header.svelte +0 -13
  4. package/dist/components/accordion/item/accordion-item-indicator.svelte +0 -12
  5. package/dist/components/accordion/item/accordion-item-root.svelte +0 -12
  6. package/dist/components/alert/alert-actions.svelte +0 -12
  7. package/dist/components/alert/alert-close-button.svelte +0 -12
  8. package/dist/components/alert/alert-content.svelte +0 -12
  9. package/dist/components/alert/alert-description.svelte +0 -12
  10. package/dist/components/alert/alert-icon.svelte +0 -12
  11. package/dist/components/alert/alert-root.svelte +1 -13
  12. package/dist/components/alert/alert-title.svelte +0 -12
  13. package/dist/components/atom/html-atom.svelte +31 -17
  14. package/dist/components/atom/types.d.ts +9 -0
  15. package/dist/components/atom/utils/base.d.ts +6 -0
  16. package/dist/components/atom/utils/base.js +8 -0
  17. package/dist/components/atom/utils/cache.d.ts +17 -0
  18. package/dist/components/atom/utils/cache.js +134 -0
  19. package/dist/components/atom/utils/classes.d.ts +14 -0
  20. package/dist/components/atom/utils/classes.js +42 -0
  21. package/dist/components/atom/utils/constants.d.ts +9 -0
  22. package/dist/components/atom/utils/constants.js +9 -0
  23. package/dist/components/atom/utils/index.d.ts +6 -0
  24. package/dist/components/atom/utils/index.js +5 -0
  25. package/dist/components/atom/utils/preset.d.ts +22 -0
  26. package/dist/components/atom/utils/preset.js +94 -0
  27. package/dist/components/atom/utils/props.d.ts +13 -0
  28. package/dist/components/atom/utils/props.js +60 -0
  29. package/dist/components/atom/utils/variants.d.ts +31 -0
  30. package/dist/components/atom/utils/variants.js +270 -0
  31. package/dist/components/card/card-body.svelte +0 -12
  32. package/dist/components/card/card-description.svelte +0 -12
  33. package/dist/components/card/card-footer.svelte +0 -12
  34. package/dist/components/card/card-header.svelte +0 -12
  35. package/dist/components/card/card-media.svelte +0 -12
  36. package/dist/components/card/card-root.svelte +0 -12
  37. package/dist/components/card/card-subtitle.svelte +0 -12
  38. package/dist/components/card/card-title.svelte +0 -12
  39. package/dist/components/collapsible/collapsible-body.svelte +5 -12
  40. package/dist/components/collapsible/collapsible-header.svelte +0 -12
  41. package/dist/components/collapsible/collapsible-indicator.svelte +0 -12
  42. package/dist/components/collapsible/collapsible-root.svelte +0 -12
  43. package/dist/components/combobox/combobox-control.svelte +0 -12
  44. package/dist/components/combobox/combobox-item.svelte +0 -12
  45. package/dist/components/combobox/combobox-item.svelte.d.ts +0 -6
  46. package/dist/components/combobox/index.d.ts +1 -1
  47. package/dist/components/container/container.svelte +0 -12
  48. package/dist/components/datagrid/column/datagrid-column-sort-icon.svelte +3 -12
  49. package/dist/components/datagrid/column/datagrid-column-sort-icon.svelte.d.ts +0 -6
  50. package/dist/components/datagrid/datagrid-body.svelte +17 -1
  51. package/dist/components/dialog/dialog-body.svelte +0 -12
  52. package/dist/components/dialog/dialog-close-button.svelte +0 -12
  53. package/dist/components/dialog/dialog-close.svelte +0 -12
  54. package/dist/components/dialog/dialog-content.svelte +4 -12
  55. package/dist/components/dialog/dialog-description.svelte +0 -12
  56. package/dist/components/dialog/dialog-footer.svelte +0 -12
  57. package/dist/components/dialog/dialog-header.svelte +0 -12
  58. package/dist/components/dialog/dialog-title.svelte +0 -12
  59. package/dist/components/dialog/index.d.ts +3 -0
  60. package/dist/components/dialog/index.js +3 -0
  61. package/dist/components/drawer/drawer-backdrop.svelte +0 -12
  62. package/dist/components/drawer/drawer-body.svelte +0 -12
  63. package/dist/components/drawer/drawer-content.svelte +5 -12
  64. package/dist/components/drawer/drawer-description.svelte +0 -12
  65. package/dist/components/drawer/drawer-footer.svelte +0 -12
  66. package/dist/components/drawer/drawer-header.svelte +0 -12
  67. package/dist/components/drawer/drawer-root.svelte +5 -4
  68. package/dist/components/drawer/drawer-title.svelte +0 -12
  69. package/dist/components/dropdown/dropdown-placeholder.svelte +0 -6
  70. package/dist/components/dropdown/dropdown-placeholder.svelte.d.ts +0 -6
  71. package/dist/components/dropdown/dropdown-query.svelte +0 -12
  72. package/dist/components/dropdown-menu/bond.svelte.d.ts +0 -4
  73. package/dist/components/dropdown-menu/dropdown-menu-content.svelte +0 -12
  74. package/dist/components/dropdown-menu/dropdown-menu-content.svelte.d.ts +0 -6
  75. package/dist/components/dropdown-menu/index.d.ts +1 -1
  76. package/dist/components/form/field/bond.svelte.d.ts +29 -17
  77. package/dist/components/form/field/bond.svelte.js +73 -49
  78. package/dist/components/form/field/field-control.svelte +21 -18
  79. package/dist/components/form/field/field-label.svelte +2 -2
  80. package/dist/components/form/field/field-root.svelte +2 -1
  81. package/dist/components/index.d.ts +2 -0
  82. package/dist/components/index.js +2 -0
  83. package/dist/components/input/input-file-control.svelte +0 -12
  84. package/dist/components/input/input-icon.svelte +3 -3
  85. package/dist/components/input/input-number-control.svelte +28 -35
  86. package/dist/components/input/input-text-control.svelte +8 -3
  87. package/dist/components/input/input-url-control.svelte +2 -2
  88. package/dist/components/input/types.d.ts +4 -4
  89. package/dist/components/kbd/index.d.ts +3 -0
  90. package/dist/components/kbd/index.js +3 -0
  91. package/dist/components/kbd/kbd.svelte +19 -0
  92. package/dist/components/kbd/kbd.svelte.d.ts +4 -0
  93. package/dist/components/kbd/shortcut.svelte +38 -0
  94. package/dist/components/kbd/shortcut.svelte.d.ts +4 -0
  95. package/dist/components/kbd/types.d.ts +20 -0
  96. package/dist/components/kbd/types.js +1 -0
  97. package/dist/components/layer/layer-inner.svelte +0 -12
  98. package/dist/components/layer/layer-root.svelte +0 -12
  99. package/dist/components/menu/menu-content.svelte +0 -12
  100. package/dist/components/menu/menu-content.svelte.d.ts +0 -6
  101. package/dist/components/popover/bond.svelte.d.ts +29 -1
  102. package/dist/components/popover/bond.svelte.js +55 -2
  103. package/dist/components/popover/index.d.ts +1 -0
  104. package/dist/components/popover/index.js +1 -0
  105. package/dist/components/popover/popover-arrow.svelte +4 -2
  106. package/dist/components/popover/popover-content.svelte +17 -90
  107. package/dist/components/popover/popover-overlay.svelte +98 -0
  108. package/dist/components/popover/popover-overlay.svelte.d.ts +4 -0
  109. package/dist/components/popover/popover-trigger.svelte +9 -0
  110. package/dist/components/popover/strategies/floating.svelte +10 -10
  111. package/dist/components/popover/types.d.ts +7 -2
  112. package/dist/components/portal/portal-inner.svelte +0 -12
  113. package/dist/components/portal/portal-root.svelte +0 -12
  114. package/dist/components/portal/types.d.ts +1 -1
  115. package/dist/components/progress/index.d.ts +3 -0
  116. package/dist/components/progress/index.js +3 -0
  117. package/dist/components/progress/progress-circular.svelte +99 -0
  118. package/dist/components/progress/progress-circular.svelte.d.ts +6 -0
  119. package/dist/components/progress/progress-linear.svelte +66 -0
  120. package/dist/components/progress/progress-linear.svelte.d.ts +6 -0
  121. package/dist/components/progress/types.d.ts +18 -0
  122. package/dist/components/progress/types.js +1 -0
  123. package/dist/components/scrollable/scrollable-container.svelte +0 -12
  124. package/dist/components/scrollable/scrollable-content.svelte +0 -12
  125. package/dist/components/scrollable/scrollable-root.svelte +0 -12
  126. package/dist/components/scrollable/scrollable-thumb.svelte +1 -12
  127. package/dist/components/scrollable/scrollable-track.svelte +0 -12
  128. package/dist/components/select/bond.svelte.d.ts +0 -4
  129. package/dist/components/select/index.d.ts +1 -1
  130. package/dist/components/select/select-placeholder.svelte +0 -6
  131. package/dist/components/select/select-placeholder.svelte.d.ts +0 -6
  132. package/dist/components/sidebar/sidebar-content.svelte +5 -12
  133. package/dist/components/stack/bond.svelte.js +6 -0
  134. package/dist/components/stack/stack-item.svelte +4 -0
  135. package/dist/components/switch/switch.svelte +2 -0
  136. package/dist/components/tabs/tab/tab-header.svelte +4 -4
  137. package/dist/components/tabs/tabs-body.svelte +0 -2
  138. package/dist/components/tabs/tabs-root.svelte +11 -3
  139. package/dist/components/toast/atoms.d.ts +1 -1
  140. package/dist/components/toast/atoms.js +1 -1
  141. package/dist/components/toast/attachments.svelte.d.ts +10 -2
  142. package/dist/components/toast/attachments.svelte.js +9 -1
  143. package/dist/components/toast/bond.svelte.d.ts +73 -0
  144. package/dist/components/toast/bond.svelte.js +132 -0
  145. package/dist/components/toast/index.d.ts +1 -1
  146. package/dist/components/toast/index.js +1 -1
  147. package/dist/components/toast/toast-close.svelte +47 -0
  148. package/dist/components/toast/toast-close.svelte.d.ts +26 -0
  149. package/dist/components/toast/toast-description.svelte +16 -24
  150. package/dist/components/toast/toast-description.svelte.d.ts +15 -19
  151. package/dist/components/toast/toast-root.svelte +36 -26
  152. package/dist/components/toast/toast-root.svelte.d.ts +16 -15
  153. package/dist/components/toast/toast-title.svelte +17 -22
  154. package/dist/components/toast/toast-title.svelte.d.ts +13 -13
  155. package/dist/components/toast/toaster.svelte.d.ts +38 -0
  156. package/dist/components/toast/toaster.svelte.js +107 -0
  157. package/dist/components/toast/types.d.ts +13 -21
  158. package/dist/components/tree/tree-body.svelte +5 -12
  159. package/dist/components/tree/tree-header.svelte +0 -12
  160. package/dist/components/tree/tree-indicator.svelte +0 -12
  161. package/dist/components/tree/tree-root.svelte +0 -12
  162. package/dist/context/preset.svelte.d.ts +53 -37
  163. package/dist/context/preset.svelte.js +29 -3
  164. package/package.json +1 -1
  165. package/dist/components/atom/utils.d.ts +0 -44
  166. package/dist/components/atom/utils.js +0 -275
  167. package/dist/components/popover/popover-engine.svelte +0 -118
  168. package/dist/components/popover/popover-engine.svelte.d.ts +0 -3
  169. package/dist/components/toast/bond.d.ts +0 -35
  170. package/dist/components/toast/bond.js +0 -59
  171. package/dist/components/toast/manager.svelte.d.ts +0 -38
  172. package/dist/components/toast/manager.svelte.js +0 -82
  173. package/dist/components/toast/toast-root-managed.svelte +0 -64
  174. package/dist/components/toast/toast-root-managed.svelte.d.ts +0 -7
  175. package/dist/components/toast/toast-toaster.svelte +0 -42
  176. package/dist/components/toast/toast-toaster.svelte.d.ts +0 -4
  177. /package/dist/components/popover/{motion.d.ts → motion.svelte.d.ts} +0 -0
  178. /package/dist/components/popover/{motion.js → motion.svelte.js} +0 -0
@@ -1,13 +1,13 @@
1
1
  <script lang="ts" generics="E extends HtmlElementTagName, B extends Base = Base">
2
- import { PortalBond, PortalsBond, Teleport } from '../portal';
2
+ import { PortalBond, PortalsBond } from '../portal';
3
3
  import { HtmlAtom, type Base } from '../atom';
4
4
  import type { HtmlElementTagName } from '../element';
5
+ import { clickout } from '../../attachments';
5
6
  import { PopoverBond } from './bond.svelte';
6
- import { animatePopoverContent } from './motion';
7
- import { ZLayer } from '../portal/zlayer.svelte';
7
+ import { animatePopoverContent } from './motion.svelte';
8
8
  import type { PopoverContentProps } from './types';
9
9
  import Floating from './strategies/floating.svelte';
10
- import { clickout } from '../../attachments';
10
+ import PopoverOverlay from './popover-overlay.svelte';
11
11
 
12
12
  const bond = PopoverBond.get();
13
13
 
@@ -15,18 +15,6 @@
15
15
  throw new Error('<PopoverOverlay /> must be used within a <Popover />');
16
16
  }
17
17
 
18
- const positionStrategy = $derived(bond?.state.props.positionStrategy ?? 'absolute');
19
-
20
- const parentLayer = (() => {
21
- try {
22
- return ZLayer.get();
23
- } catch {
24
- return undefined;
25
- }
26
- })();
27
-
28
- const layer = new ZLayer('popover', () => parentLayer?.get() ?? 0).share();
29
-
30
18
  const activePortalBond = $derived.by(() => {
31
19
  const key = bond.state.props.portal;
32
20
  if (key instanceof PortalBond) {
@@ -42,73 +30,21 @@
42
30
 
43
31
  let {
44
32
  class: klass = '',
33
+ overlay: Overlay = PopoverOverlay,
45
34
  children = undefined,
46
- animate = animatePopoverContent(),
47
35
  onclickoutside = undefined,
36
+ fallback = {
37
+ animate: animatePopoverContent()
38
+ },
48
39
  ...restProps
49
40
  }: PopoverContentProps<E, B> = $props();
50
41
 
51
- const isOpen = $derived(bond.state.isOpen && !!bond.elements.trigger);
52
42
  const portalId = $derived(activePortalBond?.id);
53
43
 
54
- /**
55
- * Calculate the final position and opacity for the popover content
56
- */
57
- function calculatePosition() {
58
- const position = bond.state.position;
59
-
60
- if (!position) {
61
- return null;
62
- }
63
-
64
- const { placement, x = 0, y = 0, middlewareData } = position;
65
- const offset = bond.state.props.offset;
66
- const openState = +isOpen;
67
-
68
- // Calculate direction multipliers based on placement
69
- const directionY = placement?.startsWith('top') ? -1 : placement?.startsWith('bottom') ? 1 : 0;
70
- const directionX = placement?.startsWith('left') ? -1 : placement?.startsWith('right') ? 1 : 0;
71
-
72
- // Calculate arrow dimensions and delta
73
- const arrowWidth = bond?.elements.arrow?.clientWidth ?? 0;
74
- const arrowHeight = bond?.elements.arrow?.clientHeight ?? 0;
75
- const arrowDelta = middlewareData?.arrow ? 1 : 0;
76
-
77
- // Calculate final position with offset and arrow adjustment
78
- const finalX = x + directionX * offset * openState + arrowDelta * directionX * arrowWidth;
79
- const finalY = y + directionY * offset * openState + arrowDelta * directionY * arrowHeight;
80
-
81
- return {
82
- transform: `translate3d(${finalX}px, ${finalY}px, 1px)`,
83
- opacity: openState.toString()
84
- };
85
- }
86
-
87
- function containerInitial(this: typeof bond.state, node: HTMLElement) {
88
- const styles = calculatePosition();
89
-
90
- // Hide content until position is calculated to avoid ghosting
91
- if (!styles) {
92
- node.style.opacity = '0';
93
- return;
94
- }
95
-
96
- node.style.transform = styles.transform;
97
- node.style.opacity = styles.opacity;
98
- }
99
-
100
- function containerAnimate(this: typeof bond.state, node: HTMLElement) {
101
- void bond.state.props.open; // Ensure reactivity to open state changes
102
-
103
- const styles = calculatePosition();
104
-
105
- if (!styles) {
106
- return;
107
- }
108
-
109
- node.style.transform = styles.transform;
110
- node.style.opacity = '1';
111
- }
44
+ const contentProps = $derived({
45
+ ...bond?.content().spread,
46
+ ...restProps
47
+ });
112
48
 
113
49
  function clickoutAttachement(node: HTMLElement) {
114
50
  const cleanup = clickout((ev) => {
@@ -119,7 +55,7 @@
119
55
 
120
56
  const trigger = bond.element('trigger');
121
57
 
122
- if (trigger && (trigger.contains(ev.target as Node) || trigger === ev.target)) {
58
+ if (trigger instanceof Element && (trigger.contains(ev.target as Node) || trigger === ev.target)) {
123
59
  return;
124
60
  }
125
61
 
@@ -132,28 +68,19 @@
132
68
 
133
69
  <Floating />
134
70
 
135
- <Teleport
136
- portal={portalId ?? 'root.l0'}
137
- as="div"
138
- class="top-0 left-0 h-min w-fit outline-none pointer-events-none"
139
- style="z-index: {layer.get()}; position: {positionStrategy};"
140
- initial={containerInitial?.bind(bond.state)}
141
- animate={containerAnimate?.bind(bond.state)}
142
- {...bond.content().spread}
143
- >
71
+ <Overlay portal={portalId ?? 'root.l0'} as="div">
144
72
  <HtmlAtom
145
73
  {@attach clickoutAttachement}
146
74
  {bond}
75
+ {fallback}
147
76
  preset="popover.content"
148
77
  class={[
149
78
  'popover-content bg-popover text-popover-foreground border-border rounded-md border p-2 opacity-0 shadow-lg outline-none',
150
- // isOpen && 'pointer-events-auto',
151
79
  '$preset',
152
80
  klass
153
81
  ]}
154
- animate={animate?.bind(bond.state)}
155
- {...restProps}
82
+ {...contentProps}
156
83
  >
157
84
  {@render children?.({ popover: bond })}
158
85
  </HtmlAtom>
159
- </Teleport>
86
+ </Overlay>
@@ -0,0 +1,98 @@
1
+ <script lang="ts">
2
+ import { Teleport, ZLayer } from "../portal";
3
+ import { PopoverBond } from "./bond.svelte";
4
+ import type { PopoverOverlayProps } from "./types";
5
+
6
+ const bond = PopoverBond.get();
7
+ const isOpen = $derived(bond?.state.isOpen ?? false);
8
+ const positionStrategy = $derived(bond?.state.props.positionStrategy ?? 'absolute');
9
+
10
+ const parentLayer = (() => {
11
+ try {
12
+ return ZLayer.get();
13
+ } catch {
14
+ return undefined;
15
+ }
16
+ })();
17
+
18
+ const layer = new ZLayer('popover', () => parentLayer?.get() ?? 0).share();
19
+
20
+ let { portal, children = undefined, ...restProps}: PopoverOverlayProps = $props();
21
+
22
+ const overlayProps = $derived({
23
+ ...bond?.overlay().spread,
24
+ ...restProps
25
+ });
26
+
27
+ /**
28
+ * Calculate the final position and opacity for the popover content
29
+ */
30
+ function calculatePosition() {
31
+ const position = bond.state.position;
32
+
33
+ if (!position) {
34
+ return null;
35
+ }
36
+
37
+ const { placement, x = 0, y = 0, middlewareData } = position;
38
+ const offset = bond.state.props.offset;
39
+ const openState = +isOpen;
40
+
41
+ // Calculate direction multipliers based on placement
42
+ const directionY = placement?.startsWith('top') ? -1 : placement?.startsWith('bottom') ? 1 : 0;
43
+ const directionX = placement?.startsWith('left') ? -1 : placement?.startsWith('right') ? 1 : 0;
44
+
45
+ const arrow = bond.element('arrow');
46
+ // Calculate arrow dimensions and delta
47
+ const arrowWidth = arrow?.clientWidth ?? 0;
48
+ const arrowHeight = arrow?.clientHeight ?? 0;
49
+ const arrowDelta = middlewareData?.arrow ? 1 : 0;
50
+
51
+ // Calculate final position with offset and arrow adjustment
52
+ const finalX = x + directionX * offset * openState + arrowDelta * directionX * arrowWidth;
53
+ const finalY = y + directionY * offset * openState + arrowDelta * directionY * arrowHeight;
54
+
55
+ return {
56
+ transform: `translate3d(${finalX}px, ${finalY}px, 1px)`,
57
+ opacity: openState.toString()
58
+ };
59
+ }
60
+
61
+ function initial(this: typeof bond.state, node: HTMLElement) {
62
+ const styles = calculatePosition();
63
+
64
+ // Hide content until position is calculated to avoid ghosting
65
+ if (!styles) {
66
+ node.style.opacity = '0';
67
+ return;
68
+ }
69
+
70
+ node.style.transform = styles.transform;
71
+ node.style.opacity = styles.opacity;
72
+ }
73
+
74
+ function animate(this: typeof bond.state, node: HTMLElement) {
75
+ void bond.state.props.open; // Ensure reactivity to open state changes
76
+
77
+ const styles = calculatePosition();
78
+
79
+ if (!styles) {
80
+ return;
81
+ }
82
+
83
+ node.style.transform = styles.transform;
84
+ node.style.opacity = '1';
85
+ }
86
+ </script>
87
+
88
+ <Teleport
89
+ {portal}
90
+ as="div"
91
+ class="top-0 left-0 h-min w-fit outline-none pointer-events-none"
92
+ style="z-index: {layer.get()}; position: {positionStrategy};"
93
+ initial={initial}
94
+ animate={animate}
95
+ {...overlayProps}
96
+ >
97
+ {@render children?.({ popover: bond })}
98
+ </Teleport>
@@ -0,0 +1,4 @@
1
+ import type { PopoverOverlayProps } from "./types";
2
+ declare const PopoverOverlay: import("svelte").Component<PopoverOverlayProps<"div", import("..").SnippetBase>, {}, "">;
3
+ type PopoverOverlay = ReturnType<typeof PopoverOverlay>;
4
+ export default PopoverOverlay;
@@ -14,6 +14,7 @@
14
14
  as = 'button' as E,
15
15
  preset = 'popover.trigger',
16
16
  children = undefined,
17
+ onpointerenter = undefined,
17
18
  ...restProps
18
19
  }: PopoverTriggerProps<E, B> = $props();
19
20
 
@@ -21,6 +22,13 @@
21
22
  ...bond.trigger().spread,
22
23
  ...restProps
23
24
  });
25
+
26
+ function handlePointerEnter(event: PointerEvent) {
27
+ onpointerenter?.(event);
28
+ if(event.defaultPrevented) return;
29
+
30
+ bond.state.tracking = true;
31
+ }
24
32
  </script>
25
33
 
26
34
  <HtmlAtom
@@ -29,6 +37,7 @@
29
37
  {preset}
30
38
  class={['border-border flex w-fit cursor-pointer rounded-md p-2', '$preset', klass]}
31
39
  type={as === 'button' ? 'button' : undefined}
40
+ onpointerenter={handlePointerEnter}
32
41
  {...triggerProps}
33
42
  >
34
43
  {@render children?.({ popover: bond })}
@@ -13,12 +13,12 @@
13
13
 
14
14
  const bond = PopoverBond.get();
15
15
 
16
- const open = $derived(bond?.state.props.open);
16
+ const tracking = $derived(bond?.state.shouldTrackPosition ?? false);
17
17
  const reference = $derived(bond?.element<BondVirtualElement>('virtual-trigger') ?? bond?.element<Element>('trigger'));
18
- const content = $derived(bond?.element<HTMLElement>('content'));
18
+ const overlay = $derived(bond?.element<HTMLElement>('overlay'));
19
19
 
20
20
  $effect.pre(() => {
21
- if (!(reference) || !content || !open) return;
21
+ if (!reference || !overlay || !tracking) return;
22
22
 
23
23
  // Use the existing positioning behavior
24
24
  const cleanup = compute(bond)({}, autoUpdate);
@@ -33,7 +33,7 @@
33
33
  const arrowElement = bond.element<HTMLElement>('arrow');
34
34
 
35
35
  // Guard: ensure required elements exist
36
- if (!reference || !content) {
36
+ if (!reference || !overlay) {
37
37
  return;
38
38
  }
39
39
 
@@ -69,7 +69,7 @@
69
69
  // Double rAF ensures browser has completed layout + paint
70
70
  await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
71
71
 
72
- const position = await computePosition(reference, content, {
72
+ const position = await computePosition(reference, overlay, {
73
73
  placement: placement ?? 'bottom',
74
74
  middleware,
75
75
  strategy: bond.state.props.positionStrategy
@@ -79,26 +79,26 @@
79
79
  const x = Math.round((position.x ?? 0) * 100) / 100;
80
80
  const y = Math.round((position.y ?? 0) * 100) / 100;
81
81
 
82
- bond.state.position = {
82
+ bond.state.notifyComputed({
83
83
  middlewareData: position.middlewareData,
84
84
  placement: position.placement,
85
85
  strategy: position.strategy,
86
86
  x,
87
87
  y
88
- };
89
- onchangeCallback?.(content, position);
88
+ });
89
+ onchangeCallback?.(overlay, position);
90
90
 
91
91
  // Set minimum width to match trigger
92
92
  if (reference && (reference instanceof Element)) {
93
93
  requestAnimationFrame(() => {
94
- content.style.minWidth = `${reference.clientWidth}px`;
94
+ overlay.style.minWidth = `${reference.clientWidth}px`;
95
95
  });
96
96
  }
97
97
  };
98
98
 
99
99
  // Use auto-update if provided, otherwise compute once
100
100
  if (updater) {
101
- return updater(reference, content, compute, {
101
+ return updater(reference, overlay, compute, {
102
102
  ancestorScroll: false
103
103
  });
104
104
  }
@@ -1,10 +1,10 @@
1
- import type { Snippet } from 'svelte';
1
+ import type { Component, Snippet } from 'svelte';
2
2
  import type { Placement } from '@floating-ui/dom';
3
3
  import type { Factory } from '../../types';
4
4
  import type { PopoverBond } from './bond.svelte';
5
5
  import type { Base, HtmlAtomProps } from '../atom';
6
6
  import type { HtmlElementTagName } from '../element';
7
- import type { PortalBond } from '../portal';
7
+ import type { PortalBond, TeleportProps } from '../portal';
8
8
  export type PopoverChildren = Snippet<[{
9
9
  popover: PopoverBond;
10
10
  }]>;
@@ -26,7 +26,12 @@ export interface AnimateParams {
26
26
  yOffset: number;
27
27
  open: boolean;
28
28
  }
29
+ export interface PopoverOverlayProps<E extends HtmlElementTagName = 'div', B extends Base = Base> extends TeleportProps<E, B, PopoverChildren> {
30
+ portal: string | PortalBond;
31
+ children?: PopoverChildren;
32
+ }
29
33
  export interface PopoverContentProps<T extends HtmlElementTagName, B extends Base = Base> extends HtmlAtomProps<T, B, PopoverChildren> {
34
+ overlay?: Component<PopoverOverlayProps>;
30
35
  onclickoutside?: (ev: PointerEvent, atom: PopoverBond) => void;
31
36
  }
32
37
  export interface PopoverIndicatorProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends HtmlAtomProps<E, B, PopoverChildren> {
@@ -15,12 +15,6 @@
15
15
  let {
16
16
  class: klass = '',
17
17
  children = undefined,
18
- onmount = undefined,
19
- ondestroy = undefined,
20
- animate = undefined,
21
- enter = undefined,
22
- exit = undefined,
23
- initial = undefined,
24
18
  ...restProps
25
19
  }: HtmlAtomProps<E, B> & HTMLAttributes<Element> = $props();
26
20
 
@@ -34,12 +28,6 @@
34
28
  {bond}
35
29
  preset="portal.inner"
36
30
  class={['border-border relative size-full', '$preset', klass]}
37
- enter={enter?.bind(bond.state)}
38
- exit={exit?.bind(bond.state)}
39
- initial={initial?.bind(bond.state)}
40
- animate={animate?.bind(bond.state)}
41
- onmount={onmount?.bind(bond.state)}
42
- ondestroy={ondestroy?.bind(bond.state)}
43
31
  {...bondProps}
44
32
  >
45
33
  {@render children?.()}
@@ -17,12 +17,6 @@
17
17
  id,
18
18
  factory = _factory,
19
19
  children = undefined,
20
- onmount = undefined,
21
- ondestroy = undefined,
22
- animate = undefined,
23
- enter = undefined,
24
- exit = undefined,
25
- initial = undefined,
26
20
  ...restProps
27
21
  }: PortalOuterProps<E, B> & HTMLAttributes<Element> = $props();
28
22
 
@@ -64,12 +58,6 @@
64
58
  {bond}
65
59
  preset="portal"
66
60
  class={['border-border pointer-events-none', '$preset', klass]}
67
- enter={enter?.bind(bond.state)}
68
- exit={exit?.bind(bond.state)}
69
- initial={initial?.bind(bond.state)}
70
- animate={animate?.bind(bond.state)}
71
- onmount={onmount?.bind(bond.state)}
72
- ondestroy={ondestroy?.bind(bond.state)}
73
61
  {...rootProps}
74
62
  >
75
63
  {@render children?.()}
@@ -16,6 +16,6 @@ export type PortalOuterProps<E extends keyof HTMLElementTagNameMap = 'div', B ex
16
16
  id: RootPortals | (string & {});
17
17
  children?: Snippet;
18
18
  };
19
- export type TeleportProps<E extends HtmlElementTagName = 'div', B extends Base = Base> = HtmlAtomProps<E, B, PortalChildren> & {
19
+ export type TeleportProps<E extends HtmlElementTagName = 'div', B extends Base = Base, Children extends Snippet<unknown[]> = PortalChildren> = HtmlAtomProps<E, B, Children> & {
20
20
  portal?: string | PortalBond;
21
21
  };
@@ -0,0 +1,3 @@
1
+ export { default as ProgressLinear } from './progress-linear.svelte';
2
+ export { default as ProgressCircular } from './progress-circular.svelte';
3
+ export * from './types';
@@ -0,0 +1,3 @@
1
+ export { default as ProgressLinear } from './progress-linear.svelte';
2
+ export { default as ProgressCircular } from './progress-circular.svelte';
3
+ export * from './types';
@@ -0,0 +1,99 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { HtmlAtom } from '../atom';
4
+ import type { ProgressCircularProps } from './types';
5
+ import { SvgElement } from '../element'
6
+
7
+ let {
8
+ class: klass = '',
9
+ value = null,
10
+ max = 100,
11
+ preset = 'progress.circular',
12
+ ...restProps
13
+ }: ProgressCircularProps & HTMLAttributes<HTMLDivElement> = $props();
14
+
15
+ const isIndeterminate = $derived(value === null || value === undefined);
16
+ const percent = $derived(isIndeterminate ? null : Math.min(100, Math.max(0, (value! / max) * 100)));
17
+
18
+ const radius = 20;
19
+ const circumference = 2 * Math.PI * radius;
20
+ const strokeDashoffset = $derived(
21
+ isIndeterminate ? circumference : circumference - (percent! / 100) * circumference
22
+ );
23
+ </script>
24
+
25
+ {#snippet defaultCircularFill()}
26
+ <SvgElement
27
+ as="circle"
28
+ preset="progress.circular.fill"
29
+ cx="24"
30
+ cy="24"
31
+ r={radius}
32
+ fill="none"
33
+ stroke-width="4"
34
+ stroke-linecap="round"
35
+ stroke-dasharray={circumference}
36
+ stroke-dashoffset={strokeDashoffset}
37
+ class={[
38
+ 'stroke-foreground origin-center duration-300',
39
+ !isIndeterminate && 'transition-[stroke-dashoffset]',
40
+ isIndeterminate && 'animate-progress-circular-indeterminate'
41
+ ]
42
+ .filter(Boolean)
43
+ .join(' ')}
44
+ />
45
+ {/snippet}
46
+
47
+ <HtmlAtom
48
+ {preset}
49
+ as="div"
50
+ class={[
51
+ 'progress-root progress-root--circular relative inline-flex items-center justify-center',
52
+ '$preset',
53
+ klass
54
+ ]}
55
+ role="progressbar"
56
+ aria-valuemin={0}
57
+ aria-valuemax={max}
58
+ aria-valuenow={isIndeterminate ? undefined : value ?? undefined}
59
+ aria-valuetext={isIndeterminate ? undefined : `${Math.round(percent!)}%`}
60
+ data-indeterminate={isIndeterminate}
61
+ data-value={isIndeterminate ? undefined : value ?? undefined}
62
+ data-max={max}
63
+ data-completed={!isIndeterminate && percent === 100}
64
+ {...restProps}
65
+ >
66
+ <svg viewBox="0 0 48 48" class="h-full w-full -rotate-90" aria-hidden="true">
67
+ <SvgElement
68
+ as="circle"
69
+ preset="progress.circular.track"
70
+ cx="24"
71
+ cy="24"
72
+ r={radius}
73
+ fill="none"
74
+ stroke-width="4"
75
+ class="stroke-input"
76
+ />
77
+ {@render defaultCircularFill()}
78
+ </svg>
79
+ </HtmlAtom>
80
+
81
+ <style>
82
+ @keyframes progress-circular-spin {
83
+ 0% { transform: rotate(0deg); }
84
+ 100% { transform: rotate(360deg); }
85
+ }
86
+
87
+ @keyframes progress-circular-dash {
88
+ 0% { stroke-dashoffset: 119; }
89
+ 50% { stroke-dashoffset: 30; }
90
+ 100% { stroke-dashoffset: 119; }
91
+ }
92
+
93
+ :global(.animate-progress-circular-indeterminate) {
94
+ animation:
95
+ progress-circular-spin 1.4s linear infinite,
96
+ progress-circular-dash 1.4s ease-in-out infinite;
97
+ transform-origin: center;
98
+ }
99
+ </style>
@@ -0,0 +1,6 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { ProgressCircularProps } from './types';
3
+ type $$ComponentProps = ProgressCircularProps & HTMLAttributes<HTMLDivElement>;
4
+ declare const ProgressCircular: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type ProgressCircular = ReturnType<typeof ProgressCircular>;
6
+ export default ProgressCircular;
@@ -0,0 +1,66 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { HtmlAtom } from '../atom';
4
+ import type { ProgressLinearProps } from './types';
5
+ import { HtmlElement } from '../element';
6
+
7
+ let {
8
+ class: klass = '',
9
+ value = null,
10
+ max = 100,
11
+ preset = 'progress.linear',
12
+ ...restProps
13
+ }: ProgressLinearProps & HTMLAttributes<HTMLDivElement> = $props();
14
+
15
+ const isIndeterminate = $derived(value === null || value === undefined);
16
+ const percent = $derived(isIndeterminate ? null : Math.min(100, Math.max(0, (value! / max) * 100)));
17
+ </script>
18
+
19
+ {#snippet defaultLinearFill({ percent: p }: { percent: number | null })}
20
+ <HtmlElement
21
+ preset="progress.linear.fill"
22
+ as="div"
23
+ class={[
24
+ 'progress-fill bg-foreground h-full rounded-full transition-[width] duration-300',
25
+ isIndeterminate && 'animate-progress-indeterminate w-1/3',
26
+ '$preset'
27
+ ]}
28
+ style={p !== null ? `width: ${p}%` : undefined}
29
+ />
30
+ {/snippet}
31
+
32
+ <HtmlAtom
33
+ {preset}
34
+ as="div"
35
+ class={['progress-root flex flex-col gap-1', '$preset', klass]}
36
+ role="progressbar"
37
+ aria-valuemin={0}
38
+ aria-valuemax={max}
39
+ aria-valuenow={isIndeterminate ? undefined : value ?? undefined}
40
+ aria-valuetext={isIndeterminate ? undefined : `${Math.round(percent!)}%`}
41
+ data-indeterminate={isIndeterminate}
42
+ data-value={isIndeterminate ? undefined : value ?? undefined}
43
+ data-max={max}
44
+ data-completed={!isIndeterminate && percent === 100}
45
+ {...restProps}
46
+ >
47
+ <HtmlElement
48
+ preset="progress.linear.track"
49
+ as="div"
50
+ class="progress-track bg-input border-none p-0.5 h-2 w-full overflow-hidden rounded-full border $preset"
51
+ >
52
+ {@render defaultLinearFill({ percent })}
53
+ </HtmlElement>
54
+ </HtmlAtom>
55
+
56
+ <style>
57
+ @keyframes progress-indeterminate {
58
+ 0% { transform: translateX(-100%); }
59
+ 50% { transform: translateX(300%); }
60
+ 100% { transform: translateX(-100%); }
61
+ }
62
+
63
+ :global(.animate-progress-indeterminate) {
64
+ animation: progress-indeterminate 1.8s ease-in-out infinite;
65
+ }
66
+ </style>
@@ -0,0 +1,6 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { ProgressLinearProps } from './types';
3
+ type $$ComponentProps = ProgressLinearProps & HTMLAttributes<HTMLDivElement>;
4
+ declare const ProgressLinear: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type ProgressLinear = ReturnType<typeof ProgressLinear>;
6
+ export default ProgressLinear;
@@ -0,0 +1,18 @@
1
+ import type { HtmlAtomProps } from '../atom';
2
+ interface ProgressSharedProps {
3
+ /**
4
+ * Current value (0–max). Set to `null` for indeterminate state.
5
+ * @default null
6
+ */
7
+ value?: number | null;
8
+ /**
9
+ * Maximum value
10
+ * @default 100
11
+ */
12
+ max?: number;
13
+ }
14
+ export interface ProgressLinearProps extends HtmlAtomProps<'div'>, ProgressSharedProps {
15
+ }
16
+ export interface ProgressCircularProps extends HtmlAtomProps<'div'>, ProgressSharedProps {
17
+ }
18
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -12,12 +12,6 @@
12
12
  let {
13
13
  class: klass = '',
14
14
  children,
15
- onmount,
16
- ondestroy,
17
- animate,
18
- enter,
19
- exit,
20
- initial,
21
15
  ...restProps
22
16
  }: ScrollableContainerProps<E, B> = $props();
23
17
 
@@ -52,12 +46,6 @@
52
46
  '$preset',
53
47
  klass
54
48
  ]}
55
- {enter}
56
- {exit}
57
- {initial}
58
- {animate}
59
- {onmount}
60
- {ondestroy}
61
49
  {...containerProps}
62
50
  >
63
51
  {#if children}