@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.
- package/CLAUDE.md +22 -0
- package/dist/actions/attention.d.ts +24 -0
- package/dist/actions/attention.js +94 -0
- package/dist/actions/collapse.js +29 -15
- package/dist/actions/floating.d.ts +53 -0
- package/dist/actions/floating.js +158 -0
- package/dist/actions/listNav.js +137 -108
- package/dist/actions/railNav.js +89 -72
- package/dist/actions/staggerEntrance.d.ts +28 -0
- package/dist/actions/staggerEntrance.js +71 -0
- package/dist/actions/tooltip.d.ts +28 -0
- package/dist/actions/tooltip.js +186 -0
- package/dist/assets/sounds/README.md +47 -0
- package/dist/assets/sounds/error.d.ts +1 -0
- package/dist/assets/sounds/error.js +4 -0
- package/dist/assets/sounds/notify.d.ts +1 -0
- package/dist/assets/sounds/notify.js +4 -0
- package/dist/assets/sounds/pop.d.ts +1 -0
- package/dist/assets/sounds/pop.js +4 -0
- package/dist/assets/sounds/send.d.ts +1 -0
- package/dist/assets/sounds/send.js +4 -0
- package/dist/assets/sounds/success.d.ts +1 -0
- package/dist/assets/sounds/success.js +4 -0
- package/dist/assets/sounds/toggle.d.ts +1 -0
- package/dist/assets/sounds/toggle.js +4 -0
- package/dist/components/AnimatedNumber.svelte +112 -0
- package/dist/components/AnimatedNumber.svelte.d.ts +8 -0
- package/dist/components/Badge.svelte +75 -4
- package/dist/components/Badge.svelte.d.ts +6 -1
- package/dist/components/Button.svelte +196 -21
- package/dist/components/Button.svelte.d.ts +10 -1
- package/dist/components/Carousel.svelte +265 -0
- package/dist/components/Carousel.svelte.d.ts +21 -0
- package/dist/components/ChipInput.svelte +63 -3
- package/dist/components/Collapse.svelte +70 -14
- package/dist/components/Collapse.svelte.d.ts +11 -0
- package/dist/components/ColorSelector.svelte +21 -24
- package/dist/components/CommandPalette.svelte +475 -0
- package/dist/components/CommandPalette.svelte.d.ts +3 -0
- package/dist/components/ContextMenu.svelte +9 -73
- package/dist/components/CopyButton.svelte +156 -0
- package/dist/components/CopyButton.svelte.d.ts +12 -0
- package/dist/components/HoldToConfirm.svelte +183 -0
- package/dist/components/HoldToConfirm.svelte.d.ts +11 -0
- package/dist/components/KeyboardShortcutsOverlay.svelte +54 -8
- package/dist/components/KeyboardShortcutsOverlay.svelte.d.ts +3 -0
- package/dist/components/PasswordMeter.svelte +87 -0
- package/dist/components/PasswordMeter.svelte.d.ts +8 -0
- package/dist/components/PinInput.svelte +186 -0
- package/dist/components/PinInput.svelte.d.ts +13 -0
- package/dist/components/QuantityStepper.svelte +185 -0
- package/dist/components/QuantityStepper.svelte.d.ts +12 -0
- package/dist/components/Skeleton.svelte +123 -0
- package/dist/components/Skeleton.svelte.d.ts +12 -0
- package/dist/components/SpeechForm.svelte +37 -0
- package/dist/components/StatusBadge.svelte +31 -3
- package/dist/components/StatusBadge.svelte.d.ts +0 -5
- package/dist/components/Tabs.svelte +270 -0
- package/dist/components/Tabs.svelte.d.ts +15 -0
- package/dist/components/TextInput.svelte +138 -38
- package/dist/components/TextInput.svelte.d.ts +9 -1
- package/dist/components/VoicePlayer.svelte +51 -0
- package/dist/components/basic/Alert.svelte +36 -0
- package/dist/components/basic/Alert.svelte.d.ts +9 -0
- package/dist/components/basic/Breadcrumb.svelte +27 -0
- package/dist/components/basic/Breadcrumb.svelte.d.ts +11 -0
- package/dist/components/basic/ButtonGroup.svelte +15 -0
- package/dist/components/basic/ButtonGroup.svelte.d.ts +8 -0
- package/dist/components/basic/Checkbox.svelte +85 -0
- package/dist/components/basic/Checkbox.svelte.d.ts +15 -0
- package/dist/components/basic/Empty.svelte +17 -0
- package/dist/components/basic/Empty.svelte.d.ts +8 -0
- package/dist/components/basic/Kbd.svelte +16 -0
- package/dist/components/basic/Kbd.svelte.d.ts +8 -0
- package/dist/components/basic/Pagination.svelte +104 -0
- package/dist/components/basic/Pagination.svelte.d.ts +12 -0
- package/dist/components/basic/RadioGroup.svelte +71 -0
- package/dist/components/basic/RadioGroup.svelte.d.ts +18 -0
- package/dist/components/basic/Separator.svelte +19 -0
- package/dist/components/basic/Separator.svelte.d.ts +8 -0
- package/dist/components/basic/Slider.svelte +72 -0
- package/dist/components/basic/Slider.svelte.d.ts +17 -0
- package/dist/components/basic/Switch.svelte +88 -0
- package/dist/components/basic/Switch.svelte.d.ts +14 -0
- package/dist/components/basic/Toggle.svelte +43 -0
- package/dist/components/basic/Toggle.svelte.d.ts +14 -0
- package/dist/components/graph/GraphCanvas.svelte +103 -0
- package/dist/components/graph/GraphCanvas.svelte.d.ts +22 -0
- package/dist/components/graph/JatuiNode.svelte +128 -0
- package/dist/components/graph/JatuiNode.svelte.d.ts +14 -0
- package/dist/components/graph/theme.d.ts +27 -0
- package/dist/components/graph/theme.js +136 -0
- package/dist/components/markup.js +62 -59
- package/dist/components/messaging/MessageItem.svelte +92 -0
- package/dist/components/messaging/MessageItem.svelte.d.ts +5 -0
- package/dist/components/messaging/TypingIndicator.svelte +63 -0
- package/dist/components/messaging/TypingIndicator.svelte.d.ts +7 -0
- package/dist/components/pipeline/PipelineColumn.svelte +44 -3
- package/dist/components/progress/ProgressBar.svelte +189 -0
- package/dist/components/progress/ProgressBar.svelte.d.ts +17 -0
- package/dist/components/progress/ProgressRing.svelte +138 -0
- package/dist/components/progress/ProgressRing.svelte.d.ts +12 -0
- package/dist/components/progress/Steps.svelte +195 -0
- package/dist/components/progress/Steps.svelte.d.ts +14 -0
- package/dist/components/session-nav/transcriptModel.js +66 -49
- package/dist/components/shell/NavigationMenu.svelte +422 -0
- package/dist/components/shell/NavigationMenu.svelte.d.ts +43 -0
- package/dist/components/shell/Sidebar.svelte +276 -0
- package/dist/components/shell/Sidebar.svelte.d.ts +32 -0
- package/dist/components/shell/SidebarGroup.svelte +180 -0
- package/dist/components/shell/SidebarGroup.svelte.d.ts +19 -0
- package/dist/components/shell/SidebarItem.svelte +170 -0
- package/dist/components/shell/SidebarItem.svelte.d.ts +24 -0
- package/dist/components/shell/shell.d.ts +30 -0
- package/dist/components/shell/shell.js +65 -0
- package/dist/components/table/DataTable.svelte +364 -0
- package/dist/components/table/DataTable.svelte.d.ts +4 -0
- package/dist/components/table/flexRender.d.ts +31 -0
- package/dist/components/table/flexRender.js +32 -0
- package/dist/components/table/types.d.ts +28 -0
- package/dist/components/table/types.js +1 -0
- package/dist/components/toast/ToastHost.svelte +21 -0
- package/dist/components/toast/ToastHost.svelte.d.ts +3 -0
- package/dist/components/toast/ToastItem.svelte +287 -0
- package/dist/components/toast/ToastItem.svelte.d.ts +9 -0
- package/dist/data/emojis.js +4 -4
- package/dist/dnd/autoScroll.js +12 -10
- package/dist/dnd/createDndBoard.svelte.js +110 -76
- package/dist/dnd/createDndBoard.test.js +161 -85
- package/dist/dnd/draggable.js +23 -15
- package/dist/dnd/dropTarget.js +29 -15
- package/dist/dnd/index.d.ts +0 -1
- package/dist/dnd/index.js +0 -1
- package/dist/dnd/types.d.ts +0 -9
- package/dist/dnd/types.js +14 -2
- package/dist/index.d.ts +60 -6
- package/dist/index.js +73 -6
- package/dist/showcase/AnimatedBeam.svelte +183 -0
- package/dist/showcase/AnimatedBeam.svelte.d.ts +26 -0
- package/dist/showcase/AuroraDrift.svelte +74 -0
- package/dist/showcase/AuroraDrift.svelte.d.ts +9 -0
- package/dist/showcase/BentoCard.svelte +50 -0
- package/dist/showcase/BentoCard.svelte.d.ts +14 -0
- package/dist/showcase/BentoGrid.svelte +43 -0
- package/dist/showcase/BentoGrid.svelte.d.ts +12 -0
- package/dist/showcase/BorderBeam.svelte +79 -0
- package/dist/showcase/BorderBeam.svelte.d.ts +12 -0
- package/dist/showcase/ClipWipe.svelte +82 -0
- package/dist/showcase/ClipWipe.svelte.d.ts +12 -0
- package/dist/showcase/Confetti.svelte +71 -0
- package/dist/showcase/Confetti.svelte.d.ts +10 -0
- package/dist/showcase/CursorSpotlight.svelte +85 -0
- package/dist/showcase/CursorSpotlight.svelte.d.ts +9 -0
- package/dist/showcase/DeviceMock.svelte +186 -0
- package/dist/showcase/DeviceMock.svelte.d.ts +11 -0
- package/dist/showcase/Dock.svelte +123 -0
- package/dist/showcase/Dock.svelte.d.ts +17 -0
- package/dist/showcase/FlipCard.svelte +103 -0
- package/dist/showcase/FlipCard.svelte.d.ts +10 -0
- package/dist/showcase/FocusReveal.svelte +83 -0
- package/dist/showcase/FocusReveal.svelte.d.ts +11 -0
- package/dist/showcase/Globe.svelte +202 -0
- package/dist/showcase/Globe.svelte.d.ts +16 -0
- package/dist/showcase/KenBurns.svelte +105 -0
- package/dist/showcase/KenBurns.svelte.d.ts +13 -0
- package/dist/showcase/Marquee.svelte +89 -0
- package/dist/showcase/Marquee.svelte.d.ts +9 -0
- package/dist/showcase/ParallaxTilt.svelte +98 -0
- package/dist/showcase/ParallaxTilt.svelte.d.ts +10 -0
- package/dist/showcase/ScrambleText.svelte +98 -0
- package/dist/showcase/ScrambleText.svelte.d.ts +11 -0
- package/dist/showcase/ShineSweep.svelte +81 -0
- package/dist/showcase/ShineSweep.svelte.d.ts +9 -0
- package/dist/showcase/Terminal.svelte +230 -0
- package/dist/showcase/Terminal.svelte.d.ts +18 -0
- package/dist/showcase/TextSplitReveal.svelte +146 -0
- package/dist/showcase/TextSplitReveal.svelte.d.ts +13 -0
- package/dist/showcase/TextWave.svelte +55 -0
- package/dist/showcase/TextWave.svelte.d.ts +8 -0
- package/dist/showcase/TypewriterText.svelte +130 -0
- package/dist/showcase/TypewriterText.svelte.d.ts +9 -0
- package/dist/showcase/backdrop/GrainGradient.svelte +126 -0
- package/dist/showcase/backdrop/GrainGradient.svelte.d.ts +23 -0
- package/dist/showcase/backdrop/MeshGradient.svelte +104 -0
- package/dist/showcase/backdrop/MeshGradient.svelte.d.ts +20 -0
- package/dist/showcase/backdrop/Metaballs.svelte +116 -0
- package/dist/showcase/backdrop/Metaballs.svelte.d.ts +18 -0
- package/dist/showcase/backdrop/NeuroNoise.svelte +115 -0
- package/dist/showcase/backdrop/NeuroNoise.svelte.d.ts +20 -0
- package/dist/showcase/backdrop/ShowcaseBackdrop.svelte +48 -0
- package/dist/showcase/backdrop/ShowcaseBackdrop.svelte.d.ts +12 -0
- package/dist/showcase/generative/GenerativeBackdrop.svelte +234 -0
- package/dist/showcase/generative/GenerativeBackdrop.svelte.d.ts +9 -0
- package/dist/showcase/generative/intent.d.ts +7 -0
- package/dist/showcase/generative/intent.js +67 -0
- package/dist/showcase/generative/manifest.d.ts +9 -0
- package/dist/showcase/generative/manifest.js +97 -0
- package/dist/showcase/generative/types.d.ts +48 -0
- package/dist/showcase/generative/types.js +8 -0
- package/dist/showcase/index.d.ts +36 -0
- package/dist/showcase/index.js +46 -0
- package/dist/showcase/scroll/SmoothScroll.svelte +49 -0
- package/dist/showcase/scroll/SmoothScroll.svelte.d.ts +12 -0
- package/dist/showcase/scroll/scrollProgress.d.ts +24 -0
- package/dist/showcase/scroll/scrollProgress.js +65 -0
- package/dist/showcase/scroll/scrollReveal.d.ts +30 -0
- package/dist/showcase/scroll/scrollReveal.js +70 -0
- package/dist/stores/commandPalette.svelte.d.ts +24 -0
- package/dist/stores/commandPalette.svelte.js +82 -0
- package/dist/stores/confirmDialog.svelte.js +5 -5
- package/dist/stores/inputDialog.svelte.js +5 -5
- package/dist/stores/toast.svelte.d.ts +28 -0
- package/dist/stores/toast.svelte.js +33 -0
- package/dist/styles/motion.css +46 -0
- package/dist/styles/tokens.css +31 -0
- package/dist/transitions/glide.d.ts +31 -0
- package/dist/transitions/glide.js +58 -0
- package/dist/types/booking.js +4 -4
- package/dist/types/comments.js +2 -2
- package/dist/types/messaging.js +3 -3
- package/dist/types/pipeline.js +2 -2
- package/dist/utils/currency.js +4 -2
- package/dist/utils/daisyuiColors.js +27 -25
- package/dist/utils/dateFormatters.d.ts +20 -0
- package/dist/utils/dateFormatters.js +65 -44
- package/dist/utils/googleMapsLoader.js +100 -46
- package/dist/utils/mentionParser.js +30 -30
- package/dist/utils/phone.js +27 -21
- package/dist/utils/phoneFormat.js +9 -9
- package/dist/utils/sound.d.ts +6 -0
- package/dist/utils/sound.js +113 -0
- package/dist/utils/splitText.d.ts +25 -0
- package/dist/utils/splitText.js +94 -0
- package/dist/utils/taskUtils.js +1 -1
- package/dist/utils/themeWipe.d.ts +21 -0
- package/dist/utils/themeWipe.js +94 -0
- package/dist/utils/viewTransition.d.ts +23 -0
- package/dist/utils/viewTransition.js +75 -0
- 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
|
+
}
|
package/dist/actions/collapse.js
CHANGED
|
@@ -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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
|
80
|
+
return "linear-gradient(to bottom, black ".concat(opts.fadeStart, "%, transparent 100%)");
|
|
69
81
|
}
|
|
70
82
|
function apply() {
|
|
71
|
-
|
|
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 =
|
|
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
|
-
|
|
103
|
+
var next = node.scrollHeight > opts.threshold + opts.epsilon;
|
|
91
104
|
if (next !== collapsible) {
|
|
92
105
|
collapsible = next;
|
|
93
|
-
opts.onCollapsible
|
|
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
|
-
|
|
115
|
+
var ro = new ResizeObserver(scheduleMeasure);
|
|
103
116
|
ro.observe(node);
|
|
104
117
|
scheduleMeasure();
|
|
105
118
|
return {
|
|
106
|
-
update(next
|
|
107
|
-
|
|
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
|
+
}
|