@x33025/sveltely 0.0.58 → 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 (188) 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} +1 -2
  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/{TokenSearchInput.demo.svelte → Library/TokenSearchInput/TokenSearchInput.demo.svelte} +1 -2
  122. package/dist/components/{TokenSearchInput.demo.svelte.d.ts → Library/TokenSearchInput/TokenSearchInput.demo.svelte.d.ts} +0 -1
  123. package/dist/components/Library/TokenSearchInput/TokenSearchInput.svelte +230 -0
  124. package/dist/components/{TokenSearchInput.svelte.d.ts → Library/TokenSearchInput/TokenSearchInput.svelte.d.ts} +2 -3
  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 -15
  146. package/dist/index.js +23 -15
  147. package/dist/style/index.css +61 -325
  148. package/dist/style/surface.d.ts +17 -0
  149. package/dist/style/surface.js +54 -0
  150. package/dist/style.css +86 -601
  151. package/dist/utils/positioning.d.ts +3 -2
  152. package/dist/utils/positioning.js +9 -5
  153. package/package.json +1 -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/TokenSearchInput.svelte +0 -124
  178. package/dist/components/Tooltip.demo.svelte +0 -16
  179. package/dist/components/Tooltip.svelte +0 -79
  180. package/dist/components/Tooltip.svelte.d.ts +0 -12
  181. /package/dist/components/{AsyncButton.demo.svelte.d.ts → Library/AsyncButton/AsyncButton.demo.svelte.d.ts} +0 -0
  182. /package/dist/components/{NavigationStack → Library/NavigationStack}/index.d.ts +0 -0
  183. /package/dist/components/{NavigationStack → Library/NavigationStack}/index.js +0 -0
  184. /package/dist/components/{Popover → Library/Popover}/Popover.demo.svelte.d.ts +0 -0
  185. /package/dist/components/{Popover → Library/Popover}/PopoverDebugOverlay.svelte.d.ts +0 -0
  186. /package/dist/components/{Sheet → Library/Sheet}/index.d.ts +0 -0
  187. /package/dist/components/{Sheet → Library/Sheet}/index.js +0 -0
  188. /package/dist/components/{Spinner.demo.svelte.d.ts → Library/Spinner/Spinner.demo.svelte.d.ts} +0 -0
