motionary 7.2.0 → 7.4.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 (62) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/chunks/builtins-HlqAkK0f.js +99 -0
  3. package/dist/chunks/builtins-HlqAkK0f.js.map +1 -0
  4. package/dist/chunks/builtins-xalxV2d5.cjs +101 -0
  5. package/dist/chunks/builtins-xalxV2d5.cjs.map +1 -0
  6. package/dist/components/angular.cjs +1 -0
  7. package/dist/components/angular.cjs.map +1 -1
  8. package/dist/components/angular.js +1 -0
  9. package/dist/components/angular.js.map +1 -1
  10. package/dist/components/effects.cjs +1 -0
  11. package/dist/components/effects.cjs.map +1 -1
  12. package/dist/components/effects.js +1 -0
  13. package/dist/components/effects.js.map +1 -1
  14. package/dist/components/fx-shop.cjs +133 -0
  15. package/dist/components/fx-shop.cjs.map +1 -0
  16. package/dist/components/fx-shop.d.cts +70 -0
  17. package/dist/components/fx-shop.d.ts +70 -0
  18. package/dist/components/fx-shop.js +129 -0
  19. package/dist/components/fx-shop.js.map +1 -0
  20. package/dist/components/fx-social.cjs +121 -0
  21. package/dist/components/fx-social.cjs.map +1 -0
  22. package/dist/components/fx-social.d.cts +66 -0
  23. package/dist/components/fx-social.d.ts +66 -0
  24. package/dist/components/fx-social.js +117 -0
  25. package/dist/components/fx-social.js.map +1 -0
  26. package/dist/components/fx.cjs +5 -98
  27. package/dist/components/fx.cjs.map +1 -1
  28. package/dist/components/fx.js +3 -96
  29. package/dist/components/fx.js.map +1 -1
  30. package/dist/components/fx2.cjs +12 -0
  31. package/dist/components/fx2.cjs.map +1 -1
  32. package/dist/components/fx2.d.cts +49 -1
  33. package/dist/components/fx2.d.ts +49 -1
  34. package/dist/components/fx2.js +9 -1
  35. package/dist/components/fx2.js.map +1 -1
  36. package/dist/components/solid.cjs +1 -0
  37. package/dist/components/solid.cjs.map +1 -1
  38. package/dist/components/solid.js +1 -0
  39. package/dist/components/solid.js.map +1 -1
  40. package/dist/components/svelte.cjs +1 -0
  41. package/dist/components/svelte.cjs.map +1 -1
  42. package/dist/components/svelte.js +1 -0
  43. package/dist/components/svelte.js.map +1 -1
  44. package/dist/components/vue.cjs +1 -0
  45. package/dist/components/vue.cjs.map +1 -1
  46. package/dist/components/vue.js +1 -0
  47. package/dist/components/vue.js.map +1 -1
  48. package/dist/components/widgets.cjs +887 -78
  49. package/dist/components/widgets.cjs.map +1 -1
  50. package/dist/components/widgets.d.cts +184 -2
  51. package/dist/components/widgets.d.ts +184 -2
  52. package/dist/components/widgets.js +874 -79
  53. package/dist/components/widgets.js.map +1 -1
  54. package/dist/components.cjs +2 -1
  55. package/dist/components.cjs.map +1 -1
  56. package/dist/components.js +2 -1
  57. package/dist/components.js.map +1 -1
  58. package/dist/widgets.umd.js +1 -1
  59. package/dist/widgets.umd.js.map +1 -1
  60. package/docs/ROADMAP.md +2 -2
  61. package/docs/components.md +50 -0
  62. package/package.json +41 -1
