@joewinke/jatui 0.1.31 → 0.2.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 (239) hide show
  1. package/CLAUDE.md +22 -0
  2. package/dist/actions/attention.d.ts +24 -0
  3. package/dist/actions/attention.js +94 -0
  4. package/dist/actions/collapse.js +29 -15
  5. package/dist/actions/floating.d.ts +53 -0
  6. package/dist/actions/floating.js +158 -0
  7. package/dist/actions/listNav.js +137 -108
  8. package/dist/actions/railNav.js +89 -72
  9. package/dist/actions/staggerEntrance.d.ts +28 -0
  10. package/dist/actions/staggerEntrance.js +71 -0
  11. package/dist/actions/tooltip.d.ts +28 -0
  12. package/dist/actions/tooltip.js +186 -0
  13. package/dist/assets/sounds/README.md +47 -0
  14. package/dist/assets/sounds/error.d.ts +1 -0
  15. package/dist/assets/sounds/error.js +4 -0
  16. package/dist/assets/sounds/notify.d.ts +1 -0
  17. package/dist/assets/sounds/notify.js +4 -0
  18. package/dist/assets/sounds/pop.d.ts +1 -0
  19. package/dist/assets/sounds/pop.js +4 -0
  20. package/dist/assets/sounds/send.d.ts +1 -0
  21. package/dist/assets/sounds/send.js +4 -0
  22. package/dist/assets/sounds/success.d.ts +1 -0
  23. package/dist/assets/sounds/success.js +4 -0
  24. package/dist/assets/sounds/toggle.d.ts +1 -0
  25. package/dist/assets/sounds/toggle.js +4 -0
  26. package/dist/components/AnimatedNumber.svelte +112 -0
  27. package/dist/components/AnimatedNumber.svelte.d.ts +8 -0
  28. package/dist/components/Badge.svelte +75 -4
  29. package/dist/components/Badge.svelte.d.ts +6 -1
  30. package/dist/components/Button.svelte +196 -21
  31. package/dist/components/Button.svelte.d.ts +10 -1
  32. package/dist/components/Carousel.svelte +265 -0
  33. package/dist/components/Carousel.svelte.d.ts +21 -0
  34. package/dist/components/ChipInput.svelte +63 -3
  35. package/dist/components/Collapse.svelte +70 -14
  36. package/dist/components/Collapse.svelte.d.ts +11 -0
  37. package/dist/components/ColorSelector.svelte +21 -24
  38. package/dist/components/CommandPalette.svelte +475 -0
  39. package/dist/components/CommandPalette.svelte.d.ts +3 -0
  40. package/dist/components/ContextMenu.svelte +9 -73
  41. package/dist/components/CopyButton.svelte +156 -0
  42. package/dist/components/CopyButton.svelte.d.ts +12 -0
  43. package/dist/components/HoldToConfirm.svelte +183 -0
  44. package/dist/components/HoldToConfirm.svelte.d.ts +11 -0
  45. package/dist/components/KeyboardShortcutsOverlay.svelte +54 -8
  46. package/dist/components/KeyboardShortcutsOverlay.svelte.d.ts +3 -0
  47. package/dist/components/PasswordMeter.svelte +87 -0
  48. package/dist/components/PasswordMeter.svelte.d.ts +8 -0
  49. package/dist/components/PinInput.svelte +186 -0
  50. package/dist/components/PinInput.svelte.d.ts +13 -0
  51. package/dist/components/QuantityStepper.svelte +185 -0
  52. package/dist/components/QuantityStepper.svelte.d.ts +12 -0
  53. package/dist/components/Skeleton.svelte +123 -0
  54. package/dist/components/Skeleton.svelte.d.ts +12 -0
  55. package/dist/components/SpeechForm.svelte +37 -0
  56. package/dist/components/StatusBadge.svelte +31 -3
  57. package/dist/components/StatusBadge.svelte.d.ts +0 -5
  58. package/dist/components/Tabs.svelte +270 -0
  59. package/dist/components/Tabs.svelte.d.ts +15 -0
  60. package/dist/components/TextInput.svelte +138 -38
  61. package/dist/components/TextInput.svelte.d.ts +9 -1
  62. package/dist/components/VoicePlayer.svelte +51 -0
  63. package/dist/components/basic/Alert.svelte +36 -0
  64. package/dist/components/basic/Alert.svelte.d.ts +9 -0
  65. package/dist/components/basic/Breadcrumb.svelte +27 -0
  66. package/dist/components/basic/Breadcrumb.svelte.d.ts +11 -0
  67. package/dist/components/basic/ButtonGroup.svelte +15 -0
  68. package/dist/components/basic/ButtonGroup.svelte.d.ts +8 -0
  69. package/dist/components/basic/Checkbox.svelte +85 -0
  70. package/dist/components/basic/Checkbox.svelte.d.ts +15 -0
  71. package/dist/components/basic/Empty.svelte +17 -0
  72. package/dist/components/basic/Empty.svelte.d.ts +8 -0
  73. package/dist/components/basic/Kbd.svelte +16 -0
  74. package/dist/components/basic/Kbd.svelte.d.ts +8 -0
  75. package/dist/components/basic/Pagination.svelte +104 -0
  76. package/dist/components/basic/Pagination.svelte.d.ts +12 -0
  77. package/dist/components/basic/RadioGroup.svelte +71 -0
  78. package/dist/components/basic/RadioGroup.svelte.d.ts +18 -0
  79. package/dist/components/basic/Separator.svelte +19 -0
  80. package/dist/components/basic/Separator.svelte.d.ts +8 -0
  81. package/dist/components/basic/Slider.svelte +72 -0
  82. package/dist/components/basic/Slider.svelte.d.ts +17 -0
  83. package/dist/components/basic/Switch.svelte +88 -0
  84. package/dist/components/basic/Switch.svelte.d.ts +14 -0
  85. package/dist/components/basic/Toggle.svelte +43 -0
  86. package/dist/components/basic/Toggle.svelte.d.ts +14 -0
  87. package/dist/components/graph/GraphCanvas.svelte +103 -0
  88. package/dist/components/graph/GraphCanvas.svelte.d.ts +22 -0
  89. package/dist/components/graph/JatuiNode.svelte +128 -0
  90. package/dist/components/graph/JatuiNode.svelte.d.ts +14 -0
  91. package/dist/components/graph/theme.d.ts +27 -0
  92. package/dist/components/graph/theme.js +136 -0
  93. package/dist/components/markup.js +62 -59
  94. package/dist/components/messaging/MessageItem.svelte +92 -0
  95. package/dist/components/messaging/MessageItem.svelte.d.ts +5 -0
  96. package/dist/components/messaging/TypingIndicator.svelte +63 -0
  97. package/dist/components/messaging/TypingIndicator.svelte.d.ts +7 -0
  98. package/dist/components/pipeline/PipelineColumn.svelte +44 -3
  99. package/dist/components/progress/ProgressBar.svelte +189 -0
  100. package/dist/components/progress/ProgressBar.svelte.d.ts +17 -0
  101. package/dist/components/progress/ProgressRing.svelte +138 -0
  102. package/dist/components/progress/ProgressRing.svelte.d.ts +12 -0
  103. package/dist/components/progress/Steps.svelte +195 -0
  104. package/dist/components/progress/Steps.svelte.d.ts +14 -0
  105. package/dist/components/session-nav/transcriptModel.js +66 -49
  106. package/dist/components/shell/NavigationMenu.svelte +422 -0
  107. package/dist/components/shell/NavigationMenu.svelte.d.ts +43 -0
  108. package/dist/components/shell/Sidebar.svelte +276 -0
  109. package/dist/components/shell/Sidebar.svelte.d.ts +32 -0
  110. package/dist/components/shell/SidebarGroup.svelte +180 -0
  111. package/dist/components/shell/SidebarGroup.svelte.d.ts +19 -0
  112. package/dist/components/shell/SidebarItem.svelte +170 -0
  113. package/dist/components/shell/SidebarItem.svelte.d.ts +24 -0
  114. package/dist/components/shell/shell.d.ts +30 -0
  115. package/dist/components/shell/shell.js +65 -0
  116. package/dist/components/table/DataTable.svelte +364 -0
  117. package/dist/components/table/DataTable.svelte.d.ts +4 -0
  118. package/dist/components/table/flexRender.d.ts +31 -0
  119. package/dist/components/table/flexRender.js +32 -0
  120. package/dist/components/table/types.d.ts +28 -0
  121. package/dist/components/table/types.js +1 -0
  122. package/dist/components/toast/ToastHost.svelte +21 -0
  123. package/dist/components/toast/ToastHost.svelte.d.ts +3 -0
  124. package/dist/components/toast/ToastItem.svelte +287 -0
  125. package/dist/components/toast/ToastItem.svelte.d.ts +9 -0
  126. package/dist/data/emojis.js +4 -4
  127. package/dist/dnd/autoScroll.js +12 -10
  128. package/dist/dnd/createDndBoard.svelte.js +110 -76
  129. package/dist/dnd/createDndBoard.test.js +161 -85
  130. package/dist/dnd/draggable.js +23 -15
  131. package/dist/dnd/dropTarget.js +29 -15
  132. package/dist/dnd/index.d.ts +0 -1
  133. package/dist/dnd/index.js +0 -1
  134. package/dist/dnd/types.d.ts +0 -9
  135. package/dist/dnd/types.js +14 -2
  136. package/dist/index.d.ts +60 -6
  137. package/dist/index.js +73 -6
  138. package/dist/showcase/AnimatedBeam.svelte +183 -0
  139. package/dist/showcase/AnimatedBeam.svelte.d.ts +26 -0
  140. package/dist/showcase/AuroraDrift.svelte +74 -0
  141. package/dist/showcase/AuroraDrift.svelte.d.ts +9 -0
  142. package/dist/showcase/BentoCard.svelte +50 -0
  143. package/dist/showcase/BentoCard.svelte.d.ts +14 -0
  144. package/dist/showcase/BentoGrid.svelte +43 -0
  145. package/dist/showcase/BentoGrid.svelte.d.ts +12 -0
  146. package/dist/showcase/BorderBeam.svelte +79 -0
  147. package/dist/showcase/BorderBeam.svelte.d.ts +12 -0
  148. package/dist/showcase/ClipWipe.svelte +82 -0
  149. package/dist/showcase/ClipWipe.svelte.d.ts +12 -0
  150. package/dist/showcase/Confetti.svelte +71 -0
  151. package/dist/showcase/Confetti.svelte.d.ts +10 -0
  152. package/dist/showcase/CursorSpotlight.svelte +85 -0
  153. package/dist/showcase/CursorSpotlight.svelte.d.ts +9 -0
  154. package/dist/showcase/DeviceMock.svelte +186 -0
  155. package/dist/showcase/DeviceMock.svelte.d.ts +11 -0
  156. package/dist/showcase/Dock.svelte +123 -0
  157. package/dist/showcase/Dock.svelte.d.ts +17 -0
  158. package/dist/showcase/FlipCard.svelte +103 -0
  159. package/dist/showcase/FlipCard.svelte.d.ts +10 -0
  160. package/dist/showcase/FocusReveal.svelte +83 -0
  161. package/dist/showcase/FocusReveal.svelte.d.ts +11 -0
  162. package/dist/showcase/Globe.svelte +202 -0
  163. package/dist/showcase/Globe.svelte.d.ts +16 -0
  164. package/dist/showcase/KenBurns.svelte +105 -0
  165. package/dist/showcase/KenBurns.svelte.d.ts +13 -0
  166. package/dist/showcase/Marquee.svelte +89 -0
  167. package/dist/showcase/Marquee.svelte.d.ts +9 -0
  168. package/dist/showcase/ParallaxTilt.svelte +98 -0
  169. package/dist/showcase/ParallaxTilt.svelte.d.ts +10 -0
  170. package/dist/showcase/ScrambleText.svelte +98 -0
  171. package/dist/showcase/ScrambleText.svelte.d.ts +11 -0
  172. package/dist/showcase/ShineSweep.svelte +81 -0
  173. package/dist/showcase/ShineSweep.svelte.d.ts +9 -0
  174. package/dist/showcase/Terminal.svelte +230 -0
  175. package/dist/showcase/Terminal.svelte.d.ts +18 -0
  176. package/dist/showcase/TextSplitReveal.svelte +146 -0
  177. package/dist/showcase/TextSplitReveal.svelte.d.ts +13 -0
  178. package/dist/showcase/TextWave.svelte +55 -0
  179. package/dist/showcase/TextWave.svelte.d.ts +8 -0
  180. package/dist/showcase/TypewriterText.svelte +130 -0
  181. package/dist/showcase/TypewriterText.svelte.d.ts +9 -0
  182. package/dist/showcase/backdrop/GrainGradient.svelte +126 -0
  183. package/dist/showcase/backdrop/GrainGradient.svelte.d.ts +23 -0
  184. package/dist/showcase/backdrop/MeshGradient.svelte +104 -0
  185. package/dist/showcase/backdrop/MeshGradient.svelte.d.ts +20 -0
  186. package/dist/showcase/backdrop/Metaballs.svelte +116 -0
  187. package/dist/showcase/backdrop/Metaballs.svelte.d.ts +18 -0
  188. package/dist/showcase/backdrop/NeuroNoise.svelte +115 -0
  189. package/dist/showcase/backdrop/NeuroNoise.svelte.d.ts +20 -0
  190. package/dist/showcase/backdrop/ShowcaseBackdrop.svelte +48 -0
  191. package/dist/showcase/backdrop/ShowcaseBackdrop.svelte.d.ts +12 -0
  192. package/dist/showcase/generative/GenerativeBackdrop.svelte +234 -0
  193. package/dist/showcase/generative/GenerativeBackdrop.svelte.d.ts +9 -0
  194. package/dist/showcase/generative/intent.d.ts +7 -0
  195. package/dist/showcase/generative/intent.js +67 -0
  196. package/dist/showcase/generative/manifest.d.ts +9 -0
  197. package/dist/showcase/generative/manifest.js +97 -0
  198. package/dist/showcase/generative/types.d.ts +48 -0
  199. package/dist/showcase/generative/types.js +8 -0
  200. package/dist/showcase/index.d.ts +36 -0
  201. package/dist/showcase/index.js +46 -0
  202. package/dist/showcase/scroll/SmoothScroll.svelte +49 -0
  203. package/dist/showcase/scroll/SmoothScroll.svelte.d.ts +12 -0
  204. package/dist/showcase/scroll/scrollProgress.d.ts +24 -0
  205. package/dist/showcase/scroll/scrollProgress.js +65 -0
  206. package/dist/showcase/scroll/scrollReveal.d.ts +30 -0
  207. package/dist/showcase/scroll/scrollReveal.js +70 -0
  208. package/dist/stores/commandPalette.svelte.d.ts +24 -0
  209. package/dist/stores/commandPalette.svelte.js +82 -0
  210. package/dist/stores/confirmDialog.svelte.js +5 -5
  211. package/dist/stores/inputDialog.svelte.js +5 -5
  212. package/dist/stores/toast.svelte.d.ts +28 -0
  213. package/dist/stores/toast.svelte.js +33 -0
  214. package/dist/styles/motion.css +46 -0
  215. package/dist/styles/tokens.css +31 -0
  216. package/dist/transitions/glide.d.ts +31 -0
  217. package/dist/transitions/glide.js +58 -0
  218. package/dist/types/booking.js +4 -4
  219. package/dist/types/comments.js +2 -2
  220. package/dist/types/messaging.js +3 -3
  221. package/dist/types/pipeline.js +2 -2
  222. package/dist/utils/currency.js +4 -2
  223. package/dist/utils/daisyuiColors.js +27 -25
  224. package/dist/utils/dateFormatters.d.ts +20 -0
  225. package/dist/utils/dateFormatters.js +65 -44
  226. package/dist/utils/googleMapsLoader.js +100 -46
  227. package/dist/utils/mentionParser.js +30 -30
  228. package/dist/utils/phone.js +27 -21
  229. package/dist/utils/phoneFormat.js +9 -9
  230. package/dist/utils/sound.d.ts +6 -0
  231. package/dist/utils/sound.js +113 -0
  232. package/dist/utils/splitText.d.ts +25 -0
  233. package/dist/utils/splitText.js +94 -0
  234. package/dist/utils/taskUtils.js +1 -1
  235. package/dist/utils/themeWipe.d.ts +21 -0
  236. package/dist/utils/themeWipe.js +94 -0
  237. package/dist/utils/viewTransition.d.ts +23 -0
  238. package/dist/utils/viewTransition.js +75 -0
  239. package/package.json +56 -4