@@ -0,0 +1,10 @@
1
+ import { type Anchor } from '../utils/positioning';
2
+ export type TooltipOptions = string | {
3
+ label: string;
4
+ disabled?: boolean;
5
+ placement?: Anchor;
6
+ };
7
+ export declare function tooltip(node: HTMLElement, initialOptions?: TooltipOptions | null): {
8
+ update(nextOptions?: TooltipOptions | null): void;
9
+ destroy(): void;
10
+ };
@@ -0,0 +1,255 @@
1
+ import { computePosition, getPlacement, getViewportRect, oppositeAnchor } from '../utils/positioning';
2
+ const TOOLTIP_STYLE_ID = 'sveltely-tooltip-action-styles';
3
+ const VIEWPORT_MARGIN = 8;
4
+ const parseOptions = (value) => {
5
+ if (typeof value === 'string') {
6
+ return {
7
+ label: value,
8
+ disabled: false,
9
+ placement: 'top'
10
+ };
11
+ }
12
+ return {
13
+ label: value?.label ?? '',
14
+ disabled: value?.disabled ?? false,
15
+ placement: value?.placement ?? 'top'
16
+ };
17
+ };
18
+ const parsePx = (value) => {
19
+ const parsed = Number.parseFloat(value);
20
+ return Number.isFinite(parsed) ? parsed : 0;
21
+ };
22
+ const getTriggerOffset = (element, currentAnchor) => {
23
+ const styles = getComputedStyle(element);
24
+ if (currentAnchor === 'top' || currentAnchor === 'bottom') {
25
+ return Math.max(parsePx(styles.paddingTop), parsePx(styles.paddingBottom));
26
+ }
27
+ return Math.max(parsePx(styles.paddingLeft), parsePx(styles.paddingRight));
28
+ };
29
+ const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
30
+ const ensureStyles = () => {
31
+ if (typeof document === 'undefined')
32
+ return;
33
+ if (document.getElementById(TOOLTIP_STYLE_ID))
34
+ return;
35
+ const style = document.createElement('style');
36
+ style.id = TOOLTIP_STYLE_ID;
37
+ style.textContent = `
38
+ .sveltely-tooltip {
39
+ --tooltip-font-size: calc(var(--sveltely-font-size) * 0.857);
40
+ --tooltip-scale: calc(var(--tooltip-font-size) / 0.75rem);
41
+ --tooltip-arrow-size: calc(var(--tooltip-font-size) * 0.667);
42
+ position: fixed;
43
+ z-index: 50;
44
+ pointer-events: none;
45
+ border-radius: var(--sveltely-border-radius);
46
+ background: black;
47
+ color: white;
48
+ padding:
49
+ calc(var(--sveltely-padding-y) * 0.33 * var(--tooltip-scale))
50
+ calc(var(--sveltely-padding-x) * 0.67 * var(--tooltip-scale));
51
+ font-size: var(--tooltip-font-size);
52
+ line-height: calc(var(--tooltip-font-size) * 1.333);
53
+ white-space: nowrap;
54
+ }
55
+
56
+ .sveltely-tooltip-arrow {
57
+ position: absolute;
58
+ width: var(--tooltip-arrow-size);
59
+ height: var(--tooltip-arrow-size);
60
+ background: black;
61
+ transform: rotate(45deg);
62
+ z-index: -1;
63
+ }
64
+
65
+ .sveltely-tooltip[data-anchor='top'] .sveltely-tooltip-arrow {
66
+ bottom: calc(var(--tooltip-arrow-size) * -0.5);
67
+ left: var(--tooltip-arrow-left, 50%);
68
+ top: auto;
69
+ transform: translateX(-50%) rotate(45deg);
70
+ }
71
+
72
+ .sveltely-tooltip[data-anchor='bottom'] .sveltely-tooltip-arrow {
73
+ top: calc(var(--tooltip-arrow-size) * -0.5);
74
+ left: var(--tooltip-arrow-left, 50%);
75
+ transform: translateX(-50%) rotate(45deg);
76
+ }
77
+
78
+ .sveltely-tooltip[data-anchor='left'] .sveltely-tooltip-arrow {
79
+ right: calc(var(--tooltip-arrow-size) * -0.5);
80
+ left: auto;
81
+ top: var(--tooltip-arrow-top, 50%);
82
+ transform: translate(50%, -50%) rotate(45deg);
83
+ }
84
+
85
+ .sveltely-tooltip[data-anchor='right'] .sveltely-tooltip-arrow {
86
+ left: calc(var(--tooltip-arrow-size) * -0.5);
87
+ top: var(--tooltip-arrow-top, 50%);
88
+ transform: translate(-50%, -50%) rotate(45deg);
89
+ }
90
+ `;
91
+ document.head.appendChild(style);
92
+ };
93
+ export function tooltip(node, initialOptions) {
94
+ if (typeof document === 'undefined') {
95
+ return {
96
+ update() { },
97
+ destroy() { }
98
+ };
99
+ }
100
+ ensureStyles();
101
+ let options = parseOptions(initialOptions);
102
+ let tooltipEl = null;
103
+ let labelEl = null;
104
+ let rafId = 0;
105
+ const cleanupTooltip = () => {
106
+ if (rafId) {
107
+ cancelAnimationFrame(rafId);
108
+ rafId = 0;
109
+ }
110
+ if (!tooltipEl)
111
+ return;
112
+ tooltipEl.remove();
113
+ tooltipEl = null;
114
+ labelEl = null;
115
+ };
116
+ const positionTooltip = () => {
117
+ if (!tooltipEl)
118
+ return;
119
+ const triggerRect = node.getBoundingClientRect();
120
+ const preferredAnchor = (() => {
121
+ const triggerOffset = getTriggerOffset(node, options.placement);
122
+ const requiredVerticalSpace = tooltipEl.offsetHeight + triggerOffset + VIEWPORT_MARGIN;
123
+ const requiredHorizontalSpace = tooltipEl.offsetWidth + triggerOffset + VIEWPORT_MARGIN;
124
+ if (options.placement === 'top' && triggerRect.top < requiredVerticalSpace) {
125
+ return oppositeAnchor(options.placement);
126
+ }
127
+ if (options.placement === 'bottom' &&
128
+ window.innerHeight - triggerRect.bottom < requiredVerticalSpace) {
129
+ return oppositeAnchor(options.placement);
130
+ }
131
+ if (options.placement === 'left' && triggerRect.left < requiredHorizontalSpace) {
132
+ return oppositeAnchor(options.placement);
133
+ }
134
+ if (options.placement === 'right' &&
135
+ window.innerWidth - triggerRect.right < requiredHorizontalSpace) {
136
+ return oppositeAnchor(options.placement);
137
+ }
138
+ return options.placement;
139
+ })();
140
+ const preferredAlign = (() => {
141
+ if (preferredAnchor !== 'top' && preferredAnchor !== 'bottom') {
142
+ return 'center';
143
+ }
144
+ const centeredPlacement = getPlacement(triggerRect, preferredAnchor, 'center');
145
+ const centeredRect = getViewportRect(centeredPlacement, tooltipEl.offsetWidth, tooltipEl.offsetHeight);
146
+ if (centeredRect.left >= VIEWPORT_MARGIN &&
147
+ centeredRect.right <= window.innerWidth - VIEWPORT_MARGIN) {
148
+ return 'center';
149
+ }
150
+ if (centeredRect.left < VIEWPORT_MARGIN && centeredRect.right > window.innerWidth - VIEWPORT_MARGIN) {
151
+ return 'center';
152
+ }
153
+ const triggerCenter = triggerRect.left + triggerRect.width / 2;
154
+ return triggerCenter <= window.innerWidth / 2 ? 'left' : 'right';
155
+ })();
156
+ const result = computePosition(triggerRect, tooltipEl.offsetWidth, tooltipEl.offsetHeight, preferredAnchor, preferredAlign);
157
+ const triggerOffset = getTriggerOffset(node, result.anchor);
158
+ const coords = result.anchor === 'top'
159
+ ? { top: result.top - triggerOffset, left: result.left }
160
+ : result.anchor === 'bottom'
161
+ ? { top: result.top + triggerOffset, left: result.left }
162
+ : result.anchor === 'left'
163
+ ? { top: result.top, left: result.left - triggerOffset }
164
+ : { top: result.top, left: result.left + triggerOffset };
165
+ const viewportRect = getViewportRect({
166
+ top: coords.top,
167
+ left: coords.left,
168
+ transform: result.transform
169
+ }, tooltipEl.offsetWidth, tooltipEl.offsetHeight);
170
+ const shiftX = viewportRect.left < VIEWPORT_MARGIN
171
+ ? VIEWPORT_MARGIN - viewportRect.left
172
+ : viewportRect.right > window.innerWidth - VIEWPORT_MARGIN
173
+ ? window.innerWidth - VIEWPORT_MARGIN - viewportRect.right
174
+ : 0;
175
+ const shiftY = viewportRect.top < VIEWPORT_MARGIN
176
+ ? VIEWPORT_MARGIN - viewportRect.top
177
+ : viewportRect.bottom > window.innerHeight - VIEWPORT_MARGIN
178
+ ? window.innerHeight - VIEWPORT_MARGIN - viewportRect.bottom
179
+ : 0;
180
+ const finalLeft = coords.left + shiftX;
181
+ const finalTop = coords.top + shiftY;
182
+ const finalRect = getViewportRect({
183
+ top: finalTop,
184
+ left: finalLeft,
185
+ transform: result.transform
186
+ }, tooltipEl.offsetWidth, tooltipEl.offsetHeight);
187
+ const arrowInset = parsePx(getComputedStyle(tooltipEl).getPropertyValue('--tooltip-arrow-size'));
188
+ const arrowPadding = arrowInset;
189
+ tooltipEl.dataset.anchor = result.anchor;
190
+ tooltipEl.style.top = `${finalTop}px`;
191
+ tooltipEl.style.left = `${finalLeft}px`;
192
+ tooltipEl.style.transform = result.transform;
193
+ if (result.anchor === 'top' || result.anchor === 'bottom') {
194
+ const arrowLeft = clamp(triggerRect.left + triggerRect.width / 2 - finalRect.left, arrowPadding, tooltipEl.offsetWidth - arrowPadding);
195
+ tooltipEl.style.setProperty('--tooltip-arrow-left', `${arrowLeft}px`);
196
+ tooltipEl.style.removeProperty('--tooltip-arrow-top');
197
+ return;
198
+ }
199
+ const arrowTop = clamp(triggerRect.top + triggerRect.height / 2 - finalRect.top, arrowPadding, tooltipEl.offsetHeight - arrowPadding);
200
+ tooltipEl.style.setProperty('--tooltip-arrow-top', `${arrowTop}px`);
201
+ tooltipEl.style.removeProperty('--tooltip-arrow-left');
202
+ };
203
+ const show = () => {
204
+ if (options.disabled || !options.label.trim())
205
+ return;
206
+ if (!tooltipEl) {
207
+ tooltipEl = document.createElement('div');
208
+ tooltipEl.className = 'sveltely-tooltip';
209
+ labelEl = document.createElement('span');
210
+ const arrowEl = document.createElement('div');
211
+ arrowEl.className = 'sveltely-tooltip-arrow';
212
+ tooltipEl.append(labelEl, arrowEl);
213
+ document.body.appendChild(tooltipEl);
214
+ }
215
+ if (labelEl) {
216
+ labelEl.textContent = options.label;
217
+ }
218
+ rafId = requestAnimationFrame(() => {
219
+ rafId = 0;
220
+ positionTooltip();
221
+ });
222
+ };
223
+ const hide = () => {
224
+ cleanupTooltip();
225
+ };
226
+ const handleWindowChange = () => hide();
227
+ node.addEventListener('mouseenter', show);
228
+ node.addEventListener('mouseleave', hide);
229
+ node.addEventListener('focusin', show);
230
+ node.addEventListener('focusout', hide);
231
+ window.addEventListener('scroll', handleWindowChange, true);
232
+ window.addEventListener('resize', handleWindowChange);
233
+ return {
234
+ update(nextOptions) {
235
+ options = parseOptions(nextOptions);
236
+ if (options.disabled || !options.label.trim()) {
237
+ hide();
238
+ return;
239
+ }
240
+ if (labelEl) {
241
+ labelEl.textContent = options.label;
242
+ positionTooltip();
243
+ }
244
+ },
245
+ destroy() {
246
+ node.removeEventListener('mouseenter', show);
247
+ node.removeEventListener('mouseleave', hide);
248
+ node.removeEventListener('focusin', show);
249
+ node.removeEventListener('focusout', hide);
250
+ window.removeEventListener('scroll', handleWindowChange, true);
251
+ window.removeEventListener('resize', handleWindowChange);
252
+ hide();
253
+ }
254
+ };
255
+ }
@@ -1,13 +1,13 @@
1
1
  <script module lang="ts">
