@x33025/sveltely 0.0.57 → 0.1.0

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 (187) hide show
  1. package/dist/actions/tooltip.d.ts +10 -0
  2. package/dist/actions/tooltip.js +255 -0
  3. package/dist/components/{AnimatedNumber.demo.svelte → Library/AnimatedNumber/AnimatedNumber.demo.svelte} +6 -10
  4. package/dist/components/{AnimatedNumber.demo.svelte.d.ts → Library/AnimatedNumber/AnimatedNumber.demo.svelte.d.ts} +0 -1
  5. package/dist/components/Library/AnimatedNumber/AnimatedNumber.svelte +29 -0
  6. package/dist/components/Library/AnimatedNumber/AnimatedNumber.svelte.d.ts +9 -0
  7. package/dist/components/Library/AnimatedNumber/index.d.ts +1 -0
  8. package/dist/components/Library/AnimatedNumber/index.js +1 -0
  9. package/dist/components/{AsyncButton.demo.svelte → Library/AsyncButton/AsyncButton.demo.svelte} +0 -1
  10. package/dist/components/Library/AsyncButton/AsyncButton.svelte +178 -0
  11. package/dist/components/{AsyncButton.svelte.d.ts → Library/AsyncButton/AsyncButton.svelte.d.ts} +7 -2
  12. package/dist/components/Library/AsyncButton/index.d.ts +1 -0
  13. package/dist/components/Library/AsyncButton/index.js +1 -0
  14. package/dist/components/Library/Button/Button.demo.svelte +17 -0
  15. package/dist/components/Library/Button/Button.demo.svelte.d.ts +23 -0
  16. package/dist/components/Library/Button/Button.svelte +134 -0
  17. package/dist/components/Library/Button/Button.svelte.d.ts +17 -0
  18. package/dist/components/Library/Button/index.d.ts +1 -0
  19. package/dist/components/Library/Button/index.js +1 -0
  20. package/dist/components/Library/Calendar/Calendar.demo.svelte +30 -0
  21. package/dist/components/Library/Calendar/Calendar.demo.svelte.d.ts +10 -0
  22. package/dist/components/Library/Calendar/Calendar.svelte +310 -0
  23. package/dist/components/Library/Calendar/Calendar.svelte.d.ts +10 -0
  24. package/dist/components/Library/Calendar/index.d.ts +1 -0
  25. package/dist/components/Library/Calendar/index.js +1 -0
  26. package/dist/components/Library/Checkbox/Checkbox.demo.svelte +20 -0
  27. package/dist/components/Library/Checkbox/Checkbox.demo.svelte.d.ts +8 -0
  28. package/dist/components/Library/Checkbox/Checkbox.svelte +134 -0
  29. package/dist/components/Library/Checkbox/Checkbox.svelte.d.ts +11 -0
  30. package/dist/components/Library/Checkbox/index.d.ts +1 -0
  31. package/dist/components/Library/Checkbox/index.js +1 -0
  32. package/dist/components/{ChipInput.demo.svelte → Library/ChipInput/ChipInput.demo.svelte} +1 -2
  33. package/dist/components/{ChipInput.demo.svelte.d.ts → Library/ChipInput/ChipInput.demo.svelte.d.ts} +0 -1
  34. package/dist/components/{ChipInput.svelte → Library/ChipInput/ChipInput.svelte} +77 -3
  35. package/dist/components/{ChipInput.svelte.d.ts → Library/ChipInput/ChipInput.svelte.d.ts} +2 -1
  36. package/dist/components/Library/ChipInput/index.d.ts +1 -0
  37. package/dist/components/Library/ChipInput/index.js +1 -0
  38. package/dist/components/Library/Dropdown/Dropdown.demo.svelte +54 -0
  39. package/dist/components/Library/Dropdown/Dropdown.demo.svelte.d.ts +8 -0
  40. package/dist/components/Library/Dropdown/Dropdown.svelte +346 -0
  41. package/dist/components/Library/Dropdown/Dropdown.svelte.d.ts +40 -0
  42. package/dist/components/Library/Dropdown/index.d.ts +2 -0
  43. package/dist/components/Library/Dropdown/index.js +1 -0
  44. package/dist/components/Library/Dropdown/types.d.ts +27 -0
  45. package/dist/components/Library/Dropdown/types.js +1 -0
  46. package/dist/components/{Popover/Popover.svelte → Library/Floating/Floating.svelte} +155 -101
  47. package/dist/components/Library/Floating/Floating.svelte.d.ts +30 -0
  48. package/dist/components/Library/Floating/registry.svelte.d.ts +6 -0
  49. package/dist/components/{Popover → Library/Floating}/registry.svelte.js +2 -23
  50. package/dist/components/{GlowEffect.svelte → Library/GlowEffect/GlowEffect.svelte} +15 -6
  51. package/dist/components/{GlowEffect.svelte.d.ts → Library/GlowEffect/GlowEffect.svelte.d.ts} +3 -2
  52. package/dist/components/Library/GlowEffect/index.d.ts +1 -0
  53. package/dist/components/Library/GlowEffect/index.js +1 -0
  54. package/dist/components/Library/NavigationStack/NavigationStack.svelte +242 -0
  55. package/dist/components/Library/NavigationStack/NavigationStack.svelte.d.ts +15 -0
  56. package/dist/components/Library/NavigationStack/SidebarToggle.svelte +52 -0
  57. package/dist/components/Library/NavigationStack/SidebarToggle.svelte.d.ts +10 -0
  58. package/dist/components/Library/NavigationStack/Toolbar.svelte +59 -0
  59. package/dist/components/Library/NavigationStack/Toolbar.svelte.d.ts +11 -0
  60. package/dist/components/{Pagination.demo.svelte → Library/Pagination/Pagination.demo.svelte} +0 -1
  61. package/dist/components/{Pagination.demo.svelte.d.ts → Library/Pagination/Pagination.demo.svelte.d.ts} +0 -1
  62. package/dist/components/Library/Pagination/Pagination.svelte +227 -0
  63. package/dist/components/{Pagination.svelte.d.ts → Library/Pagination/Pagination.svelte.d.ts} +3 -3
  64. package/dist/components/Library/Pagination/index.d.ts +1 -0
  65. package/dist/components/Library/Pagination/index.js +1 -0
  66. package/dist/components/Library/Popover/Popover.demo.svelte +21 -0
  67. package/dist/components/Library/Popover/Popover.svelte +92 -0
  68. package/dist/components/Library/Popover/Popover.svelte.d.ts +14 -0
  69. package/dist/components/{Popover → Library/Popover}/PopoverDebugOverlay.svelte +1 -1
  70. package/dist/components/Library/Popover/index.d.ts +1 -0
  71. package/dist/components/Library/Popover/index.js +1 -0
  72. package/dist/components/Library/ScrollView/ScrollView.svelte +89 -0
  73. package/dist/components/Library/ScrollView/ScrollView.svelte.d.ts +12 -0
  74. package/dist/components/Library/ScrollView/index.d.ts +1 -0
  75. package/dist/components/Library/ScrollView/index.js +1 -0
  76. package/dist/components/{SearchInput.demo.svelte → Library/SearchInput/SearchInput.demo.svelte} +2 -3
  77. package/dist/components/{SearchInput.demo.svelte.d.ts → Library/SearchInput/SearchInput.demo.svelte.d.ts} +0 -1
  78. package/dist/components/Library/SearchInput/SearchInput.svelte +88 -0
  79. package/dist/components/{SearchInput.svelte.d.ts → Library/SearchInput/SearchInput.svelte.d.ts} +3 -3
  80. package/dist/components/Library/SearchInput/index.d.ts +1 -0
  81. package/dist/components/Library/SearchInput/index.js +1 -0
  82. package/dist/components/{SegmentedPicker.demo.svelte → Library/SegmentedPicker/SegmentedPicker.demo.svelte} +2 -3
  83. package/dist/components/{SegmentedPicker.demo.svelte.d.ts → Library/SegmentedPicker/SegmentedPicker.demo.svelte.d.ts} +0 -1
  84. package/dist/components/Library/SegmentedPicker/SegmentedPicker.svelte +106 -0
  85. package/dist/components/{SegmentedPicker.svelte.d.ts → Library/SegmentedPicker/SegmentedPicker.svelte.d.ts} +2 -2
  86. package/dist/components/Library/SegmentedPicker/index.d.ts +1 -0
  87. package/dist/components/Library/SegmentedPicker/index.js +1 -0
  88. package/dist/components/{Sheet → Library/Sheet}/Sheet.demo.svelte +4 -17
  89. package/dist/components/Library/Sheet/Sheet.demo.svelte.d.ts +23 -0
  90. package/dist/components/Library/Sheet/Sheet.svelte +113 -0
  91. package/dist/components/{Sheet → Library/Sheet}/Sheet.svelte.d.ts +4 -2
  92. package/dist/components/{Slider.demo.svelte → Library/Slider/Slider.demo.svelte} +2 -3
  93. package/dist/components/{Slider.demo.svelte.d.ts → Library/Slider/Slider.demo.svelte.d.ts} +0 -1
  94. package/dist/components/Library/Slider/Slider.svelte +122 -0
  95. package/dist/components/{Slider.svelte.d.ts → Library/Slider/Slider.svelte.d.ts} +2 -3
  96. package/dist/components/Library/Slider/index.d.ts +1 -0
  97. package/dist/components/Library/Slider/index.js +1 -0
  98. package/dist/components/{Spinner.demo.svelte → Library/Spinner/Spinner.demo.svelte} +3 -1
  99. package/dist/components/Library/Spinner/Spinner.svelte +32 -0
  100. package/dist/components/{Spinner.svelte.d.ts → Library/Spinner/Spinner.svelte.d.ts} +3 -2
  101. package/dist/components/Library/Spinner/index.d.ts +1 -0
  102. package/dist/components/Library/Spinner/index.js +1 -0
  103. package/dist/components/Library/Switch/Switch.demo.svelte +20 -0
  104. package/dist/components/Library/Switch/Switch.demo.svelte.d.ts +8 -0
  105. package/dist/components/Library/Switch/Switch.svelte +168 -0
  106. package/dist/components/Library/Switch/Switch.svelte.d.ts +11 -0
  107. package/dist/components/Library/Switch/index.d.ts +1 -0
  108. package/dist/components/Library/Switch/index.js +1 -0
  109. package/dist/components/Library/TextShimmer/TextShimmer.demo.svelte +14 -0
  110. package/dist/components/Library/TextShimmer/TextShimmer.demo.svelte.d.ts +23 -0
  111. package/dist/components/Library/TextShimmer/TextShimmer.svelte +88 -0
  112. package/dist/components/Library/TextShimmer/TextShimmer.svelte.d.ts +11 -0
  113. package/dist/components/Library/TextShimmer/index.d.ts +1 -0
  114. package/dist/components/Library/TextShimmer/index.js +1 -0
  115. package/dist/components/Library/TimePicker/TimePicker.demo.svelte +18 -0
  116. package/dist/components/Library/TimePicker/TimePicker.demo.svelte.d.ts +10 -0
  117. package/dist/components/Library/TimePicker/TimePicker.svelte +143 -0
  118. package/dist/components/Library/TimePicker/TimePicker.svelte.d.ts +13 -0
  119. package/dist/components/Library/TimePicker/index.d.ts +2 -0
  120. package/dist/components/Library/TimePicker/index.js +1 -0
  121. package/dist/components/Library/TokenSearchInput/TokenSearchInput.demo.svelte +19 -0
  122. package/dist/components/Library/TokenSearchInput/TokenSearchInput.demo.svelte.d.ts +9 -0
  123. package/dist/components/Library/TokenSearchInput/TokenSearchInput.svelte +230 -0
  124. package/dist/components/Library/TokenSearchInput/TokenSearchInput.svelte.d.ts +14 -0
  125. package/dist/components/Library/TokenSearchInput/index.d.ts +1 -0
  126. package/dist/components/Library/TokenSearchInput/index.js +1 -0
  127. package/dist/components/Library/Tooltip/Tooltip.demo.svelte +14 -0
  128. package/dist/components/{Tooltip.demo.svelte.d.ts → Library/Tooltip/Tooltip.demo.svelte.d.ts} +0 -1
  129. package/dist/components/Library/Tooltip/index.d.ts +2 -0
  130. package/dist/components/Library/Tooltip/index.js +1 -0
  131. package/dist/components/Library/WheelPicker/WheelColumn.svelte +302 -0
  132. package/dist/components/Library/WheelPicker/WheelColumn.svelte.d.ts +29 -0
  133. package/dist/components/Library/WheelPicker/WheelPicker.svelte +114 -0
  134. package/dist/components/Library/WheelPicker/WheelPicker.svelte.d.ts +9 -0
  135. package/dist/components/Library/WheelPicker/index.d.ts +2 -0
  136. package/dist/components/Library/WheelPicker/index.js +1 -0
  137. package/dist/components/Library/WheelPicker/types.d.ts +10 -0
  138. package/dist/components/Library/WheelPicker/types.js +1 -0
  139. package/dist/components/Local/ComponentGrid.svelte +7 -6
  140. package/dist/components/Local/ComponentGrid.svelte.d.ts +1 -1
  141. package/dist/components/Local/HeroCard.svelte +18 -8
  142. package/dist/components/Local/HeroCard.svelte.d.ts +1 -1
  143. package/dist/components/Local/StyleControls.svelte +119 -0
  144. package/dist/components/Local/StyleControls.svelte.d.ts +15 -0
  145. package/dist/index.d.ts +24 -14
  146. package/dist/index.js +23 -14
  147. package/dist/style/index.css +61 -280
  148. package/dist/style/surface.d.ts +17 -0
  149. package/dist/style/surface.js +54 -0
  150. package/dist/style.css +102 -523
  151. package/dist/utils/positioning.d.ts +3 -2
  152. package/dist/utils/positioning.js +9 -5
  153. package/package.json +2 -1
  154. package/dist/components/AnimatedNumber.svelte +0 -18
  155. package/dist/components/AnimatedNumber.svelte.d.ts +0 -8
  156. package/dist/components/AsyncButton.svelte +0 -93
  157. package/dist/components/NavigationStack/NavigationStack.svelte +0 -76
  158. package/dist/components/NavigationStack/NavigationStack.svelte.d.ts +0 -10
  159. package/dist/components/NavigationStack/SidebarToggle.svelte +0 -36
  160. package/dist/components/NavigationStack/SidebarToggle.svelte.d.ts +0 -9
  161. package/dist/components/NavigationStack/Toolbar.svelte +0 -25
  162. package/dist/components/NavigationStack/Toolbar.svelte.d.ts +0 -9
  163. package/dist/components/Pagination.svelte +0 -144
  164. package/dist/components/Popover/Popover.demo.svelte +0 -35
  165. package/dist/components/Popover/Popover.svelte.d.ts +0 -13
  166. package/dist/components/Popover/index.d.ts +0 -2
  167. package/dist/components/Popover/index.js +0 -2
  168. package/dist/components/Popover/registry.svelte.d.ts +0 -18
  169. package/dist/components/SearchInput.svelte +0 -39
  170. package/dist/components/SegmentedPicker.svelte +0 -51
  171. package/dist/components/Sheet/Sheet.demo.svelte.d.ts +0 -8
  172. package/dist/components/Sheet/Sheet.svelte +0 -60
  173. package/dist/components/Slider.svelte +0 -47
  174. package/dist/components/Spinner.svelte +0 -7
  175. package/dist/components/TextShimmer.svelte +0 -60
  176. package/dist/components/TextShimmer.svelte.d.ts +0 -10
  177. package/dist/components/Tooltip.demo.svelte +0 -16
  178. package/dist/components/Tooltip.svelte +0 -79
  179. package/dist/components/Tooltip.svelte.d.ts +0 -12
  180. /package/dist/components/{AsyncButton.demo.svelte.d.ts → Library/AsyncButton/AsyncButton.demo.svelte.d.ts} +0 -0
  181. /package/dist/components/{NavigationStack → Library/NavigationStack}/index.d.ts +0 -0
  182. /package/dist/components/{NavigationStack → Library/NavigationStack}/index.js +0 -0
  183. /package/dist/components/{Popover → Library/Popover}/Popover.demo.svelte.d.ts +0 -0
  184. /package/dist/components/{Popover → Library/Popover}/PopoverDebugOverlay.svelte.d.ts +0 -0
  185. /package/dist/components/{Sheet → Library/Sheet}/index.d.ts +0 -0
  186. /package/dist/components/{Sheet → Library/Sheet}/index.js +0 -0
  187. /package/dist/components/{Spinner.demo.svelte.d.ts → Library/Spinner/Spinner.demo.svelte.d.ts} +0 -0