@@ -0,0 +1,66 @@
1
+ type MotionSensitivity = 'full' | 'gentle' | 'minimal' | 'static';
2
+ type Cleanup = () => void;
3
+
4
+ /**
5
+ * 5.0 — unified plugin-style effect registration. Every effect (built-in or
6
+ * yours) is a plain object registered once and played the same way:
7
+ * `playEffect(el, name)`, `bindEffect(el, name, { trigger })` or
8
+ * `<usa-fx effect="name" trigger="click">`. Effects get a context that
9
+ * already applies reduced motion, motion sensitivity, intensity and the
10
+ * animation budget.
11
+ */
12
+
13
+ declare const EFFECT_KINDS: readonly ["enter", "exit", "attention", "click", "hover", "card", "loop", "page", "background", "text", "cursor", "scroll"];
14
+ type EffectKind = (typeof EFFECT_KINDS)[number];
15
+ interface EffectContext {
16
+ /** Reduced motion applies (OS setting, `minimal` / `static` sensitivity). */
17
+ readonly reduced: boolean;
18
+ readonly sensitivity: MotionSensitivity;
19
+ /** The triggering event (pointer position for click effects), if any. */
20
+ readonly event?: Event;
21
+ /** `el.animate()` with the library's motion rules (may return `null`). */
22
+ animate(el: Element, keyframes: Keyframe[], options: KeyframeAnimationOptions): Animation | null;
23
+ /** Register teardown for long-running effects (loops, listeners). */
24
+ onCleanup(fn: Cleanup): void;
25
+ }
26
+ interface EffectDefinition<O extends Record<string, unknown> = Record<string, any>> {
27
+ /** Unique, kebab-case. */
28
+ name: string;
29
+ kind: EffectKind;
30
+ /** One line for docs and the gallery. */
31
+ description?: string;
32
+ /** Option defaults (merged under the caller's options). */
33
+ defaults?: Partial<O>;
34
+ /**
35
+ * Under reduced motion: `'skip'` (do nothing — default for loop, background
36
+ * and cursor effects) or `'run'` (run with `ctx.reduced === true`, the
37
+ * effect degrades itself — default for everything else).
38
+ */
39
+ reduced?: 'skip' | 'run';
40
+ /** Play the effect. Return an Animation / Promise to be awaited, or a cleanup. */
41
+ run(el: HTMLElement, options: O, ctx: EffectContext): void | Cleanup | Animation | null | Promise<unknown>;
42
+ }
43
+
44
+ /**
45
+ * 7.4 — Chat & social motion (`motionary/fx/social`, also
46
+ * `motionary/components/fx-social`):
47
+ *
48
+ * - `typing-dots` (loop) — three dots bounce in a wave inside the element.
49
+ * - `message-in` (enter) — a chat bubble pops in from its side (`side`
50
+ * "left" | "right", or `data-side`), with a little overshoot.
51
+ * - `reaction-burst` (click) — the element's emoji (`emoji`) floats up in a
52
+ * small fan and fades.
53
+ * - `read-receipt` (enter) — ✓✓ ticks draw in and turn blue (`color`).
54
+ * - `mention-glow` (attention) — a soft highlight sweeps behind an @mention.
55
+ *
56
+ * Reduced motion: typing-dots shows static dots, message-in / read-receipt
57
+ * fade, reaction-burst does nothing, mention-glow sets a static highlight.
58
+ */
59
+
60
+ /** Fan-out angles (deg) for `n` floating emoji, centred on straight up (7.4). */
61
+ declare function fanAngles(n: number, spread?: number): number[];
62
+ declare const SOCIAL_FX: EffectDefinition[];
63
+ /** Register the 7.4 chat & social pack (idempotent). */
64
+ declare function registerSocialPack(): void;
65
+
66
+ export { SOCIAL_FX, fanAngles, registerSocialPack };
@@ -0,0 +1,66 @@
1
+ type MotionSensitivity = 'full' | 'gentle' | 'minimal' | 'static';
2
+ type Cleanup = () => void;
3
+
4
+ /**
5
+ * 5.0 — unified plugin-style effect registration. Every effect (built-in or
6
+ * yours) is a plain object registered once and played the same way:
7
+ * `playEffect(el, name)`, `bindEffect(el, name, { trigger })` or
8
+ * `<usa-fx effect="name" trigger="click">`. Effects get a context that
9
+ * already applies reduced motion, motion sensitivity, intensity and the
10
+ * animation budget.
11
+ */
12
+
13
+ declare const EFFECT_KINDS: readonly ["enter", "exit", "attention", "click", "hover", "card", "loop", "page", "background", "text", "cursor", "scroll"];
14
+ type EffectKind = (typeof EFFECT_KINDS)[number];
15
+ interface EffectContext {
16
+ /** Reduced motion applies (OS setting, `minimal` / `static` sensitivity). */
17
+ readonly reduced: boolean;
18
+ readonly sensitivity: MotionSensitivity;
19
+ /** The triggering event (pointer position for click effects), if any. */
20
+ readonly event?: Event;
21
+ /** `el.animate()` with the library's motion rules (may return `null`). */
22
+ animate(el: Element, keyframes: Keyframe[], options: KeyframeAnimationOptions): Animation | null;
23
+ /** Register teardown for long-running effects (loops, listeners). */
24
+ onCleanup(fn: Cleanup): void;
25
+ }
26
+ interface EffectDefinition<O extends Record<string, unknown> = Record<string, any>> {
27
+ /** Unique, kebab-case. */
28
+ name: string;
29
+ kind: EffectKind;
30
+ /** One line for docs and the gallery. */
31
+ description?: string;
32
+ /** Option defaults (merged under the caller's options). */
33
+ defaults?: Partial<O>;
34
+ /**
35
+ * Under reduced motion: `'skip'` (do nothing — default for loop, background
36
+ * and cursor effects) or `'run'` (run with `ctx.reduced === true`, the
37
+ * effect degrades itself — default for everything else).
38
+ */
39
+ reduced?: 'skip' | 'run';
40
+ /** Play the effect. Return an Animation / Promise to be awaited, or a cleanup. */
41
+ run(el: HTMLElement, options: O, ctx: EffectContext): void | Cleanup | Animation | null | Promise<unknown>;
42
+ }
43
+
44
+ /**
45
+ * 7.4 — Chat & social motion (`motionary/fx/social`, also
46
+ * `motionary/components/fx-social`):
47
+ *
48
+ * - `typing-dots` (loop) — three dots bounce in a wave inside the element.
49
+ * - `message-in` (enter) — a chat bubble pops in from its side (`side`
50
+ * "left" | "right", or `data-side`), with a little overshoot.
51
+ * - `reaction-burst` (click) — the element's emoji (`emoji`) floats up in a
52
+ * small fan and fades.
53
+ * - `read-receipt` (enter) — ✓✓ ticks draw in and turn blue (`color`).
54
+ * - `mention-glow` (attention) — a soft highlight sweeps behind an @mention.
55
+ *
56
+ * Reduced motion: typing-dots shows static dots, message-in / read-receipt
57
+ * fade, reaction-burst does nothing, mention-glow sets a static highlight.
58
+ */
59
+
60
+ /** Fan-out angles (deg) for `n` floating emoji, centred on straight up (7.4). */
61
+ declare function fanAngles(n: number, spread?: number): number[];
62
+ declare const SOCIAL_FX: EffectDefinition[];
63
+ /** Register the 7.4 chat & social pack (idempotent). */
64
+ declare function registerSocialPack(): void;
65
+
66
+ export { SOCIAL_FX, fanAngles, registerSocialPack };
@@ -0,0 +1,117 @@
1
+ import { registerEffects } from '../chunks/registry-CyKExAmE.js';
2
+ import '../chunks/base-2-yYc93C.js';
3
+
4
+ /** Fan-out angles (deg) for `n` floating emoji, centred on straight up (7.4). */
5
+ function fanAngles(n, spread = 60) {
6
+ if (n <= 1)
7
+ return [0];
8
+ return Array.from({ length: n }, (_, i) => Math.round(-spread / 2 + (spread * i) / (n - 1)));
9
+ }
10
+ const span = (cls, text = '') => {
11
+ const s = document.createElement('span');
12
+ s.className = cls;
13
+ s.setAttribute('aria-hidden', 'true');
14
+ s.textContent = text;
15
+ return s;
16
+ };
17
+ const SOCIAL_FX = [
18
+ {
19
+ name: 'typing-dots',
20
+ kind: 'loop',
21
+ description: 'Three dots bounce in a wave inside the element — the “is typing…” indicator (`color`, `period`).',
22
+ defaults: { color: 'currentColor', period: 1100 },
23
+ run: (el, o, ctx) => {
24
+ const box = span('usa-fx-typing');
25
+ Object.assign(box.style, { display: 'inline-flex', gap: '4px', alignItems: 'center', padding: '2px 0' });
26
+ const dots = [0, 1, 2].map(() => {
27
+ const d = span('');
28
+ Object.assign(d.style, { width: '7px', height: '7px', borderRadius: '50%', background: o.color, opacity: '.6', display: 'inline-block' });
29
+ box.appendChild(d);
30
+ return d;
31
+ });
32
+ el.appendChild(box);
33
+ const anims = ctx.reduced ? [] : dots.map((d, i) => ctx.animate(d, [{ transform: 'translateY(0)', opacity: 0.4 }, { transform: 'translateY(-5px)', opacity: 1, offset: 0.3 }, { transform: 'translateY(0)', opacity: 0.4, offset: 0.6 }, { transform: 'translateY(0)', opacity: 0.4 }], { duration: o.period, delay: (i * o.period) / 6, iterations: Infinity }));
34
+ const stop = () => (anims.forEach((a) => a?.cancel()), box.remove());
35
+ ctx.onCleanup(stop);
36
+ return stop;
37
+ },
38
+ },
39
+ {
40
+ name: 'message-in',
41
+ kind: 'enter',
42
+ description: 'A chat bubble pops in from its side (`side` left | right, or `data-side`) with a small overshoot (`duration`).',
43
+ defaults: { side: '', duration: 420 },
44
+ run: (el, o, ctx) => {
45
+ const side = o.side || el.dataset.side || 'left';
46
+ if (ctx.reduced)
47
+ return ctx.animate(el, [{ opacity: 0 }, { opacity: 1 }], { duration: 200 })?.finished.catch(() => undefined);
48
+ el.style.transformOrigin = side === 'right' ? '100% 100%' : '0 100%';
49
+ return ctx.animate(el, [{ transform: `translateX(${side === 'right' ? 24 : -24}px) scale(.6)`, opacity: 0 }, { transform: 'scale(1.04)', opacity: 1, offset: 0.65 }, { transform: 'none', opacity: 1 }], { duration: o.duration, easing: 'cubic-bezier(.2,.9,.3,1)' })?.finished.catch(() => undefined);
50
+ },
51
+ },
52
+ {
53
+ name: 'reaction-burst',
54
+ kind: 'click',
55
+ description: 'The reaction emoji (`emoji`, default the element text) floats up in a small fan and fades (`count`, `spread`).',
56
+ defaults: { emoji: '', count: 5, spread: 70, duration: 900 },
57
+ reduced: 'skip',
58
+ run: (el, o, ctx) => {
59
+ const r = el.getBoundingClientRect();
60
+ const emo = o.emoji || (el.textContent || '❤️').trim().slice(0, 2) || '❤️';
61
+ const parts = fanAngles(o.count, o.spread).map((deg, i) => {
62
+ const s = span('', emo);
63
+ Object.assign(s.style, { position: 'fixed', left: `${r.left + r.width / 2 - 10}px`, top: `${r.top}px`, fontSize: '20px', pointerEvents: 'none', zIndex: '2147483000' });
64
+ document.body.appendChild(s);
65
+ const rad = (deg * Math.PI) / 180;
66
+ const dist = 50 + (i % 2) * 18;
67
+ const a = ctx.animate(s, [{ transform: 'translate(0,0) scale(.4)', opacity: 0 }, { transform: `translate(${(Math.sin(rad) * dist * 0.5).toFixed(1)}px,${(-dist * 0.5).toFixed(1)}px) scale(1.1)`, opacity: 1, offset: 0.3 }, { transform: `translate(${(Math.sin(rad) * dist).toFixed(1)}px,${(-Math.cos(rad) * dist - 20).toFixed(1)}px) scale(.9)`, opacity: 0 }], { duration: o.duration, delay: i * 40, easing: 'ease-out' });
68
+ const end = () => s.remove();
69
+ if (a)
70
+ a.finished.then(end, end);
71
+ else
72
+ end();
73
+ ctx.onCleanup(end);
74
+ return a;
75
+ });
76
+ return Promise.all(parts.map((a) => a?.finished.catch(() => undefined)));
77
+ },
78
+ },
79
+ {
80
+ name: 'read-receipt',
81
+ kind: 'enter',
82
+ description: '✓✓ ticks draw in one after the other and turn `color` (blue) — “seen” (`color`).',
83
+ defaults: { color: '#3b82f6', duration: 600 },
84
+ run: (el, o, ctx) => {
85
+ let t = el.querySelector('.usa-fx-ticks');
86
+ if (!t) {
87
+ t = span('usa-fx-ticks', '✓✓');
88
+ Object.assign(t.style, { display: 'inline-block', marginLeft: '4px', letterSpacing: '-4px', fontWeight: '700' });
89
+ el.appendChild(t);
90
+ }
91
+ if (ctx.reduced)
92
+ return void (t.style.color = o.color);
93
+ return ctx.animate(t, [{ clipPath: 'inset(0 100% 0 0)', color: 'currentColor' }, { clipPath: 'inset(0 0 0 0)', color: 'currentColor', offset: 0.6 }, { clipPath: 'inset(0 0 0 0)', color: o.color }], { duration: o.duration, easing: 'ease-out', fill: 'forwards' })?.finished.catch(() => undefined);
94
+ },
95
+ },
96
+ {
97
+ name: 'mention-glow',
98
+ kind: 'attention',
99
+ description: 'A soft highlight sweeps in behind an @mention, then settles (`color`).',
100
+ defaults: { color: 'rgba(250,204,21,.45)', duration: 900 },
101
+ run: (el, o, ctx) => {
102
+ el.style.backgroundImage = `linear-gradient(${o.color},${o.color})`;
103
+ el.style.backgroundRepeat = 'no-repeat';
104
+ el.style.borderRadius = el.style.borderRadius || '4px';
105
+ if (ctx.reduced)
106
+ return void (el.style.backgroundSize = '100% 100%');
107
+ return ctx.animate(el, [{ backgroundSize: '0% 100%' }, { backgroundSize: '100% 100%' }], { duration: o.duration, easing: 'cubic-bezier(.3,.8,.3,1)', fill: 'forwards' })?.finished.catch(() => undefined);
108
+ },
109
+ },
110
+ ];
111
+ /** Register the 7.4 chat & social pack (idempotent). */
112
+ function registerSocialPack() {
113
+ registerEffects(SOCIAL_FX);
114
+ }
115
+
116
+ export { SOCIAL_FX, fanAngles, registerSocialPack };
117
+ //# sourceMappingURL=fx-social.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fx-social.js","sources":["../../src/components/fx2/social.ts"],"sourcesContent":["/**\n * 7.4 — Chat & social motion (`motionary/fx/social`, also\n * `motionary/components/fx-social`):\n *\n * - `typing-dots` (loop) — three dots bounce in a wave inside the element.\n * - `message-in` (enter) — a chat bubble pops in from its side (`side`\n * \"left\" | \"right\", or `data-side`), with a little overshoot.\n * - `reaction-burst` (click) — the element's emoji (`emoji`) floats up in a\n * small fan and fades.\n * - `read-receipt` (enter) — ✓✓ ticks draw in and turn blue (`color`).\n * - `mention-glow` (attention) — a soft highlight sweeps behind an @mention.\n *\n * Reduced motion: typing-dots shows static dots, message-in / read-receipt\n * fade, reaction-burst does nothing, mention-glow sets a static highlight.\n */\nimport type { EffectContext, EffectDefinition } from '../fx/registry';\nimport { registerEffects } from '../fx/registry';\n\n/** Fan-out angles (deg) for `n` floating emoji, centred on straight up (7.4). */\nexport function fanAngles(n: number, spread = 60): number[] {\n if (n <= 1) return [0];\n return Array.from({ length: n }, (_, i) => Math.round(-spread / 2 + (spread * i) / (n - 1)));\n}\n\nconst span = (cls: string, text = ''): HTMLSpanElement => {\n const s = document.createElement('span');\n s.className = cls;\n s.setAttribute('aria-hidden', 'true');\n s.textContent = text;\n return s;\n};\n\nexport const SOCIAL_FX: EffectDefinition[] = [\n {\n name: 'typing-dots',\n kind: 'loop',\n description: 'Three dots bounce in a wave inside the element — the “is typing…” indicator (`color`, `period`).',\n defaults: { color: 'currentColor', period: 1100 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n const box = span('usa-fx-typing');\n Object.assign(box.style, { display: 'inline-flex', gap: '4px', alignItems: 'center', padding: '2px 0' });\n const dots = [0, 1, 2].map(() => {\n const d = span('');\n Object.assign(d.style, { width: '7px', height: '7px', borderRadius: '50%', background: o.color, opacity: '.6', display: 'inline-block' });\n box.appendChild(d);\n return d;\n });\n el.appendChild(box);\n const anims = ctx.reduced ? [] : dots.map((d, i) => ctx.animate(d, [{ transform: 'translateY(0)', opacity: 0.4 }, { transform: 'translateY(-5px)', opacity: 1, offset: 0.3 }, { transform: 'translateY(0)', opacity: 0.4, offset: 0.6 }, { transform: 'translateY(0)', opacity: 0.4 }], { duration: o.period, delay: (i * o.period) / 6, iterations: Infinity }));\n const stop = () => (anims.forEach((a) => a?.cancel()), box.remove());\n ctx.onCleanup(stop);\n return stop;\n },\n },\n {\n name: 'message-in',\n kind: 'enter',\n description: 'A chat bubble pops in from its side (`side` left | right, or `data-side`) with a small overshoot (`duration`).',\n defaults: { side: '', duration: 420 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n const side = o.side || el.dataset.side || 'left';\n if (ctx.reduced) return ctx.animate(el, [{ opacity: 0 }, { opacity: 1 }], { duration: 200 })?.finished.catch(() => undefined);\n el.style.transformOrigin = side === 'right' ? '100% 100%' : '0 100%';\n return ctx.animate(el, [{ transform: `translateX(${side === 'right' ? 24 : -24}px) scale(.6)`, opacity: 0 }, { transform: 'scale(1.04)', opacity: 1, offset: 0.65 }, { transform: 'none', opacity: 1 }], { duration: o.duration, easing: 'cubic-bezier(.2,.9,.3,1)' })?.finished.catch(() => undefined);\n },\n },\n {\n name: 'reaction-burst',\n kind: 'click',\n description: 'The reaction emoji (`emoji`, default the element text) floats up in a small fan and fades (`count`, `spread`).',\n defaults: { emoji: '', count: 5, spread: 70, duration: 900 },\n reduced: 'skip',\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n const r = el.getBoundingClientRect();\n const emo = o.emoji || (el.textContent || '❤️').trim().slice(0, 2) || '❤️';\n const parts = fanAngles(o.count, o.spread).map((deg, i) => {\n const s = span('', emo);\n Object.assign(s.style, { position: 'fixed', left: `${r.left + r.width / 2 - 10}px`, top: `${r.top}px`, fontSize: '20px', pointerEvents: 'none', zIndex: '2147483000' });\n document.body.appendChild(s);\n const rad = (deg * Math.PI) / 180;\n const dist = 50 + (i % 2) * 18;\n const a = ctx.animate(s, [{ transform: 'translate(0,0) scale(.4)', opacity: 0 }, { transform: `translate(${(Math.sin(rad) * dist * 0.5).toFixed(1)}px,${(-dist * 0.5).toFixed(1)}px) scale(1.1)`, opacity: 1, offset: 0.3 }, { transform: `translate(${(Math.sin(rad) * dist).toFixed(1)}px,${(-Math.cos(rad) * dist - 20).toFixed(1)}px) scale(.9)`, opacity: 0 }], { duration: o.duration, delay: i * 40, easing: 'ease-out' });\n const end = () => s.remove();\n if (a) a.finished.then(end, end);\n else end();\n ctx.onCleanup(end);\n return a;\n });\n return Promise.all(parts.map((a) => a?.finished.catch(() => undefined)));\n },\n },\n {\n name: 'read-receipt',\n kind: 'enter',\n description: '✓✓ ticks draw in one after the other and turn `color` (blue) — “seen” (`color`).',\n defaults: { color: '#3b82f6', duration: 600 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n let t = el.querySelector('.usa-fx-ticks') as HTMLElement | null;\n if (!t) {\n t = span('usa-fx-ticks', '✓✓');\n Object.assign(t.style, { display: 'inline-block', marginLeft: '4px', letterSpacing: '-4px', fontWeight: '700' });\n el.appendChild(t);\n }\n if (ctx.reduced) return void (t.style.color = o.color);\n return ctx.animate(t, [{ clipPath: 'inset(0 100% 0 0)', color: 'currentColor' }, { clipPath: 'inset(0 0 0 0)', color: 'currentColor', offset: 0.6 }, { clipPath: 'inset(0 0 0 0)', color: o.color }], { duration: o.duration, easing: 'ease-out', fill: 'forwards' })?.finished.catch(() => undefined);\n },\n },\n {\n name: 'mention-glow',\n kind: 'attention',\n description: 'A soft highlight sweeps in behind an @mention, then settles (`color`).',\n defaults: { color: 'rgba(250,204,21,.45)', duration: 900 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n el.style.backgroundImage = `linear-gradient(${o.color},${o.color})`;\n el.style.backgroundRepeat = 'no-repeat';\n el.style.borderRadius = el.style.borderRadius || '4px';\n if (ctx.reduced) return void (el.style.backgroundSize = '100% 100%');\n return ctx.animate(el, [{ backgroundSize: '0% 100%' }, { backgroundSize: '100% 100%' }], { duration: o.duration, easing: 'cubic-bezier(.3,.8,.3,1)', fill: 'forwards' })?.finished.catch(() => undefined);\n },\n },\n];\n\n/** Register the 7.4 chat & social pack (idempotent). */\nexport function registerSocialPack(): void {\n registerEffects(SOCIAL_FX);\n}\n"],"names":[],"mappings":"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"}
@@ -2,9 +2,10 @@
2
2
 
