use-scroll-animate 8.8.0 → 9.0.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/CHANGELOG.md +38 -0
- package/README.md +2 -2
- package/README_ja.md +2 -2
- package/README_zh.md +2 -2
- package/bin/usa-codemod-9.mjs +71 -0
- package/dist/chunks/manifest-B08-vo9G.cjs +81 -0
- package/dist/chunks/manifest-B08-vo9G.cjs.map +1 -0
- package/dist/chunks/manifest-PJ0h8RS_.js +76 -0
- package/dist/chunks/manifest-PJ0h8RS_.js.map +1 -0
- package/dist/components/dsl.cjs +210 -0
- package/dist/components/dsl.cjs.map +1 -0
- package/dist/components/dsl.d.cts +76 -0
- package/dist/components/dsl.d.ts +76 -0
- package/dist/components/dsl.js +203 -0
- package/dist/components/dsl.js.map +1 -0
- package/dist/components/effects.cjs +14 -14
- package/dist/components/effects.cjs.map +1 -1
- package/dist/components/effects.d.cts +8 -8
- package/dist/components/effects.d.ts +8 -8
- package/dist/components/effects.js +11 -11
- package/dist/components/effects.js.map +1 -1
- package/dist/components/fx2.cjs +5 -5
- package/dist/components/fx2.js +1 -1
- package/dist/components/marketplace.cjs +81 -71
- package/dist/components/marketplace.cjs.map +1 -1
- package/dist/components/marketplace.d.cts +33 -2
- package/dist/components/marketplace.d.ts +33 -2
- package/dist/components/marketplace.js +73 -68
- package/dist/components/marketplace.js.map +1 -1
- package/dist/components/widgets.cjs +593 -186
- package/dist/components/widgets.cjs.map +1 -1
- package/dist/components/widgets.d.cts +152 -2
- package/dist/components/widgets.d.ts +152 -2
- package/dist/components/widgets.js +587 -187
- package/dist/components/widgets.js.map +1 -1
- package/dist/components.umd.js +2 -2
- package/dist/components.umd.js.map +1 -1
- package/dist/widgets.umd.js +1 -1
- package/dist/widgets.umd.js.map +1 -1
- package/docs/ROADMAP.md +12 -14
- package/docs/components.md +40 -4
- package/docs/deprecations.md +4 -0
- package/docs/upgrading-9.md +37 -0
- package/package.json +33 -2
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 5.0 — unified plugin-style effect registration. Every effect (built-in or
|
|
3
|
+
* yours) is a plain object registered once and played the same way:
|
|
4
|
+
* `playEffect(el, name)`, `bindEffect(el, name, { trigger })` or
|
|
5
|
+
* `<usa-fx effect="name" trigger="click">`. Effects get a context that
|
|
6
|
+
* already applies reduced motion, motion sensitivity, intensity and the
|
|
7
|
+
* animation budget.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
declare const EFFECT_TRIGGERS: readonly ["click", "hover", "enter", "load", "loop", "manual"];
|
|
11
|
+
type EffectTrigger = (typeof EFFECT_TRIGGERS)[number];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* `motionary/dsl` (= `motionary/components/dsl`, 9.0) — the declarative
|
|
15
|
+
* motion DSL. Describe motion as one readable string instead of code:
|
|
16
|
+
*
|
|
17
|
+
* ```html
|
|
18
|
+
* <section data-motion="enter: fade-up 600ms ease-out stagger 80ms; hover: pop; click: confetti count=40">
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Grammar — rules separated by `;`, each `trigger: effect [modifiers…]`:
|
|
22
|
+
* - trigger: `enter` · `click` · `hover` · `load` · `loop` · `manual`
|
|
23
|
+
* - effect: any registered effect name (timeline presets, packs, plugins)
|
|
24
|
+
* - modifiers: a duration (`600ms` / `0.6s`), `delay 120ms`,
|
|
25
|
+
* `stagger 80ms` (children one after another), an easing (`ease-out`,
|
|
26
|
+
* `linear`, `spring`, `cubic-bezier(…)`, `steps(…)`), `once`, and
|
|
27
|
+
* `key=value` effect options (numbers / booleans parsed).
|
|
28
|
+
*
|
|
29
|
+
* `parseMotion()` → rules + errors, `serializeMotion()` back to a string,
|
|
30
|
+
* `motion\`…\`` tagged template, `applyMotion(root)` binds every
|
|
31
|
+
* `[data-motion]` under `root` (and watches for new ones with `observe`),
|
|
32
|
+
* `bindMotion(el, rules)` for one element, and `createComponent(json)`
|
|
33
|
+
* builds live markup from the 8.9 `describeComponent()` JSON.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
interface MotionRule {
|
|
37
|
+
trigger: EffectTrigger;
|
|
38
|
+
effect: string;
|
|
39
|
+
duration?: number;
|
|
40
|
+
delay?: number;
|
|
41
|
+
stagger?: number;
|
|
42
|
+
easing?: string;
|
|
43
|
+
once?: boolean;
|
|
44
|
+
options: Record<string, string | number | boolean>;
|
|
45
|
+
}
|
|
46
|
+
interface MotionParse {
|
|
47
|
+
rules: MotionRule[];
|
|
48
|
+
errors: string[];
|
|
49
|
+
}
|
|
50
|
+
/** Parse a motion string into rules (+ human-readable errors for what was skipped) (9.0). */
|
|
51
|
+
declare function parseMotion(src: string): MotionParse;
|
|
52
|
+
/** Rules back to the canonical motion string (9.0). */
|
|
53
|
+
declare function serializeMotion(rules: MotionRule[]): string;
|
|
54
|
+
/** Tagged template: motion`enter: fade-up ${dur}ms` → the motion string (validated in dev via `parseMotion`) (9.0). */
|
|
55
|
+
declare function motion(strings: TemplateStringsArray, ...vals: unknown[]): string;
|
|
56
|
+
/** Bind parsed rules (or a motion string) to one element; returns the cleanup (9.0). */
|
|
57
|
+
declare function bindMotion(el: HTMLElement, rules: MotionRule[] | string, onError?: (msg: string) => void): () => void;
|
|
58
|
+
/** Bind every `[data-motion]` under `root` (default `document`); `observe` also binds ones added later. Returns { errors, cleanup } (9.0). */
|
|
59
|
+
declare function applyMotion(root?: ParentNode, opts?: {
|
|
60
|
+
observe?: boolean;
|
|
61
|
+
attribute?: string;
|
|
62
|
+
}): {
|
|
63
|
+
errors: string[];
|
|
64
|
+
cleanup: () => void;
|
|
65
|
+
};
|
|
66
|
+
interface ComponentJSON {
|
|
67
|
+
$schema?: string;
|
|
68
|
+
tag: string;
|
|
69
|
+
attrs?: Record<string, string>;
|
|
70
|
+
children?: (ComponentJSON | string)[];
|
|
71
|
+
}
|
|
72
|
+
/** Build live markup from the 8.9 `describeComponent()` / `exportComponent(el, 'json')` format (9.0). */
|
|
73
|
+
declare function createComponent(desc: ComponentJSON | string): Element;
|
|
74
|
+
|
|
75
|
+
export { applyMotion, bindMotion, createComponent, motion, parseMotion, serializeMotion };
|
|
76
|
+
export type { ComponentJSON, MotionParse, MotionRule };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 5.0 — unified plugin-style effect registration. Every effect (built-in or
|
|
3
|
+
* yours) is a plain object registered once and played the same way:
|
|
4
|
+
* `playEffect(el, name)`, `bindEffect(el, name, { trigger })` or
|
|
5
|
+
* `<usa-fx effect="name" trigger="click">`. Effects get a context that
|
|
6
|
+
* already applies reduced motion, motion sensitivity, intensity and the
|
|
7
|
+
* animation budget.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
declare const EFFECT_TRIGGERS: readonly ["click", "hover", "enter", "load", "loop", "manual"];
|
|
11
|
+
type EffectTrigger = (typeof EFFECT_TRIGGERS)[number];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* `motionary/dsl` (= `motionary/components/dsl`, 9.0) — the declarative
|
|
15
|
+
* motion DSL. Describe motion as one readable string instead of code:
|
|
16
|
+
*
|
|
17
|
+
* ```html
|
|
18
|
+
* <section data-motion="enter: fade-up 600ms ease-out stagger 80ms; hover: pop; click: confetti count=40">
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Grammar — rules separated by `;`, each `trigger: effect [modifiers…]`:
|
|
22
|
+
* - trigger: `enter` · `click` · `hover` · `load` · `loop` · `manual`
|
|
23
|
+
* - effect: any registered effect name (timeline presets, packs, plugins)
|
|
24
|
+
* - modifiers: a duration (`600ms` / `0.6s`), `delay 120ms`,
|
|
25
|
+
* `stagger 80ms` (children one after another), an easing (`ease-out`,
|
|
26
|
+
* `linear`, `spring`, `cubic-bezier(…)`, `steps(…)`), `once`, and
|
|
27
|
+
* `key=value` effect options (numbers / booleans parsed).
|
|
28
|
+
*
|
|
29
|
+
* `parseMotion()` → rules + errors, `serializeMotion()` back to a string,
|
|
30
|
+
* `motion\`…\`` tagged template, `applyMotion(root)` binds every
|
|
31
|
+
* `[data-motion]` under `root` (and watches for new ones with `observe`),
|
|
32
|
+
* `bindMotion(el, rules)` for one element, and `createComponent(json)`
|
|
33
|
+
* builds live markup from the 8.9 `describeComponent()` JSON.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
interface MotionRule {
|
|
37
|
+
trigger: EffectTrigger;
|
|
38
|
+
effect: string;
|
|
39
|
+
duration?: number;
|
|
40
|
+
delay?: number;
|
|
41
|
+
stagger?: number;
|
|
42
|
+
easing?: string;
|
|
43
|
+
once?: boolean;
|
|
44
|
+
options: Record<string, string | number | boolean>;
|
|
45
|
+
}
|
|
46
|
+
interface MotionParse {
|
|
47
|
+
rules: MotionRule[];
|
|
48
|
+
errors: string[];
|
|
49
|
+
}
|
|
50
|
+
/** Parse a motion string into rules (+ human-readable errors for what was skipped) (9.0). */
|
|
51
|
+
declare function parseMotion(src: string): MotionParse;
|
|
52
|
+
/** Rules back to the canonical motion string (9.0). */
|
|
53
|
+
declare function serializeMotion(rules: MotionRule[]): string;
|
|
54
|
+
/** Tagged template: motion`enter: fade-up ${dur}ms` → the motion string (validated in dev via `parseMotion`) (9.0). */
|
|
55
|
+
declare function motion(strings: TemplateStringsArray, ...vals: unknown[]): string;
|
|
56
|
+
/** Bind parsed rules (or a motion string) to one element; returns the cleanup (9.0). */
|
|
57
|
+
declare function bindMotion(el: HTMLElement, rules: MotionRule[] | string, onError?: (msg: string) => void): () => void;
|
|
58
|
+
/** Bind every `[data-motion]` under `root` (default `document`); `observe` also binds ones added later. Returns { errors, cleanup } (9.0). */
|
|
59
|
+
declare function applyMotion(root?: ParentNode, opts?: {
|
|
60
|
+
observe?: boolean;
|
|
61
|
+
attribute?: string;
|
|
62
|
+
}): {
|
|
63
|
+
errors: string[];
|
|
64
|
+
cleanup: () => void;
|
|
65
|
+
};
|
|
66
|
+
interface ComponentJSON {
|
|
67
|
+
$schema?: string;
|
|
68
|
+
tag: string;
|
|
69
|
+
attrs?: Record<string, string>;
|
|
70
|
+
children?: (ComponentJSON | string)[];
|
|
71
|
+
}
|
|
72
|
+
/** Build live markup from the 8.9 `describeComponent()` / `exportComponent(el, 'json')` format (9.0). */
|
|
73
|
+
declare function createComponent(desc: ComponentJSON | string): Element;
|
|
74
|
+
|
|
75
|
+
export { applyMotion, bindMotion, createComponent, motion, parseMotion, serializeMotion };
|
|
76
|
+
export type { ComponentJSON, MotionParse, MotionRule };
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { hasEffect, bindEffect, EFFECT_TRIGGERS } from '../chunks/registry-CnO7ZVPK.js';
|
|
2
|
+
import '../chunks/base-CLuqlLfG.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `motionary/dsl` (= `motionary/components/dsl`, 9.0) — the declarative
|
|
6
|
+
* motion DSL. Describe motion as one readable string instead of code:
|
|
7
|
+
*
|
|
8
|
+
* ```html
|
|
9
|
+
* <section data-motion="enter: fade-up 600ms ease-out stagger 80ms; hover: pop; click: confetti count=40">
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Grammar — rules separated by `;`, each `trigger: effect [modifiers…]`:
|
|
13
|
+
* - trigger: `enter` · `click` · `hover` · `load` · `loop` · `manual`
|
|
14
|
+
* - effect: any registered effect name (timeline presets, packs, plugins)
|
|
15
|
+
* - modifiers: a duration (`600ms` / `0.6s`), `delay 120ms`,
|
|
16
|
+
* `stagger 80ms` (children one after another), an easing (`ease-out`,
|
|
17
|
+
* `linear`, `spring`, `cubic-bezier(…)`, `steps(…)`), `once`, and
|
|
18
|
+
* `key=value` effect options (numbers / booleans parsed).
|
|
19
|
+
*
|
|
20
|
+
* `parseMotion()` → rules + errors, `serializeMotion()` back to a string,
|
|
21
|
+
* `motion\`…\`` tagged template, `applyMotion(root)` binds every
|
|
22
|
+
* `[data-motion]` under `root` (and watches for new ones with `observe`),
|
|
23
|
+
* `bindMotion(el, rules)` for one element, and `createComponent(json)`
|
|
24
|
+
* builds live markup from the 8.9 `describeComponent()` JSON.
|
|
25
|
+
*/
|
|
26
|
+
const EASINGS = { ease: 'ease', 'ease-in': 'ease-in', 'ease-out': 'ease-out', 'ease-in-out': 'ease-in-out', linear: 'linear', spring: 'cubic-bezier(0.34, 1.56, 0.64, 1)', smooth: 'cubic-bezier(0.22, 1, 0.36, 1)' };
|
|
27
|
+
const TIME = /^(\d+(?:\.\d+)?)(ms|s)$/;
|
|
28
|
+
const time = (t) => {
|
|
29
|
+
const m = t.match(TIME);
|
|
30
|
+
return m ? Math.round(Number(m[1]) * (m[2] === 's' ? 1000 : 1)) : undefined;
|
|
31
|
+
};
|
|
32
|
+
const value = (v) => (v === 'true' ? true : v === 'false' ? false : v !== '' && !Number.isNaN(Number(v)) ? Number(v) : v);
|
|
33
|
+
/** Split on whitespace, keeping `fn(…)` groups together. */
|
|
34
|
+
function tokens(s) {
|
|
35
|
+
const out = [];
|
|
36
|
+
let cur = '';
|
|
37
|
+
let depth = 0;
|
|
38
|
+
for (const ch of s) {
|
|
39
|
+
if (ch === '(')
|
|
40
|
+
depth++;
|
|
41
|
+
if (ch === ')')
|
|
42
|
+
depth = Math.max(0, depth - 1);
|
|
43
|
+
if (/\s/.test(ch) && !depth) {
|
|
44
|
+
if (cur)
|
|
45
|
+
out.push(cur);
|
|
46
|
+
cur = '';
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
cur += ch;
|
|
50
|
+
}
|
|
51
|
+
if (cur)
|
|
52
|
+
out.push(cur);
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
/** Parse a motion string into rules (+ human-readable errors for what was skipped) (9.0). */
|
|
56
|
+
function parseMotion(src) {
|
|
57
|
+
const rules = [];
|
|
58
|
+
const errors = [];
|
|
59
|
+
for (const raw of src.split(';')) {
|
|
60
|
+
const part = raw.trim();
|
|
61
|
+
if (!part)
|
|
62
|
+
continue;
|
|
63
|
+
const i = part.indexOf(':');
|
|
64
|
+
if (i < 0) {
|
|
65
|
+
errors.push(`"${part}": expected "trigger: effect"`);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const trigger = part.slice(0, i).trim();
|
|
69
|
+
if (!EFFECT_TRIGGERS.includes(trigger)) {
|
|
70
|
+
errors.push(`"${trigger}": unknown trigger (${EFFECT_TRIGGERS.join(', ')})`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const [effect, ...mods] = tokens(part.slice(i + 1));
|
|
74
|
+
if (!effect || !/^[a-z][a-z0-9-]*$/.test(effect)) {
|
|
75
|
+
errors.push(`"${part}": missing effect name`);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const r = { trigger, effect, options: {} };
|
|
79
|
+
for (let k = 0; k < mods.length; k++) {
|
|
80
|
+
const m = mods[k];
|
|
81
|
+
if ((m === 'delay' || m === 'stagger') && time(mods[k + 1] || '') != null)
|
|
82
|
+
r[m] = time(mods[++k]);
|
|
83
|
+
else if (time(m) != null)
|
|
84
|
+
r.duration = time(m);
|
|
85
|
+
else if (m === 'once')
|
|
86
|
+
r.once = true;
|
|
87
|
+
else if (EASINGS[m])
|
|
88
|
+
r.easing = EASINGS[m];
|
|
89
|
+
else if (/^(cubic-bezier|steps|linear)\(.*\)$/.test(m))
|
|
90
|
+
r.easing = m;
|
|
91
|
+
else if (/^[a-zA-Z][\w-]*=/.test(m)) {
|
|
92
|
+
const j = m.indexOf('=');
|
|
93
|
+
r.options[m.slice(0, j)] = value(m.slice(j + 1));
|
|
94
|
+
}
|
|
95
|
+
else
|
|
96
|
+
errors.push(`"${m}" in "${part}": unknown modifier`);
|
|
97
|
+
}
|
|
98
|
+
rules.push(r);
|
|
99
|
+
}
|
|
100
|
+
return { rules, errors };
|
|
101
|
+
}
|
|
102
|
+
/** Rules back to the canonical motion string (9.0). */
|
|
103
|
+
function serializeMotion(rules) {
|
|
104
|
+
const inv = Object.fromEntries(Object.entries(EASINGS).map(([k, v]) => [v, k]));
|
|
105
|
+
return rules
|
|
106
|
+
.map((r) => {
|
|
107
|
+
const p = [`${r.trigger}: ${r.effect}`];
|
|
108
|
+
if (r.duration != null)
|
|
109
|
+
p.push(`${r.duration}ms`);
|
|
110
|
+
if (r.easing)
|
|
111
|
+
p.push(inv[r.easing] && inv[r.easing] !== 'ease' ? inv[r.easing] : r.easing);
|
|
112
|
+
if (r.delay != null)
|
|
113
|
+
p.push(`delay ${r.delay}ms`);
|
|
114
|
+
if (r.stagger != null)
|
|
115
|
+
p.push(`stagger ${r.stagger}ms`);
|
|
116
|
+
if (r.once)
|
|
117
|
+
p.push('once');
|
|
118
|
+
for (const [k, v] of Object.entries(r.options))
|
|
119
|
+
p.push(`${k}=${v}`);
|
|
120
|
+
return p.join(' ');
|
|
121
|
+
})
|
|
122
|
+
.join('; ');
|
|
123
|
+
}
|
|
124
|
+
/** Tagged template: motion`enter: fade-up ${dur}ms` → the motion string (validated in dev via `parseMotion`) (9.0). */
|
|
125
|
+
function motion(strings, ...vals) {
|
|
126
|
+
return strings.reduce((a, s, i) => a + s + (i < vals.length ? String(vals[i]) : ''), '').replace(/\s+/g, ' ').trim();
|
|
127
|
+
}
|
|
128
|
+
/** Bind parsed rules (or a motion string) to one element; returns the cleanup (9.0). */
|
|
129
|
+
function bindMotion(el, rules, onError) {
|
|
130
|
+
const parsed = typeof rules === 'string' ? parseMotion(rules) : { rules, errors: [] };
|
|
131
|
+
parsed.errors.forEach((e) => onError?.(e));
|
|
132
|
+
const cleanups = [];
|
|
133
|
+
for (const r of parsed.rules) {
|
|
134
|
+
if (!hasEffect(r.effect)) {
|
|
135
|
+
onError?.(`"${r.effect}": effect not registered (register its pack or plugin first)`);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const opts = { ...r.options, trigger: r.trigger };
|
|
139
|
+
if (r.duration != null)
|
|
140
|
+
opts.duration = r.duration;
|
|
141
|
+
if (r.easing)
|
|
142
|
+
opts.easing = r.easing;
|
|
143
|
+
if (r.once)
|
|
144
|
+
opts.once = true;
|
|
145
|
+
const targets = r.stagger != null && el.children.length ? Array.from(el.children) : [el];
|
|
146
|
+
targets.forEach((t, i) => {
|
|
147
|
+
const delay = (r.delay || 0) + (r.stagger || 0) * i;
|
|
148
|
+
try {
|
|
149
|
+
cleanups.push(bindEffect(t, r.effect, delay ? { ...opts, delay } : opts));
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
onError?.(String(e.message || e));
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return () => cleanups.splice(0).forEach((c) => c());
|
|
157
|
+
}
|
|
158
|
+
/** Bind every `[data-motion]` under `root` (default `document`); `observe` also binds ones added later. Returns { errors, cleanup } (9.0). */
|
|
159
|
+
function applyMotion(root = document, opts = {}) {
|
|
160
|
+
const attr = opts.attribute || 'data-motion';
|
|
161
|
+
const errors = [];
|
|
162
|
+
const bound = new Map();
|
|
163
|
+
const bindOne = (el) => {
|
|
164
|
+
if (bound.has(el))
|
|
165
|
+
return;
|
|
166
|
+
bound.set(el, bindMotion(el, el.getAttribute(attr) || '', (m) => errors.push(m)));
|
|
167
|
+
};
|
|
168
|
+
const scan = (n) => {
|
|
169
|
+
if (n.hasAttribute?.(attr))
|
|
170
|
+
bindOne(n);
|
|
171
|
+
n.querySelectorAll?.(`[${attr}]`).forEach(bindOne);
|
|
172
|
+
};
|
|
173
|
+
scan(root);
|
|
174
|
+
let mo = null;
|
|
175
|
+
if (opts.observe && typeof MutationObserver !== 'undefined') {
|
|
176
|
+
mo = new MutationObserver((list) => list.forEach((m) => m.addedNodes.forEach((n) => n.nodeType === 1 && scan(n))));
|
|
177
|
+
mo.observe(root, { childList: true, subtree: true });
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
errors,
|
|
181
|
+
cleanup: () => {
|
|
182
|
+
mo?.disconnect();
|
|
183
|
+
bound.forEach((c) => c());
|
|
184
|
+
bound.clear();
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/** Build live markup from the 8.9 `describeComponent()` / `exportComponent(el, 'json')` format (9.0). */
|
|
189
|
+
function createComponent(desc) {
|
|
190
|
+
const d = typeof desc === 'string' ? JSON.parse(desc) : desc;
|
|
191
|
+
if (!d || typeof d.tag !== 'string' || !/^[a-z][a-z0-9-]*$/.test(d.tag) || d.tag === 'script')
|
|
192
|
+
throw new Error('[motionary] createComponent: invalid tag');
|
|
193
|
+
const el = document.createElement(d.tag);
|
|
194
|
+
for (const [k, v] of Object.entries(d.attrs || {}))
|
|
195
|
+
if (!/^on/i.test(k))
|
|
196
|
+
el.setAttribute(k, String(v));
|
|
197
|
+
for (const c of d.children || [])
|
|
198
|
+
el.append(typeof c === 'string' ? document.createTextNode(c) : createComponent(c));
|
|
199
|
+
return el;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export { applyMotion, bindMotion, createComponent, motion, parseMotion, serializeMotion };
|
|
203
|
+
//# sourceMappingURL=dsl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsl.js","sources":["../../src/components/dsl/index.ts"],"sourcesContent":["/**\n * `motionary/dsl` (= `motionary/components/dsl`, 9.0) — the declarative\n * motion DSL. Describe motion as one readable string instead of code:\n *\n * ```html\n * <section data-motion=\"enter: fade-up 600ms ease-out stagger 80ms; hover: pop; click: confetti count=40\">\n * ```\n *\n * Grammar — rules separated by `;`, each `trigger: effect [modifiers…]`:\n * - trigger: `enter` · `click` · `hover` · `load` · `loop` · `manual`\n * - effect: any registered effect name (timeline presets, packs, plugins)\n * - modifiers: a duration (`600ms` / `0.6s`), `delay 120ms`,\n * `stagger 80ms` (children one after another), an easing (`ease-out`,\n * `linear`, `spring`, `cubic-bezier(…)`, `steps(…)`), `once`, and\n * `key=value` effect options (numbers / booleans parsed).\n *\n * `parseMotion()` → rules + errors, `serializeMotion()` back to a string,\n * `motion\\`…\\`` tagged template, `applyMotion(root)` binds every\n * `[data-motion]` under `root` (and watches for new ones with `observe`),\n * `bindMotion(el, rules)` for one element, and `createComponent(json)`\n * builds live markup from the 8.9 `describeComponent()` JSON.\n */\nimport { bindEffect, hasEffect, EFFECT_TRIGGERS, type EffectTrigger } from '../fx/registry';\n\nexport interface MotionRule {\n trigger: EffectTrigger;\n effect: string;\n duration?: number;\n delay?: number;\n stagger?: number;\n easing?: string;\n once?: boolean;\n options: Record<string, string | number | boolean>;\n}\nexport interface MotionParse {\n rules: MotionRule[];\n errors: string[];\n}\n\nconst EASINGS: Record<string, string> = { ease: 'ease', 'ease-in': 'ease-in', 'ease-out': 'ease-out', 'ease-in-out': 'ease-in-out', linear: 'linear', spring: 'cubic-bezier(0.34, 1.56, 0.64, 1)', smooth: 'cubic-bezier(0.22, 1, 0.36, 1)' };\nconst TIME = /^(\\d+(?:\\.\\d+)?)(ms|s)$/;\nconst time = (t: string): number | undefined => {\n const m = t.match(TIME);\n return m ? Math.round(Number(m[1]) * (m[2] === 's' ? 1000 : 1)) : undefined;\n};\nconst value = (v: string): string | number | boolean => (v === 'true' ? true : v === 'false' ? false : v !== '' && !Number.isNaN(Number(v)) ? Number(v) : v);\n\n/** Split on whitespace, keeping `fn(…)` groups together. */\nfunction tokens(s: string): string[] {\n const out: string[] = [];\n let cur = '';\n let depth = 0;\n for (const ch of s) {\n if (ch === '(') depth++;\n if (ch === ')') depth = Math.max(0, depth - 1);\n if (/\\s/.test(ch) && !depth) {\n if (cur) out.push(cur);\n cur = '';\n } else cur += ch;\n }\n if (cur) out.push(cur);\n return out;\n}\n\n/** Parse a motion string into rules (+ human-readable errors for what was skipped) (9.0). */\nexport function parseMotion(src: string): MotionParse {\n const rules: MotionRule[] = [];\n const errors: string[] = [];\n for (const raw of src.split(';')) {\n const part = raw.trim();\n if (!part) continue;\n const i = part.indexOf(':');\n if (i < 0) {\n errors.push(`\"${part}\": expected \"trigger: effect\"`);\n continue;\n }\n const trigger = part.slice(0, i).trim() as EffectTrigger;\n if (!(EFFECT_TRIGGERS as readonly string[]).includes(trigger)) {\n errors.push(`\"${trigger}\": unknown trigger (${EFFECT_TRIGGERS.join(', ')})`);\n continue;\n }\n const [effect, ...mods] = tokens(part.slice(i + 1));\n if (!effect || !/^[a-z][a-z0-9-]*$/.test(effect)) {\n errors.push(`\"${part}\": missing effect name`);\n continue;\n }\n const r: MotionRule = { trigger, effect, options: {} };\n for (let k = 0; k < mods.length; k++) {\n const m = mods[k];\n if ((m === 'delay' || m === 'stagger') && time(mods[k + 1] || '') != null) r[m] = time(mods[++k]);\n else if (time(m) != null) r.duration = time(m);\n else if (m === 'once') r.once = true;\n else if (EASINGS[m]) r.easing = EASINGS[m];\n else if (/^(cubic-bezier|steps|linear)\\(.*\\)$/.test(m)) r.easing = m;\n else if (/^[a-zA-Z][\\w-]*=/.test(m)) {\n const j = m.indexOf('=');\n r.options[m.slice(0, j)] = value(m.slice(j + 1));\n } else errors.push(`\"${m}\" in \"${part}\": unknown modifier`);\n }\n rules.push(r);\n }\n return { rules, errors };\n}\n\n/** Rules back to the canonical motion string (9.0). */\nexport function serializeMotion(rules: MotionRule[]): string {\n const inv = Object.fromEntries(Object.entries(EASINGS).map(([k, v]) => [v, k]));\n return rules\n .map((r) => {\n const p: string[] = [`${r.trigger}: ${r.effect}`];\n if (r.duration != null) p.push(`${r.duration}ms`);\n if (r.easing) p.push(inv[r.easing] && inv[r.easing] !== 'ease' ? inv[r.easing] : r.easing);\n if (r.delay != null) p.push(`delay ${r.delay}ms`);\n if (r.stagger != null) p.push(`stagger ${r.stagger}ms`);\n if (r.once) p.push('once');\n for (const [k, v] of Object.entries(r.options)) p.push(`${k}=${v}`);\n return p.join(' ');\n })\n .join('; ');\n}\n\n/** Tagged template: motion`enter: fade-up ${dur}ms` → the motion string (validated in dev via `parseMotion`) (9.0). */\nexport function motion(strings: TemplateStringsArray, ...vals: unknown[]): string {\n return strings.reduce((a, s, i) => a + s + (i < vals.length ? String(vals[i]) : ''), '').replace(/\\s+/g, ' ').trim();\n}\n\n/** Bind parsed rules (or a motion string) to one element; returns the cleanup (9.0). */\nexport function bindMotion(el: HTMLElement, rules: MotionRule[] | string, onError?: (msg: string) => void): () => void {\n const parsed = typeof rules === 'string' ? parseMotion(rules) : { rules, errors: [] };\n parsed.errors.forEach((e) => onError?.(e));\n const cleanups: (() => void)[] = [];\n for (const r of parsed.rules) {\n if (!hasEffect(r.effect)) {\n onError?.(`\"${r.effect}\": effect not registered (register its pack or plugin first)`);\n continue;\n }\n const opts: Record<string, unknown> = { ...r.options, trigger: r.trigger };\n if (r.duration != null) opts.duration = r.duration;\n if (r.easing) opts.easing = r.easing;\n if (r.once) opts.once = true;\n const targets = r.stagger != null && el.children.length ? (Array.from(el.children) as HTMLElement[]) : [el];\n targets.forEach((t, i) => {\n const delay = (r.delay || 0) + (r.stagger || 0) * i;\n try {\n cleanups.push(bindEffect(t, r.effect, delay ? { ...opts, delay } : opts));\n } catch (e) {\n onError?.(String((e as Error).message || e));\n }\n });\n }\n return () => cleanups.splice(0).forEach((c) => c());\n}\n\n/** Bind every `[data-motion]` under `root` (default `document`); `observe` also binds ones added later. Returns { errors, cleanup } (9.0). */\nexport function applyMotion(root: ParentNode = document, opts: { observe?: boolean; attribute?: string } = {}): { errors: string[]; cleanup: () => void } {\n const attr = opts.attribute || 'data-motion';\n const errors: string[] = [];\n const bound = new Map<Element, () => void>();\n const bindOne = (el: Element) => {\n if (bound.has(el)) return;\n bound.set(el, bindMotion(el as HTMLElement, el.getAttribute(attr) || '', (m) => errors.push(m)));\n };\n const scan = (n: ParentNode) => {\n if ((n as Element).hasAttribute?.(attr)) bindOne(n as Element);\n n.querySelectorAll?.(`[${attr}]`).forEach(bindOne);\n };\n scan(root);\n let mo: MutationObserver | null = null;\n if (opts.observe && typeof MutationObserver !== 'undefined') {\n mo = new MutationObserver((list) => list.forEach((m) => m.addedNodes.forEach((n) => n.nodeType === 1 && scan(n as Element))));\n mo.observe(root as Node, { childList: true, subtree: true });\n }\n return {\n errors,\n cleanup: () => {\n mo?.disconnect();\n bound.forEach((c) => c());\n bound.clear();\n },\n };\n}\n\nexport interface ComponentJSON {\n $schema?: string;\n tag: string;\n attrs?: Record<string, string>;\n children?: (ComponentJSON | string)[];\n}\n/** Build live markup from the 8.9 `describeComponent()` / `exportComponent(el, 'json')` format (9.0). */\nexport function createComponent(desc: ComponentJSON | string): Element {\n const d: ComponentJSON = typeof desc === 'string' ? JSON.parse(desc) : desc;\n if (!d || typeof d.tag !== 'string' || !/^[a-z][a-z0-9-]*$/.test(d.tag) || d.tag === 'script') throw new Error('[motionary] createComponent: invalid tag');\n const el = document.createElement(d.tag);\n for (const [k, v] of Object.entries(d.attrs || {})) if (!/^on/i.test(k)) el.setAttribute(k, String(v));\n for (const c of d.children || []) el.append(typeof c === 'string' ? document.createTextNode(c) : createComponent(c));\n return el;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1124,7 +1124,7 @@ const P = (enter, hover, click, attention, background) => ({
|
|
|
1124
1124
|
attention: { effect: attention },
|
|
1125
1125
|
background: { effect: background },
|
|
1126
1126
|
});
|
|
1127
|
-
const
|
|
1127
|
+
const MOTION_THEMES = {
|
|
1128
1128
|
neon: {
|
|
1129
1129
|
name: 'neon',
|
|
1130
1130
|
vars: { bg: '#07070c', fg: '#e8e8ff', accent: '#22d3ee', 'accent-2': '#ff2bd6', surface: '#11111c', border: '1px solid #22d3ee', radius: '10px', shadow: '0 0 18px #22d3ee66, inset 0 0 12px #ff2bd622', font: 'ui-monospace, SFMono-Regular, Menlo, monospace' },
|
|
@@ -1156,15 +1156,15 @@ const THEMES = {
|
|
|
1156
1156
|
presets: P('drop-bounce', 'jelly', 'brutal-shift', 'shake', 'voronoi'),
|
|
1157
1157
|
},
|
|
1158
1158
|
};
|
|
1159
|
-
const
|
|
1159
|
+
const MOTION_THEME_NAMES = Object.keys(MOTION_THEMES);
|
|
1160
1160
|
const BASE_CSS = `[data-usa-theme]{background:var(--usa-theme-bg);color:var(--usa-theme-fg);font-family:var(--usa-theme-font)}
|
|
1161
1161
|
[data-usa-theme] .usa-surface{background:var(--usa-theme-surface);border:var(--usa-theme-border);border-radius:var(--usa-theme-radius);box-shadow:var(--usa-theme-shadow)}
|
|
1162
1162
|
[data-usa-theme] .usa-accent{color:var(--usa-theme-accent)}
|
|
1163
1163
|
[data-usa-theme=glass] .usa-surface{-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}`;
|
|
1164
1164
|
const pack = (t) => {
|
|
1165
|
-
const p = typeof t === 'string' ?
|
|
1165
|
+
const p = typeof t === 'string' ? MOTION_THEMES[t] : t;
|
|
1166
1166
|
if (!p)
|
|
1167
|
-
throw new Error(`[motionary] unknown theme "${String(t)}" — ${
|
|
1167
|
+
throw new Error(`[motionary] unknown theme "${String(t)}" — ${MOTION_THEME_NAMES.join(', ')}`);
|
|
1168
1168
|
return p;
|
|
1169
1169
|
};
|
|
1170
1170
|
/** The CSS custom properties of a theme (design + motion tokens). */
|
|
@@ -1180,8 +1180,8 @@ function themeCss(t, selector) {
|
|
|
1180
1180
|
const p = pack(t);
|
|
1181
1181
|
return `${selector || `[data-usa-theme=${p.name}]`}{${Object.entries(themeVars(p)).map(([k, v]) => `${k}:${v}`).join(';')}}`;
|
|
1182
1182
|
}
|
|
1183
|
-
/** Apply a theme to `root` (default `<html>`). Returns an undo. */
|
|
1184
|
-
function
|
|
1183
|
+
/** Apply a 5.8 motion theme to `root` (default `<html>`). Returns an undo (8.9). */
|
|
1184
|
+
function applyMotionTheme(t, root) {
|
|
1185
1185
|
const p = pack(t);
|
|
1186
1186
|
const el = root || document.documentElement;
|
|
1187
1187
|
base.adoptStyles('usa-theme', BASE_CSS);
|
|
@@ -1270,17 +1270,17 @@ const THEME_FX = [
|
|
|
1270
1270
|
},
|
|
1271
1271
|
];
|
|
1272
1272
|
/** `<usa-theme name="neon | paper | glass | retro | brutalist">` — a themed subtree. */
|
|
1273
|
-
function
|
|
1273
|
+
function defineMotionTheme(tag = 'usa-motion-theme') {
|
|
1274
1274
|
return base.defineElement(tag, (Base) => class UsaTheme extends Base {
|
|
1275
1275
|
static get observedAttributes() {
|
|
1276
1276
|
return ['name'];
|
|
1277
1277
|
}
|
|
1278
1278
|
get theme() {
|
|
1279
1279
|
const n = this.str('name', 'neon');
|
|
1280
|
-
return
|
|
1280
|
+
return MOTION_THEMES[n] ? n : 'neon';
|
|
1281
1281
|
}
|
|
1282
1282
|
mount() {
|
|
1283
|
-
this.onCleanup(
|
|
1283
|
+
this.onCleanup(applyMotionTheme(this.theme, this));
|
|
1284
1284
|
this.querySelectorAll('[data-theme-fx]').forEach((el) => {
|
|
1285
1285
|
const role = (el.dataset.themeFx || 'click');
|
|
1286
1286
|
if (!THEME_ROLES.includes(role))
|
|
@@ -1355,7 +1355,7 @@ function defineEffectElements() {
|
|
|
1355
1355
|
player.defineStory();
|
|
1356
1356
|
audio.defineAudio();
|
|
1357
1357
|
defineGestureFx();
|
|
1358
|
-
|
|
1358
|
+
defineMotionTheme();
|
|
1359
1359
|
player.definePlayer();
|
|
1360
1360
|
}
|
|
1361
1361
|
/** Register the built-ins and every pack (idempotent). */
|
|
@@ -1392,20 +1392,20 @@ exports.CURSOR_FX = CURSOR_FX;
|
|
|
1392
1392
|
exports.EFFECT_PACKS = EFFECT_PACKS;
|
|
1393
1393
|
exports.GESTURES = GESTURES;
|
|
1394
1394
|
exports.MICRO_FX = MICRO_FX;
|
|
1395
|
+
exports.MOTION_THEMES = MOTION_THEMES;
|
|
1396
|
+
exports.MOTION_THEME_NAMES = MOTION_THEME_NAMES;
|
|
1395
1397
|
exports.PAGE_FX = PAGE_FX;
|
|
1396
1398
|
exports.PHYSICS_FX = PHYSICS_FX;
|
|
1397
|
-
exports.THEMES = THEMES;
|
|
1398
1399
|
exports.THEME_FX = THEME_FX;
|
|
1399
|
-
exports.THEME_NAMES = THEME_NAMES;
|
|
1400
1400
|
exports.THEME_ROLES = THEME_ROLES;
|
|
1401
1401
|
exports.angleDelta = angleDelta;
|
|
1402
|
-
exports.
|
|
1402
|
+
exports.applyMotionTheme = applyMotionTheme;
|
|
1403
1403
|
exports.bindGesture = bindGesture;
|
|
1404
1404
|
exports.bounceKeyframes = bounceKeyframes;
|
|
1405
1405
|
exports.bumpCount = bumpCount;
|
|
1406
1406
|
exports.defineEffectElements = defineEffectElements;
|
|
1407
1407
|
exports.defineGestureFx = defineGestureFx;
|
|
1408
|
-
exports.
|
|
1408
|
+
exports.defineMotionTheme = defineMotionTheme;
|
|
1409
1409
|
exports.flingVelocity = flingVelocity;
|
|
1410
1410
|
exports.playThemeEffect = playThemeEffect;
|
|
1411
1411
|
exports.registerAllEffects = registerAllEffects;
|