@@ -1,42 +1,73 @@
1
1
  <script lang="ts">
2
2
  import { tick, onDestroy } from 'svelte';
3
3
  import type { Snippet } from 'svelte';
4
- import { portalContent } from '../../actions/portal';
5
- import { computePosition, type Anchor, type Align } from '../../utils/positioning';
4
+ import { portalContent } from '../../../actions/portal';
5
+ import {
6
+ autoAlignForViewport,
7
+ computePosition,
8
+ type Anchor
9
+ } from '../../../utils/positioning';
6
10
  import {
7
- registerPopover,
8
- unregisterPopover,
9
- setParentId,
10
- setOpen,
11
11
  hasOpenChild,
12
- isAncestor
12
+ isAncestor,
13
+ registerFloating,
14
+ setOpen,
15
+ setParentId,
16
+ unregisterFloating
13
17
  } from './registry.svelte';
14
18
 
19
+ type TriggerApi = {
20
+ useTrigger: (node: HTMLElement) => { destroy: () => void };
21
+ open: boolean;
22
+ toggle: () => void;
23
+ openPanel: () => Promise<void>;
24
+ closePanel: () => void;
25
+ };
26
+
15
27
  interface Props {
16
- trigger: Snippet;
28
+ trigger: Snippet<[TriggerApi]>;
17
29
  children: Snippet;
18
30
  open?: boolean;
19
- class?: string;
20
- align?: Align;
21
- anchor?: Anchor;
31
+ placement?: Anchor;
32
+ rootClass?: string;
33
+ rootStyle?: string;
34
+ panelClass?: string;
35
+ panelStyle?: string;
36
+ contentClass?: string;
37
+ contentStyle?: string;
38
+ panelRole?: string;
39
+ panelAriaModal?: 'true' | 'false';
40
+ matchPanelRadiusToSource?: boolean;
41
+ closeOnPointerLeave?: boolean;
22
42
  }
