@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.
- package/CHANGELOG.md +106 -0
- package/CODE_OF_CONDUCT.md +26 -0
- package/CONTRIBUTING.md +100 -0
- package/LICENSE +22 -0
- package/README.md +278 -0
- package/SECURITY.md +36 -0
- package/SUPPORT.md +38 -0
- package/TRADEMARKS.md +14 -0
- package/bin/synced-motion.mjs +5 -0
- package/dist/astro.d.ts +15 -0
- package/dist/astro.js +51 -0
- package/dist/astro.js.map +1 -0
- package/dist/chunk-24KKECMK.js +281 -0
- package/dist/chunk-24KKECMK.js.map +1 -0
- package/dist/chunk-3WUVBPYX.js +162 -0
- package/dist/chunk-3WUVBPYX.js.map +1 -0
- package/dist/chunk-HCWQV65E.js +20 -0
- package/dist/chunk-HCWQV65E.js.map +1 -0
- package/dist/chunk-JET2MYEG.js +2287 -0
- package/dist/chunk-JET2MYEG.js.map +1 -0
- package/dist/chunk-KA3OPI4F.js +40 -0
- package/dist/chunk-KA3OPI4F.js.map +1 -0
- package/dist/chunk-ML7HTCZT.js +642 -0
- package/dist/chunk-ML7HTCZT.js.map +1 -0
- package/dist/chunk-NIXAEIHN.js +23 -0
- package/dist/chunk-NIXAEIHN.js.map +1 -0
- package/dist/chunk-VOIQPPQZ.js +299 -0
- package/dist/chunk-VOIQPPQZ.js.map +1 -0
- package/dist/chunk-WCG7TQSH.js +31 -0
- package/dist/chunk-WCG7TQSH.js.map +1 -0
- package/dist/cli.js +382 -0
- package/dist/cli.js.map +1 -0
- package/dist/full.d.ts +13 -0
- package/dist/full.js +201 -0
- package/dist/full.js.map +1 -0
- package/dist/index.d.ts +249 -0
- package/dist/index.js +183 -0
- package/dist/index.js.map +1 -0
- package/dist/lenis.d.ts +19 -0
- package/dist/lenis.js +7 -0
- package/dist/lenis.js.map +1 -0
- package/dist/mcp.d.ts +16 -0
- package/dist/mcp.js +82 -0
- package/dist/mcp.js.map +1 -0
- package/dist/plugins.d.ts +14 -0
- package/dist/plugins.js +17 -0
- package/dist/plugins.js.map +1 -0
- package/dist/react.d.ts +7 -0
- package/dist/react.js +32 -0
- package/dist/react.js.map +1 -0
- package/dist/recipes.d.ts +76 -0
- package/dist/recipes.js +129 -0
- package/dist/recipes.js.map +1 -0
- package/dist/styles.css +57 -0
- package/dist/styles.css.map +1 -0
- package/dist/svelte.d.ts +10 -0
- package/dist/svelte.js +30 -0
- package/dist/svelte.js.map +1 -0
- package/dist/vue.d.ts +13 -0
- package/dist/vue.js +35 -0
- package/dist/vue.js.map +1 -0
- package/dist/wordpress.d.ts +15 -0
- package/dist/wordpress.js +49 -0
- package/dist/wordpress.js.map +1 -0
- package/docs/API.md +176 -0
- package/docs/ATTRIBUTE-API.md +358 -0
- package/docs/CAPABILITIES.md +82 -0
- package/docs/INTEGRATIONS.md +92 -0
- package/docs/PERFORMANCE.md +150 -0
- package/docs/README.md +35 -0
- package/docs/RECIPE-REFERENCE.md +1358 -0
- package/docs/RECIPES.md +115 -0
- package/docs/TOOLING.md +65 -0
- package/docs/WEBFLOW-MIGRATION.md +39 -0
- 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.
|
package/CONTRIBUTING.md
ADDED
|
@@ -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.
|
package/dist/astro.d.ts
ADDED
|
@@ -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
|