2
2
  export const demo = {
3
3
  name: 'AnimatedNumber',
4
- description: 'Spring-driven numeric transitions.',
5
- isProminent: false
4
+ description: 'Spring-driven numeric transitions.'
6
5
  };
7
6
  </script>
8
7
 
9
8
  <script lang="ts">
10
9
  import AnimatedNumber from './AnimatedNumber.svelte';
10
+ import Button from '../Button/Button.svelte';
11
11
 
12
12
  let value = $state(1234);
13
13
 
@@ -17,12 +17,8 @@
17
17
  </script>
18
18
 
19
19
  <div class="vstack center gap-3">
20
- <AnimatedNumber {value} class="text-3xl font-semibold text-zinc-900" />
21
- <button
22
- type="button"
23
- class="rounded-full bg-zinc-900 px-3 py-2 text-sm text-white"
24
- onclick={bump}
25
- >
26
- Change number
27
- </button>
20
+ <div class="text-3xl font-semibold text-zinc-900">
21
+ <AnimatedNumber {value} />
22
+ </div>
23
+ <Button label="Change number" variant="solid" onclick={bump} />
28
24
  </div>
@@ -1,7 +1,6 @@
1
1
  export declare const demo: {
2
2
  name: string;
3
3
  description: string;
4
- isProminent: boolean;
5
4
  };