43
+
23
44
  type Point = { x: number; y: number };
24
- const createPopoverId = () => {
45
+
46
+ const createFloatingId = () => {
25
47
  if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
26
48
  return crypto.randomUUID();
27
49
  }
28
- return `popover-${Math.random().toString(36).slice(2, 10)}`;
50
+ return `floating-${Math.random().toString(36).slice(2, 10)}`;
29
51
  };
30
52
 
31
53
  let {
32
54
  trigger,
33
55
  children,
34
56
  open = $bindable(false),
35
- class: className = '',
36
- align = 'left',
37
- anchor = 'bottom'
57
+ placement = 'bottom',
58
+ rootClass = '',
59
+ rootStyle = '',
60
+ panelClass = '',
61
+ panelStyle = '',
62
+ contentClass = '',
63
+ contentStyle = '',
64
+ panelRole = 'dialog',
65
+ panelAriaModal = 'false',
66
+ matchPanelRadiusToSource = false,
67
+ closeOnPointerLeave = false
38
68
  }: Props = $props();
39
69
 
70
+ let rootEl = $state<HTMLElement | null>(null);
40
71
  let triggerEl = $state<HTMLElement | null>(null);
41
72
  let panelEl = $state<HTMLElement | null>(null);
42
73
  let contentEl = $state<HTMLElement | null>(null);