package/CLAUDE.md CHANGED
@@ -239,6 +239,28 @@ If the project uses JST (Joe's Software Template), browse component demos at `/c
239
239
  - Check the component source in `src/lib/components/` for full prop types
240
240
  - Prefer jatui components over building custom ones when there's a match
241
241
 
242
+ # Layering Policy (DaisyUI is an implementation detail)
243
+
244
+ Three rules keep DaisyUI swappable instead of load-bearing:
245
+
246
+ 1. **jatui is the only API consumers touch.** App code imports `<Button>`,
247
+ `<TextInput>`, `<Modal>` — it never hand-writes `btn btn-primary` for
248
+ anything jatui covers. Consumer repos enforce this with the ratchet:
249
+ `node scripts/check-daisy-leakage.mjs <src> --baseline <file>` (count may
250
+ only shrink; marketing routes can be `--allow`ed).
251
+ 2. **DaisyUI class names live only inside jatui components.** They are
252
+ internal skin, like vendored CSS — never part of a component's public
253
+ props/API.
254
+ 3. **jatui owns the token layer.** Components consume `--jatui-*`
255
+ (`styles/tokens.css`: radius/spacing/border) and `--motion-*`
256
+ (`styles/motion.css`: easing/duration) custom properties. DaisyUI theme
257
+ variables feed INTO those tokens (as fallback-chained inputs), never
258
+ appear directly in component styles for values the tokens cover.
259
+
260
+ Net effect: dropping or replacing DaisyUI would be a change to the token
261
+ files and component internals — a skin swap inside this package, not an
262
+ app-wide migration for consumers.
263
+
242
264
  # Accessibility (a11y)
243
265
 
244
266
  @~/code/jat/shared/a11y-patterns.md
@@ -0,0 +1,24 @@
1
+ export type AttentionEffect = 'shake' | 'ping';
2
+ export interface AttentionOptions {
3
+ effect: AttentionEffect;
4
+ /** Change this value to retrigger. Any truthy/changing value fires the effect. */
5
+ trigger?: unknown;
6
+ }
7
+ /**
8
+ * Retriggerable attention action — fires once per `trigger` change.
9
+ *
10
+ * use:attention={{ effect: 'shake', trigger: myTrigger }}
11
+ *
12
+ * shake — horizontal translate, 4–6px amplitude, 2–3 oscillations, ≤300ms total.
13
+ * Use for invalid-input / reject feedback. Pair with a static error affordance
14
+ * (color, icon, label) so the state survives without motion.
15
+ * Reduced-motion: skipped entirely.
16
+ *
17
+ * ping — single expanding fading ring behind the element. Use for notification
18
+ * dots and badges. Fires once per trigger change; NEVER loops infinitely.
19
+ * Reduced-motion: skipped entirely.
20
+ */
21
+ export declare function attention(node: HTMLElement, options: AttentionOptions): {
22
+ update(newOptions: AttentionOptions): void;
23
+ destroy(): void;
24
+ };
@@ -0,0 +1,94 @@
1
+ // direction taxonomy after animista.net (Ana Travas, BSD-2-Clause site license); keyframes re-authored on jatui motion tokens
2
+ /**
3
+ * Retriggerable attention action — fires once per `trigger` change.
4
+ *
5
+ * use:attention={{ effect: 'shake', trigger: myTrigger }}
6
+ *
7
+ * shake — horizontal translate, 4–6px amplitude, 2–3 oscillations, ≤300ms total.
8
+ * Use for invalid-input / reject feedback. Pair with a static error affordance
9
+ * (color, icon, label) so the state survives without motion.
10
+ * Reduced-motion: skipped entirely.
11
+ *
12
+ * ping — single expanding fading ring behind the element. Use for notification
13
+ * dots and badges. Fires once per trigger change; NEVER loops infinitely.
14
+ * Reduced-motion: skipped entirely.
15
+ */
16
+ export function attention(node, options) {
17
+ var currentTrigger = options.trigger;
18
+ var pingEl = null;
19
+ var shakeId = null;
20
+ function prefersReduced() {
21
+ return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
22
+ }
23
+ function clearShake() {
24
+ node.style.animation = '';
25
+ if (shakeId !== null) {
26
+ clearTimeout(shakeId);
27
+ shakeId = null;
28
+ }
29
+ }
30
+ function clearPing() {
31
+ if (pingEl) {
32
+ pingEl.remove();
33
+ pingEl = null;
34
+ }
35
+ }
36
+ function runShake() {
37
+ if (prefersReduced())
38
+ return;
39
+ clearShake();
40
+ // 3 oscillations × 2 half-cycles = 6 keyframe segments in ~280ms
41
+ // translate: 0 → +5px → -5px → +4px → -4px → +2px → 0
42
+ var kf = [
43
+ { transform: 'translateX(0)' },
44
+ { transform: 'translateX(5px)' },
45
+ { transform: 'translateX(-5px)' },
46
+ { transform: 'translateX(4px)' },
47
+ { transform: 'translateX(-4px)' },
48
+ { transform: 'translateX(2px)' },
49
+ { transform: 'translateX(0)' }
50
+ ];
51
+ node.animate(kf, { duration: 280, easing: 'ease-in-out', fill: 'none' });
52
+ }
53
+ function runPing() {
54
+ if (prefersReduced())
55
+ return;
56
+ clearPing();
57
+ var rect = node.getBoundingClientRect();
58
+ var size = Math.max(rect.width, rect.height);
59
+ // Ensure node is position-capable for the pseudo-ring
60
+ var pos = getComputedStyle(node).position;
61
+ if (pos === 'static')
62
+ node.style.position = 'relative';
63
+ pingEl = document.createElement('span');
64
+ pingEl.style.cssText = "\n\t\t\tposition:absolute;\n\t\t\tinset:-4px;\n\t\t\tborder-radius:inherit;\n\t\t\tborder:2px solid currentColor;\n\t\t\topacity:0.7;\n\t\t\tpointer-events:none;\n\t\t\tz-index:-1;\n\t\t";
65
+ node.appendChild(pingEl);
66
+ var scale = 1 + 24 / size;
67
+ pingEl.animate([
68
+ { transform: 'scale(1)', opacity: '0.7' },
69
+ { transform: "scale(".concat(scale.toFixed(2), ")"), opacity: '0' }
70
+ ], { duration: 600, easing: 'ease-out', fill: 'forwards' }).onfinish = function () { return clearPing(); };
71
+ }
72
+ function fire(effect) {
73
+ if (effect === 'shake')
74
+ runShake();
75
+ else
76
+ runPing();
77
+ }
78
+ // Fire on mount if trigger is set
79
+ if (options.trigger !== undefined) {
80
+ fire(options.effect);
81
+ }
82
+ return {
83
+ update: function (newOptions) {
84
+ if (newOptions.trigger !== currentTrigger) {
85
+ currentTrigger = newOptions.trigger;
86
+ fire(newOptions.effect);
87
+ }
88
+ },
89
+ destroy: function () {
90
+ clearShake();
91
+ clearPing();
92
+ }
93
+ };
94
+ }
@@ -58,22 +58,34 @@
58
58
  * state (e.g. a `SvelteSet` of ids, with the id interpolating the row's own id) —
59
59
  * one action instance attaches per row element.
60
60
  */
61
- const DEFAULTS = { threshold: 120, expanded: false, fadeStart: 55, epsilon: 4 };
62
- export function collapse(node, options = {}) {
63
- let opts = { ...DEFAULTS, ...options };
64
- let collapsible = false;
65
- let rafId = 0;
66
- let applied = false;
61
+ var __assign = (this && this.__assign) || function () {
62
+ __assign = Object.assign || function(t) {
63
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
64
+ s = arguments[i];
65
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
66
+ t[p] = s[p];
67
+ }
68
+ return t;
69
+ };
70
+ return __assign.apply(this, arguments);
71
+ };
72
+ var DEFAULTS = { threshold: 120, expanded: false, fadeStart: 55, epsilon: 4 };
73
+ export function collapse(node, options) {
74
+ if (options === void 0) { options = {}; }
75
+ var opts = __assign(__assign({}, DEFAULTS), options);
76
+ var collapsible = false;
77
+ var rafId = 0;
78
+ var applied = false;
67
79
  function gradient() {
68
- return `linear-gradient(to bottom, black ${opts.fadeStart}%, transparent 100%)`;
80
+ return "linear-gradient(to bottom, black ".concat(opts.fadeStart, "%, transparent 100%)");
69
81
  }
70
82
  function apply() {
71
- const shouldCollapse = collapsible && !opts.expanded;
83
+ var shouldCollapse = collapsible && !opts.expanded;
72
84
  if (shouldCollapse === applied)
73
85
  return; // idempotent — avoids RO feedback loops
74
86
  applied = shouldCollapse;
75
87
  if (shouldCollapse) {
76
- node.style.maxHeight = `${opts.threshold}px`;
88
+ node.style.maxHeight = "".concat(opts.threshold, "px");
77
89
  node.style.overflow = 'hidden';
78
90
  node.style.maskImage = gradient();
79
91
  node.style.webkitMaskImage = gradient();
@@ -86,11 +98,12 @@ export function collapse(node, options = {}) {
86
98
  }
87
99
  }
88
100
  function measure() {
101
+ var _a;
89
102
  // scrollHeight is the full content height even while collapsed.
90
- const next = node.scrollHeight > opts.threshold + opts.epsilon;
103
+ var next = node.scrollHeight > opts.threshold + opts.epsilon;
91
104
  if (next !== collapsible) {
92
105
  collapsible = next;
93
- opts.onCollapsible?.(collapsible);
106
+ (_a = opts.onCollapsible) === null || _a === void 0 ? void 0 : _a.call(opts, collapsible);
94
107
  }
95
108
  apply();
96
109
  }
@@ -99,12 +112,13 @@ export function collapse(node, options = {}) {
99
112
  rafId = requestAnimationFrame(measure);
100
113
  }
101
114
  // Re-measure when the content's natural size changes (streaming, {@html}, lazy images).
102
- const ro = new ResizeObserver(scheduleMeasure);
115
+ var ro = new ResizeObserver(scheduleMeasure);
103
116
  ro.observe(node);
104
117
  scheduleMeasure();
105
118
  return {
106
- update(next = {}) {
107
- opts = { ...DEFAULTS, ...next };
119
+ update: function (next) {
120
+ if (next === void 0) { next = {}; }
121
+ opts = __assign(__assign({}, DEFAULTS), next);
108
122
  // expanded/threshold/fade may have changed — re-measure and let
109
123
  // apply() compare the freshly computed shouldCollapse against the
110
124
  // real last-applied state. (Force-flipping `applied` here used to make
@@ -112,7 +126,7 @@ export function collapse(node, options = {}) {
112
126
  // silently skipping the style update.)
113
127
  scheduleMeasure();
114
128
  },
115
- destroy() {
129
+ destroy: function () {
116
130
  cancelAnimationFrame(rafId);
117
131
  ro.disconnect();
118
132
  },
@@ -0,0 +1,53 @@
1
+ /**
2
+ * use:floating — anchored-positioning Svelte action
3
+ *
4
+ * Wraps @floating-ui/dom computePosition + autoUpdate so every popover-like
5
+ * component shares one battle-tested positioning primitive instead of each
6
+ * hand-rolling viewport clamping.
7
+ *
8
+ * Usage (element anchor):
9
+ * <div use:floating={{ anchor: triggerEl, placement: 'bottom-start', flip: true, shift: true, offset: 4, onDismiss: close }}>
10
+ *
11
+ * Usage (virtual / cursor point anchor):
12
+ * const virtualAnchor = makeVirtualAnchor(x, y)
13
+ * <div use:floating={{ anchor: virtualAnchor, placement: 'bottom-start', onDismiss: close }}>
14
+ *
15
+ * Animation: entrance fade + 2px rise, var(--motion-glide) var(--motion-fast).
16
+ * Exit is handled by the caller removing the element from the DOM.
17
+ * Reduced-motion guard: animation is skipped when the user prefers reduced motion.
18
+ *
19
+ * Dismiss:
20
+ * - Click outside the floating element fires onDismiss
21
+ * - Escape key fires onDismiss
22
+ * - Focus returns to the anchor element (or document.activeElement before mount)
23
+ * when the floating element is dismissed
24
+ *
25
+ * Accessibility:
26
+ * - The node must already carry role="menu" / role="listbox" etc. — this action
27
+ * does not set ARIA roles.
28
+ */
29
+ import type { Placement, ReferenceElement } from '@floating-ui/dom';
30
+ export type { Placement };
31
+ export interface FloatingOptions {
32
+ /** Anchor element or virtual element (with getBoundingClientRect). */
33
+ anchor: ReferenceElement | null;
34
+ /** Preferred placement. @floating-ui/dom may flip/shift if enabled. Default 'bottom-start'. */
35
+ placement?: Placement;
36
+ /** Whether to flip to the opposite side when there's not enough room. Default true. */
37
+ flip?: boolean;
38
+ /** Whether to shift along the axis to stay in view. Default true. */
39
+ shift?: boolean;
40
+ /** Pixel distance between anchor and floating element. Default 4. */
41
+ offset?: number;
42
+ /** Called when the floating element should be dismissed (outside-click or Escape). */
43
+ onDismiss?: () => void;
44
+ }
45
+ /**
46
+ * Create a virtual anchor from a viewport point (e.g. cursor coordinates).
47
+ * Pass the returned object as `anchor` when there is no real DOM element to anchor to.
48
+ */
49
+ export declare function makeVirtualAnchor(x: number, y: number): ReferenceElement;
50
+ export declare function floating(node: HTMLElement, options: FloatingOptions): {
51
+ update(next: FloatingOptions): void;
52
+ destroy(): void;
53
+ };
@@ -0,0 +1,158 @@
1
+ /**
2
+ * use:floating — anchored-positioning Svelte action
3
+ *
4
+ * Wraps @floating-ui/dom computePosition + autoUpdate so every popover-like
5
+ * component shares one battle-tested positioning primitive instead of each
6
+ * hand-rolling viewport clamping.
7
+ *
8
+ * Usage (element anchor):
9
+ * <div use:floating={{ anchor: triggerEl, placement: 'bottom-start', flip: true, shift: true, offset: 4, onDismiss: close }}>
10
+ *
11
+ * Usage (virtual / cursor point anchor):
12
+ * const virtualAnchor = makeVirtualAnchor(x, y)
13
+ * <div use:floating={{ anchor: virtualAnchor, placement: 'bottom-start', onDismiss: close }}>
14
+ *
15
+ * Animation: entrance fade + 2px rise, var(--motion-glide) var(--motion-fast).
16
+ * Exit is handled by the caller removing the element from the DOM.
17
+ * Reduced-motion guard: animation is skipped when the user prefers reduced motion.
18
+ *
19
+ * Dismiss:
20
+ * - Click outside the floating element fires onDismiss
21
+ * - Escape key fires onDismiss
22
+ * - Focus returns to the anchor element (or document.activeElement before mount)
23
+ * when the floating element is dismissed
24
+ *
25
+ * Accessibility:
26
+ * - The node must already carry role="menu" / role="listbox" etc. — this action
27
+ * does not set ARIA roles.
28
+ */
29
+ var __assign = (this && this.__assign) || function () {
30
+ __assign = Object.assign || function(t) {
31
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
32
+ s = arguments[i];
33
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
34
+ t[p] = s[p];
35
+ }
36
+ return t;
37
+ };
38
+ return __assign.apply(this, arguments);
39
+ };
40
+ import { computePosition, autoUpdate, flip, shift, offset as fuOffset } from '@floating-ui/dom';
41
+ /**
42
+ * Create a virtual anchor from a viewport point (e.g. cursor coordinates).
43
+ * Pass the returned object as `anchor` when there is no real DOM element to anchor to.
44
+ */
45
+ export function makeVirtualAnchor(x, y) {
46
+ return {
47
+ getBoundingClientRect: function () {
48
+ return {
49
+ width: 0,
50
+ height: 0,
51
+ x: x,
52
+ y: y,
53
+ top: y,
54
+ left: x,
55
+ right: x,
56
+ bottom: y,
57
+ toJSON: function () { return this; }
58
+ };
59
+ }
60
+ };
61
+ }
62
+ function prefersReducedMotion() {
63
+ return typeof window !== 'undefined' &&
64
+ window.matchMedia('(prefers-reduced-motion: reduce)').matches;
65
+ }
66
+ export function floating(node, options) {
67
+ var opts = __assign({ placement: 'bottom-start', flip: true, shift: true, offset: 4 }, options);
68
+ var cleanup = null;
69
+ // Remember the element focused before this floating opened so we can return focus on dismiss.
70
+ var returnFocusTarget = document.activeElement;
71
+ // Entrance animation
72
+ node.style.opacity = '0';
73
+ node.style.transform = 'translateY(2px)';
74
+ node.style.transition = prefersReducedMotion()
75
+ ? 'none'
76
+ : [
77
+ "opacity var(--motion-fast, 150ms) var(--motion-glide, cubic-bezier(0.16,1,0.3,1))",
78
+ "transform var(--motion-fast, 150ms) var(--motion-glide, cubic-bezier(0.16,1,0.3,1))"
79
+ ].join(', ');
80
+ function applyPosition() {
81
+ if (!opts.anchor)
82
+ return;
83
+ var middlewares = [];
84
+ if (opts.offset != null)
85
+ middlewares.push(fuOffset(opts.offset));
86
+ if (opts.flip)
87
+ middlewares.push(flip());
88
+ if (opts.shift)
89
+ middlewares.push(shift({ padding: 8 }));
90
+ computePosition(opts.anchor, node, {
91
+ placement: opts.placement,
92
+ strategy: 'fixed',
93
+ middleware: middlewares,
94
+ }).then(function (_a) {
95
+ var x = _a.x, y = _a.y;
96
+ node.style.position = 'fixed';
97
+ node.style.left = "".concat(x, "px");
98
+ node.style.top = "".concat(y, "px");
99
+ });
100
+ }
101
+ function startAutoUpdate() {
102
+ cleanup === null || cleanup === void 0 ? void 0 : cleanup();
103
+ cleanup = null;
104
+ if (!opts.anchor)
105
+ return;
106
+ // For virtual anchors (plain objects), autoUpdate won't observe DOM mutations
107
+ // on the reference. That's fine — the caller re-runs update() when coords change.
108
+ var isVirtual = !('nodeType' in opts.anchor);
109
+ if (isVirtual) {
110
+ applyPosition();
111
+ return;
112
+ }
113
+ cleanup = autoUpdate(opts.anchor, node, applyPosition);
114
+ }
115
+ function handleOutsidePointer(e) {
116
+ var _a;
117
+ if (!node.contains(e.target)) {
118
+ (_a = opts.onDismiss) === null || _a === void 0 ? void 0 : _a.call(opts);
119
+ }
120
+ }
121
+ function handleKeydown(e) {
122
+ var _a;
123
+ if (e.key === 'Escape') {
124
+ (_a = opts.onDismiss) === null || _a === void 0 ? void 0 : _a.call(opts);
125
+ }
126
+ }
127
+ function returnFocus() {
128
+ if (returnFocusTarget && typeof returnFocusTarget.focus === 'function') {
129
+ returnFocusTarget.focus();
130
+ }
131
+ }
132
+ startAutoUpdate();
133
+ // Animate in after first position has been applied (next microtask)
134
+ requestAnimationFrame(function () {
135
+ node.style.opacity = '1';
136
+ node.style.transform = 'translateY(0)';
137
+ });
138
+ // Defer outside-pointer listeners to avoid catching the opening event itself
139
+ var listenerTimer = setTimeout(function () {
140
+ document.addEventListener('click', handleOutsidePointer, true);
141
+ document.addEventListener('contextmenu', handleOutsidePointer, true);
142
+ }, 0);
143
+ document.addEventListener('keydown', handleKeydown);
144
+ return {
145
+ update: function (next) {
146
+ opts = __assign({ placement: 'bottom-start', flip: true, shift: true, offset: 4 }, next);
147
+ startAutoUpdate();
148
+ },
149
+ destroy: function () {
150
+ clearTimeout(listenerTimer);
151
+ cleanup === null || cleanup === void 0 ? void 0 : cleanup();
152
+ document.removeEventListener('click', handleOutsidePointer, true);
153
+ document.removeEventListener('contextmenu', handleOutsidePointer, true);
154
+ document.removeEventListener('keydown', handleKeydown);
155
+ returnFocus();
156
+ }
157
+ };
158
+ }