6
5
  import AnimatedNumber from './AnimatedNumber.svelte';
7
6
  declare const AnimatedNumber: import("svelte").Component<Record<string, never>, {}, "">;
@@ -0,0 +1,29 @@
1
+ <script lang="ts">
2
+ import { Spring } from 'svelte/motion';
3
+ import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
4
+
5
+ interface Props {
6
+ value: number;
7
+ as?: keyof HTMLElementTagNameMap;
8
+ }
9
+
10
+ let { value, as = 'span', ...restProps }: Props & StyleProps & Record<string, unknown> = $props();
11
+
12
+ const spring = Spring.of(() => value);
13
+ const display = $derived(Math.round(spring.current).toLocaleString());
14
+ const extractedStyleProps = $derived.by(() => extractStyleProps(restProps));
15
+ const styleProps = $derived(extractedStyleProps.styleProps);
16
+ const props = $derived(extractedStyleProps.restProps);
17
+ const rootStyle = $derived.by(() => surfaceStyle(styleProps, 'animated-number'));
18
+ </script>
19
+
20
+ <svelte:element this={as} class="animated-number tabular-nums" style={rootStyle} {...props}>
21
+ {display}
22
+ </svelte:element>
23
+
24
+ <style>
25
+ .animated-number {
26
+ font-size: var(--animated-number-font-size, var(--sveltely-font-size));
27
+ line-height: 1;
28
+ }
29
+ </style>
@@ -0,0 +1,9 @@
1
+ import { type StyleProps } from '../../../style/surface';
2
+ interface Props {
3
+ value: number;
4
+ as?: keyof HTMLElementTagNameMap;
5
+ }
6
+ type $$ComponentProps = Props & StyleProps & Record<string, unknown>;
7
+ declare const AnimatedNumber: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type AnimatedNumber = ReturnType<typeof AnimatedNumber>;
9
+ export default AnimatedNumber;
@@ -0,0 +1 @@
1
+ export { default } from './AnimatedNumber.svelte';
@@ -0,0 +1 @@
1
+ export { default } from './AnimatedNumber.svelte';
@@ -20,5 +20,4 @@
20
20
  icon={SaveIcon}