@@ -45,35 +76,42 @@
45
76
  let resolvedAnchor = $state<Anchor>('bottom');
46
77
  let computedPanelRadius = $state<string | null>(null);
47
78
 
48
- const popoverId = createPopoverId();
49
- let parentPopoverId = $state<string | null>(null);
79
+ const floatingId = createFloatingId();
80
+ let parentFloatingId = $state<string | null>(null);
50
81
 
51
- /**
52
- * Detect parent popover by walking the DOM upward from the trigger element.
53
- * Works even with portaling because the trigger stays in its original
54
- * DOM position (inside the parent's portaled content).
55
- */
56
- const detectParentPopoverId = (): string | null => {
57
- let current = triggerEl?.parentElement ?? null;
82
+ registerFloating(floatingId);
83
+
84
+ const detectParentFloatingId = (): string | null => {
85
+ let current = rootEl?.parentElement ?? null;
58
86
  while (current) {
59
- const id = current.getAttribute('data-popover-id');
60
- if (id && id !== popoverId) return id;
87
+ const id = current.getAttribute('data-floating-id');
88
+ if (id && id !== floatingId) return id;
61
89
  current = current.parentElement;
62
90
  }
63
91
  return null;
64
92
  };
65
93
 
66
- registerPopover(popoverId);
67
-
68
94
  $effect(() => {
69
- if (!triggerEl) return;
70
- parentPopoverId = detectParentPopoverId();
71
- setParentId(popoverId, parentPopoverId);
95
+ if (!rootEl) return;
96
+ parentFloatingId = detectParentFloatingId();
97
+ setParentId(floatingId, parentFloatingId);
72
98
  });
73
99
 
74
- $effect(() => setOpen(popoverId, open));
100
+ $effect(() => setOpen(floatingId, open));
101
+
102
+ onDestroy(() => unregisterFloating(floatingId));
75
103
 
76
- onDestroy(() => unregisterPopover(popoverId));
104
+ const useTrigger = (node: HTMLElement) => {
105
+ triggerEl = node;
106
+
107
+ return {
108
+ destroy: () => {
109
+ if (triggerEl === node) {
110
+ triggerEl = null;
111
+ }
112
+ }
113
+ };
114
+ };
77
115
 
78
116
  const isInsideRect = (rect: DOMRect, x: number, y: number) =>
79
117
  x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
@@ -95,15 +133,15 @@
95
133
 
96
134
  const getSafePolygon = (
97
135
  triggerRect: DOMRect,
98
- popoverRect: DOMRect,
136
+ floatingRect: DOMRect,
99
137
  currentAnchor: Anchor
100
138
  ): Point[] => {
101
139
  if (currentAnchor === 'bottom') {
102
140
  return [
103
141
  { x: triggerRect.left, y: triggerRect.top },
104
142
  { x: triggerRect.right, y: triggerRect.top },
105
- { x: popoverRect.right, y: popoverRect.top },
106
- { x: popoverRect.left, y: popoverRect.top }
143
+ { x: floatingRect.right, y: floatingRect.top },
144
+ { x: floatingRect.left, y: floatingRect.top }
107
145
  ];
108
146
  }
109
147
 
@@ -111,25 +149,25 @@
111
149
  return [
112
150
  { x: triggerRect.left, y: triggerRect.bottom },
113
151
  { x: triggerRect.right, y: triggerRect.bottom },
114
- { x: popoverRect.right, y: popoverRect.bottom },
115
- { x: popoverRect.left, y: popoverRect.bottom }
152
+ { x: floatingRect.right, y: floatingRect.bottom },
153
+ { x: floatingRect.left, y: floatingRect.bottom }
116
154
  ];
117
155
  }
118
156
 
119
- if (currentAnchor === 'leading') {
157
+ if (currentAnchor === 'left') {
120
158
  return [
121
159
  { x: triggerRect.right, y: triggerRect.top },
122
160
  { x: triggerRect.right, y: triggerRect.bottom },
123
- { x: popoverRect.right, y: popoverRect.bottom },
124
- { x: popoverRect.right, y: popoverRect.top }
161
+ { x: floatingRect.right, y: floatingRect.bottom },
162
+ { x: floatingRect.right, y: floatingRect.top }
125
163
  ];
126
164
  }
127
165
 
128
166
  return [
129
167
  { x: triggerRect.left, y: triggerRect.top },
130
168
  { x: triggerRect.left, y: triggerRect.bottom },
131
- { x: popoverRect.left, y: popoverRect.bottom },
132
- { x: popoverRect.left, y: popoverRect.top }
169
+ { x: floatingRect.left, y: floatingRect.bottom },
170
+ { x: floatingRect.left, y: floatingRect.top }
133
171
  ];
134
172
  };
135
173
 
@@ -140,7 +178,7 @@
140
178
  };
