@motion.page/sdk 0.1.1 → 0.1.2

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 (4) hide show
  1. package/LICENSE +113 -0
  2. package/README.md +125 -43
  3. package/llms.txt +64 -0
  4. package/package.json +4 -3
package/LICENSE ADDED
@@ -0,0 +1,113 @@
1
+ Functional Source License, Version 1.1, Apache 2.0 Future License
2
+
3
+ Abbreviation
4
+
5
+ FSL-1.1-Apache-2.0
6
+
7
+ Notice
8
+
9
+ Copyright © 2025 Motion.page (David Babinec)
10
+
11
+ Terms and Conditions
12
+
13
+ Licensor: Motion.page (David Babinec)
14
+ Licensed Work: @motion.page/sdk
15
+ The Licensed Work is copyright © 2025 Motion.page (David Babinec).
16
+ Additional Use Grant: None
17
+ Change Date: The earlier of the date two years after the date the Licensed Work
18
+ is made available under this License, or a date specified by the
19
+ Licensor.
20
+ Change License: Apache License, Version 2.0
21
+
22
+ For information about alternative licensing arrangements for the Licensed Work,
23
+ please contact: hello@motion.page
24
+
25
+ ---
26
+
27
+ Functional Source License, Version 1.1, Apache 2.0 Future License
28
+
29
+ Purpose
30
+
31
+ This license gives you broad permission to use, modify, and share the software
32
+ for any purpose, with one condition: you may not use it to compete with us.
33
+ Once the change date passes, this software converts to the Apache 2.0 license.
34
+
35
+ Acceptance
36
+
37
+ To use the Licensed Work, you must agree to all the terms of this license.
38
+ The license is between you and the Licensor.
39
+
40
+ Copyright License
41
+
42
+ The Licensor grants you a non-exclusive, worldwide, royalty-free copyright license
43
+ to use, copy, distribute, make available, and prepare derivative works of the
44
+ Licensed Work, with the condition that you exercise these rights only for
45
+ Permitted Purposes.
46
+
47
+ Patent License
48
+
49
+ The Licensor grants you a non-exclusive, worldwide, royalty-free patent license
50
+ under patents that the Licensor can license, or becomes able to license, to make,
51
+ have made, use, sell, offer for sale, import, and have imported the Licensed Work,
52
+ with the condition that you exercise these rights only for Permitted Purposes.
53
+
54
+ Permitted Purposes
55
+
56
+ A Permitted Purpose is any purpose other than a Competing Use.
57
+
58
+ A Competing Use means use of the Licensed Work in or for a commercial product or
59
+ service that competes with the Licensed Work or any other product or service the
60
+ Licensor or any of its affiliates provides using the Licensed Work. Competing
61
+ products and services include, but are not limited to, no-code animation builders,
62
+ visual animation editors, visual timeline editors, or similar software tools that
63
+ enable users to create, edit, or manage animations through a visual interface,
64
+ which compete with the Licensed Work or any product or service the Licensor
65
+ provides using the Licensed Work.
66
+
67
+ Goods and services compete even when they provide functionality through different
68
+ kinds of interfaces or for different technical platforms. Applications can compete
69
+ with services, libraries with plugins, frameworks with development tools, and so
70
+ on, even if they are written in different programming languages or for different
71
+ computer architectures. Goods and services compete even when provided free of
72
+ charge.
73
+
74
+ If you have questions about whether your use qualifies as a Permitted Purpose,
75
+ or if you would like to negotiate an alternative licensing arrangement, please
76
+ contact the Licensor at hello@motion.page.
77
+
78
+ Notices
79
+
80
+ You must ensure that anyone who receives a copy of any part of the Licensed Work
81
+ from you also receives a copy of this license, and that anyone who modifies the
82
+ Licensed Work provides reasonable notice that they have modified it.
83
+
84
+ No Other Rights
85
+
86
+ This license does not grant you any right in any trademark or logo of the
87
+ Licensor or its affiliates.
88
+
89
+ Termination
90
+
91
+ If you violate any term of this license, your rights under it terminate
92
+ immediately.
93
+
94
+ No Liability
95
+
96
+ As far as the law allows, the Licensed Work comes as-is, without any warranty
97
+ or condition, and the Licensor will not be liable to you for any damages arising
98
+ out of these terms or the use or nature of the Licensed Work, under any kind of
99
+ legal claim.
100
+
101
+ Change Date
102
+
103
+ On the Change Date, the Licensed Work will become available under the Change
104
+ License. The Change Date is the earlier of:
105
+ - Two years after the date the Licensed Work was first made available under
106
+ this License, or
107
+ - A date the Licensor specifies.
108
+
109
+ Change License
110
+
111
+ On and after the Change Date, you may use the Licensed Work under the terms of
112
+ the Apache License, Version 2.0 (the "Change License"), as published by the
113
+ Apache Software Foundation.
package/README.md CHANGED
@@ -3,8 +3,8 @@
3
3
  A high-performance animation SDK with a declarative API. Scroll-triggered animations, page transitions, custom cursors, gesture controls, text splitting, and more — zero runtime dependencies.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@motion.page/sdk)](https://www.npmjs.com/package/@motion.page/sdk)
6
- ![Bundle Size](https://img.shields.io/bundlephobia/minzip/@motion.page/sdk)
7
- ![License](https://img.shields.io/badge/license-Proprietary-red)
6
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@motion.page/sdk)](https://bundlephobia.com/package/@motion.page/sdk)
7
+ [![License](https://img.shields.io/badge/license-FSL--1.1--Apache--2.0-blue)](./LICENSE)
8
8
 
9
9
  ---
10
10
 
@@ -13,6 +13,7 @@ A high-performance animation SDK with a declarative API. Scroll-triggered animat
13
13
  - [Installation](#installation)
14
14
  - [Quick Start](#quick-start)
15
15
  - [Core Concept](#core-concept)
16
+ - [Implicit Values](#implicit-values)
16
17
  - [API Reference](#api-reference)
17
18
  - [Motion()](#motion-function)
18
19
  - [Motion Static Methods](#motion-static-methods)
@@ -41,6 +42,10 @@ yarn add @motion.page/sdk
41
42
  pnpm add @motion.page/sdk
42
43
  ```
43
44
 
45
+ 📖 Full documentation and interactive examples: [motion.page](https://motion.page)
46
+
47
+ > **⚠️ Browser-only:** This SDK requires a browser environment (`document`, `window`). In SSR frameworks (Next.js, Nuxt, Astro), wrap SDK calls in `useEffect`, `onMounted`, or client-side scripts.
48
+
44
49
  For direct browser use without a bundler, see [Browser Build](#browser-build).
45
50
 
46
51
  ---
@@ -55,7 +60,6 @@ import { Motion } from '@motion.page/sdk';
55
60
  // Fade in and slide up
56
61
  Motion('hero-intro', '#hero', {
57
62
  from: { opacity: 0, y: 50 },
58
- to: { opacity: 1, y: 0 },
59
63
  duration: 0.8,
60
64
  ease: 'power2.out',
61
65
  }).play();
@@ -67,7 +71,6 @@ Motion('hero-intro', '#hero', {
67
71
  // Scrub animation progress to scroll position
68
72
  Motion('scroll-reveal', '.card', {
69
73
  from: { opacity: 0, y: 40 },
70
- to: { opacity: 1, y: 0 },
71
74
  duration: 0.6,
72
75
  }).onScroll({ scrub: true, start: 'top 80%', end: 'top 30%' });
73
76
  ```
@@ -91,13 +94,11 @@ Motion('intro-sequence', [
91
94
  {
92
95
  target: '.title',
93
96
  from: { opacity: 0, y: -30 },
94
- to: { opacity: 1, y: 0 },
95
97
  duration: 0.6,
96
98
  },
97
99
  {
98
100
  target: '.cards',
99
101
  from: { opacity: 0, y: 20 },
100
- to: { opacity: 1, y: 0 },
101
102
  duration: 0.5,
102
103
  stagger: { each: 0.1, from: 'start' },
103
104
  position: '+=0.1', // starts 0.1s after the previous entry ends
@@ -105,7 +106,6 @@ Motion('intro-sequence', [
105
106
  {
106
107
  target: '.cta',
107
108
  from: { opacity: 0, scale: 0.9 },
108
- to: { opacity: 1, scale: 1 },
109
109
  duration: 0.4,
110
110
  position: '<', // starts at the same time as the previous entry
111
111
  },
@@ -147,9 +147,86 @@ If `Motion('name', target, config)` is called when `'name'` already has a timeli
147
147
 
148
148
  ```ts
149
149
  Motion('hero').kill();
150
- Motion('hero', '#hero', { from: { opacity: 0 }, to: { opacity: 1 }, duration: 0.8 }).onPageLoad();
150
+ Motion('hero', '#hero', { from: { opacity: 0 }, duration: 0.8 }).onPageLoad();
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Implicit Values
156
+
157
+ The SDK automatically resolves a missing `from` or `to` by reading the element's **current computed CSS** at build time (i.e. when `Motion()` is first called). This means you rarely need to specify both ends of an animation.
158
+
159
+ ### Three cases
160
+
161
+ | Config | SDK behaviour |
162
+ |--------|--------------|
163
+ | `from` only | Reads current CSS as the `to` target. Animate **from** custom values **into** the element's natural state. |
164
+ | `to` only | Reads current CSS as the `from` starting point. Animate **from** the natural state **to** custom values. |
165
+ | Both | Both endpoints are explicit. Only needed when **neither** endpoint matches the element's natural CSS. |
166
+
167
+ ### Common pattern — reveal animations only need `from`
168
+
169
+ ```ts
170
+ // ❌ Redundant — opacity:1 and y:0 are the element's natural CSS defaults
171
+ Motion('reveal', '.card', {
172
+ from: { opacity: 0, y: 40 },
173
+ to: { opacity: 1, y: 0 },
174
+ duration: 0.6,
175
+ }).onScroll({ scrub: true });
176
+
177
+ // ✅ Correct — SDK reads opacity:1 and y:0 from computed CSS automatically
178
+ Motion('reveal', '.card', {
179
+ from: { opacity: 0, y: 40 },
180
+ duration: 0.6,
181
+ }).onScroll({ scrub: true });
182
+ ```
183
+
184
+ ### When `to` only is correct
185
+
186
+ ```ts
187
+ // Animate FROM the element's current state TO a hover state
188
+ Motion('btn-hover', '.btn', {
189
+ to: { scale: 1.05, backgroundColor: '#0099ff' },
190
+ duration: 0.3,
191
+ }).onHover({ onLeave: 'reverse' });
151
192
  ```
152
193
 
194
+ ### When you need both
195
+
196
+ ```ts
197
+ // Neither endpoint is the element's natural state
198
+ Motion('parallax', '.layer', {
199
+ from: { x: -20, y: -20 },
200
+ to: { x: 20, y: 20 },
201
+ }).onMouseMove({ type: 'axis' });
202
+
203
+ // Animating between two non-default positions
204
+ Motion('swipe', '.panel', {
205
+ from: { x: -100 },
206
+ to: { x: 100 },
207
+ }).onGesture({ types: ['touch'], events: { Left: 'play', Right: 'reverse' } });
208
+ ```
209
+
210
+ ### Natural CSS defaults (common values the SDK resolves automatically)
211
+
212
+ | Property | Natural default |
213
+ |----------|----------------|
214
+ | `opacity` | `1` |
215
+ | `x`, `y`, `z` | `0` |
216
+ | `scale`, `scaleX`, `scaleY` | `1` |
217
+ | `rotate`, `rotateX`, `rotateY` | `0` |
218
+ | `skewX`, `skewY` | `0` |
219
+
220
+ > **Note:** `height: 'auto'` is **not** a natural default for the animation engine — it must be specified explicitly in `to` when needed (e.g. accordion reveals).
221
+
222
+ ### Build-time vs. play-time
223
+
224
+ The SDK reads computed CSS **at build time** (when `Motion()` is called), not at play time. If the element's styles change after the timeline is created, call `.kill()` and rebuild the timeline.
225
+
226
+ ### Edge case — transform cache
227
+
228
+ Transform properties (`x`, `y`, `scale`, `rotate`, etc.) are read from the SDK's **internal transform cache** rather than `getComputedStyle`. This ensures composited transforms remain consistent across animations. Plain CSS properties (`opacity`, `color`, `width`, etc.) are read directly from `getComputedStyle`.
229
+
153
230
  ---
154
231
 
155
232
  ## API Reference
@@ -338,7 +415,7 @@ tl.call(
338
415
  | `">-0.1"` | 0.1 s before the end of the previous entry |
339
416
 
340
417
  ```ts
341
- Motion('demo', '.box', { from: { opacity: 0 }, to: { opacity: 1 }, duration: 1 })
418
+ Motion('demo', '.box', { from: { opacity: 0 }, duration: 1 })
342
419
  .call(() => console.log('halfway'), [], 0.5)
343
420
  .call(() => console.log('done'), [], '>');
344
421
  ```
@@ -413,7 +490,7 @@ interface ClickConfig {
413
490
  ```ts
414
491
  Motion('menu-toggle', '#menu', {
415
492
  from: { height: 0, opacity: 0 },
416
- to: { height: 'auto', opacity: 1 },
493
+ to: { height: 'auto' }, // height: 'auto' must be explicit
417
494
  duration: 0.4,
418
495
  ease: 'power2.inOut',
419
496
  }).onClick({ target: '#menu-btn', toggle: 'reverse' });
@@ -456,12 +533,11 @@ interface ScrollConfig {
456
533
  // Pin the parent section while the child content animates
457
534
  Motion('content-reveal', '.content', {
458
535
  from: { opacity: 0, y: 40 },
459
- to: { opacity: 1, y: 0 },
460
536
  duration: 1,
461
537
  }).onScroll({ scrub: true, pin: '.section-wrapper', start: 'top top', end: '+=600' });
462
538
  ```
463
539
 
464
- **`toggleActions`** controls what happens at each scroll boundary. Format: `"onEnter onLeave onEnterBack onLeaveBack"`. Default: `"play reverse play reverse"`. Valid actions: `play`, `pause`, `reverse`, `restart`, `reset`, `complete`, `kill`, `none`.
540
+ **`toggleActions`** controls what happens at each scroll boundary. Format: `"onEnter onLeave onEnterBack onLeaveBack"`. Default: `"play reverse play reverse"`. Valid actions: `play`, `pause`, `resume`, `reverse`, `restart`, `reset`, `complete`, `none`.
465
541
 
466
542
  ```ts
467
543
  // Play once — never reverse (common for reveal animations)
@@ -507,8 +583,7 @@ Motion('h-scroll', '.panel', {
507
583
 
508
584
  ```ts
509
585
  Motion('parallax', '.hero-bg', {
510
- from: { y: 0 },
511
- to: { y: -100 },
586
+ to: { y: -100 },
512
587
  }).onScroll({ scrub: 1, start: 'top top', end: 'bottom top' });
513
588
  ```
514
589
 
@@ -550,8 +625,8 @@ Play the animation automatically when the page finishes loading. If called after
550
625
 
551
626
  ```ts
552
627
  Motion('page-intro', [
553
- { target: '.logo', from: { opacity: 0 }, to: { opacity: 1 }, duration: 0.5 },
554
- { target: '.nav', from: { y: -20, opacity: 0 }, to: { y: 0, opacity: 1 }, duration: 0.4 },
628
+ { target: '.logo', from: { opacity: 0 }, duration: 0.5 },
629
+ { target: '.nav', from: { y: -20, opacity: 0 }, duration: 0.4 },
555
630
  ]).onPageLoad();
556
631
  ```
557
632
 
@@ -660,8 +735,7 @@ animationStep: { Up: 0.2, Down: 0.1 } // different step size per direction
660
735
 
661
736
  ```ts
662
737
  Motion('swipe-gallery', '.gallery', {
663
- from: { x: 0 },
664
- to: { x: -100 },
738
+ to: { x: -100 },
665
739
  }).onGesture({
666
740
  types: ['pointer', 'touch'],
667
741
  events: {
@@ -770,7 +844,6 @@ Attach callbacks via the `AnimationConfig` object or directly on the `Timeline`
770
844
  ```ts
771
845
  Motion('slide-in', '.card', {
772
846
  from: { opacity: 0, x: -40 },
773
- to: { opacity: 1, x: 0 },
774
847
  duration: 0.6,
775
848
  onStart: () => console.log('started'),
776
849
  onUpdate: (progress) => console.log('progress:', progress),
@@ -784,7 +857,7 @@ Motion('slide-in', '.card', {
784
857
  #### Via `Timeline` Methods
785
858
 
786
859
  ```ts
787
- Motion('slide-in', '.card', { from: { opacity: 0 }, to: { opacity: 1 }, duration: 0.6 })
860
+ Motion('slide-in', '.card', { from: { opacity: 0 }, duration: 0.6 })
788
861
  .onStart(() => console.log('started'))
789
862
  .onUpdate((progress, time) => console.log(progress, time))
790
863
  .onComplete(() => console.log('done'));
@@ -867,7 +940,7 @@ drawSVG // string | { start?: number; end?: n
867
940
 
868
941
  // Motion path
869
942
  path: {
870
- target: string | Element | string; // SVG <path> selector, element, or raw path data (starts with M/m)
943
+ target: string | Element; // SVG <path> selector, element, or raw path data (starts with M/m)
871
944
  align?: string | Element; // Align bounding box to this element
872
945
  alignAt?: [number, number]; // Origin point [x%, y%], default [50, 50]
873
946
  start?: number; // Path start (0–1), default 0
@@ -991,7 +1064,6 @@ Split elements receive data attributes for CSS targeting:
991
1064
  ```ts
992
1065
  Motion('text-reveal', '.headline', {
993
1066
  from: { opacity: 0, y: 20 },
994
- to: { opacity: 1, y: 0 },
995
1067
  duration: 0.5,
996
1068
  split: 'chars',
997
1069
  stagger: { each: 0.03, from: 'start' },
@@ -1007,7 +1079,6 @@ Motion('reveal', 'h1', {
1007
1079
  split: 'lines',
1008
1080
  mask: true,
1009
1081
  from: { y: '100%' },
1010
- to: { y: 0 },
1011
1082
  stagger: 0.1,
1012
1083
  }).onPageLoad();
1013
1084
  ```
@@ -1049,23 +1120,22 @@ Easing names are **case-insensitive** strings. Pass them to `AnimationConfig.eas
1049
1120
  | Family | Variants |
1050
1121
  |--------|----------|
1051
1122
  | `linear`, `none` | — |
1052
- | `power1` | `power1.in` · `power1.out` · `power1.inout` |
1053
- | `power2` | `power2.in` · `power2.out` · `power2.inout` |
1054
- | `power3` | `power3.in` · `power3.out` · `power3.inout` |
1055
- | `power4` | `power4.in` · `power4.out` · `power4.inout` |
1056
- | `sine` | `sine.in` · `sine.out` · `sine.inout` |
1057
- | `expo` | `expo.in` · `expo.out` · `expo.inout` |
1058
- | `circ` | `circ.in` · `circ.out` · `circ.inout` |
1059
- | `back` | `back.in` · `back.out` · `back.inout` |
1060
- | `elastic` | `elastic.in` · `elastic.out` · `elastic.inout` |
1061
- | `bounce` | `bounce.in` · `bounce.out` · `bounce.inout` |
1123
+ | `power1` | `power1.in` · `power1.out` · `power1.inOut` |
1124
+ | `power2` | `power2.in` · `power2.out` · `power2.inOut` |
1125
+ | `power3` | `power3.in` · `power3.out` · `power3.inOut` |
1126
+ | `power4` | `power4.in` · `power4.out` · `power4.inOut` |
1127
+ | `sine` | `sine.in` · `sine.out` · `sine.inOut` |
1128
+ | `expo` | `expo.in` · `expo.out` · `expo.inOut` |
1129
+ | `circ` | `circ.in` · `circ.out` · `circ.inOut` |
1130
+ | `back` | `back.in` · `back.out` · `back.inOut` |
1131
+ | `elastic` | `elastic.in` · `elastic.out` · `elastic.inOut` |
1132
+ | `bounce` | `bounce.in` · `bounce.out` · `bounce.inOut` |
1062
1133
 
1063
1134
  Unknown strings fall back to `power1.out`.
1064
1135
 
1065
1136
  ```ts
1066
1137
  Motion('spring-in', '.box', {
1067
1138
  from: { scale: 0 },
1068
- to: { scale: 1 },
1069
1139
  duration: 0.8,
1070
1140
  ease: 'elastic.out',
1071
1141
  }).play();
@@ -1110,7 +1180,6 @@ import type {
1110
1180
  GestureEvent,
1111
1181
  GestureAction,
1112
1182
  GestureInputType,
1113
- TimelineAction,
1114
1183
 
1115
1184
  // Cursor
1116
1185
  CursorConfig,
@@ -1126,19 +1195,24 @@ import { Types } from '@motion.page/sdk';
1126
1195
 
1127
1196
  ## Browser Build
1128
1197
 
1129
- A pre-built IIFE bundle (`motion-sdk.browser.js`) is included in the package's `dist/` folder and can be used directly via a `<script>` tag — no bundler required. You can also load it from a CDN that mirrors npm packages (e.g. jsDelivr or unpkg).
1198
+ ### Browser Build (IIFE)
1199
+
1200
+ An IIFE build script is included but not part of the default build output. To generate a browser bundle:
1201
+
1202
+ ```bash
1203
+ bun run packages/sdk/scripts/build-iife.ts
1204
+ ```
1205
+
1206
+ This creates a self-contained script that exposes `window.Motion` and `window.MotionTimeline`:
1130
1207
 
1131
1208
  ```html
1132
- <!-- From your own server / CDN -->
1133
1209
  <script src="motion-sdk.browser.js"></script>
1134
1210
  <script>
1135
- // Globals are exposed on window:
1136
1211
  const { Motion, MotionTimeline } = window;
1137
1212
 
1138
- Motion('fade-in', '.hero', {
1139
- from: { opacity: 0 },
1140
- to: { opacity: 1 },
1141
- duration: 1,
1213
+ Motion('fade', '.hero', {
1214
+ from: { opacity: 0, y: 30 },
1215
+ duration: 0.8,
1142
1216
  }).onPageLoad();
1143
1217
  </script>
1144
1218
  ```
@@ -1160,4 +1234,12 @@ Modern evergreen browsers:
1160
1234
 
1161
1235
  ## License
1162
1236
 
1163
- Proprietarysee [LICENSE](../../LICENSE) for details.
1237
+ **FSL-1.1-Apache-2.0**[Functional Source License, Version 1.1, Apache 2.0 Future License](./LICENSE)
1238
+
1239
+ **TL;DR:** Free for everyone. Use it in your websites, apps, SaaS products, client projects — commercial or not. No restrictions.
1240
+
1241
+ **The one exception:** You cannot use this SDK to build a product that competes with Motion.page (e.g., a no-code animation builder, visual animation editor, or similar tool). If you're building something like that, [contact us](mailto:hello@motion.page) for an enterprise license.
1242
+
1243
+ After 2 years from each release, the code converts to the [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) license with no restrictions at all.
1244
+
1245
+ See [LICENSE](./LICENSE) for the full legal text.
package/llms.txt ADDED
@@ -0,0 +1,64 @@
1
+ # @motion.page/sdk
2
+
3
+ > Zero-dependency animation SDK with named timelines, 8 trigger types, text splitting, FLIP morphing, custom cursors, and SVG drawing. Browser-only (requires document/window).
4
+
5
+ For complete SDK documentation, install the motion-page skill: `npx skills add motion-page/claude-plugin`
6
+
7
+ ## Getting Started
8
+
9
+ - **Installation**: npm install @motion.page/sdk; ESM, CJS, and browser IIFE builds
10
+ - **Quick Start**: Basic fade-in, scroll-triggered, and multi-step timeline examples
11
+ - **Core Concept**: Named timelines — Motion(name) retrieves or creates; same name = same instance
12
+ - **Implicit Values**: from-only resolves current CSS as to; to-only resolves current CSS as from; natural defaults (opacity:1, x:0, y:0, scale:1) are auto-filled
13
+
14
+ ## Core API
15
+
16
+ - **Motion()**: Factory with 3 overloads — retrieve timeline, single animation, multi-step array
17
+ - **Motion.set()**: Instant property setting (zero duration)
18
+ - **Motion.kill() / killAll()**: Destroy named timelines; killAll for SPA cleanup
19
+ - **Motion.reset()**: Kill tweens on targets and revert text splits
20
+ - **Motion.refreshScrollTriggers()**: Recalculate scroll positions after DOM changes
21
+ - **Motion.cleanup()**: Remove ScrollTrigger spacer/marker DOM nodes
22
+ - **Motion.utils**: toArray, clamp, random, snap, interpolate, mapRange, normalize, wrap — all support currying
23
+
24
+ ## Timeline
25
+
26
+ - **Playback Control**: play, pause, reverse, restart, seek
27
+ - **State**: progress, time, timeScale, duration, isActive — getter/setter pattern
28
+ - **Lifecycle Callbacks**: onStart, onUpdate(progress, time), onComplete
29
+ - **Sequencing**: tl.call(fn, params, position) — fire functions at timeline positions
30
+
31
+ ## Triggers
32
+
33
+ - **.onPageLoad()**: Auto-play when DOM ready
34
+ - **.onScroll(config)**: start, end, scrub, pin, pinSpacing, markers, toggleActions, snap, scroller
35
+ - **.onHover(config)**: target, each, onLeave (reverse/pause/stop/restart/none), leaveDelay
36
+ - **.onClick(config)**: target, each, toggle (reverse/restart/play), secondTarget, preventDefault
37
+ - **.onMouseMove(config)**: type (distance/axis), smooth, startProgress, leaveProgress
38
+ - **.onGesture(config)**: types (pointer/touch/wheel/scroll), events map, tolerance, dragMinimum, lockAxis
39
+ - **.onCursor(config)**: type (basic/text/media), smooth, squeeze, hideNative, default/hover/click states
40
+ - **.onPageExit(config)**: mode (all/include/exclude), selectors, skipHref
41
+
42
+ ## Animation Config
43
+
44
+ - **AnimationConfig**: from, to, duration, delay, ease, stagger, repeat, split, mask, fit, axis, callbacks
45
+ - **AnimationVars**: Transforms, opacity, colors, CSS properties, filter, drawSVG, path, custom properties
46
+ - **Easing**: power1-4, sine, expo, circ, back, elastic, bounce — .in/.out/.inOut
47
+ - **Stagger**: each, amount, from (start/center/edges/random/end/index), grid, axis, ease
48
+ - **Position Parameter**: Absolute (number), relative (+=/-=), anchored (<, >, <0.2, >-0.1)
49
+
50
+ ## Features
51
+
52
+ - **Text Splitting**: split: chars/words/lines; mask: true for clip reveals; data-split-* attributes
53
+ - **FLIP Morphing**: fit: { target, scale, resize, absolute } — animate between element states
54
+ - **DrawSVG**: String format ("0% 100%") or object ({ start, end } as 0-100 percentages)
55
+ - **Motion Path**: path: { target, align, start, end, rotate }
56
+ - **Custom Cursors**: type: basic/text/media; mp-cursor-text and mp-cursor-media HTML attributes
57
+
58
+ ## Optional
59
+
60
+ - **Types Reference**: All exported TypeScript types and interfaces
61
+ - **Browser Build**: IIFE bundle exposing window.Motion and window.MotionTimeline
62
+ - **SPA Cleanup**: Motion.killAll() + Motion.cleanup() on route change
63
+ - **Migration from GSAP**: gsap.to → Motion(name, target, {to}).play(); ScrollTrigger → .onScroll()
64
+ - **Migration from Framer Motion**: motion.div → Motion(name, selector, config); whileHover → .onHover()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motion.page/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "High-performance CSS animation SDK with scroll, hover, gesture, and cursor triggers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,7 +14,8 @@
14
14
  }
15
15
  },
16
16
  "files": [
17
- "dist"
17
+ "dist",
18
+ "llms.txt"
18
19
  ],
19
20
  "scripts": {
20
21
  "build": "rm -rf dist && tsc -p tsconfig.build.json && bun build src/index.ts --outdir dist --minify --sourcemap=linked && mkdir -p dist/.cjs-tmp && bun build src/index.ts --outdir dist/.cjs-tmp --format=cjs --minify --sourcemap=linked && mv dist/.cjs-tmp/index.js dist/index.cjs && mv dist/.cjs-tmp/index.js.map dist/index.cjs.map && rm -rf dist/.cjs-tmp",
@@ -42,7 +43,7 @@
42
43
  "transform"
43
44
  ],
44
45
  "author": "Motion.page",
45
- "license": "SEE LICENSE IN LICENSE",
46
+ "license": "FSL-1.1-Apache-2.0",
46
47
  "homepage": "https://motion.page",
47
48
  "engines": {
48
49
  "node": ">=18"