use-scroll-animate 8.9.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +2 -2
  3. package/README_ja.md +2 -2
  4. package/README_zh.md +2 -2
  5. package/dist/chunks/manifest-B08-vo9G.cjs +81 -0
  6. package/dist/chunks/manifest-B08-vo9G.cjs.map +1 -0
  7. package/dist/chunks/manifest-PJ0h8RS_.js +76 -0
  8. package/dist/chunks/manifest-PJ0h8RS_.js.map +1 -0
  9. package/dist/components/dsl.cjs +210 -0
  10. package/dist/components/dsl.cjs.map +1 -0
  11. package/dist/components/dsl.d.cts +76 -0
  12. package/dist/components/dsl.d.ts +76 -0
  13. package/dist/components/dsl.js +203 -0
  14. package/dist/components/dsl.js.map +1 -0
  15. package/dist/components/effects.cjs +6 -29
  16. package/dist/components/effects.cjs.map +1 -1
  17. package/dist/components/effects.d.cts +3 -14
  18. package/dist/components/effects.d.ts +3 -14
  19. package/dist/components/effects.js +8 -27
  20. package/dist/components/effects.js.map +1 -1
  21. package/dist/components/fx2.cjs +5 -5
  22. package/dist/components/fx2.js +1 -1
  23. package/dist/components/marketplace.cjs +81 -71
  24. package/dist/components/marketplace.cjs.map +1 -1
  25. package/dist/components/marketplace.d.cts +33 -2
  26. package/dist/components/marketplace.d.ts +33 -2
  27. package/dist/components/marketplace.js +73 -68
  28. package/dist/components/marketplace.js.map +1 -1
  29. package/dist/components/widgets.cjs +323 -198
  30. package/dist/components/widgets.cjs.map +1 -1
  31. package/dist/components/widgets.d.cts +95 -2
  32. package/dist/components/widgets.d.ts +95 -2
  33. package/dist/components/widgets.js +322 -199
  34. package/dist/components/widgets.js.map +1 -1
  35. package/dist/components.umd.js +2 -2
  36. package/dist/components.umd.js.map +1 -1
  37. package/dist/widgets.umd.js +1 -1
  38. package/dist/widgets.umd.js.map +1 -1
  39. package/docs/ROADMAP.md +12 -14
  40. package/docs/components.md +25 -5
  41. package/docs/deprecations.md +1 -1
  42. package/docs/upgrading-9.md +11 -1
  43. package/package.json +31 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [9.0.0] - 2026-10-09
