@syncedco/motion 0.1.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 (75) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/CODE_OF_CONDUCT.md +26 -0
  3. package/CONTRIBUTING.md +100 -0
  4. package/LICENSE +22 -0
  5. package/README.md +278 -0
  6. package/SECURITY.md +36 -0
  7. package/SUPPORT.md +38 -0
  8. package/TRADEMARKS.md +14 -0
  9. package/bin/synced-motion.mjs +5 -0
  10. package/dist/astro.d.ts +15 -0
  11. package/dist/astro.js +51 -0
  12. package/dist/astro.js.map +1 -0
  13. package/dist/chunk-24KKECMK.js +281 -0
  14. package/dist/chunk-24KKECMK.js.map +1 -0
  15. package/dist/chunk-3WUVBPYX.js +162 -0
  16. package/dist/chunk-3WUVBPYX.js.map +1 -0
  17. package/dist/chunk-HCWQV65E.js +20 -0
  18. package/dist/chunk-HCWQV65E.js.map +1 -0
  19. package/dist/chunk-JET2MYEG.js +2287 -0
  20. package/dist/chunk-JET2MYEG.js.map +1 -0
  21. package/dist/chunk-KA3OPI4F.js +40 -0
  22. package/dist/chunk-KA3OPI4F.js.map +1 -0
  23. package/dist/chunk-ML7HTCZT.js +642 -0
  24. package/dist/chunk-ML7HTCZT.js.map +1 -0
  25. package/dist/chunk-NIXAEIHN.js +23 -0
  26. package/dist/chunk-NIXAEIHN.js.map +1 -0
  27. package/dist/chunk-VOIQPPQZ.js +299 -0
  28. package/dist/chunk-VOIQPPQZ.js.map +1 -0
  29. package/dist/chunk-WCG7TQSH.js +31 -0
  30. package/dist/chunk-WCG7TQSH.js.map +1 -0
  31. package/dist/cli.js +382 -0
  32. package/dist/cli.js.map +1 -0
  33. package/dist/full.d.ts +13 -0
  34. package/dist/full.js +201 -0
  35. package/dist/full.js.map +1 -0
  36. package/dist/index.d.ts +249 -0
  37. package/dist/index.js +183 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/lenis.d.ts +19 -0
  40. package/dist/lenis.js +7 -0
  41. package/dist/lenis.js.map +1 -0
  42. package/dist/mcp.d.ts +16 -0
  43. package/dist/mcp.js +82 -0
  44. package/dist/mcp.js.map +1 -0
  45. package/dist/plugins.d.ts +14 -0
  46. package/dist/plugins.js +17 -0
  47. package/dist/plugins.js.map +1 -0
  48. package/dist/react.d.ts +7 -0
  49. package/dist/react.js +32 -0
  50. package/dist/react.js.map +1 -0
  51. package/dist/recipes.d.ts +76 -0
  52. package/dist/recipes.js +129 -0
  53. package/dist/recipes.js.map +1 -0
  54. package/dist/styles.css +57 -0
  55. package/dist/styles.css.map +1 -0
  56. package/dist/svelte.d.ts +10 -0
  57. package/dist/svelte.js +30 -0
  58. package/dist/svelte.js.map +1 -0
  59. package/dist/vue.d.ts +13 -0
  60. package/dist/vue.js +35 -0
  61. package/dist/vue.js.map +1 -0
  62. package/dist/wordpress.d.ts +15 -0
  63. package/dist/wordpress.js +49 -0
  64. package/dist/wordpress.js.map +1 -0
  65. package/docs/API.md +176 -0
  66. package/docs/ATTRIBUTE-API.md +358 -0
  67. package/docs/CAPABILITIES.md +82 -0
  68. package/docs/INTEGRATIONS.md +92 -0
  69. package/docs/PERFORMANCE.md +150 -0
  70. package/docs/README.md +35 -0
  71. package/docs/RECIPE-REFERENCE.md +1358 -0
  72. package/docs/RECIPES.md +115 -0
  73. package/docs/TOOLING.md +65 -0
  74. package/docs/WEBFLOW-MIGRATION.md +39 -0
  75. package/package.json +167 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,106 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## Versioning policy