141
179
 
142
180
  const updateRadiusFromSource = () => {
143
- if (!panelEl || !contentEl) {
181
+ if (!matchPanelRadiusToSource || !panelEl || !contentEl) {
144
182
  computedPanelRadius = null;
145
183
  return;
146
184
  }
@@ -172,6 +210,23 @@
172
210
  computedPanelRadius = `${panelRadius}px`;
173
211
  };
174
212
 
213
+ const positionPanel = () => {
214
+ if (!triggerEl || !panelEl) return;
215
+ const rect = triggerEl.getBoundingClientRect();
216
+ const preferredAlign =
217
+ placement === 'top' || placement === 'bottom' ? autoAlignForViewport(rect) : 'left';
218
+ const result = computePosition(
219
+ rect,
220
+ panelEl.offsetWidth,
221
+ panelEl.offsetHeight,
222
+ placement,
223
+ preferredAlign
224
+ );
225
+ panelCoords = { top: result.top, left: result.left };
226
+ panelTransform = result.transform;
227
+ resolvedAnchor = result.anchor;
228
+ };
229
+
175
230
  const positionAndMeasure = async () => {
176
231
  await tick();
177
232
  await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));
@@ -179,31 +234,22 @@
179
234
  updateRadiusFromSource();
180
235
  };