11
+
12
+ ### ⚠ Breaking
13
+ - Removed the 8.9 deprecations: `applyTheme()`, `THEMES`, `THEME_NAMES`, `<usa-theme>` / `defineTheme()` (`motionary/components/effects`). Use `applyMotionTheme()`, `MOTION_THEMES`, `MOTION_THEME_NAMES`, `<usa-motion-theme>` / `defineMotionTheme()` — same behaviour. `npx usa-codemod-9 --write src` rewrites identifiers and tags; see [docs/upgrading-9.md](docs/upgrading-9.md).
14
+
15
+ ### Added
16
+ - **Declarative motion DSL — `motionary/dsl`** (= `motionary/components/dsl`): one readable string per element — `data-motion="enter: fade-up 600ms ease-out stagger 80ms; hover: pop; click: confetti count=40"`. Triggers `enter` · `click` · `hover` · `load` · `loop` · `manual`; modifiers: duration (`600ms` / `0.6s`), `delay`, `stagger` (children in turn — `delay` / `stagger` are passed as the effect's `delay` option, honoured by the entrance presets and every effect that takes one), easing (`ease-out`, `spring`, `smooth`, `cubic-bezier(…)`, `steps(…)`), `once`, `key=value` effect options. `applyMotion(root, { observe })`, `bindMotion(el, rules)`, `parseMotion()` (rules + readable errors), `serializeMotion()`, `motion` tagged template, `createComponent(json)` (builds live markup from the 8.9 `describeComponent()` JSON).
17
+ - **Plugin marketplace GA — `motionary/marketplace`** (`motionary/components/marketplace` now re-exports it and keeps the 6.9 manifest API): `MARKETPLACE` (first-party catalogue of the 8.x effect packs), `searchPlugins(query)`, `installPlugin(listing | url, { load })` (first-party registrar or validated third-party pack), `installedPlugins()`, `fetchMarketplace(url)` (`motionary/marketplace` v1 index).
18
+ - **2 new components (9.0)** in `motionary/components/widgets`: `<usa-motion rules="…">` (the DSL as an element; `parsed`, `errors`, `usa:motion-error`) and `<usa-plugin-store>` (search + one-click install with staggered result cards; `plugins`, `loader`, `search()`, `install()`; `usa:install` / `usa:install-error`).
19
+ - Chinese roadmap 9.1 → 10.0 (`docs/ROADMAP.md`). `motionary` and `use-scroll-animate` are published with the npm `latest` tag.
20
+
21
+ ### Accessibility
22
+ - `<usa-plugin-store>` is a labelled `search` region with a labelled search field, a live result count and real buttons whose text reports the install state. `<usa-motion>` adds no semantics; effects bound by the DSL honour reduced motion like every other effect.
23
+
24
+ ### Fixed
25
+ - `<usa-plugin-store>` called `CSS.escape` without checking that the `CSS` global exists (throws in jsdom / some SSR shims) — now guarded with a fallback.
26
+ - the 9.0 removal check treated the internal style-sheet id and the theme switcher's `localStorage` key `'usa-theme'` as leftovers of `<usa-theme>`; they are kept (saved theme choices survive the upgrade).
27
+ - the gallery / Store motion-theme cards still named the removed `defineTheme` (they would not have defined their element) → `defineMotionTheme`.
28
+
10
29
  ## [8.9.0] - 2026-10-09
11
30
 
12
31
  ### Added
package/README.md CHANGED
@@ -134,7 +134,7 @@ Animated components need no framework at all:
134
134
  | **Generative backgrounds** | 6 canvas backgrounds (flow-field, voronoi, mesh-gradient, starfield, metaballs, contours) + 9 background elements (aurora, particles, grain, blobs, water ripple, Acrylic / Mica, …) |
135
135
  | **Sound-reactive** | `<usa-audio>` + Web Audio beat detection (`createBeatDetector()`, `onBeat()`); 3 audio visualisers (spectrum-bars, pulse-ring, wave-ring); any effect can fire on the beat |
136
136
  | **Cursor & gestures** | 5 cursor effects (comet / ribbon / sparkle trails, magnetic dots, spotlight) + `<usa-cursor>`; fling · twist · long-press → effects with `<usa-gesture-fx>`; `<usa-swipeable>`, `<usa-pinch-zoom>` |
137
- | **Themes** | 5 theme packs (neon · paper · glass · retro · brutalist) via `<usa-theme>` / `applyTheme()`, each with a signature effect; motion tokens (`/components/tokens`) |
137
+ | **Themes** | 5 theme packs (neon · paper · glass · retro · brutalist) via `<usa-motion-theme>` / `applyMotionTheme()`, each with a signature effect; motion tokens (`/components/tokens`) |
138
138
  | **Micro-interactions** | 23 ready-made UI moments: copy-success, like-heart, add-to-cart, send-plane, upvote, trash-shake, input-shake, success-check, notify-badge, … |
139
139
  | **`<usa-player>` & stories** | `<usa-player>` plays JSON animations (keyframe tracks, presets, effects; load / view / scroll / click triggers) exported from the Playground; `<usa-story>` with 6 scroll-story templates |
140
140
  | **WebGL** | `<usa-shader>`, `<usa-distort>`, `<usa-liquid>`, `<usa-post-fx>` — 5 particle presets, 9 post effects (bloom, CRT, chromatic, glitch, …) with CSS fallbacks and a power-saving governor |
@@ -166,7 +166,7 @@ Import one category (`motionary/components/cards`), everything (`motionary/compo
166
166
  | **Layout** (`/components/layout`) | `<usa-auto-animate>` · `<usa-masonry>` |
167
167
  | **Packs** (`/components/packs`) | `<usa-pack>` |
168
168
  | **Effect registry** (`/components/fx`) | `<usa-fx>` |
169
- | **Effect packs** (`/components/effects`) | `<usa-player>` · `<usa-story>` · `<usa-audio>` · `<usa-theme>` · `<usa-gesture-fx>` |
169
+ | **Effect packs** (`/components/effects`) | `<usa-player>` · `<usa-story>` · `<usa-audio>` · `<usa-motion-theme>` · `<usa-gesture-fx>` |
170
170
 
171
171
  ## Accessibility & reduced motion
172
172
 
package/README_ja.md CHANGED
@@ -132,7 +132,7 @@ export class Hero {}
132
132
  | **ジェネラティブ背景** | キャンバス背景 6 種(flow-field・voronoi・mesh-gradient・starfield・metaballs・contours)+ 背景要素 9 種(オーロラ・パーティクル・グレイン・Acrylic / Mica など) |
133
133
  | **サウンド連動** | `<usa-audio>` と Web Audio のビート検出(`createBeatDetector()`・`onBeat()`)、オーディオビジュアライザー 3 種、任意のエフェクトをビートで発火 |
134
134
  | **カーソル・ジェスチャー** | カーソルエフェクト 5 種 + `<usa-cursor>`、fling · twist · long-press でエフェクト(`<usa-gesture-fx>`)、`<usa-swipeable>`・`<usa-pinch-zoom>` |
135
- | **テーマ** | テーマ 5 種(neon · paper · glass · retro · brutalist)を `<usa-theme>` / `applyTheme()` で、各テーマに専用エフェクト。モーショントークン(`/components/tokens`) |
135
+ | **テーマ** | テーマ 5 種(neon · paper · glass · retro · brutalist)を `<usa-motion-theme>` / `applyMotionTheme()` で、各テーマに専用エフェクト。モーショントークン(`/components/tokens`) |
136
136
  | **マイクロインタラクション** | 既製の UI 演出 23 種:copy-success・like-heart・add-to-cart・send-plane・upvote・trash-shake など |
137
137
  | **`<usa-player>` とストーリー** | `<usa-player>` は Playground から書き出した JSON アニメーションを再生(キーフレーム・プリセット・エフェクト、load / view / scroll / click トリガー)。`<usa-story>` のストーリーテンプレート 6 種 |
138
138
  | **WebGL** | `<usa-shader>`・`<usa-distort>`・`<usa-liquid>`・`<usa-post-fx>` — パーティクル 5 種、ポストエフェクト 9 種(CSS フォールバックと省電力制御付き) |
@@ -164,7 +164,7 @@ export class Hero {}
164
164
  | **レイアウト** (`/components/layout`) | `<usa-auto-animate>` · `<usa-masonry>` |
165
165
  | **パック** (`/components/packs`) | `<usa-pack>` |
166
166
  | **エフェクト登録** (`/components/fx`) | `<usa-fx>` |
167
- | **エフェクトパック** (`/components/effects`) | `<usa-player>` · `<usa-story>` · `<usa-audio>` · `<usa-theme>` · `<usa-gesture-fx>` |
167
+ | **エフェクトパック** (`/components/effects`) | `<usa-player>` · `<usa-story>` · `<usa-audio>` · `<usa-motion-theme>` · `<usa-gesture-fx>` |
168
168
 
169
169
  ## アクセシビリティと reduced motion
170
170
 
package/README_zh.md CHANGED
@@ -132,7 +132,7 @@ export class Hero {}
132
132
  | **生成式背景** | 6 种画布背景(flow-field、voronoi、mesh-gradient、starfield、metaballs、contours)+ 9 个背景元素(极光、粒子、胶片颗粒、流体色块、水波、亚克力 / 云母……) |
133
133
  | **声音响应** | `<usa-audio>` + Web Audio 节拍检测(`createBeatDetector()`、`onBeat()`);3 种音频可视化(spectrum-bars、pulse-ring、wave-ring);任意效果都可随节拍触发 |
134
134
  | **光标与手势** | 5 种光标效果(彗星 / 丝带 / 星光拖尾、磁性圆点、聚光灯)+ `<usa-cursor>`;甩动 · 旋转 · 长按触发效果(`<usa-gesture-fx>`);`<usa-swipeable>`、`<usa-pinch-zoom>` |
135
- | **主题** | 5 套主题(neon · paper · glass · retro · brutalist),通过 `<usa-theme>` / `applyTheme()` 使用,各带一个标志性效果;动效令牌(`/components/tokens`) |
135
+ | **主题** | 5 套主题(neon · paper · glass · retro · brutalist),通过 `<usa-motion-theme>` / `applyMotionTheme()` 使用,各带一个标志性效果;动效令牌(`/components/tokens`) |
136
136
  | **微交互** | 23 个现成的界面瞬间:copy-success、like-heart、add-to-cart、send-plane、upvote、trash-shake、input-shake、success-check、notify-badge…… |
137
137
  | **`<usa-player>` 与滚动叙事** | `<usa-player>` 播放 JSON 动画(关键帧轨道、预设、效果;load / view / scroll / click 触发),可从 Playground 导出;`<usa-story>` 含 6 个滚动叙事模板 |
138
138
  | **WebGL** | `<usa-shader>`、`<usa-distort>`、`<usa-liquid>`、`<usa-post-fx>` —— 5 个粒子预设、9 种后期效果(bloom、CRT、色散、故障……),带 CSS 降级与省电调速 |
@@ -164,7 +164,7 @@ export class Hero {}
164
164
  | **布局** (`/components/layout`) | `<usa-auto-animate>` · `<usa-masonry>` |
165
165
  | **效果包** (`/components/packs`) | `<usa-pack>` |
166
166
  | **效果注册表** (`/components/fx`) | `<usa-fx>` |
167
- | **效果包** (`/components/effects`) | `<usa-player>` · `<usa-story>` · `<usa-audio>` · `<usa-theme>` · `<usa-gesture-fx>` |
167
+ | **效果包** (`/components/effects`) | `<usa-player>` · `<usa-story>` · `<usa-audio>` · `<usa-motion-theme>` · `<usa-gesture-fx>` |
168
168
 
169
169
  ## 无障碍与减少动态效果
170
170
 
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+
3
+ var registry = require('./registry-BVklOepd.cjs');
4
+
5
+ const EFFECT_PACK_FORMAT = 'motionary/effect-pack';
6
+ const SEMVER = /^\d+\.\d+\.\d+(?:-[\w.]+)?$/;
7
+ const PKG = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
8
+ /** Build a manifest from an effect pack. */
9
+ function packManifest(name, packVersion, effects, extra = {}) {
10
+ return {
11
+ format: EFFECT_PACK_FORMAT,
12
+ version: 1,
13
+ name,
14
+ packVersion,
15
+ ...extra,
16
+ effects: effects.map((e) => ({ name: e.name, kind: e.kind, ...(e.description ? { description: e.description } : {}), ...(e.defaults ? { defaults: JSON.parse(JSON.stringify(e.defaults)) } : {}) })),
17
+ };
18
+ }
19
+ /** Check a manifest (and optionally the module's effects against it). */
20
+ function validateManifest(m, effects) {
21
+ const errors = [];
22
+ const x = m;
23
+ if (!x || typeof x !== 'object')
24
+ return { ok: false, errors: ['manifest must be an object'] };
25
+ if (x.format !== EFFECT_PACK_FORMAT)
26
+ errors.push(`format must be "${EFFECT_PACK_FORMAT}"`);
27
+ if (x.version !== 1)
28
+ errors.push('version must be 1');
29
+ if (!x.name || !PKG.test(x.name))
30
+ errors.push('name must be an npm package name');
31
+ if (!x.packVersion || !SEMVER.test(x.packVersion))
32
+ errors.push('packVersion must be semver (x.y.z)');
33
+ if (!Array.isArray(x.effects) || !x.effects.length)
34
+ errors.push('effects must be a non-empty array');
35
+ const seen = new Set();
36
+ for (const e of x.effects || []) {
37
+ if (!e || !/^[a-z][a-z0-9-]*$/.test(e.name || ''))
38
+ errors.push(`invalid effect name "${e?.name}"`);
39
+ else if (seen.has(e.name))
40
+ errors.push(`duplicate effect "${e.name}"`);
41
+ else
42
+ seen.add(e.name);
43
+ if (!e || !registry.EFFECT_KINDS.includes(e.kind))
44
+ errors.push(`effect "${e?.name}": unknown kind "${e?.kind}"`);
45
+ }
46
+ if (effects) {
47
+ const names = new Set(effects.map((e) => e.name));
48
+ for (const n of seen)
49
+ if (!names.has(n))
50
+ errors.push(`effect "${n}" is in the manifest but not exported`);
51
+ for (const n of names)
52
+ if (!seen.has(n))
53
+ errors.push(`effect "${n}" is exported but missing from the manifest`);
54
+ }
55
+ return { ok: !errors.length, errors };
56
+ }
57
+ /**
58
+ * Import an effect pack (a URL / specifier, or an already imported module
59
+ * with `effects` / `default` and `manifest`), validate and register it.
60
+ * Returns the registered effect names.
61
+ */
62
+ async function loadEffectPack(src, opts = {}) {
63
+ const mod = typeof src === 'string' ? await import(/* @vite-ignore */ src) : src;
64
+ const effects = mod.effects || mod.default || [];
65
+ const manifest = opts.manifest || mod.manifest;
66
+ const v = validateManifest(manifest, effects);
67
+ if (!v.ok)
68
+ throw new Error(`[motionary] invalid effect pack: ${v.errors.join('; ')}`);
69
+ const clash = effects.filter((e) => registry.hasEffect(e.name));
70
+ if (clash.length && !opts.override)
71
+ throw new Error(`[motionary] effect pack "${manifest.name}" would replace ${clash.map((e) => e.name).join(', ')} (pass { override: true })`);
72
+ for (const e of effects)
73
+ registry.registerEffect(e, { override: !!opts.override });
74
+ return effects.map((e) => e.name);
75
+ }
76
+
77
+ exports.EFFECT_PACK_FORMAT = EFFECT_PACK_FORMAT;
78
+ exports.loadEffectPack = loadEffectPack;
79
+ exports.packManifest = packManifest;
80
+ exports.validateManifest = validateManifest;
81
+ //# sourceMappingURL=manifest-B08-vo9G.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-B08-vo9G.cjs","sources":["../../src/components/fx2/manifest.ts"],"sourcesContent":["/**\n * 6.9 — effect marketplace manifest (`motionary/components/marketplace`).\n *\n * A third-party effect pack is an ES module that exports its effects (an\n * `EffectDefinition[]` as `effects` or `default`) plus a JSON manifest:\n *\n * ```json\n * { \"format\": \"motionary/effect-pack\", \"version\": 1,\n * \"name\": \"@acme/motion-snow\", \"packVersion\": \"1.2.0\",\n * \"description\": \"Snow and frost effects\", \"license\": \"MIT\",\n * \"author\": \"Acme\", \"entry\": \"./dist/index.js\", \"requires\": \">=6.9\",\n * \"effects\": [{ \"name\": \"frost\", \"kind\": \"background\", \"description\": \"…\",\n * \"defaults\": { \"speed\": 1 } }] }\n * ```\n *\n * `packManifest()` writes one from your effects, `validateManifest()` checks\n * one (format, semver, unique kebab-case names, known kinds, effects match\n * the module), and `loadEffectPack()` imports a pack (URL or module),\n * validates it and registers its effects — refusing names that already\n * exist unless `override`.\n */\nimport type { EffectDefinition } from '../fx/registry';\nimport { EFFECT_KINDS, registerEffect, hasEffect } from '../fx/registry';\n\nexport const EFFECT_PACK_FORMAT = 'motionary/effect-pack';\n\nexport interface EffectPackManifest {\n format: typeof EFFECT_PACK_FORMAT;\n version: 1;\n name: string;\n packVersion: string;\n description?: string;\n license?: string;\n author?: string;\n homepage?: string;\n entry?: string;\n requires?: string;\n keywords?: string[];\n effects: { name: string; kind: string; description?: string; defaults?: Record<string, unknown> }[];\n}\n\nconst SEMVER = /^\\d+\\.\\d+\\.\\d+(?:-[\\w.]+)?$/;\nconst PKG = /^(?:@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/;\n\n/** Build a manifest from an effect pack. */\nexport function packManifest(name: string, packVersion: string, effects: EffectDefinition[], extra: Partial<Omit<EffectPackManifest, 'format' | 'version' | 'name' | 'packVersion' | 'effects'>> = {}): EffectPackManifest {\n return {\n format: EFFECT_PACK_FORMAT,\n version: 1,\n name,\n packVersion,\n ...extra,\n effects: effects.map((e) => ({ name: e.name, kind: e.kind, ...(e.description ? { description: e.description } : {}), ...(e.defaults ? { defaults: JSON.parse(JSON.stringify(e.defaults)) } : {}) })),\n };\n}\n\n/** Check a manifest (and optionally the module's effects against it). */\nexport function validateManifest(m: unknown, effects?: EffectDefinition[]): { ok: boolean; errors: string[] } {\n const errors: string[] = [];\n const x = m as Partial<EffectPackManifest> | null;\n if (!x || typeof x !== 'object') return { ok: false, errors: ['manifest must be an object'] };\n if (x.format !== EFFECT_PACK_FORMAT) errors.push(`format must be \"${EFFECT_PACK_FORMAT}\"`);\n if (x.version !== 1) errors.push('version must be 1');\n if (!x.name || !PKG.test(x.name)) errors.push('name must be an npm package name');\n if (!x.packVersion || !SEMVER.test(x.packVersion)) errors.push('packVersion must be semver (x.y.z)');\n if (!Array.isArray(x.effects) || !x.effects.length) errors.push('effects must be a non-empty array');\n const seen = new Set<string>();\n for (const e of x.effects || []) {\n if (!e || !/^[a-z][a-z0-9-]*$/.test(e.name || '')) errors.push(`invalid effect name \"${e?.name}\"`);\n else if (seen.has(e.name)) errors.push(`duplicate effect \"${e.name}\"`);\n else seen.add(e.name);\n if (!e || !(EFFECT_KINDS as readonly string[]).includes(e.kind)) errors.push(`effect \"${e?.name}\": unknown kind \"${e?.kind}\"`);\n }\n if (effects) {\n const names = new Set(effects.map((e) => e.name));\n for (const n of seen) if (!names.has(n)) errors.push(`effect \"${n}\" is in the manifest but not exported`);\n for (const n of names) if (!seen.has(n)) errors.push(`effect \"${n}\" is exported but missing from the manifest`);\n }\n return { ok: !errors.length, errors };\n}\n\n/**\n * Import an effect pack (a URL / specifier, or an already imported module\n * with `effects` / `default` and `manifest`), validate and register it.\n * Returns the registered effect names.\n */\nexport async function loadEffectPack(src: string | { effects?: EffectDefinition[]; default?: EffectDefinition[]; manifest?: EffectPackManifest }, opts: { manifest?: EffectPackManifest; override?: boolean } = {}): Promise<string[]> {\n const mod: any = typeof src === 'string' ? await import(/* @vite-ignore */ src) : src;\n const effects: EffectDefinition[] = mod.effects || mod.default || [];\n const manifest = opts.manifest || mod.manifest;\n const v = validateManifest(manifest, effects);\n if (!v.ok) throw new Error(`[motionary] invalid effect pack: ${v.errors.join('; ')}`);\n const clash = effects.filter((e) => hasEffect(e.name));\n if (clash.length && !opts.override) throw new Error(`[motionary] effect pack \"${manifest.name}\" would replace ${clash.map((e) => e.name).join(', ')} (pass { override: true })`);\n for (const e of effects) registerEffect(e, { override: !!opts.override });\n return effects.map((e) => e.name);\n}\n"],"names":["EFFECT_KINDS","hasEffect","registerEffect"],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import { hasEffect, registerEffect, EFFECT_KINDS } from './registry-CnO7ZVPK.js';
2
+
3
+ const EFFECT_PACK_FORMAT = 'motionary/effect-pack';
4
+ const SEMVER = /^\d+\.\d+\.\d+(?:-[\w.]+)?$/;
5
+ const PKG = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
6
+ /** Build a manifest from an effect pack. */
7
+ function packManifest(name, packVersion, effects, extra = {}) {
8
+ return {
9
+ format: EFFECT_PACK_FORMAT,
10
+ version: 1,
11
+ name,
12
+ packVersion,
13
+ ...extra,
14
+ effects: effects.map((e) => ({ name: e.name, kind: e.kind, ...(e.description ? { description: e.description } : {}), ...(e.defaults ? { defaults: JSON.parse(JSON.stringify(e.defaults)) } : {}) })),
15
+ };
16
+ }
17
+ /** Check a manifest (and optionally the module's effects against it). */
18
+ function validateManifest(m, effects) {
19
+ const errors = [];
20
+ const x = m;
21
+ if (!x || typeof x !== 'object')
22
+ return { ok: false, errors: ['manifest must be an object'] };
23
+ if (x.format !== EFFECT_PACK_FORMAT)
24
+ errors.push(`format must be "${EFFECT_PACK_FORMAT}"`);
25
+ if (x.version !== 1)
26
+ errors.push('version must be 1');
27
+ if (!x.name || !PKG.test(x.name))
28
+ errors.push('name must be an npm package name');
29
+ if (!x.packVersion || !SEMVER.test(x.packVersion))
30
+ errors.push('packVersion must be semver (x.y.z)');
31
+ if (!Array.isArray(x.effects) || !x.effects.length)
32
+ errors.push('effects must be a non-empty array');
33
+ const seen = new Set();
34
+ for (const e of x.effects || []) {
35
+ if (!e || !/^[a-z][a-z0-9-]*$/.test(e.name || ''))
36
+ errors.push(`invalid effect name "${e?.name}"`);
37
+ else if (seen.has(e.name))
38
+ errors.push(`duplicate effect "${e.name}"`);
39
+ else
40
+ seen.add(e.name);
41
+ if (!e || !EFFECT_KINDS.includes(e.kind))
42
+ errors.push(`effect "${e?.name}": unknown kind "${e?.kind}"`);
43
+ }
44
+ if (effects) {
45
+ const names = new Set(effects.map((e) => e.name));
46
+ for (const n of seen)
47
+ if (!names.has(n))
48
+ errors.push(`effect "${n}" is in the manifest but not exported`);
49
+ for (const n of names)
50
+ if (!seen.has(n))
51
+ errors.push(`effect "${n}" is exported but missing from the manifest`);
52
+ }
53
+ return { ok: !errors.length, errors };
54
+ }
55
+ /**
56
+ * Import an effect pack (a URL / specifier, or an already imported module
57
+ * with `effects` / `default` and `manifest`), validate and register it.
58
+ * Returns the registered effect names.
59
+ */
60
+ async function loadEffectPack(src, opts = {}) {
61
+ const mod = typeof src === 'string' ? await import(/* @vite-ignore */ src) : src;
62
+ const effects = mod.effects || mod.default || [];
63
+ const manifest = opts.manifest || mod.manifest;
64
+ const v = validateManifest(manifest, effects);
65
+ if (!v.ok)
66
+ throw new Error(`[motionary] invalid effect pack: ${v.errors.join('; ')}`);
67
+ const clash = effects.filter((e) => hasEffect(e.name));
68
+ if (clash.length && !opts.override)
69
+ throw new Error(`[motionary] effect pack "${manifest.name}" would replace ${clash.map((e) => e.name).join(', ')} (pass { override: true })`);
70
+ for (const e of effects)
71
+ registerEffect(e, { override: !!opts.override });
72
+ return effects.map((e) => e.name);
73
+ }
74
+
75
+ export { EFFECT_PACK_FORMAT as E, loadEffectPack as l, packManifest as p, validateManifest as v };
76
+ //# sourceMappingURL=manifest-PJ0h8RS_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-PJ0h8RS_.js","sources":["../../src/components/fx2/manifest.ts"],"sourcesContent":["/**\n * 6.9 — effect marketplace manifest (`motionary/components/marketplace`).\n *\n * A third-party effect pack is an ES module that exports its effects (an\n * `EffectDefinition[]` as `effects` or `default`) plus a JSON manifest:\n *\n * ```json\n * { \"format\": \"motionary/effect-pack\", \"version\": 1,\n * \"name\": \"@acme/motion-snow\", \"packVersion\": \"1.2.0\",\n * \"description\": \"Snow and frost effects\", \"license\": \"MIT\",\n * \"author\": \"Acme\", \"entry\": \"./dist/index.js\", \"requires\": \">=6.9\",\n * \"effects\": [{ \"name\": \"frost\", \"kind\": \"background\", \"description\": \"…\",\n * \"defaults\": { \"speed\": 1 } }] }\n * ```\n *\n * `packManifest()` writes one from your effects, `validateManifest()` checks\n * one (format, semver, unique kebab-case names, known kinds, effects match\n * the module), and `loadEffectPack()` imports a pack (URL or module),\n * validates it and registers its effects — refusing names that already\n * exist unless `override`.\n */\nimport type { EffectDefinition } from '../fx/registry';\nimport { EFFECT_KINDS, registerEffect, hasEffect } from '../fx/registry';\n\nexport const EFFECT_PACK_FORMAT = 'motionary/effect-pack';\n\nexport interface EffectPackManifest {\n format: typeof EFFECT_PACK_FORMAT;\n version: 1;\n name: string;\n packVersion: string;\n description?: string;\n license?: string;\n author?: string;\n homepage?: string;\n entry?: string;\n requires?: string;\n keywords?: string[];\n effects: { name: string; kind: string; description?: string; defaults?: Record<string, unknown> }[];\n}\n\nconst SEMVER = /^\\d+\\.\\d+\\.\\d+(?:-[\\w.]+)?$/;\nconst PKG = /^(?:@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/;\n\n/** Build a manifest from an effect pack. */\nexport function packManifest(name: string, packVersion: string, effects: EffectDefinition[], extra: Partial<Omit<EffectPackManifest, 'format' | 'version' | 'name' | 'packVersion' | 'effects'>> = {}): EffectPackManifest {\n return {\n format: EFFECT_PACK_FORMAT,\n version: 1,\n name,\n packVersion,\n ...extra,\n effects: effects.map((e) => ({ name: e.name, kind: e.kind, ...(e.description ? { description: e.description } : {}), ...(e.defaults ? { defaults: JSON.parse(JSON.stringify(e.defaults)) } : {}) })),\n };\n}\n\n/** Check a manifest (and optionally the module's effects against it). */\nexport function validateManifest(m: unknown, effects?: EffectDefinition[]): { ok: boolean; errors: string[] } {\n const errors: string[] = [];\n const x = m as Partial<EffectPackManifest> | null;\n if (!x || typeof x !== 'object') return { ok: false, errors: ['manifest must be an object'] };\n if (x.format !== EFFECT_PACK_FORMAT) errors.push(`format must be \"${EFFECT_PACK_FORMAT}\"`);\n if (x.version !== 1) errors.push('version must be 1');\n if (!x.name || !PKG.test(x.name)) errors.push('name must be an npm package name');\n if (!x.packVersion || !SEMVER.test(x.packVersion)) errors.push('packVersion must be semver (x.y.z)');\n if (!Array.isArray(x.effects) || !x.effects.length) errors.push('effects must be a non-empty array');\n const seen = new Set<string>();\n for (const e of x.effects || []) {\n if (!e || !/^[a-z][a-z0-9-]*$/.test(e.name || '')) errors.push(`invalid effect name \"${e?.name}\"`);\n else if (seen.has(e.name)) errors.push(`duplicate effect \"${e.name}\"`);\n else seen.add(e.name);\n if (!e || !(EFFECT_KINDS as readonly string[]).includes(e.kind)) errors.push(`effect \"${e?.name}\": unknown kind \"${e?.kind}\"`);\n }\n if (effects) {\n const names = new Set(effects.map((e) => e.name));\n for (const n of seen) if (!names.has(n)) errors.push(`effect \"${n}\" is in the manifest but not exported`);\n for (const n of names) if (!seen.has(n)) errors.push(`effect \"${n}\" is exported but missing from the manifest`);\n }\n return { ok: !errors.length, errors };\n}\n\n/**\n * Import an effect pack (a URL / specifier, or an already imported module\n * with `effects` / `default` and `manifest`), validate and register it.\n * Returns the registered effect names.\n */\nexport async function loadEffectPack(src: string | { effects?: EffectDefinition[]; default?: EffectDefinition[]; manifest?: EffectPackManifest }, opts: { manifest?: EffectPackManifest; override?: boolean } = {}): Promise<string[]> {\n const mod: any = typeof src === 'string' ? await import(/* @vite-ignore */ src) : src;\n const effects: EffectDefinition[] = mod.effects || mod.default || [];\n const manifest = opts.manifest || mod.manifest;\n const v = validateManifest(manifest, effects);\n if (!v.ok) throw new Error(`[motionary] invalid effect pack: ${v.errors.join('; ')}`);\n const clash = effects.filter((e) => hasEffect(e.name));\n if (clash.length && !opts.override) throw new Error(`[motionary] effect pack \"${manifest.name}\" would replace ${clash.map((e) => e.name).join(', ')} (pass { override: true })`);\n for (const e of effects) registerEffect(e, { override: !!opts.override });\n return effects.map((e) => e.name);\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,210 @@
1
+ 'use strict';
2
+
3
+ var registry = require('../chunks/registry-BVklOepd.cjs');
4
+ require('../chunks/base-DoRUZBy-.cjs');
5
+
6
+ /**
7
+ * `motionary/dsl` (= `motionary/components/dsl`, 9.0) — the declarative
8
+ * motion DSL. Describe motion as one readable string instead of code:
9
+ *
10
+ * ```html
11
+ * <section data-motion="enter: fade-up 600ms ease-out stagger 80ms; hover: pop; click: confetti count=40">
12
+ * ```
13
+ *
14
+ * Grammar — rules separated by `;`, each `trigger: effect [modifiers…]`:
15
+ * - trigger: `enter` · `click` · `hover` · `load` · `loop` · `manual`
16
+ * - effect: any registered effect name (timeline presets, packs, plugins)
17
+ * - modifiers: a duration (`600ms` / `0.6s`), `delay 120ms`,
18
+ * `stagger 80ms` (children one after another), an easing (`ease-out`,
19
+ * `linear`, `spring`, `cubic-bezier(…)`, `steps(…)`), `once`, and
20
+ * `key=value` effect options (numbers / booleans parsed).
21
+ *
22
+ * `parseMotion()` → rules + errors, `serializeMotion()` back to a string,
23
+ * `motion\`…\`` tagged template, `applyMotion(root)` binds every
24
+ * `[data-motion]` under `root` (and watches for new ones with `observe`),
25
+ * `bindMotion(el, rules)` for one element, and `createComponent(json)`
26
+ * builds live markup from the 8.9 `describeComponent()` JSON.
27
+ */
28
+ 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)' };
29
+ const TIME = /^(\d+(?:\.\d+)?)(ms|s)$/;
30
+ const time = (t) => {
31
+ const m = t.match(TIME);
32
+ return m ? Math.round(Number(m[1]) * (m[2] === 's' ? 1000 : 1)) : undefined;
33
+ };
34
+ const value = (v) => (v === 'true' ? true : v === 'false' ? false : v !== '' && !Number.isNaN(Number(v)) ? Number(v) : v);
35
+ /** Split on whitespace, keeping `fn(…)` groups together. */
36
+ function tokens(s) {
37
+ const out = [];
38
+ let cur = '';
39
+ let depth = 0;
40
+ for (const ch of s) {
41
+ if (ch === '(')
42
+ depth++;
43
+ if (ch === ')')
44
+ depth = Math.max(0, depth - 1);
45
+ if (/\s/.test(ch) && !depth) {
46
+ if (cur)
47
+ out.push(cur);
48
+ cur = '';
49
+ }
50
+ else
51
+ cur += ch;
52
+ }
53
+ if (cur)
54
+ out.push(cur);
55
+ return out;
56
+ }
57
+ /** Parse a motion string into rules (+ human-readable errors for what was skipped) (9.0). */
58
+ function parseMotion(src) {
59
+ const rules = [];
60
+ const errors = [];
61
+ for (const raw of src.split(';')) {
62
+ const part = raw.trim();
63
+ if (!part)
64
+ continue;
65
+ const i = part.indexOf(':');
66
+ if (i < 0) {
67
+ errors.push(`"${part}": expected "trigger: effect"`);
68
+ continue;
69
+ }
70
+ const trigger = part.slice(0, i).trim();
71
+ if (!registry.EFFECT_TRIGGERS.includes(trigger)) {
72
+ errors.push(`"${trigger}": unknown trigger (${registry.EFFECT_TRIGGERS.join(', ')})`);
73
+ continue;
74
+ }
75
+ const [effect, ...mods] = tokens(part.slice(i + 1));
76
+ if (!effect || !/^[a-z][a-z0-9-]*$/.test(effect)) {
77
+ errors.push(`"${part}": missing effect name`);
78
+ continue;
79
+ }
80
+ const r = { trigger, effect, options: {} };
81
+ for (let k = 0; k < mods.length; k++) {
82
+ const m = mods[k];
83
+ if ((m === 'delay' || m === 'stagger') && time(mods[k + 1] || '') != null)
84
+ r[m] = time(mods[++k]);
85
+ else if (time(m) != null)
86
+ r.duration = time(m);
87
+ else if (m === 'once')
88
+ r.once = true;
89
+ else if (EASINGS[m])
90
+ r.easing = EASINGS[m];
91
+ else if (/^(cubic-bezier|steps|linear)\(.*\)$/.test(m))
92
+ r.easing = m;
93
+ else if (/^[a-zA-Z][\w-]*=/.test(m)) {
94
+ const j = m.indexOf('=');
95
+ r.options[m.slice(0, j)] = value(m.slice(j + 1));
96
+ }
97
+ else
98
+ errors.push(`"${m}" in "${part}": unknown modifier`);
99
+ }
100
+ rules.push(r);
101
+ }
102
+ return { rules, errors };
103
+ }
104
+ /** Rules back to the canonical motion string (9.0). */
105
+ function serializeMotion(rules) {
106
+ const inv = Object.fromEntries(Object.entries(EASINGS).map(([k, v]) => [v, k]));
107
+ return rules
108
+ .map((r) => {
109
+ const p = [`${r.trigger}: ${r.effect}`];
110
+ if (r.duration != null)
111
+ p.push(`${r.duration}ms`);
112
+ if (r.easing)
113
+ p.push(inv[r.easing] && inv[r.easing] !== 'ease' ? inv[r.easing] : r.easing);
114
+ if (r.delay != null)
115
+ p.push(`delay ${r.delay}ms`);
116
+ if (r.stagger != null)
117
+ p.push(`stagger ${r.stagger}ms`);
118
+ if (r.once)
119
+ p.push('once');
120
+ for (const [k, v] of Object.entries(r.options))
121
+ p.push(`${k}=${v}`);
122
+ return p.join(' ');
123
+ })
124
+ .join('; ');
125
+ }
126
+ /** Tagged template: motion`enter: fade-up ${dur}ms` → the motion string (validated in dev via `parseMotion`) (9.0). */
127
+ function motion(strings, ...vals) {
128
+ return strings.reduce((a, s, i) => a + s + (i < vals.length ? String(vals[i]) : ''), '').replace(/\s+/g, ' ').trim();
129
+ }
130
+ /** Bind parsed rules (or a motion string) to one element; returns the cleanup (9.0). */
131
+ function bindMotion(el, rules, onError) {
132
+ const parsed = typeof rules === 'string' ? parseMotion(rules) : { rules, errors: [] };
133
+ parsed.errors.forEach((e) => onError?.(e));
134
+ const cleanups = [];
135
+ for (const r of parsed.rules) {
136
+ if (!registry.hasEffect(r.effect)) {
137
+ onError?.(`"${r.effect}": effect not registered (register its pack or plugin first)`);
138
+ continue;
139
+ }
140
+ const opts = { ...r.options, trigger: r.trigger };
141
+ if (r.duration != null)
142
+ opts.duration = r.duration;
143
+ if (r.easing)
144
+ opts.easing = r.easing;
145
+ if (r.once)
146
+ opts.once = true;
147
+ const targets = r.stagger != null && el.children.length ? Array.from(el.children) : [el];
148
+ targets.forEach((t, i) => {
149
+ const delay = (r.delay || 0) + (r.stagger || 0) * i;
150
+ try {
151
+ cleanups.push(registry.bindEffect(t, r.effect, delay ? { ...opts, delay } : opts));
152
+ }
153
+ catch (e) {
154
+ onError?.(String(e.message || e));
155
+ }
156
+ });
157
+ }
158
+ return () => cleanups.splice(0).forEach((c) => c());
159
+ }
160
+ /** Bind every `[data-motion]` under `root` (default `document`); `observe` also binds ones added later. Returns { errors, cleanup } (9.0). */
161
+ function applyMotion(root = document, opts = {}) {
162
+ const attr = opts.attribute || 'data-motion';
163
+ const errors = [];
164
+ const bound = new Map();
165
+ const bindOne = (el) => {
166
+ if (bound.has(el))
167
+ return;
168
+ bound.set(el, bindMotion(el, el.getAttribute(attr) || '', (m) => errors.push(m)));
169
+ };
170
+ const scan = (n) => {
171
+ if (n.hasAttribute?.(attr))
172
+ bindOne(n);
173
+ n.querySelectorAll?.(`[${attr}]`).forEach(bindOne);
174
+ };
175
+ scan(root);
176
+ let mo = null;
177
+ if (opts.observe && typeof MutationObserver !== 'undefined') {
178
+ mo = new MutationObserver((list) => list.forEach((m) => m.addedNodes.forEach((n) => n.nodeType === 1 && scan(n))));
179
+ mo.observe(root, { childList: true, subtree: true });
180
+ }
181
+ return {
182
+ errors,
183
+ cleanup: () => {
184
+ mo?.disconnect();
185
+ bound.forEach((c) => c());
186
+ bound.clear();
187
+ },
188
+ };
189
+ }
190
+ /** Build live markup from the 8.9 `describeComponent()` / `exportComponent(el, 'json')` format (9.0). */
191
+ function createComponent(desc) {
192
+ const d = typeof desc === 'string' ? JSON.parse(desc) : desc;
193
+ if (!d || typeof d.tag !== 'string' || !/^[a-z][a-z0-9-]*$/.test(d.tag) || d.tag === 'script')
194
+ throw new Error('[motionary] createComponent: invalid tag');
195
+ const el = document.createElement(d.tag);
196
+ for (const [k, v] of Object.entries(d.attrs || {}))
197
+ if (!/^on/i.test(k))
198
+ el.setAttribute(k, String(v));
199
+ for (const c of d.children || [])
200
+ el.append(typeof c === 'string' ? document.createTextNode(c) : createComponent(c));
201
+ return el;
202
+ }
203
+
204
+ exports.applyMotion = applyMotion;
205
+ exports.bindMotion = bindMotion;
206
+ exports.createComponent = createComponent;
207
+ exports.motion = motion;
208
+ exports.parseMotion = parseMotion;
209
+ exports.serializeMotion = serializeMotion;
210
+ //# sourceMappingURL=dsl.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsl.cjs","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":["EFFECT_TRIGGERS","hasEffect","bindEffect"],"mappings":"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"}
@@ -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 };