9
+
10
+ - **Recipe IDs are public API.** Removing or renaming one is a major change.
11
+ - **Recipe behaviour** carries its own `version` field in the manifest. A
12
+ visual change to an existing recipe is a minor bump; a change to its root
13
+ selector, required slots or parameter bounds is a major one.
14
+ - **The attribute prefix is `data-motion-`.** Renaming it is a major change.
15
+ - **Bundle budgets** in `scripts/check-size.mjs` are part of the contract. They
16
+ are raised deliberately, never quietly.
17
+
18
+ ## [0.1.0] - 2026-09-25
19
+
20
+ Initial release: the recipe schema, compiler, registry and runtime; sixty
21
+ recipes across twelve families; the CLI and local MCP server; React, Vue,
22
+ Svelte, Astro and WordPress adapters; and the recipe gallery.
23
+
24
+ The notes below record what changed during pre-release hardening.
25
+
26
+ ### Removed — breaking
27
+
28
+ - **The `data-sf-*` attribute vocabulary is gone.** Every authoring attribute
29
+ is now `data-motion-*`, with no alias layer and no compatibility shim.
30
+ Runtime state attributes are `data-motion-runtime`, `data-motion-reduced`,
31
+ `data-motion-scroll-locked` and `data-motion-recipe`; custom events are
32
+ `motion:*`; the package's own custom properties are `--motion-*`. Synced
33
+ Flow's `--sf-colour-*`, `--sf-space-*` and `data-sf-theme` are untouched.
34
+
35
+ To migrate, rename `data-sf-` to `data-motion-` in your markup. There is no
36
+ deprecation period because the package has not been published.
37
+
38
+ - `normalizeMotionAliases`, `canonicalSelector`, `CANONICAL_ATTRIBUTE_PREFIX`
39
+ and `LEGACY_ATTRIBUTE_PREFIX` are removed, along with the CLI's
40
+ `--legacy-prefix` flag. Dropping the alias pass also removes a full-tree
41
+ attribute walk from every mount.
42
+
43
+ ### Added
44
+
45
+ - `@syncedco/motion/recipes` exports all sixty recipes individually, so a page
46
+ can bundle only the ones it uses.
47
+ - `@syncedco/motion/full` registers every optional GSAP plugin in one import,
48
+ preserving the previous batteries-included behaviour.
49
+ - `@syncedco/motion/plugins` exposes the optional plugin set for selective use.
50
+ - `data-motion-*` is the attribute vocabulary throughout. The runtime marks
51
+ state with `data-motion-runtime`, `data-motion-reduced`,
52
+ `data-motion-scroll-locked` and `data-motion-recipe`, and the package's own
53
+ custom properties are `--motion-*`.
54
+ - `synced-motion add <id...>` prints ready-to-paste markup with every required
55
+ slot, and warns when a recipe needs an optional plugin.
56
+ - `synced-motion --version` and per-command `--help`.
57
+ - Playwright browser tests covering one recipe per family: clean mount,
58
+ perceivable content, teardown and reduced motion, plus menu focus behaviour.
59
+ - `npm run size:check` enforces per-scenario gzip budgets against the built
60
+ package as a consumer installs it.
61
+ - `docs/RECIPE-REFERENCE.md`, generated from the registry and verified in CI.
62
+ - `docs/API.md` documenting the JavaScript surface: options, the runtime,
63
+ registries, `inspect()` diagnostics, the `setup` context and exported types.
64
+ - `docs/PERFORMANCE.md` covering entry points, per-recipe imports, optional
65
+ plugins, budgets and runtime cost.
66
+ - `CONTRIBUTING.md` and a `docs/README.md` index.
67
+ - Continuous integration across Node 20, 22 and 24, a browser-test job, a
68
+ tag-driven publish workflow and a GitHub Pages build for the gallery.
69
+
70
+ ### Changed
71
+
72
+ - **Authoring metadata no longer reaches the browser.** Recipes are split into
73
+ lean runtime specs and separate authoring metadata; prose, preview data and
74
+ fixture markup stay in the tooling path.
75
+ - **Optional GSAP plugins are opt-in.** The core imports gsap and ScrollTrigger
76
+ only. The forty-three recipes needing nothing else are unaffected; the other
77
+ seventeen are skipped with an actionable diagnostic until their plugin is
78
+ supplied.
79
+ - `createMotionRegistry` and `validateMotionRecipe` accept a `mode` option. The
80
+ default (`complete`) is unchanged.
81
+ - The menu moves focus when its entrance completes rather than on a fixed
82
+ timer.
83
+
84
+ ### Fixed
85
+
86
+ - The menu no longer fails to move focus into its panel. Focus was being set
87
+ 180 ms after opening, while the items were still `visibility: hidden` from
88
+ their entrance tween, so the call silently did nothing.
89
+ - Destroying the runtime no longer leaves an expanded menu panel visible; the
90
+ authored `hidden`, `aria-hidden` and `aria-expanded` state is restored.
91
+ - The menu closes on an outside click, and only returns focus to its trigger
92
+ when focus was inside the panel.
93
+ - A font-loading or window `load` event resolving after `destroy()` no longer
94
+ refreshes a torn-down runtime.
95
+ - Thirteen exports (`createMenus`, `createReveals`, `createSplitText` and
96
+ others) shipped without type declarations. Declaration coverage is now
97
+ verified against the real runtime exports of every entry point.
98
+ - The MCP server reports the real package version instead of a hard-coded one.
99
+
100
+ ### Payload
101
+
102
+ | Scenario | Before | After |
103
+ | --- | --- | --- |
104
+ | Three recipes | 16.2 kB gzip | 5.8 kB gzip |
105
+ | All sixty recipes | 25.4 kB gzip | 16.9 kB gzip |
106
+ | GSAP plugins forced on consumers | 6 | 1 (ScrollTrigger) |
@@ -0,0 +1,26 @@
1
+ # Code Of Conduct
2
+
3
+ Synced Motion aims to be a practical, respectful open-source project.
4
+
5
+ ## Expected Behaviour
6
+
7
+ - Be considerate and constructive.
8
+ - Keep feedback focused on the work.
9
+ - Assume good intent, and ask for clarification when something is unclear.
10
+ - Respect maintainers' time and project scope.
11
+ - Welcome people with different levels of animation, accessibility, GSAP, and
12
+ frontend experience.
13
+
14
+ ## Unacceptable Behaviour
15
+
16
+ - Harassment, threats, or personal attacks.
17
+ - Discriminatory language or behaviour.
18
+ - Repeated off-topic, hostile, or bad-faith comments.
19
+ - Publishing private information without permission.
20
+ - Pressuring maintainers for unpaid commercial support.
21
+
22
+ ## Reporting
23
+
24
+ Report conduct concerns to SyncedCo through [syncedco.com](https://syncedco.com).
25
+ Maintainers may remove comments, close issues, or block contributors when needed
26
+ to keep the project healthy.
@@ -0,0 +1,100 @@
1
+ # Contributing
2
+
3
+ Thanks for considering a contribution. By taking part you agree to the
4
+ [code of conduct](CODE_OF_CONDUCT.md). For vulnerabilities, follow the
5
+ [security policy](SECURITY.md) rather than opening an issue. For questions and
6
+ bug reports, see [support](SUPPORT.md).
7
+
8
+ ## Setup
9
+
10
+ ```bash
11
+ npm install
12
+ npx playwright install chromium # for browser tests
13
+ ```
14
+
15
+ ## The gate
16
+
17
+ ```bash
18
+ npm run check
19
+ ```
20
+
21
+ This is what CI runs. In order:
22
+
23
+ | Step | What it proves |
24
+ | --- | --- |
25
+ | `flow:check`, `flow:lint`, `flow:doctor` | The showcase's design system is valid and its generated CSS is current. |
26
+ | `units:check` | No stray `px`; fixed dimensions use tokens or `rem`. |
27
+ | `test` | Unit and DOM behaviour under jsdom. |
28
+ | `build` | The package builds and declarations are copied. |
29
+ | `types:check` | A consumer on NodeNext can import every subpath, and every runtime export is declared. |
30
+ | `size:check` | No bundle budget regressed. |
31
+ | `docs:check` | `docs/RECIPE-REFERENCE.md` matches the registry. |
32
+ | `motion:validate`, `motion:doctor` | Every recipe passes the schema; project wiring is intact. |
33
+ | `mcp:check` | The MCP server starts and exposes its tools. |
34
+
35
+ Browser tests are separate because they need a real engine:
36
+
37
+ ```bash
38
+ npm run test:browser # headless
39
+ npm run test:browser:ui # interactive
40
+ ```
41
+
42
+ **Run them whenever you change a pattern's DOM, focus or timing behaviour.**
43
+ jsdom has no layout, so ScrollTrigger never fires, SplitText never splits, Flip
44
+ measures nothing, and an element that is `visibility: hidden` will still accept
45
+ focus. Every one of those has hidden a real bug.
46
+
47
+ ## Adding a recipe
48
+
49
+ 1. Write the pattern factory in `src/patterns/`. It takes a context object and
50
+ returns a cleanup function, an object with `destroy()`, or an array of
51
+ either.
52
+ 2. Add the runtime spec to `src/recipes/specs.js`. Annotate both the
53
+ `spec(...)` call and the nested `setupFactory(...)` call with
54
+ `/* @__PURE__ */` so the recipe stays tree-shakeable.
55
+ 3. Add the prose to `src/recipes/authoring.js`. Never put prose or fixture
56
+ markup in `specs.js` — it would ship to every visitor.
57
+ 4. Add it to `builtinMotionSpecs`.
58
+ 5. `npm run docs:build` to regenerate the reference.
59
+ 6. Add a unit test, and a browser test if it involves focus, layout or timing.
60
+ 7. `npm run check && npm run test:browser`.
61
+
62
+ The validator will reject the recipe if it targets `html`, `body` or `:root`,
63
+ animates a layout property without `performance.allowLayout`, omits a declared
64
+ reduced-motion strategy, no-JavaScript behaviour or accessibility note, or
65
+ lacks a fixture whose markup contains the root and every required slot.
66
+
67
+ See [the recipe system](docs/RECIPES.md) for the full contract.
68
+
69
+ ## What the project will not accept
70
+
71
+ - jQuery, or a page-builder runtime dependency.
72
+ - A hard dependency on Synced Flow. The package is standalone.
73
+ - Optional GSAP plugins imported from the core. They belong in
74
+ `src/plugins.js` and `@syncedco/motion/full`.
75
+ - Authoring metadata reachable from the browser runtime.
76
+ - Motion that hides content it might fail to reveal.
77
+ - Inline colours, spacing or typography. Motion animates transforms, opacity
78
+ and semantic state.
79
+ - A recipe with no cleanup path.
80
+
81
+ ## Style
82
+
83
+ Match the surrounding code: no semicolons, single quotes, two-space indent,
84
+ named exports. Comments explain why, not what.
85
+
86
+ ## Commits and releases
87
+
88
+ Do not commit, push, publish or deploy without approval. Releases are
89
+ automated from [Conventional Commits](https://www.conventionalcommits.org/):
90
+ `fix:` is a patch and `feat:` is a minor. While the version is below 1.0.0, a
91
+ breaking change (`feat!:` or a `BREAKING CHANGE:` footer) is also a minor; from
92
+ 1.0.0 it is a major. Do not bump `package.json` or edit released
93
+ `CHANGELOG.md` entries by hand.
94
+
95
+ Every push to `main` updates a release pull request with the next version and
96
+ changelog. Merging it tags `vX.Y.Z`, creates the GitHub release, runs the full
97
+ gate including browser tests, and publishes to npm through trusted publishing.
98
+
99
+ See [CHANGELOG.md](CHANGELOG.md) for the versioning policy — recipe IDs and the
100
+ attribute prefix are public API, and bundle budgets are part of the contract.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SyncedCo Limited
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,278 @@
1
+ # Synced Motion
2
+
3
+ Accessible scroll and interaction animation for the web, in two attributes.
4
+
5
+ Sixty production recipes built on GSAP, where reduced motion, keyboard
6
+ behaviour, no-JavaScript fallbacks and deterministic cleanup are part of the
7
+ contract instead of something you remember to add later.
8
+
9
+ Framework-neutral. No jQuery, no page builder runtime, no generated class
10
+ names. Works in plain HTML, React, Vue, Svelte, Astro and WordPress.
11
+
12
+ ```bash
13
+ npm install @syncedco/motion gsap
14
+ ```
15
+
16
+ ## Five minutes
17
+
18
+ ```js
19
+ import { createSyncedMotion } from '@syncedco/motion'
20
+ import '@syncedco/motion/styles.css'
21
+
22
+ const motion = createSyncedMotion()
23
+ ```
24
+
25
+ ```html
26
+ <h1 data-motion-reveal="up">Engaging experiences without framework debt.</h1>
27
+
28
+ <ul data-motion-stagger>
29
+ <li data-motion-stagger-item>Discover</li>
30
+ <li data-motion-stagger-item>Compose</li>
31
+ <li data-motion-stagger-item>Ship</li>
32
+ </ul>
33
+ ```
34
+
35
+ That is the whole integration. The heading rises in as it enters the viewport,
36
+ the list cascades, and both stay exactly where you authored them if JavaScript
37
+ never runs or the visitor prefers reduced motion.
38
+
39
+ Call `motion.destroy()` on route change or hot reload.
40
+
41
+ Don't know the attribute you need? Ask for it:
42
+
43
+ ```bash
44
+ npx synced-motion add reveal-rise
45
+ ```
46
+
47
+ ## What makes it different
48
+
49
+ Most animation libraries hand you a tween and leave the hard parts to you.
50
+ Here every recipe must declare, and is tested against, four things:
51
+
52
+ | | |
53
+ | --- | --- |
54
+ | **Reduced motion** | What happens under `prefers-reduced-motion`. Never "nothing moves and the content is now invisible". |
55
+ | **Without JavaScript** | The authored state stays readable. Motion never hides content it might fail to reveal. |
56
+ | **Accessibility** | Reading order, focus order and native semantics are unchanged. |
57
+ | **Cleanup** | `destroy()` returns the DOM to how you wrote it. Verified in a real browser. |
58
+
59
+ The validator enforces this: it will not let a recipe target `body`, animate
60
+ layout properties without explicitly opting in, or ship without a declared
61
+ fallback.
62
+
63
+ ## Pay for what you use
64
+
65
+ The core imports GSAP and ScrollTrigger. Nothing else.
66
+
67
+ ```js
68
+ // All sixty recipes, ScrollTrigger only. 16.9 kB gzip
69
+ import { createSyncedMotion } from '@syncedco/motion'
70
+
71
+ // Only what this page uses. 5.8 kB gzip
72
+ import { createMotionRuntime, createMotionRegistry } from '@syncedco/motion'
73
+ import { revealRise, marquee } from '@syncedco/motion/recipes'
74
+
75
+ createMotionRuntime({
76
+ registry: createMotionRegistry([revealRise, marquee], { mode: 'runtime' }),
77
+ })
78
+ ```
79
+
80
+ Seventeen recipes need an optional GSAP plugin (SplitText, Flip, DrawSVG,
81
+ MorphSVG or MotionPath). Rather than putting all five in your bundle, the core
82
+ skips those recipes and tells you exactly what is missing:
83
+
84
+ ```js
85
+ motion.inspect().skipped
86
+ // [{ id: 'split-lines-rise', reason: 'missing-dependency',
87
+ // dependencies: ['SplitText'],
88
+ // fix: 'Pass { dependencies: { SplitText } } or import from "@syncedco/motion/full".' }]
89
+ ```
90
+
91
+ Two ways to resolve it:
92
+
93
+ ```js
94
+ // Everything, one import.
95
+ import { createSyncedMotion } from '@syncedco/motion/full'
96
+
97
+ // Or just the plugin you actually need.
98
+ import { SplitText } from 'gsap/SplitText'
99
+ createSyncedMotion({ dependencies: { SplitText } })
100
+ ```
101
+
102
+ These numbers are enforced by `npm run size:check`, measured against the built
103
+ package as a consumer installs it.
104
+
105
+ ## Browse the recipes
106
+
107
+ ```bash
108
+ npm run gallery
109
+ ```
110
+
111
+ Search all sixty, inspect their slots and fallbacks, tune bounded parameters,
112
+ simulate reduced motion, and copy the markup. Or read
113
+ [the generated reference](docs/RECIPE-REFERENCE.md), which is produced from the
114
+ registry so it cannot drift from the code.
115
+
116
+ ## Command line and agents
117
+
118
+ The CLI and the local MCP server share one side-effect-free service, so an
119
+ agent and a human get identical answers.
120
+
121
+ ```bash
122
+ npx synced-motion add reveal-rise # ready-to-paste markup
123
+ npx synced-motion suggest "cinematic pinned story"
124
+ npx synced-motion catalog --json
125
+ npx synced-motion scan --file src/page.html # find roots, report missing slots
126
+ npx synced-motion compose "restrained but cinematic" --file src/page.html
127
+ npx synced-motion doctor
128
+ npx synced-motion mcp # local stdio MCP server
129
+ ```
130
+
131
+ The MCP server is local and provider-agnostic. It uploads nothing and needs no
132
+ account. See [CLI and MCP tools](docs/TOOLING.md).
133
+
134
+ ## Frameworks and CMSs
135
+
136
+ ```js
137
+ import { useSyncedMotion } from '@syncedco/motion/react'
138
+ import { useSyncedMotion } from '@syncedco/motion/vue'
139
+ import { syncedMotion } from '@syncedco/motion/svelte'
140
+ import { createAstroMotion } from '@syncedco/motion/astro'
141
+ import { createWordPressMotion } from '@syncedco/motion/wordpress'
142
+ ```
143
+
144
+ React and Vue are optional peer dependencies. Svelte, Astro and WordPress use
145
+ small lifecycle adapters that keep their runtimes out of the core bundle. See
146
+ [Framework and CMS integrations](docs/INTEGRATIONS.md).
147
+
148
+ ## Pairs well with Synced Flow
149
+
150
+ Synced Motion works with any CSS — Tailwind, vanilla, CSS modules, your own
151
+ design system. It has no dependency on Synced Flow and never will.
152
+
153
+ That said, the two were built to the same rule, and it shows when you use them
154
+ together: **Flow decides what things look like, Motion decides how they
155
+ arrive.** Nothing in this package writes a colour, a spacing value or a font
156
+ size, so a theme change in Flow can never be undermined by a stale value baked
157
+ into an animation. There is no overlap to reconcile and no fight over
158
+ specificity.
159
+
160
+ ```bash
161
+ npm install @syncedco/flow @syncedco/motion gsap
162
+ ```
163
+
164
+ ```html
165
+ <!-- sf-* owns the look. data-motion-* owns the arrival. -->
166
+ <section class="sf-section">
167
+ <div class="sf-container sf-stack">
168
+ <p class="sf-kicker" data-motion-reveal="fade">A motion system</p>
169
+ <h1 class="sf-text-display" data-motion-split="lines">
170
+ Engaging experiences without framework debt.
171
+ </h1>
172
+ </div>
173
+ </section>
174
+ ```
175
+
176
+ The two vocabularies stay legible side by side: you can read that markup and
177
+ know exactly which package is responsible for what. Motion toggles semantic
178
+ state — `data-active`, `aria-current`, `aria-expanded` — and your CSS decides
179
+ how that state looks, which is the same seam whether or not the CSS is Flow's.
180
+
181
+ Keep brand tokens in `synced-flow.config.mjs`. This repository's showcase is a
182
+ worked example of the pairing; run `npm run dev` to see it.
183
+
184
+ ## Writing your own recipe
185
+
186
+ The built-ins are not a fixed menu. A custom recipe is the same contract:
187
+
188
+ ```js
189
+ import { createMotionRegistry, createMotionRuntime, defineMotionRecipe } from '@syncedco/motion'
190
+
191
+ const reveal = defineMotionRecipe({
192
+ schemaVersion: '1',
193
+ id: 'project-reveal',
194
+ version: '1.0.0',
195
+ title: 'Project reveal',
196
+ description: 'Reveals project cards in their local section.',
197
+ intent: 'Introduce project cards when the section enters the viewport.',
198
+ family: 'reveals',
199
+ tags: ['reveal', 'cards'],
200
+ root: { selector: '[data-motion-projects]' },
201
+ slots: [{ name: 'root' }, { name: 'items', selector: '[data-motion-project]', multiple: true }],
202
+ parameters: { duration: { type: 'number', default: 0.6, min: 0, max: 2 } },
203
+ triggers: [{ type: 'viewport' }],
204
+ reducedMotion: { strategy: 'final' },
205
+ noJs: { behavior: 'Cards remain visible in their authored final state.' },
206
+ accessibility: { notes: 'Reading and focus order never change.' },
207
+ performance: { class: 'low' },
208
+ dependencies: ['gsap'],
209
+ preview: { fixture: 'default', viewport: 'standard', activation: 'auto' },
210
+ fixtures: [{
211
+ id: 'default',
212
+ label: 'Default',
213
+ markup: '<section data-motion-projects><article data-motion-project>Project</article></section>',
214
+ parameters: {},
215
+ }],
216
+ setup({ gsap, slots, parameters, reduced }) {
217
+ if (reduced) return
218
+ const tween = gsap.from(slots.items, {
219
+ autoAlpha: 0, y: '1.5rem', duration: parameters.duration, stagger: 0.08,
220
+ })
221
+ return () => tween.revert()
222
+ },
223
+ })
224
+
225
+ createMotionRuntime({ registry: createMotionRegistry([reveal]) })
226
+ ```
227
+
228
+ Your recipe appears in the gallery, the CLI and the MCP server automatically.
229
+ See [the recipe system](docs/RECIPES.md).
230
+
231
+ ## Principles
232
+
233
+ - reduced motion by default;
234
+ - usable content when JavaScript fails;
235
+ - semantic state over inline visual values;
236
+ - transforms and opacity before layout animation;
237
+ - deterministic cleanup;
238
+ - framework-neutral browser APIs;
239
+ - no jQuery, no page builder runtime.
240
+
241
+ ## Documentation
242
+
243
+ [Full index](docs/README.md).
244
+
245
+ - [Recipe reference](docs/RECIPE-REFERENCE.md) — all sixty, generated
246
+ - [Declarative attribute API](docs/ATTRIBUTE-API.md)
247
+ - [JavaScript API](docs/API.md)
248
+ - [Bundle size and performance](docs/PERFORMANCE.md)
249
+ - [Motion recipe system](docs/RECIPES.md)
250
+ - [CLI and MCP tools](docs/TOOLING.md)
251
+ - [Framework and CMS integrations](docs/INTEGRATIONS.md)
252
+ - [Capability blueprint](docs/CAPABILITIES.md)
253
+ - [Webflow migration workflow](docs/WEBFLOW-MIGRATION.md)
254
+ - [Changelog](CHANGELOG.md)
255
+
256
+ ## Contributing
257
+
258
+ ```bash
259
+ npm install
260
+ npm run check # design system, units, tests, build, types, budgets, docs
261
+ npm run test:browser # Playwright; run npx playwright install chromium first
262
+ ```
263
+
264
+ `npm run check` is the same gate CI runs. See [CONTRIBUTING.md](CONTRIBUTING.md)
265
+ and the [code of conduct](CODE_OF_CONDUCT.md).
266
+
267
+ - [Support](SUPPORT.md) — where to ask, and what to include
268
+ - [Security policy](SECURITY.md) — please don't file vulnerabilities publicly
269
+ - [Trademarks](TRADEMARKS.md) — the licence covers the code, not the branding
270
+
271
+ ## Scope
272
+
273
+ This recreates the published-page capabilities an expressive marketing site
274
+ needs. It is not a hosted visual editor, a CMS, or a hosting product.
275
+
276
+ ## Licence
277
+
278
+ MIT © SyncedCo Limited. Maintained by [SyncedCo](https://syncedco.com).
package/SECURITY.md ADDED
@@ -0,0 +1,36 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ Security fixes target the latest published version and the current `main`
6
+ branch.
7
+
8
+ ## Reporting A Vulnerability
9
+
10
+ Please do not open a public GitHub issue for suspected vulnerabilities.
11
+
12
+ Report security concerns to SyncedCo through [syncedco.com](https://syncedco.com)
13
+ and include:
14
+
15
+ - affected package version or commit
16
+ - affected command, entry point, recipe, or integration
17
+ - reproduction steps
18
+ - expected and actual impact
19
+ - any relevant logs or runtime diagnostics from `motion.inspect()`
20
+
21
+ We will review the report, confirm whether the issue is valid, and coordinate a
22
+ fix before public disclosure where appropriate.
23
+
24
+ ## Scope
25
+
26
+ Security reports may include issues in the CLI, the local MCP server, package
27
+ distribution, the framework and CMS adapters, recipe `setup` execution, or the
28
+ examples and gallery.
29
+
30
+ Note that recipe `setup` functions are executable code. Registering a recipe
31
+ from an untrusted source runs that code with the privileges of the page, in the
32
+ same way importing any third-party module does. Treat recipe manifests from
33
+ outside your project as untrusted input.
34
+
35
+ General support questions, animation behaviour, and feature requests should use
36
+ [GitHub issues](https://github.com/SyncedCo/synced-motion/issues).
package/SUPPORT.md ADDED
@@ -0,0 +1,38 @@
1
+ # Support
2
+
3
+ Synced Motion is maintained by SyncedCo.
4
+
5
+ - Website: [syncedco.com](https://syncedco.com)
6
+ - GitHub: [github.com/SyncedCo/synced-motion](https://github.com/SyncedCo/synced-motion)
7
+ - Issues: [github.com/SyncedCo/synced-motion/issues](https://github.com/SyncedCo/synced-motion/issues)
8
+ - Security: [SECURITY.md](SECURITY.md)
9
+ - Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
10
+
11
+ ## Community Support
12
+
13
+ Use GitHub issues for reproducible bugs, documentation problems, CLI issues,
14
+ and focused feature requests for the open-source core.
15
+
16
+ Before opening an issue, please include:
17
+
18
+ - the package version and the GSAP version
19
+ - the framework or environment
20
+ - the recipe ID, or the markup that should have animated
21
+ - the output of `motion.inspect()`, which reports what mounted, what was
22
+ skipped and why, and any errors
23
+ - the expected and actual behaviour
24
+
25
+ If a recipe did nothing, check `inspect().skipped` first: a
26
+ `missing-dependency` entry means an optional GSAP plugin was not supplied, and
27
+ `missing-slots` means the markup was missing a required element. Both include
28
+ the fix.
29
+
30
+ ## Commercial And Team Support
31
+
32
+ For paid implementation, motion-system audits, accessibility review, migration
33
+ from Webflow interactions, training, workshops, or team support, contact
34
+ SyncedCo through [syncedco.com](https://syncedco.com).
35
+
36
+ Commercial services are optional support around the open-source core. Premium
37
+ templates, hosted tools, and paid starter kits are not included in this package
38
+ unless explicitly released separately.
package/TRADEMARKS.md ADDED
@@ -0,0 +1,14 @@
1
+ # Trademark And Brand Use
2
+
3
+ The MIT licence covers the Synced Motion software. It does not grant trademark,
4
+ brand, logo, or endorsement rights.
5
+
6
+ Names such as Synced, SyncedCo, and Synced Motion may be used to truthfully
7
+ refer to this project, compatibility, forks, or integrations.
8
+
9
+ Do not use Synced, SyncedCo, or Synced Motion names, logos, or branding in a way
10
+ that suggests official sponsorship, endorsement, partnership, or ownership
11
+ unless SyncedCo has given written permission.
12
+
13
+ Forks and derived projects should use a distinct name if they are distributed as
14
+ their own product.
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { runMotionCli } from '../dist/cli.js'
3
+
4
+ const result = await runMotionCli()
5
+ if (result.code) process.exitCode = result.code
@@ -0,0 +1,15 @@
1
+ import type { MotionRuntime, MotionRuntimeOptions } from './index.js'
2
+
3
+ export interface AstroMotionOptions extends Omit<MotionRuntimeOptions, 'root'> {
4
+ document?: Document
5
+ root?: Document | Element | string | (() => Document | Element | null | undefined)
6
+ }
7
+
8
+ export interface AstroMotionController {
9
+ readonly runtime: MotionRuntime | undefined
10
+ mount(): MotionRuntime | undefined
11
+ refresh(): void
12
+ destroy(): void
13
+ }
14
+
15
+ export declare function createAstroMotion(options?: AstroMotionOptions): AstroMotionController