181
236
 
182
- const getPopoverIdsFromEvent = (event: Event) => {
237
+ const getFloatingIdsFromEvent = (event: Event) => {
183
238
  const ids: string[] = [];
184
239
  for (const node of event.composedPath()) {
185
240
  if (!(node instanceof Element)) continue;
186
- const id = node.getAttribute('data-popover-id');
241
+ const id = node.getAttribute('data-floating-id');
187
242
  if (!id || ids.includes(id)) continue;
188
243
  ids.push(id);
189
244
  }
190
245
  return ids;
191
246
  };
192
247
 
193
- const isInPopoverTree = (candidateId: string | null) => isAncestor(candidateId, popoverId);
248
+ const isInFloatingTree = (candidateId: string | null) => isAncestor(candidateId, floatingId);
194
249
 
195
- const isEventInPopoverTree = (event: Event) => {
196
- const ids = getPopoverIdsFromEvent(event);
197
- return ids.some(isInPopoverTree);
198
- };
199
-
200
- const positionPanel = () => {
201
- if (!triggerEl || !panelEl) return;
202
- const rect = triggerEl.getBoundingClientRect();
203
- const result = computePosition(rect, panelEl.offsetWidth, panelEl.offsetHeight, anchor, align);
204
- panelCoords = { top: result.top, left: result.left };
205
- panelTransform = result.transform;
206
- resolvedAnchor = result.anchor;
250
+ const isEventInFloatingTree = (event: Event) => {
251
+ const ids = getFloatingIdsFromEvent(event);
252
+ return ids.some(isInFloatingTree);
207
253
  };
208
254
 
209
255
  async function openPanel() {
@@ -224,15 +270,9 @@
224
270
  }
225
271
  }
226
272
 
227
- function handleTriggerKeydown(event: KeyboardEvent) {
228
- if (event.key !== 'Enter' && event.key !== ' ') return;
229
- event.preventDefault();
230
- toggle();
231
- }
232
-
233
273
  function handleOutsideClick(event: MouseEvent) {
234
274
  if (!open) return;
235
- if (isEventInPopoverTree(event)) return;
275
+ if (isEventInFloatingTree(event)) return;
236
276
  closePanel();
237
277
  }
238
278
 
@@ -242,17 +282,18 @@
242
282
  }
243
283
 
244
284
  function handlePointerMove(event: MouseEvent) {
285
+ if (!closeOnPointerLeave) return;
245
286
  if (!open || !triggerEl || !panelEl) return;
246
- if (isEventInPopoverTree(event)) return;
247
- if (hasOpenChild(popoverId)) return;
287
+ if (isEventInFloatingTree(event)) return;
288
+ if (hasOpenChild(floatingId)) return;
248
289
 
249
290
  const pointer = { x: event.clientX, y: event.clientY };
250
291
  const triggerRect = triggerEl.getBoundingClientRect();
251
- const popoverRect = panelEl.getBoundingClientRect();
252
- const safePolygon = getSafePolygon(triggerRect, popoverRect, resolvedAnchor);
292
+ const floatingRect = panelEl.getBoundingClientRect();
293
+ const safePolygon = getSafePolygon(triggerRect, floatingRect, resolvedAnchor);
253
294
 
254
295
  if (isInsideRect(triggerRect, pointer.x, pointer.y)) return;
255
- if (isInsideRect(popoverRect, pointer.x, pointer.y)) return;
296
+ if (isInsideRect(floatingRect, pointer.x, pointer.y)) return;
256
297
  if (pointInPolygon(pointer, safePolygon)) return;
257
298
 
258
299
  closePanel();
@@ -262,51 +303,64 @@
262
303
  if (!open) return;
263
304
  void positionAndMeasure();
264
305
  });