21
21
  label="Run async action"
22
22
  action={runDemo}
23
- class="rounded-full bg-zinc-900 px-3 py-2 text-sm text-white"
24
23
  />
@@ -0,0 +1,178 @@
1
+ <script lang="ts">
2
+ import { CircleAlertIcon } from '@lucide/svelte';
3
+ import type { Component } from 'svelte';
4
+ import type { HTMLButtonAttributes } from 'svelte/elements';
5
+ import { tooltip } from '../../../actions/tooltip';
6
+ import Spinner from '../Spinner';
7
+ import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
8
+
9
+ type Props = {
10
+ icon?: Component<{ class?: string; size?: number | string }>;
11
+ label: string;
12
+ action: () => void | Promise<void>;
13
+ error?: unknown | null;
14
+ loading?: boolean;
15
+ disableWhileLoading?: boolean;
16
+ variant?: 'iconAndLabel' | 'iconOnly';
17
+ iconColor?: string;
18
+ iconSize?: number | string;
19
+ labelColor?: string;
20
+ } & StyleProps & Omit<HTMLButtonAttributes, 'children' | 'onclick' | 'class' | 'style'>;
21
+
22
+ let {
23
+ icon,
24
+ label,
25
+ action,
26
+ error = $bindable<unknown | null>(null),
27
+ loading = undefined,
28
+ disableWhileLoading = true,
29
+ variant = 'iconAndLabel',
30
+ iconColor,
31
+ iconSize,
32
+ labelColor,
33
+ disabled = false,
34
+ type = 'button',
35
+ ...restProps
36
+ }: Props = $props();
37
+
38
+ const extractedStyleProps = $derived.by(() => extractStyleProps(restProps));
39
+ const styleProps = $derived(extractedStyleProps.styleProps);
40
+ const props = $derived(extractedStyleProps.restProps);
41
+
42
+ let internalLoading = $state(false);
43
+
44
+ const isControlledLoading = $derived(loading !== undefined);
45
+ const effectiveLoading = $derived(isControlledLoading ? loading : internalLoading);
46
+ const effectiveDisabled = $derived(disabled || (disableWhileLoading && effectiveLoading));
47
+
48
+ const handleClick = async () => {
49
+ if (effectiveDisabled) return;
50
+ error = null;
51
+ if (isControlledLoading) {
52
+ try {
53
+ await action();
54
+ } catch (caught) {
55
+ error = caught;
56
+ }
57
+ return;
58
+ }
59
+
60
+ internalLoading = true;
61
+ try {
62
+ await action();
63
+ } catch (caught) {
64
+ error = caught;
65
+ } finally {
66
+ internalLoading = false;
67
+ }
68
+ };
69
+
70
+ const errorLabel = $derived.by(() => {
71
+ if (!error) return null;
72
+ if (typeof error === 'string' && error.trim().length > 0) return error;
73
+ if (error instanceof Error && error.message.trim().length > 0) return error.message;
74
+ return 'Something went wrong';
75
+ });
76
+
77
+ const toRem = (value: number | string | undefined) =>
78
+ value === undefined ? undefined : typeof value === 'number' ? `${value}rem` : value;
79
+
80
+ const triggerStyle = $derived.by(() => surfaceStyle(styleProps, 'async-button'));
81
+
82
+ const iconStyle = $derived.by(() => {
83
+ const declarations: string[] = [];
84
+
85
+ if (iconColor !== undefined) {
86
+ declarations.push(`color: ${iconColor};`);
87
+ }
88
+
89
+ if (iconSize !== undefined) {
90
+ const size = toRem(iconSize);
91
+ declarations.push(`width: ${size};`, `height: ${size};`);
92
+ }
93
+
94
+ return declarations.join(' ');
95
+ });
96
+
97
+ const labelStyle = $derived.by(() => {
98
+ if (labelColor === undefined) return '';
99
+ return `color: ${labelColor};`;
100
+ });
101
+ </script>
102
+
103
+ <button
104
+ {type}
105
+ use:tooltip={{ label: errorLabel ?? '', disabled: !errorLabel }}
106
+ class="async-button inline-flex items-center disabled:cursor-not-allowed disabled:opacity-50 {variant ===
107
+ 'iconOnly'
108
+ ? 'async-button-icon-only'
109
+ : ''}"
110
+ style={triggerStyle}
111
+ disabled={effectiveDisabled}
112
+ aria-busy={effectiveLoading}
113
+ aria-label={variant === 'iconOnly' ? label : undefined}
114
+ data-error={error ? 'true' : 'false'}
115
+ {...props}
116
+ onclick={handleClick}
117
+ >
118
+ <span class="async-button-icon-frame inline-grid shrink-0 place-items-center" style={iconStyle}>
119
+ {#if effectiveLoading}
120
+ <Spinner size={iconSize !== undefined ? toRem(iconSize) : 'var(--async-button-icon-size)'} />
121
+ {:else if error}
122
+ <CircleAlertIcon class="async-button-icon text-red-600" />
123
+ {:else if icon}
124
+ {@const Icon = icon}
125
+ <Icon class="async-button-icon" />
126
+ {/if}
127
+ </span>
128
+ {#if variant === 'iconAndLabel'}
129
+ <span class="async-button-text" style={labelStyle}>{label}</span>
130
+ {/if}
131
+ </button>
132
+
133
+ <style>
134
+ .async-button {
135
+ --async-button-font-size: var(--sveltely-font-size);
136
+ --async-button-scale: calc(var(--async-button-font-size) / 1rem);
137
+ --async-button-icon-size: calc(var(--async-button-font-size) * 1.143);
138
+ border: 1px solid var(--async-button-border-color, var(--sveltely-primary-color));
139
+ border-radius: var(--async-button-border-radius, var(--sveltely-border-radius));
140
+ background: var(--async-button-background, var(--sveltely-primary-color));
141
+ color: var(--async-button-color, white);
142
+ gap: var(--async-button-gap, var(--sveltely-gap));
143
+ font-size: var(--async-button-font-size);
144
+ line-height: 1.25;
145
+ padding:
146
+ var(--async-button-padding-y, calc(var(--sveltely-padding-y) * 0.67 * var(--async-button-scale)))
147
+ var(--async-button-padding-x, calc(var(--sveltely-padding-x) * var(--async-button-scale)));
148
+ transition: color 150ms, border-color 150ms, background-color 150ms;
149
+ }
150
+
151
+ .async-button:hover {
152
+ background: var(
153
+ --async-button-hover-background,
154
+ var(--sveltely-active-hover-color)
155
+ );
156
+ }
157
+
158
+ .async-button-icon-only {
159
+ padding:
160
+ var(--async-button-padding-y, calc(var(--sveltely-padding-y) * 0.67 * var(--async-button-scale)))
161
+ var(--async-button-padding-x, calc(var(--sveltely-padding-x) * 0.67 * var(--async-button-scale)));
162
+ min-width: calc((var(--async-button-padding-x, calc(var(--sveltely-padding-x) * 0.67 * var(--async-button-scale))) * 2) + 1rem);
163
+ min-height: calc((var(--async-button-padding-y, calc(var(--sveltely-padding-y) * 0.67 * var(--async-button-scale))) * 2) + 1rem);
164
+ }
165
+
166
+ .async-button-icon-frame {
167
+ display: inline-flex;
168
+ align-items: center;
169
+ justify-content: center;
170
+ width: var(--async-button-icon-size);
171
+ height: var(--async-button-icon-size);
172
+ }
173
+
174
+ .async-button-icon {
175
+ width: 100%;
176
+ height: 100%;
177
+ }
178
+ </style>
@@ -1,16 +1,21 @@
1
1
  import type { Component } from 'svelte';
2
2
  import type { HTMLButtonAttributes } from 'svelte/elements';
3
+ import { type StyleProps } from '../../../style/surface';
3
4
  type Props = {
4
5
  icon?: Component<{
5
6
  class?: string;
7
+ size?: number | string;
6
8
  }>;
7
9
  label: string;
8
10
  action: () => void | Promise<void>;
9
11
  error?: unknown | null;
10
12
  loading?: boolean;
11
13
  disableWhileLoading?: boolean;
12
- style?: 'iconAndLabel' | 'iconOnly';
13
- } & Omit<HTMLButtonAttributes, 'children' | 'onclick'>;
14
+ variant?: 'iconAndLabel' | 'iconOnly';
15
+ iconColor?: string;
16
+ iconSize?: number | string;
17
+ labelColor?: string;
18
+ } & StyleProps & Omit<HTMLButtonAttributes, 'children' | 'onclick' | 'class' | 'style'>;
14
19
  declare const AsyncButton: Component<Props, {}, "error">;
15
20
  type AsyncButton = ReturnType<typeof AsyncButton>;
16
21
  export default AsyncButton;
@@ -0,0 +1 @@
1
+ export { default } from './AsyncButton.svelte';
@@ -0,0 +1 @@
1
+ export { default } from './AsyncButton.svelte';
@@ -0,0 +1,17 @@
1
+ <script module lang="ts">
2
+ export const demo = {
3
+ name: 'Button',
4
+ description: 'Token-aware button primitive with optional icon support.'
5
+ };
6
+ </script>
7
+
8
+ <script lang="ts">
9
+ import { SaveIcon } from '@lucide/svelte';
10
+ import Button from './Button.svelte';
11
+ </script>
12
+
13
+ <div class="hstack items-center gap-3">
14
+ <Button label="Default" />
15
+ <Button label="Solid" variant="solid" />
16
+ <Button icon={SaveIcon} label="With icon" />
17
+ </div>
@@ -0,0 +1,23 @@
1
+ export declare const demo: {
2
+ name: string;
3
+ description: string;
4
+ };
5
+ import Button from './Button.svelte';
6
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
7
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
8
+ $$bindings?: Bindings;
9
+ } & Exports;
10
+ (internal: unknown, props: {
11
+ $$events?: Events;
12
+ $$slots?: Slots;
13
+ }): Exports & {
14
+ $set?: any;
15
+ $on?: any;
16
+ };
17
+ z_$$bindings?: Bindings;
18
+ }
19
+ declare const Button: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
20
+ [evt: string]: CustomEvent<any>;
21
+ }, {}, {}, string>;
22
+ type Button = InstanceType<typeof Button>;
23
+ export default Button;