3
3
  var base = require('../chunks/base-BaQV-2ha.cjs');
4
4
  var registry = require('../chunks/registry-DehBVRDV.cjs');
5
- var core = require('../chunks/core-BGAyaY6L.cjs');
6
- var fx = require('../chunks/fx-lBGVtQO1.cjs');
5
+ var builtins = require('../chunks/builtins-xalxV2d5.cjs');
6
+ require('../chunks/core-BGAyaY6L.cjs');
7
7
  require('./tokens.cjs');
8
+ require('../chunks/fx-lBGVtQO1.cjs');
8
9
 
9
10
  function defineFx(tag = 'usa-fx') {
10
11
  return base.defineElement(tag, (Base) => class UsaFx extends Base {
@@ -41,100 +42,6 @@ function defineFx(tag = 'usa-fx') {
41
42
  });
42
43
  }
43
44
 
44
- /**
45
- * 5.0 built-in effects, all registered through `registerEffect()`:
46
- * every timeline preset as an `enter` effect, attention seekers, and the
47
- * click effects (burst, confetti, shake, ripple).
48
- */
49
- const enter = Object.entries(core.TIMELINE_PRESETS).map(([name, frames]) => ({
50
- name,
51
- kind: 'enter',
52
- description: `Entrance: ${name} (same keyframes as the timeline preset).`,
53
- defaults: { duration: 600, delay: 0, easing: 'cubic-bezier(0.22, 1, 0.36, 1)' },
54
- run: (el, o, ctx) => ctx.animate(el, ctx.reduced ? [{ opacity: 0 }, { opacity: 1 }] : frames, { duration: o.duration, delay: o.delay, easing: o.easing, fill: 'backwards' }),
55
- }));
56
- const A = (name, description, frames, duration = 700, easing = 'ease-in-out') => ({
57
- name,
58
- kind: 'attention',
59
- description,
60
- defaults: { duration, iterations: 1 },
61
- run: (el, o, ctx) => (ctx.reduced ? ctx.animate(el, [{ opacity: 1 }, { opacity: 0.6 }, { opacity: 1 }], { duration: 400 }) : ctx.animate(el, frames, { duration: o.duration, easing, iterations: o.iterations })),
62
- });
63
- const attention = [
64
- A('pulse', 'Gentle scale pulse.', [{ transform: 'scale(1)' }, { transform: 'scale(1.08)' }, { transform: 'scale(1)' }], 600),
65
- A('pop', 'Quick overshoot pop.', [{ transform: 'scale(1)' }, { transform: 'scale(1.18)', offset: 0.4 }, { transform: 'scale(0.96)', offset: 0.7 }, { transform: 'scale(1)' }], 450, 'cubic-bezier(0.34, 1.56, 0.64, 1)'),
66
- A('jelly', 'Rubbery squash-and-stretch.', [{ transform: 'scale(1,1)' }, { transform: 'scale(1.25,0.75)', offset: 0.3 }, { transform: 'scale(0.75,1.25)', offset: 0.4 }, { transform: 'scale(1.15,0.85)', offset: 0.5 }, { transform: 'scale(0.95,1.05)', offset: 0.65 }, { transform: 'scale(1.05,0.95)', offset: 0.75 }, { transform: 'scale(1,1)' }], 900),
67
- A('wiggle', 'Playful rotate wiggle.', [{ transform: 'rotate(0)' }, { transform: 'rotate(-8deg)', offset: 0.2 }, { transform: 'rotate(7deg)', offset: 0.4 }, { transform: 'rotate(-5deg)', offset: 0.6 }, { transform: 'rotate(3deg)', offset: 0.8 }, { transform: 'rotate(0)' }], 650),
68
- A('heartbeat', 'Double-beat heart pulse.', [{ transform: 'scale(1)' }, { transform: 'scale(1.2)', offset: 0.14 }, { transform: 'scale(1)', offset: 0.28 }, { transform: 'scale(1.2)', offset: 0.42 }, { transform: 'scale(1)', offset: 0.7 }], 1100),
69
- A('bounce', 'Hop up and settle with a squash.', [{ transform: 'translateY(0) scale(1,1)' }, { transform: 'translateY(-22px) scale(0.95,1.05)', offset: 0.35 }, { transform: 'translateY(0) scale(1.08,0.92)', offset: 0.6 }, { transform: 'translateY(-6px) scale(1,1)', offset: 0.8 }, { transform: 'translateY(0) scale(1,1)' }], 800),
70
- A('flash', 'Two soft flashes (well under 3 per second).', [{ opacity: 1 }, { opacity: 0.25, offset: 0.25 }, { opacity: 1, offset: 0.5 }, { opacity: 0.25, offset: 0.75 }, { opacity: 1 }], 1400),
71
- A('tada', 'Scale + shake celebration.', [{ transform: 'scale(1) rotate(0)' }, { transform: 'scale(0.9) rotate(-3deg)', offset: 0.1 }, { transform: 'scale(1.1) rotate(3deg)', offset: 0.3 }, { transform: 'scale(1.1) rotate(-3deg)', offset: 0.5 }, { transform: 'scale(1.1) rotate(3deg)', offset: 0.7 }, { transform: 'scale(1) rotate(0)' }], 1000),
72
- ];
73
- const click = [
74
- {
75
- name: 'burst',
76
- kind: 'click',
77
- description: 'Particle burst from the click point (or `x` / `y`, or the element center).',
78
- defaults: { count: 12 },
79
- run: (el, o, ctx) => {
80
- if (ctx.reduced)
81
- return;
82
- const r = el.getBoundingClientRect();
83
- const e = ctx.event;
84
- fx.burst(o.x ?? e?.clientX ?? r.left + r.width / 2, o.y ?? e?.clientY ?? r.top + r.height / 2, o);
85
- },
86
- },
87
- {
88
- name: 'confetti',
89
- kind: 'click',
90
- description: 'Confetti cannon from the element.',
91
- defaults: { count: 80 },
92
- run: (el, o, ctx) => {
93
- if (ctx.reduced)
94
- return;
95
- const r = el.getBoundingClientRect();
96
- fx.confetti({ x: r.left + r.width / 2, y: r.top + r.height / 2, ...o });
97
- },
98
- },
99
- {
100
- name: 'shake',
101
- kind: 'attention',
102
- description: 'Horizontal "no" shake (errors, wrong password).',
103
- defaults: { intensity: 8, duration: 480 },
104
- run: (el, o, ctx) => (ctx.reduced ? ctx.animate(el, [{ opacity: 1 }, { opacity: 0.5 }, { opacity: 1 }], { duration: 300 }) : fx.shake(el, o.intensity, o.duration)),
105
- },
106
- {
107
- name: 'ripple',
108
- kind: 'click',
109
- description: 'Material-style ink ripple from the pointer.',
110
- defaults: { color: 'currentColor', duration: 600 },
111
- run: (el, o, ctx) => {
112
- var _a;
113
- if (ctx.reduced)
114
- return;
115
- const r = el.getBoundingClientRect();
116
- const e = ctx.event;
117
- const d = Math.hypot(r.width, r.height) * 2;
118
- const dot = document.createElement('span');
119
- dot.setAttribute('aria-hidden', 'true');
120
- Object.assign(dot.style, { position: 'absolute', left: `${(e?.clientX ?? r.left + r.width / 2) - r.left - d / 2}px`, top: `${(e?.clientY ?? r.top + r.height / 2) - r.top - d / 2}px`, width: `${d}px`, height: `${d}px`, borderRadius: '50%', background: o.color, opacity: '0.25', pointerEvents: 'none' });
121
- if (getComputedStyle(el).position === 'static')
122
- el.style.position = 'relative';
123
- (_a = el.style).overflow || (_a.overflow = 'hidden');
124
- el.appendChild(dot);
125
- const a = ctx.animate(dot, [{ transform: 'scale(0)', opacity: 0.3 }, { transform: 'scale(1)', opacity: 0 }], { duration: o.duration, easing: 'ease-out' });
126
- const done = () => dot.remove();
127
- if (a)
128
- a.finished.then(done, done);
129
- else
130
- done();
131
- return a;
132
- },
133
- },
134
- ];
135
- /** Every built-in 5.0 effect definition. */
136
- const BUILTIN_EFFECTS = [...enter, ...attention, ...click];
137
-
138
45
  /**
139
46
  * motionary/components/fx — unified plugin-style effects (5.0).
140
47
  * `registerEffect({ name, kind, run })`, `playEffect(el, name)`,
@@ -145,7 +52,7 @@ const BUILTIN_EFFECTS = [...enter, ...attention, ...click];
145
52
  */
146
53
  /** Register the built-in effects (idempotent; `defineFxComponents()` calls it). */
147
54
  function registerBuiltinEffects() {
148
- registry.registerEffects(BUILTIN_EFFECTS);
55
+ registry.registerEffects(builtins.BUILTIN_EFFECTS);
149
56
  }
150
57
  /** Register every component of this category under its default tag (+ the built-in effects). */
151
58
  function defineFxComponents() {
@@ -162,7 +69,7 @@ exports.listEffects = registry.listEffects;
162
69
  exports.playEffect = registry.playEffect;
163
70
  exports.registerEffect = registry.registerEffect;
164
71
  exports.registerEffects = registry.registerEffects;
165
- exports.BUILTIN_EFFECTS = BUILTIN_EFFECTS;
72
+ exports.BUILTIN_EFFECTS = builtins.BUILTIN_EFFECTS;
166
73
  exports.defineFx = defineFx;
167
74
  exports.defineFxComponents = defineFxComponents;
168
75
  exports.registerBuiltinEffects = registerBuiltinEffects;
@@ -1 +1 @@
1
- {"version":3,"file":"fx.cjs","sources":["../../src/components/fx/fx-el.ts","../../src/components/fx/builtins.ts","../../src/components/fx/index.ts"],"sourcesContent":["import { defineElement, type UsaElement } from '../base';\nimport { bindEffect, playEffect, EFFECT_TRIGGERS, type EffectTrigger } from './registry';\n\n/**\n * `<usa-fx effect=\"pop\" trigger=\"click\">` — plays any registered effect\n * (`registerEffect()`) on its first element child (or itself with `self`).\n * `trigger`: `click` (default) · `hover` · `enter` · `load` · `loop` · `manual`;\n * `options` (JSON) is passed to the effect; `once`. Method `play()`.\n */\nexport interface UsaFxElement extends UsaElement {\n readonly target: HTMLElement;\n play(): Promise<void>;\n}\n\nexport function defineFx(tag = 'usa-fx'): CustomElementConstructor | undefined {\n return defineElement(tag, (Base) =>\n class UsaFx extends Base {\n static get observedAttributes(): string[] {\n return ['effect', 'trigger', 'options'];\n }\n get target(): HTMLElement {\n return this.flag('self') ? this : ((this.firstElementChild as HTMLElement) || this);\n }\n private opts(): Record<string, unknown> {\n try {\n return JSON.parse(this.str('options', '{}')) || {};\n } catch {\n return {};\n }\n }\n play(): Promise<void> {\n return playEffect(this.target, this.str('effect', 'pop'), this.opts()).catch(() => undefined);\n }\n mount(): void {\n if (!this.style.display) this.style.display = 'inline-block';\n const name = this.str('effect', 'pop');\n const t = this.str('trigger', 'click') as EffectTrigger;\n try {\n this.onCleanup(bindEffect(this.target, name, { ...this.opts(), trigger: EFFECT_TRIGGERS.includes(t) ? t : 'click', once: this.flag('once') }));\n this.removeAttribute('data-unknown');\n } catch {\n this.setAttribute('data-unknown', name); // not registered (yet)\n }\n }\n }\n );\n}\n","/**\n * 5.0 built-in effects, all registered through `registerEffect()`:\n * every timeline preset as an `enter` effect, attention seekers, and the\n * click effects (burst, confetti, shake, ripple).\n */\nimport { TIMELINE_PRESETS } from '../timeline/core';\nimport { burst, confetti, shake } from '../click/fx';\nimport type { EffectDefinition } from './registry';\n\nconst enter: EffectDefinition[] = Object.entries(TIMELINE_PRESETS).map(([name, frames]) => ({\n name,\n kind: 'enter' as const,\n description: `Entrance: ${name} (same keyframes as the timeline preset).`,\n defaults: { duration: 600, delay: 0, easing: 'cubic-bezier(0.22, 1, 0.36, 1)' },\n run: (el: HTMLElement, o: any, ctx) => ctx.animate(el, ctx.reduced ? [{ opacity: 0 }, { opacity: 1 }] : frames, { duration: o.duration, delay: o.delay, easing: o.easing, fill: 'backwards' }),\n}));\n\nconst A = (name: string, description: string, frames: Keyframe[], duration = 700, easing = 'ease-in-out'): EffectDefinition => ({\n name,\n kind: 'attention',\n description,\n defaults: { duration, iterations: 1 },\n run: (el, o: any, ctx) => (ctx.reduced ? ctx.animate(el, [{ opacity: 1 }, { opacity: 0.6 }, { opacity: 1 }], { duration: 400 }) : ctx.animate(el, frames, { duration: o.duration, easing, iterations: o.iterations })),\n});\n\nconst attention: EffectDefinition[] = [\n A('pulse', 'Gentle scale pulse.', [{ transform: 'scale(1)' }, { transform: 'scale(1.08)' }, { transform: 'scale(1)' }], 600),\n A('pop', 'Quick overshoot pop.', [{ transform: 'scale(1)' }, { transform: 'scale(1.18)', offset: 0.4 }, { transform: 'scale(0.96)', offset: 0.7 }, { transform: 'scale(1)' }], 450, 'cubic-bezier(0.34, 1.56, 0.64, 1)'),\n A('jelly', 'Rubbery squash-and-stretch.', [{ transform: 'scale(1,1)' }, { transform: 'scale(1.25,0.75)', offset: 0.3 }, { transform: 'scale(0.75,1.25)', offset: 0.4 }, { transform: 'scale(1.15,0.85)', offset: 0.5 }, { transform: 'scale(0.95,1.05)', offset: 0.65 }, { transform: 'scale(1.05,0.95)', offset: 0.75 }, { transform: 'scale(1,1)' }], 900),\n A('wiggle', 'Playful rotate wiggle.', [{ transform: 'rotate(0)' }, { transform: 'rotate(-8deg)', offset: 0.2 }, { transform: 'rotate(7deg)', offset: 0.4 }, { transform: 'rotate(-5deg)', offset: 0.6 }, { transform: 'rotate(3deg)', offset: 0.8 }, { transform: 'rotate(0)' }], 650),\n A('heartbeat', 'Double-beat heart pulse.', [{ transform: 'scale(1)' }, { transform: 'scale(1.2)', offset: 0.14 }, { transform: 'scale(1)', offset: 0.28 }, { transform: 'scale(1.2)', offset: 0.42 }, { transform: 'scale(1)', offset: 0.7 }], 1100),\n A('bounce', 'Hop up and settle with a squash.', [{ transform: 'translateY(0) scale(1,1)' }, { transform: 'translateY(-22px) scale(0.95,1.05)', offset: 0.35 }, { transform: 'translateY(0) scale(1.08,0.92)', offset: 0.6 }, { transform: 'translateY(-6px) scale(1,1)', offset: 0.8 }, { transform: 'translateY(0) scale(1,1)' }], 800),\n A('flash', 'Two soft flashes (well under 3 per second).', [{ opacity: 1 }, { opacity: 0.25, offset: 0.25 }, { opacity: 1, offset: 0.5 }, { opacity: 0.25, offset: 0.75 }, { opacity: 1 }], 1400),\n A('tada', 'Scale + shake celebration.', [{ transform: 'scale(1) rotate(0)' }, { transform: 'scale(0.9) rotate(-3deg)', offset: 0.1 }, { transform: 'scale(1.1) rotate(3deg)', offset: 0.3 }, { transform: 'scale(1.1) rotate(-3deg)', offset: 0.5 }, { transform: 'scale(1.1) rotate(3deg)', offset: 0.7 }, { transform: 'scale(1) rotate(0)' }], 1000),\n];\n\nconst click: EffectDefinition[] = [\n {\n name: 'burst',\n kind: 'click',\n description: 'Particle burst from the click point (or `x` / `y`, or the element center).',\n defaults: { count: 12 },\n run: (el, o: any, ctx) => {\n if (ctx.reduced) return;\n const r = el.getBoundingClientRect();\n const e = ctx.event as PointerEvent | undefined;\n burst(o.x ?? e?.clientX ?? r.left + r.width / 2, o.y ?? e?.clientY ?? r.top + r.height / 2, o);\n },\n },\n {\n name: 'confetti',\n kind: 'click',\n description: 'Confetti cannon from the element.',\n defaults: { count: 80 },\n run: (el, o: any, ctx) => {\n if (ctx.reduced) return;\n const r = el.getBoundingClientRect();\n confetti({ x: r.left + r.width / 2, y: r.top + r.height / 2, ...o });\n },\n },\n {\n name: 'shake',\n kind: 'attention',\n description: 'Horizontal \"no\" shake (errors, wrong password).',\n defaults: { intensity: 8, duration: 480 },\n run: (el, o: any, ctx) => (ctx.reduced ? ctx.animate(el, [{ opacity: 1 }, { opacity: 0.5 }, { opacity: 1 }], { duration: 300 }) : shake(el, o.intensity, o.duration)),\n },\n {\n name: 'ripple',\n kind: 'click',\n description: 'Material-style ink ripple from the pointer.',\n defaults: { color: 'currentColor', duration: 600 },\n run: (el, o: any, ctx) => {\n if (ctx.reduced) return;\n const r = el.getBoundingClientRect();\n const e = ctx.event as PointerEvent | undefined;\n const d = Math.hypot(r.width, r.height) * 2;\n const dot = document.createElement('span');\n dot.setAttribute('aria-hidden', 'true');\n Object.assign(dot.style, { position: 'absolute', left: `${(e?.clientX ?? r.left + r.width / 2) - r.left - d / 2}px`, top: `${(e?.clientY ?? r.top + r.height / 2) - r.top - d / 2}px`, width: `${d}px`, height: `${d}px`, borderRadius: '50%', background: o.color, opacity: '0.25', pointerEvents: 'none' });\n if (getComputedStyle(el).position === 'static') el.style.position = 'relative';\n el.style.overflow ||= 'hidden';\n el.appendChild(dot);\n const a = ctx.animate(dot, [{ transform: 'scale(0)', opacity: 0.3 }, { transform: 'scale(1)', opacity: 0 }], { duration: o.duration, easing: 'ease-out' });\n const done = () => dot.remove();\n if (a) a.finished.then(done, done);\n else done();\n return a;\n },\n },\n];\n\n/** Every built-in 5.0 effect definition. */\nexport const BUILTIN_EFFECTS: EffectDefinition[] = [...enter, ...attention, ...click];\n","/**\n * motionary/components/fx — unified plugin-style effects (5.0).\n * `registerEffect({ name, kind, run })`, `playEffect(el, name)`,\n * `bindEffect(el, name, { trigger })`, `<usa-fx effect trigger>`. Built-ins:\n * every timeline preset (`enter`), `pulse` · `pop` · `jelly` · `wiggle` ·\n * `heartbeat` · `bounce` · `flash` · `tada` · `shake` (attention),\n * `burst` · `confetti` · `ripple` (click). More packs: `motionary/components/effects`.\n */\nimport { defineFx, type UsaFxElement } from './fx-el';\nimport { registerEffects } from './registry';\nimport { BUILTIN_EFFECTS } from './builtins';\n\nexport { defineFx };\nexport { registerEffect, registerEffects, playEffect, bindEffect, getEffect, hasEffect, listEffects, EFFECT_KINDS, EFFECT_TRIGGERS } from './registry';\nexport type { EffectDefinition, EffectContext, EffectKind, EffectTrigger } from './registry';\nexport { BUILTIN_EFFECTS };\nexport type { UsaFxElement };\n\n/** Register the built-in effects (idempotent; `defineFxComponents()` calls it). */\nexport function registerBuiltinEffects(): void {\n registerEffects(BUILTIN_EFFECTS);\n}\n\n/** Register every component of this category under its default tag (+ the built-in effects). */\nexport function defineFxComponents(): void {\n registerBuiltinEffects();\n defineFx();\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'usa-fx': UsaFxElement;\n }\n}\n"],"names":["defineElement","playEffect","bindEffect","EFFECT_TRIGGERS","TIMELINE_PRESETS","burst","confetti","shake","registerEffects"],"mappings":"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"}
1
+ {"version":3,"file":"fx.cjs","sources":["../../src/components/fx/fx-el.ts","../../src/components/fx/index.ts"],"sourcesContent":["import { defineElement, type UsaElement } from '../base';\nimport { bindEffect, playEffect, EFFECT_TRIGGERS, type EffectTrigger } from './registry';\n\n/**\n * `<usa-fx effect=\"pop\" trigger=\"click\">` — plays any registered effect\n * (`registerEffect()`) on its first element child (or itself with `self`).\n * `trigger`: `click` (default) · `hover` · `enter` · `load` · `loop` · `manual`;\n * `options` (JSON) is passed to the effect; `once`. Method `play()`.\n */\nexport interface UsaFxElement extends UsaElement {\n readonly target: HTMLElement;\n play(): Promise<void>;\n}\n\nexport function defineFx(tag = 'usa-fx'): CustomElementConstructor | undefined {\n return defineElement(tag, (Base) =>\n class UsaFx extends Base {\n static get observedAttributes(): string[] {\n return ['effect', 'trigger', 'options'];\n }\n get target(): HTMLElement {\n return this.flag('self') ? this : ((this.firstElementChild as HTMLElement) || this);\n }\n private opts(): Record<string, unknown> {\n try {\n return JSON.parse(this.str('options', '{}')) || {};\n } catch {\n return {};\n }\n }\n play(): Promise<void> {\n return playEffect(this.target, this.str('effect', 'pop'), this.opts()).catch(() => undefined);\n }\n mount(): void {\n if (!this.style.display) this.style.display = 'inline-block';\n const name = this.str('effect', 'pop');\n const t = this.str('trigger', 'click') as EffectTrigger;\n try {\n this.onCleanup(bindEffect(this.target, name, { ...this.opts(), trigger: EFFECT_TRIGGERS.includes(t) ? t : 'click', once: this.flag('once') }));\n this.removeAttribute('data-unknown');\n } catch {\n this.setAttribute('data-unknown', name); // not registered (yet)\n }\n }\n }\n );\n}\n","/**\n * motionary/components/fx — unified plugin-style effects (5.0).\n * `registerEffect({ name, kind, run })`, `playEffect(el, name)`,\n * `bindEffect(el, name, { trigger })`, `<usa-fx effect trigger>`. Built-ins:\n * every timeline preset (`enter`), `pulse` · `pop` · `jelly` · `wiggle` ·\n * `heartbeat` · `bounce` · `flash` · `tada` · `shake` (attention),\n * `burst` · `confetti` · `ripple` (click). More packs: `motionary/components/effects`.\n */\nimport { defineFx, type UsaFxElement } from './fx-el';\nimport { registerEffects } from './registry';\nimport { BUILTIN_EFFECTS } from './builtins';\n\nexport { defineFx };\nexport { registerEffect, registerEffects, playEffect, bindEffect, getEffect, hasEffect, listEffects, EFFECT_KINDS, EFFECT_TRIGGERS } from './registry';\nexport type { EffectDefinition, EffectContext, EffectKind, EffectTrigger } from './registry';\nexport { BUILTIN_EFFECTS };\nexport type { UsaFxElement };\n\n/** Register the built-in effects (idempotent; `defineFxComponents()` calls it). */\nexport function registerBuiltinEffects(): void {\n registerEffects(BUILTIN_EFFECTS);\n}\n\n/** Register every component of this category under its default tag (+ the built-in effects). */\nexport function defineFxComponents(): void {\n registerBuiltinEffects();\n defineFx();\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'usa-fx': UsaFxElement;\n }\n}\n"],"names":["defineElement","playEffect","bindEffect","EFFECT_TRIGGERS","registerEffects","BUILTIN_EFFECTS"],"mappings":";;;;;;;;;AAcM,SAAU,QAAQ,CAAC,GAAG,GAAG,QAAQ,EAAA;AACrC,IAAA,OAAOA,kBAAa,CAAC,GAAG,EAAE,CAAC,IAAI,KAC7B,MAAM,KAAM,SAAQ,IAAI,CAAA;AACtB,QAAA,WAAW,kBAAkB,GAAA;AAC3B,YAAA,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC;QACzC;AACA,QAAA,IAAI,MAAM,GAAA;YACR,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,IAAK,IAAI,CAAC,iBAAiC,IAAI,IAAI,CAAC;QACrF;QACQ,IAAI,GAAA;AACV,YAAA,IAAI;AACF,gBAAA,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE;YACpD;AAAE,YAAA,MAAM;AACN,gBAAA,OAAO,EAAE;YACX;QACF;QACA,IAAI,GAAA;AACF,YAAA,OAAOC,mBAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,SAAS,CAAC;QAC/F;QACA,KAAK,GAAA;AACH,YAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO;AAAE,gBAAA,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,cAAc;YAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC;YACtC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAkB;AACvD,YAAA,IAAI;gBACF,IAAI,CAAC,SAAS,CAACC,mBAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,EAAEC,wBAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC9I,gBAAA,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC;YACtC;AAAE,YAAA,MAAM;gBACN,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;YAC1C;QACF;AACD,KAAA,CACF;AACH;;AC9CA;;;;;;;AAOG;AAWH;SACgB,sBAAsB,GAAA;IACpCC,wBAAe,CAACC,wBAAe,CAAC;AAClC;AAEA;SACgB,kBAAkB,GAAA;AAChC,IAAA,sBAAsB,EAAE;AACxB,IAAA,QAAQ,EAAE;AACZ;;;;;;;;;;;;;;;;"}
@@ -1,9 +1,10 @@
1
1
  import { u as defineElement } from '../chunks/base-2-yYc93C.js';
2
2
  import { playEffect, bindEffect, EFFECT_TRIGGERS, registerEffects } from '../chunks/registry-CyKExAmE.js';
3
3
  export { EFFECT_KINDS, getEffect, hasEffect, listEffects, registerEffect } from '../chunks/registry-CyKExAmE.js';
4
- import { T as TIMELINE_PRESETS } from '../chunks/core-D5rU0CV6.js';
5
- import { b as burst, c as confetti, s as shake } from '../chunks/fx-CMxWNwH8.js';
4
+ import { B as BUILTIN_EFFECTS } from '../chunks/builtins-HlqAkK0f.js';
5
+ import '../chunks/core-D5rU0CV6.js';
6
6
  import './tokens.js';
7
+ import '../chunks/fx-CMxWNwH8.js';
7
8
 
8
9
  function defineFx(tag = 'usa-fx') {
9
10
  return defineElement(tag, (Base) => class UsaFx extends Base {
@@ -40,100 +41,6 @@ function defineFx(tag = 'usa-fx') {
40
41
  });
41
42
  }
42
43
 
43
- /**
44
- * 5.0 built-in effects, all registered through `registerEffect()`:
45
- * every timeline preset as an `enter` effect, attention seekers, and the
46
- * click effects (burst, confetti, shake, ripple).
47
- */
48
- const enter = Object.entries(TIMELINE_PRESETS).map(([name, frames]) => ({
49
- name,
50
- kind: 'enter',
51
- description: `Entrance: ${name} (same keyframes as the timeline preset).`,
52
- defaults: { duration: 600, delay: 0, easing: 'cubic-bezier(0.22, 1, 0.36, 1)' },
53
- run: (el, o, ctx) => ctx.animate(el, ctx.reduced ? [{ opacity: 0 }, { opacity: 1 }] : frames, { duration: o.duration, delay: o.delay, easing: o.easing, fill: 'backwards' }),
54
- }));
55
- const A = (name, description, frames, duration = 700, easing = 'ease-in-out') => ({
56
- name,
57
- kind: 'attention',
58
- description,
59
- defaults: { duration, iterations: 1 },
60
- run: (el, o, ctx) => (ctx.reduced ? ctx.animate(el, [{ opacity: 1 }, { opacity: 0.6 }, { opacity: 1 }], { duration: 400 }) : ctx.animate(el, frames, { duration: o.duration, easing, iterations: o.iterations })),
61
- });
62
- const attention = [
63
- A('pulse', 'Gentle scale pulse.', [{ transform: 'scale(1)' }, { transform: 'scale(1.08)' }, { transform: 'scale(1)' }], 600),
64
- A('pop', 'Quick overshoot pop.', [{ transform: 'scale(1)' }, { transform: 'scale(1.18)', offset: 0.4 }, { transform: 'scale(0.96)', offset: 0.7 }, { transform: 'scale(1)' }], 450, 'cubic-bezier(0.34, 1.56, 0.64, 1)'),
65
- A('jelly', 'Rubbery squash-and-stretch.', [{ transform: 'scale(1,1)' }, { transform: 'scale(1.25,0.75)', offset: 0.3 }, { transform: 'scale(0.75,1.25)', offset: 0.4 }, { transform: 'scale(1.15,0.85)', offset: 0.5 }, { transform: 'scale(0.95,1.05)', offset: 0.65 }, { transform: 'scale(1.05,0.95)', offset: 0.75 }, { transform: 'scale(1,1)' }], 900),
66
- A('wiggle', 'Playful rotate wiggle.', [{ transform: 'rotate(0)' }, { transform: 'rotate(-8deg)', offset: 0.2 }, { transform: 'rotate(7deg)', offset: 0.4 }, { transform: 'rotate(-5deg)', offset: 0.6 }, { transform: 'rotate(3deg)', offset: 0.8 }, { transform: 'rotate(0)' }], 650),
67
- A('heartbeat', 'Double-beat heart pulse.', [{ transform: 'scale(1)' }, { transform: 'scale(1.2)', offset: 0.14 }, { transform: 'scale(1)', offset: 0.28 }, { transform: 'scale(1.2)', offset: 0.42 }, { transform: 'scale(1)', offset: 0.7 }], 1100),
68
- A('bounce', 'Hop up and settle with a squash.', [{ transform: 'translateY(0) scale(1,1)' }, { transform: 'translateY(-22px) scale(0.95,1.05)', offset: 0.35 }, { transform: 'translateY(0) scale(1.08,0.92)', offset: 0.6 }, { transform: 'translateY(-6px) scale(1,1)', offset: 0.8 }, { transform: 'translateY(0) scale(1,1)' }], 800),
69
- A('flash', 'Two soft flashes (well under 3 per second).', [{ opacity: 1 }, { opacity: 0.25, offset: 0.25 }, { opacity: 1, offset: 0.5 }, { opacity: 0.25, offset: 0.75 }, { opacity: 1 }], 1400),
70
- A('tada', 'Scale + shake celebration.', [{ transform: 'scale(1) rotate(0)' }, { transform: 'scale(0.9) rotate(-3deg)', offset: 0.1 }, { transform: 'scale(1.1) rotate(3deg)', offset: 0.3 }, { transform: 'scale(1.1) rotate(-3deg)', offset: 0.5 }, { transform: 'scale(1.1) rotate(3deg)', offset: 0.7 }, { transform: 'scale(1) rotate(0)' }], 1000),
71
- ];
72
- const click = [
73
- {
74
- name: 'burst',
75
- kind: 'click',
76
- description: 'Particle burst from the click point (or `x` / `y`, or the element center).',
77
- defaults: { count: 12 },
78
- run: (el, o, ctx) => {
79
- if (ctx.reduced)
80
- return;
81
- const r = el.getBoundingClientRect();
82
- const e = ctx.event;
83
- burst(o.x ?? e?.clientX ?? r.left + r.width / 2, o.y ?? e?.clientY ?? r.top + r.height / 2, o);
84
- },
85
- },
86
- {
87
- name: 'confetti',
88
- kind: 'click',
89
- description: 'Confetti cannon from the element.',
90
- defaults: { count: 80 },
91
- run: (el, o, ctx) => {
92
- if (ctx.reduced)
93
- return;
94
- const r = el.getBoundingClientRect();
95
- confetti({ x: r.left + r.width / 2, y: r.top + r.height / 2, ...o });
96
- },
97
- },
98
- {
99
- name: 'shake',
100
- kind: 'attention',
101
- description: 'Horizontal "no" shake (errors, wrong password).',
102
- defaults: { intensity: 8, duration: 480 },
103
- run: (el, o, ctx) => (ctx.reduced ? ctx.animate(el, [{ opacity: 1 }, { opacity: 0.5 }, { opacity: 1 }], { duration: 300 }) : shake(el, o.intensity, o.duration)),
104
- },
105
- {
106
- name: 'ripple',
107
- kind: 'click',
108
- description: 'Material-style ink ripple from the pointer.',
109
- defaults: { color: 'currentColor', duration: 600 },
110
- run: (el, o, ctx) => {
111
- var _a;
112
- if (ctx.reduced)
113
- return;
114
- const r = el.getBoundingClientRect();
115
- const e = ctx.event;
116
- const d = Math.hypot(r.width, r.height) * 2;
117
- const dot = document.createElement('span');
118
- dot.setAttribute('aria-hidden', 'true');
119
- Object.assign(dot.style, { position: 'absolute', left: `${(e?.clientX ?? r.left + r.width / 2) - r.left - d / 2}px`, top: `${(e?.clientY ?? r.top + r.height / 2) - r.top - d / 2}px`, width: `${d}px`, height: `${d}px`, borderRadius: '50%', background: o.color, opacity: '0.25', pointerEvents: 'none' });
120
- if (getComputedStyle(el).position === 'static')
121
- el.style.position = 'relative';
122
- (_a = el.style).overflow || (_a.overflow = 'hidden');
123
- el.appendChild(dot);
124
- const a = ctx.animate(dot, [{ transform: 'scale(0)', opacity: 0.3 }, { transform: 'scale(1)', opacity: 0 }], { duration: o.duration, easing: 'ease-out' });
125
- const done = () => dot.remove();
126
- if (a)
127
- a.finished.then(done, done);
128
- else
129
- done();
130
- return a;
131
- },
132
- },
133
- ];
134
- /** Every built-in 5.0 effect definition. */
135
- const BUILTIN_EFFECTS = [...enter, ...attention, ...click];
136
-
137
44
  /**
138
45
  * motionary/components/fx — unified plugin-style effects (5.0).
139
46
  * `registerEffect({ name, kind, run })`, `playEffect(el, name)`,