306
+
307
+ $effect(() => {
308
+ if (typeof window === 'undefined') return;
309
+ const handleWindowChange = () => closePanel();
310
+ window.addEventListener('scroll', handleWindowChange, true);
311
+ window.addEventListener('resize', handleWindowChange);
312
+ return () => {
313
+ window.removeEventListener('scroll', handleWindowChange, true);
314
+ window.removeEventListener('resize', handleWindowChange);
315
+ };
316
+ });
317
+
318
+ const resolvedPanelStyle = $derived.by(() => {
319
+ const declarations = [
320
+ `top: ${panelCoords.top}px;`,
321
+ `left: ${panelCoords.left}px;`,
322
+ `transform: ${panelTransform};`
323
+ ];
324
+ if (computedPanelRadius) {
325
+ declarations.push(`border-radius: ${computedPanelRadius};`);
326
+ }
327
+ if (panelStyle) {
328
+ declarations.push(panelStyle);
329
+ }
330
+ return declarations.join(' ');
331
+ });
265
332
  </script>
266
333
 
267
334
  <svelte:window
268
335
  onclick={handleOutsideClick}
269
- onscroll={closePanel}
270
- onresize={closePanel}
271
336
  onkeydown={handleEscape}
272
337
  onmousemove={handlePointerMove}
273
338
  />
274
339
 
275
340
  <div
276
- class="relative inline-block text-left"
277
- data-popover-root
278
- data-popover-id={popoverId}
279
- data-popover-parent-id={parentPopoverId ?? ''}
341
+ bind:this={rootEl}
342
+ class={rootClass}
343
+ style={rootStyle}
344
+ data-floating-root
345
+ data-floating-id={floatingId}
346
+ data-floating-parent-id={parentFloatingId ?? ''}
280
347
  >
281
- <div bind:this={triggerEl}>
282
- <div
283
- class="text-left"
284
- role="button"
285
- tabindex="0"
286
- onclick={toggle}
287
- onkeydown={handleTriggerKeydown}
288
- aria-expanded={open}
289
- aria-haspopup="dialog"
290
- >
291
- {@render trigger()}
292
- </div>
293
- </div>
348
+ {@render trigger({ useTrigger, open, toggle, openPanel, closePanel })}
294
349
 
295
350
  {#if open}
296
351
  <div
297
352
  use:portalContent
298
- class="popover fixed z-50 focus:outline-none {className}"
299
- data-popover
300
- data-popover-id={popoverId}
301
- data-popover-parent-id={parentPopoverId ?? ''}
302
- style="top: {panelCoords.top}px; left: {panelCoords.left}px; transform: {panelTransform}; border-radius: {computedPanelRadius ??
303
- ''};"
304
- role="dialog"
305
- aria-modal="false"
306
- tabindex="-1"
307
353
  bind:this={panelEl}
354
+ class={panelClass}
355
+ style={resolvedPanelStyle}
356
+ data-floating
357
+ data-floating-id={floatingId}
358
+ data-floating-parent-id={parentFloatingId ?? ''}
359
+ role={panelRole}
360
+ aria-modal={panelAriaModal}
361
+ tabindex="-1"
308
362
  >
309
- <div role="none" bind:this={contentEl}>
363
+ <div bind:this={contentEl} class={contentClass} style={contentStyle}>
310
364
  {@render children()}
311
365
  </div>
312
366
  </div>
@@ -0,0 +1,30 @@
1
+ import type { Snippet } from 'svelte';
2
+ import { type Anchor } from '../../../utils/positioning';
3
+ type TriggerApi = {
4
+ useTrigger: (node: HTMLElement) => {
5
+ destroy: () => void;
6
+ };
7
+ open: boolean;
8
+ toggle: () => void;
9
+ openPanel: () => Promise<void>;
10
+ closePanel: () => void;
11
+ };
12
+ interface Props {
13
+ trigger: Snippet<[TriggerApi]>;
14
+ children: Snippet;
15
+ open?: boolean;
16
+ placement?: Anchor;
17
+ rootClass?: string;
18
+ rootStyle?: string;
19
+ panelClass?: string;
20
+ panelStyle?: string;
21
+ contentClass?: string;
22
+ contentStyle?: string;
23
+ panelRole?: string;
24
+ panelAriaModal?: 'true' | 'false';
25
+ matchPanelRadiusToSource?: boolean;
26
+ closeOnPointerLeave?: boolean;
27
+ }
28
+ declare const Floating: import("svelte").Component<Props, {}, "open">;
29
+ type Floating = ReturnType<typeof Floating>;
30
+ export default Floating;
@@ -0,0 +1,6 @@
1
+ export declare function registerFloating(id: string): void;
2
+ export declare function unregisterFloating(id: string): void;
3
+ export declare function setParentId(id: string, parentId: string | null): void;
4
+ export declare function setOpen(id: string, open: boolean): void;
5
+ export declare function hasOpenChild(parentId: string): boolean;
6
+ export declare function isAncestor(candidateId: string | null, ancestorId: string): boolean;
@@ -1,8 +1,8 @@
1
1
  const registry = new Map();
2
- export function registerPopover(id) {
2
+ export function registerFloating(id) {
3
3
  registry.set(id, { parentId: null, open: false });
4
4
  }
5
- export function unregisterPopover(id) {
5
+ export function unregisterFloating(id) {
6
6
  registry.delete(id);
7
7
  }
8
8
  export function setParentId(id, parentId) {
@@ -15,12 +15,6 @@ export function setOpen(id, open) {
15
15
  if (entry)
16
16
  entry.open = open;
17
17
  }
18
- export function getParentId(id) {
19
- return registry.get(id)?.parentId ?? null;
20
- }
21
- /**
22
- * Returns true if any registered popover lists `parentId` as its parent and is currently open.
23
- */
24
18
  export function hasOpenChild(parentId) {
25
19
  for (const [, entry] of registry) {
26
20
  if (entry.parentId === parentId && entry.open)
@@ -28,10 +22,6 @@ export function hasOpenChild(parentId) {
28
22
  }
29
23
  return false;
30
24
  }
31
- /**
32
- * Walk the parent chain from `candidateId` upward.
33
- * Returns true if `ancestorId` is found in the chain.
34
- */
35
25
  export function isAncestor(candidateId, ancestorId) {
36
26
  let currentId = candidateId;
37
27
  const visited = new Set();
@@ -45,14 +35,3 @@ export function isAncestor(candidateId, ancestorId) {
45
35
  }
46
36
  return false;
47
37
  }
48
- /**
49
- * Returns the IDs of all currently open popovers.
50
- */
51
- export function getOpenPopoverIds() {
52
- const ids = [];
53
- for (const [id, entry] of registry) {
54
- if (entry.open)
55
- ids.push(id);
56
- }
57
- return ids;
58
- }
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
+ import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
3
+
2
4
  interface Props {
3
- class?: string;
4
5
  colors?: string[];
5
6
  mode?: 'breathe' | 'colorShift';
6
7
  blur?: number | 'softest' | 'soft' | 'medium' | 'strong' | 'stronger' | 'strongest' | 'none';
@@ -9,13 +10,18 @@
9
10
  }
10
11
 
11
12
  let {
12
- class: className = '',
13
13
  colors = ['#FF5733', '#33FF57', '#3357FF', '#F1C40F'],
14
14
  mode = 'breathe',
15
15
  blur = 'medium',
16
16
  scale = 1,
17
- duration = 5
18
- }: Props = $props();
17
+ duration = 5,
18
+ ...restProps
19
+ }: Props & StyleProps & Record<string, unknown> = $props();
20
+
21
+ const extractedStyleProps = $derived.by(() => extractStyleProps(restProps));
22
+ const styleProps = $derived(extractedStyleProps.styleProps);
23
+ const props = $derived(extractedStyleProps.restProps);
24
+ const rootStyle = $derived.by(() => surfaceStyle(styleProps, 'glow-effect'));
19
25
 
20
26
  const getBlurClass = (blurValue: Props['blur']) => {
21
27
  if (typeof blurValue === 'number') return `blur-[${blurValue}px]`;
@@ -50,11 +56,14 @@
50
56
  </script>
51
57
 
52
58
  <div
53
- class="pointer-events-none absolute inset-0 -z-10 h-full w-full overflow-hidden rounded-full {getBlurClass(
59
+ class="pointer-events-none absolute inset-0 -z-10 h-full w-full overflow-hidden {getBlurClass(
54
60
  blur
55
- )} {className}"
61
+ )}"
62
+ style={rootStyle}
56
63
  style:isolation="isolate"
57
64
  style:transform-origin="center"
65
+ style:border-radius="var(--sveltely-border-radius)"
66
+ {...props}
58
67
  >
59
68
  <div
60
69
  class="absolute transform-gpu {animationClass}"
@@ -1,11 +1,12 @@
1
+ import { type StyleProps } from '../../../style/surface';
1
2
  interface Props {
2
- class?: string;
3
3
  colors?: string[];
4
4
  mode?: 'breathe' | 'colorShift';
5
5
  blur?: number | 'softest' | 'soft' | 'medium' | 'strong' | 'stronger' | 'strongest' | 'none';
6
6
  scale?: number;
7
7
  duration?: number;
8
8
  }
9
- declare const GlowEffect: import("svelte").Component<Props, {}, "">;
9
+ type $$ComponentProps = Props & StyleProps & Record<string, unknown>;
10
+ declare const GlowEffect: import("svelte").Component<$$ComponentProps, {}, "">;
10
11
  type GlowEffect = ReturnType<typeof GlowEffect>;
11
12
  export default GlowEffect;
@@ -0,0 +1 @@
1
+ export { default } from './GlowEffect.svelte';
@@ -0,0 +1 @@
1
+ export { default } from './GlowEffect.svelte';