use-scroll-animate 3.8.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +17 -14
  3. package/README_ja.md +11 -11
  4. package/README_zh.md +12 -12
  5. package/dist/chunks/{base-BpROOcey.js → base-ZARFccur.js} +2 -2
  6. package/dist/chunks/{base-BpROOcey.js.map → base-ZARFccur.js.map} +1 -1
  7. package/dist/chunks/core-Co-6AL0h.js +218 -0
  8. package/dist/chunks/core-Co-6AL0h.js.map +1 -0
  9. package/dist/chunks/{core-uxs3ETou.js → core-DKY-fVzR.js} +2 -2
  10. package/dist/chunks/{core-uxs3ETou.js.map → core-DKY-fVzR.js.map} +1 -1
  11. package/dist/chunks/core-DXqZm5Il.cjs +222 -0
  12. package/dist/chunks/core-DXqZm5Il.cjs.map +1 -0
  13. package/dist/chunks/{index-tags-BANJ-e4H.js → index-tags-43Xtd01A.js} +3 -2
  14. package/dist/chunks/index-tags-43Xtd01A.js.map +1 -0
  15. package/dist/chunks/{index-tags-wbuPiMR6.cjs → index-tags-BQh_uGqH.cjs} +3 -2
  16. package/dist/chunks/index-tags-BQh_uGqH.cjs.map +1 -0
  17. package/dist/chunks/{spring-C-fw7_9f.js → spring-E2ickYNI.js} +2 -2
  18. package/dist/chunks/{spring-C-fw7_9f.js.map → spring-E2ickYNI.js.map} +1 -1
  19. package/dist/chunks/{variants-CHe1VbSn.js → variants-DvnxvRCM.js} +2 -2
  20. package/dist/chunks/{variants-CHe1VbSn.js.map → variants-DvnxvRCM.js.map} +1 -1
  21. package/dist/components/angular.cjs +3 -1
  22. package/dist/components/angular.cjs.map +1 -1
  23. package/dist/components/angular.d.cts +29 -17
  24. package/dist/components/angular.d.ts +29 -17
  25. package/dist/components/angular.js +7 -5
  26. package/dist/components/angular.js.map +1 -1
  27. package/dist/components/background.js +3 -3
  28. package/dist/components/cards.js +3 -3
  29. package/dist/components/click.js +3 -3
  30. package/dist/components/depth.js +4 -4
  31. package/dist/components/feedback.js +2 -2
  32. package/dist/components/gesture.js +5 -5
  33. package/dist/components/interaction.js +2 -2
  34. package/dist/components/jsx.d.cts +2 -1
  35. package/dist/components/jsx.d.ts +2 -1
  36. package/dist/components/layout.js +2 -2
  37. package/dist/components/lazy.cjs +2 -1
  38. package/dist/components/lazy.cjs.map +1 -1
  39. package/dist/components/lazy.d.cts +2 -1
  40. package/dist/components/lazy.d.ts +2 -1
  41. package/dist/components/lazy.js +2 -1
  42. package/dist/components/lazy.js.map +1 -1
  43. package/dist/components/packs.cjs +194 -0
  44. package/dist/components/packs.cjs.map +1 -0
  45. package/dist/components/packs.css +3 -0
  46. package/dist/components/packs.d.cts +107 -0
  47. package/dist/components/packs.d.ts +107 -0
  48. package/dist/components/packs.js +185 -0
  49. package/dist/components/packs.js.map +1 -0
  50. package/dist/components/page.js +3 -3
  51. package/dist/components/physics.js +4 -4
  52. package/dist/components/react.cjs +2 -2
  53. package/dist/components/react.cjs.map +1 -1
  54. package/dist/components/react.d.cts +1 -1
  55. package/dist/components/react.d.ts +1 -1
  56. package/dist/components/react.js +2 -2
  57. package/dist/components/react.js.map +1 -1
  58. package/dist/components/reveal.js +2 -2
  59. package/dist/components/solid.cjs +3 -1
  60. package/dist/components/solid.cjs.map +1 -1
  61. package/dist/components/solid.d.cts +29 -17
  62. package/dist/components/solid.d.ts +29 -17
  63. package/dist/components/solid.js +7 -5
  64. package/dist/components/solid.js.map +1 -1
  65. package/dist/components/svelte.cjs +3 -1
  66. package/dist/components/svelte.cjs.map +1 -1
  67. package/dist/components/svelte.d.cts +29 -17
  68. package/dist/components/svelte.d.ts +29 -17
  69. package/dist/components/svelte.js +7 -5
  70. package/dist/components/svelte.js.map +1 -1
  71. package/dist/components/svg.js +2 -2
  72. package/dist/components/text.js +2 -2
  73. package/dist/components/timeline.cjs +6 -219
  74. package/dist/components/timeline.cjs.map +1 -1
  75. package/dist/components/timeline.js +5 -217
  76. package/dist/components/timeline.js.map +1 -1
  77. package/dist/components/transitions.cjs +7 -120
  78. package/dist/components/transitions.cjs.map +1 -1
  79. package/dist/components/transitions.css +0 -1
  80. package/dist/components/transitions.d.cts +5 -32
  81. package/dist/components/transitions.d.ts +5 -32
  82. package/dist/components/transitions.js +10 -121
  83. package/dist/components/transitions.js.map +1 -1
  84. package/dist/components/ui.js +5 -5
  85. package/dist/components/vue.cjs +3 -1
  86. package/dist/components/vue.cjs.map +1 -1
  87. package/dist/components/vue.d.cts +29 -17
  88. package/dist/components/vue.d.ts +29 -17
  89. package/dist/components/vue.js +7 -5
  90. package/dist/components/vue.js.map +1 -1
  91. package/dist/components/webgl.js +2 -2
  92. package/dist/components.cjs +18 -10
  93. package/dist/components.cjs.map +1 -1
  94. package/dist/components.css +1 -1
  95. package/dist/components.d.cts +67 -33
  96. package/dist/components.d.ts +67 -33
  97. package/dist/components.js +14 -10
  98. package/dist/components.js.map +1 -1
  99. package/dist/components.umd.js +2 -2
  100. package/dist/components.umd.js.map +1 -1
  101. package/dist/index.cjs +5 -102
  102. package/dist/index.cjs.map +1 -1
  103. package/dist/index.d.cts +72 -30
  104. package/dist/index.d.ts +72 -30
  105. package/dist/index.js +4 -103
  106. package/dist/index.js.map +1 -1
  107. package/dist/index.umd.js +2 -2
  108. package/dist/index.umd.js.map +1 -1
  109. package/docs/API.md +6 -6
  110. package/docs/ROADMAP.md +14 -0
  111. package/docs/components.md +16 -4
  112. package/docs/migration-from-aos.md +1 -1
  113. package/docs/migration-from-gsap-scrolltrigger.md +6 -6
  114. package/docs/upgrading-4.md +65 -0
  115. package/package.json +13 -2
  116. package/dist/chunks/index-tags-BANJ-e4H.js.map +0 -1
  117. package/dist/chunks/index-tags-wbuPiMR6.cjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,53 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [4.0.0] - 2026-10-07
11
+
12
+ 4.0 completes the 3.x release train by consolidating overlapping APIs. Every removal has a drop-in replacement that shipped during 3.x — see **[Upgrading to 4.0](./docs/upgrading-4.md)** (run your app on 3.9 first: it warns once wherever removed APIs are used).
13
+
14
+ ### ⚠ Breaking changes
15
+ - **`sequence()` removed** from `use-scroll-animate` → use **`timeline()`**, now also exported from the root entry (`import { timeline } from 'use-scroll-animate'`, `ScrollAnimate.timeline` in the UMD build) alongside `resolvePosition` and `TIMELINE_PRESETS`. `SequenceStep` / `SequenceOptions` / `SequenceController` types removed (use `Timeline`, `TimelineOptions`, `TimelineStepOptions`).
16
+ - **`connectedAnimation()` removed** from `components/transitions` → use **`sharedTransition(update)`** with `data-shared="id"` (`components/layout`; View Transitions API + FLIP fallback). `ConnectedOptions` type removed.
17
+ - **`<usa-flip-list>` / `defineFlipList()` removed** from `components/transitions` → use **`<usa-auto-animate>` / `autoAnimate()`** (`components/layout`), which also animates additions, removals and size changes. `flip()` stays.
18
+ - CDN snippets in docs and the showcase now point at `use-scroll-animate@4`.
19
+
20
+ ### Changed
21
+ - The Animation Store's timeline recipe, the vanilla example, README (EN / 中文 / 日本語), API docs and the AOS / GSAP migration guides use `timeline()`.
22
+ - The component gallery's transitions category shows a `flip()` demo instead of the removed helpers.
23
+
24
+ ### Docs
25
+ - New **[docs/upgrading-4.md](./docs/upgrading-4.md)** (step-by-step migration with before / after code).
26
+ - New **[docs/ROADMAP.md](./docs/ROADMAP.md)** — the post-4.0 plan (v4.1 → v5.0).
27
+
28
+ ### Migration
29
+ | 3.x | 4.0 |
30
+ |---|---|
31
+ | `sequence([{ target: '.a' }, { target: '.b', gap: -200 }], { trigger: '.hero' })` | `timeline().to('.a', 'fade-up').to('.b', 'fade-up', { at: '-=200' })` + play on view / `scrub()` |
32
+ | `connectedAnimation(thumb, detail)` | `sharedTransition(() => { … })` with `data-shared="id"` on both |
33
+ | `<usa-flip-list>` | `<usa-auto-animate>` |
34
+
35
+ npm: **4.0.0 is published as `latest`**; 3.x remains installable as `use-scroll-animate@3`.
36
+
37
+ ## [3.9.0] - 2026-10-07
38
+
39
+ ### Added
40
+ - **Effect packs** — new category `use-scroll-animate/components/packs`: ready-made motion for whole page types. Mark elements with `data-role` and apply a pack with `<usa-pack name="…">` or `applyPack(name, root)` (returns undo):
41
+ - `ecommerce` — `product` (reveal + lift), `add-to-cart` (press + fly to cart), `cart` (bump), `price` (count up), `badge` (pulse)
42
+ - `portfolio` — `project`, `heading`, `stat`, `contact`
43
+ - `dashboard` — `card`, `stat`, `alert`, `action`
44
+ - `game` — `button`, `score`, `item` (float), `hit` (shake), `reward`
45
+ - `landing` — `hero`, `feature`, `cta`, `logo`, `stat`
46
+ - Helpers: `flyToCart(from, to)` (arc flight + cart bump), `countUp(el)` (keeps currency / separators / decimals, accessible label), `PACKS`, `PACK_PRIMITIVES`.
47
+ - Reduced motion: packs leave content static (numbers show their final value, no flights / pulses / floats).
48
+ - Showcase: new **Effect packs** gallery category with a live demo per pack and a `flyToCart()` demo.
49
+
50
+ ### Deprecated (removed in 4.0)
51
+ - `sequence()` → `timeline()` (since 3.1).
52
+ - `connectedAnimation()` → `sharedTransition()` (since 3.6).
53
+ - `<usa-flip-list>` / `defineFlipList()` → `<usa-auto-animate>` / `autoAnimate()` (since 3.6).
54
+
55
+ Each logs a one-time console warning linking to the new **[Upgrading to 4.0](./docs/upgrading-4.md)** guide.
56
+
10
57
  ## [3.8.0] - 2026-10-07
11
58
 
12
59
  ### Added
package/README.md CHANGED
@@ -12,6 +12,8 @@
12
12
 
13
13
  **[✨ Live showcase — every effect, live, with copy-paste code](https://harrisoncn.github.io/use-scroll-animate/)** · **[🧩 Component gallery](https://harrisoncn.github.io/use-scroll-animate/showcase/components.html)** · **[🎛 Playground](https://harrisoncn.github.io/use-scroll-animate/showcase/playground.html)**
14
14
 
15
+ > **4.0** consolidates the API: `timeline()` replaces `sequence()`, `sharedTransition()` replaces `connectedAnimation()`, `<usa-auto-animate>` replaces `<usa-flip-list>` — see [Upgrading to 4.0](./docs/upgrading-4.md) · [Roadmap](./docs/ROADMAP.md).
16
+
15
17
  </div>
16
18
 
17
19
  ## Why `use-scroll-animate`?
@@ -37,7 +39,7 @@ defineComponents(); // or per category: import { defineTextComponents } from 'us
37
39
 
38
40
  ```html
39
41
  <!-- or with no build step -->
40
- <script src="https://unpkg.com/use-scroll-animate@3/dist/components.umd.js"></script>
42
+ <script src="https://unpkg.com/use-scroll-animate@4/dist/components.umd.js"></script>
41
43
  <usa-typewriter words="Hello, Windows.|Hello, web."></usa-typewriter>
42
44
  <usa-spinner kind="fluent"></usa-spinner>
43
45
  ```
@@ -49,7 +51,7 @@ defineComponents(); // or per category: import { defineTextComponents } from 'us
49
51
  | **Interaction** (`/components/interaction`) | `<usa-ripple>` · `<usa-magnetic>` · `<usa-tilt>` · `<usa-spotlight>` (Fluent reveal highlight) · `<usa-press>` · `<usa-toggle>` |
50
52
  | **Loading & feedback** (`/components/feedback`) | `<usa-spinner>` (WinUI ring, Windows dots, ring, dots, pulse, bars) · `<usa-skeleton>` · `<usa-progress>` · `<usa-toaster>` + `toast()` · `<usa-check>` |
51
53
  | **Background & decoration** (`/components/background`) | `<usa-aurora>` · `<usa-particles>` · `<usa-grain>` · `<usa-marquee>` · `<usa-acrylic>` (Acrylic / Mica) · `<usa-grid-glow>` · `<usa-blobs>` · `<usa-water-ripple>` · `<usa-dot-network>` · `fluentPreset()` (Mica · Acrylic · Reveal) |
52
- | **Transitions** (`/components/transitions`) | `<usa-dialog>` (modal / drawer / sheet) · `<usa-accordion>` · `<usa-flip-list>` · `<usa-view-switch>` · `viewTransition()` · `flip()` · `connectedAnimation()` |
54
+ | **Transitions** (`/components/transitions`) | `<usa-dialog>` (modal / drawer / sheet) · `<usa-accordion>` · `<usa-view-switch>` · `viewTransition()` · `flip()` |
53
55
  | **Spring & physics** (`/components/physics`) | `<usa-spring>` (bounce-in · pop · drop · jelly · rubber-band) · `<usa-draggable>` (spring-back · inertia · snap) · `<usa-overscroll>` · `spring()` · `createSpring()` · `SPRING_PRESETS` |
54
56
  | **Card effects** (`/components/cards`) | `<usa-card>` (flip · holo · glass · border-glow · conic-border · lift · spotlight · sheen · parallax-layers · expand — combinable) · `<usa-card-stack>` (swipe) · `<usa-sticky-stack>` · `<usa-carousel-3d>` |
55
57
  | **Click & tap** (`/components/click`) | `<usa-button>` **button click deformation** (squash · wobble · gooey · dent · shape morph · submit→loading→success) · `<usa-icon-morph>` · `<usa-click>` (ripple · burst · confetti · squish · press-spring · shake) · `<usa-like>` · `<usa-hold>` · `<usa-double-tap>` · `<usa-checkbox>` · `confetti()` · `haptic()` |
@@ -61,6 +63,7 @@ defineComponents(); // or per category: import { defineTextComponents } from 'us
61
63
  | **Canvas & WebGL** (`/components/webgl`) | `<usa-shader>` (gradient · plasma · waves · aurora · custom GLSL) · `<usa-distort>` · `<usa-liquid>` · `glQuad()` — graceful fallback |
62
64
  | **3D & depth** (`/components/depth`) | `<usa-cube>` · `<usa-depth>` (pointer · gyroscope · scroll depth parallax) · `deviceTilt()` · (+ `<usa-carousel-3d>` in cards) |
63
65
  | **Layout animation** (`/components/layout`) | `<usa-auto-animate>` / `autoAnimate()` (list & grid reflow) · `<usa-masonry>` · `sharedTransition()` (shared elements) |
66
+ | **Effect packs** (`/components/packs`) | `<usa-pack>` (`name="ecommerce \| portfolio \| dashboard \| game \| landing"`) · `applyPack()` · `flyToCart()` · `countUp()` |
64
67
 
65
68
  Whole bundle ≈ 22 kB gzip (JS + CSS); one category 3.5–6.4 kB; a single component ≈ 2 kB. The scroll-animation core below is unaffected.
66
69
 
@@ -108,7 +111,7 @@ Notes:
108
111
  - With the native engine, `duration`, `delay`, `threshold`, `offset` and `stagger` don't apply; the animation spans `viewRange` (default `['entry 0%', 'entry 100%']`, i.e. from the moment the element starts entering until it is fully in view). `easing` still applies.
109
112
  - `once` (default) freezes the end state when the animation completes, so scrolling back up does not reverse it; with `repeat: true` it keeps following the scroll in both directions.
110
113
  - Callbacks (`onEnter`, `onLeave`, `onStart`, `onComplete`), `onProgress`, `progressVar` and `parallax` keep working.
111
- - Class-name mode (`useClassNames`), `prefers-reduced-motion`, `animate()`, `sequence()` and `staggerChildren()` always use the JS engine.
114
+ - Class-name mode (`useClassNames`), `prefers-reduced-motion`, `animate()`, `timeline()` and `staggerChildren()` always use the JS engine.
112
115
  - `supportsScrollTimeline()` is exported if you want to branch on support yourself.
113
116
 
114
117
  ## v1.4.0 New Features ✨
@@ -136,21 +139,21 @@ const stop = staggerChildren(document.querySelector('#feed'), {
136
139
  // later: stop();
137
140
  ```
138
141
 
139
- ### Timelines with `sequence()`
140
- Chain animations across elements. Each step starts when the previous one ends; `gap` adds a pause (negative values overlap) and `at` sets an absolute start time.
142
+ ### Timelines with `timeline()`
143
+ Chain animations across elements on one playhead. Each step starts when the previous one ends; `at` overlaps (`'-=300'`), waits (`'+=200'`), aligns with the previous step (`'<'`), jumps to a label or an absolute time. Play it, reverse it, seek it, or scrub it with scroll. (Replaces `sequence()`, removed in 4.0 — see [upgrading-4.md](./docs/upgrading-4.md).)
141
144
 
142
145
  ```js
143
- import { sequence } from 'use-scroll-animate';
146
+ import { timeline } from 'use-scroll-animate';
144
147
 
145
- const tl = sequence([
146
- { target: '.hero h1', animation: 'fade-in-up', duration: 700 },
147
- { target: '.hero p', animation: 'blur-in', gap: -300 },
148
- { target: '.hero .btn', animation: 'scale-up', stagger: 80 },
149
- ], { trigger: '.hero', easing: 'soft-spring' }); // auto-plays once when .hero enters
148
+ const tl = timeline({ defaults: { duration: 700 } })
149
+ .to('.hero h1', 'fade-up')
150
+ .to('.hero p', 'blur', { at: '-=300' })
151
+ .to('.hero .btn', 'scale', { stagger: 80 });
150
152
 
151
- await tl.play(); // or play manually; resolves when every step is done
152
- tl.cancel(); // stop and leave everything visible
153
+ await tl.play(); // resolves at the end
154
+ tl.scrub(document.querySelector('.hero')); // or tie progress to scroll
153
155
  ```
156
+ Declaratively: `<usa-timeline>` with `data-tl="fade-up"` children (`use-scroll-animate/components/timeline`).
154
157
 
155
158
  ### New presets
156
159
  `scale-up`, `blur-in-up`, `flip-up`, `flip-down`, `rotate-left`, `rotate-right`, and clip-path reveals `clip-up`, `clip-down`, `clip-left`, `clip-right`, `clip-circle`.
@@ -310,7 +313,7 @@ ScrollAnimate.destroy(); // disconnect everything
310
313
  const sa = createScrollAnimate({ root: document.querySelector('#scroller') }); // isolated instance
311
314
 
312
315
  // Helpers (tree-shakeable)
313
- import { sequence, staggerChildren, getScrollProgress } from 'use-scroll-animate';
316
+ import { timeline, staggerChildren, getScrollProgress } from 'use-scroll-animate';
314
317
  ```
315
318
 
316
319
  ### Watching the DOM (`watch()`)
package/README_ja.md CHANGED
@@ -19,7 +19,7 @@
19
19
  `use-scroll-animate` は違います:
20
20
  - ⚡ **依存関係なし**:純粋な Vanilla JS/TypeScript。
21
21
  - 🚀 **高パフォーマンス**:`IntersectionObserver` とネイティブの `Web Animations API` で駆動。デフォルトではスクロールイベントリスナーなし(オプトインのスクロール進捗モードは、対象要素が画面内にある間だけ passive・rAF スロットルのリスナーを1つ使用)、レイアウトスラッシングなし。
22
- - 🪶 **超軽量**:Gzip後コア約4.8KB(`sequence`・`staggerChildren`・React/Vue ヘルパーを含む全体で約6.1KB)。
22
+ - 🪶 **超軽量**:Gzip後コア約4.8KB(`timeline`・`staggerChildren`・React/Vue ヘルパーを含む全体で約6.1KB)。
23
23
  - 🧩 **フレームワークに依存しない**:Vanilla JS、React、Vue、Svelteなどとシームレスに動作。一流の React Hooks と Vue Composables を内蔵。
24
24
  - ♿ **アクセシブル**:`prefers-reduced-motion` を標準でサポート。
25
25
 
@@ -39,7 +39,7 @@ defineComponents(); // カテゴリ単位: import { defineTextComponents } from
39
39
  | **インタラクション**(`/components/interaction`) | `<usa-ripple>` · `<usa-magnetic>` · `<usa-tilt>` · `<usa-spotlight>`(Fluent Reveal)· `<usa-press>` · `<usa-toggle>` |
40
40
  | **ローディング・フィードバック**(`/components/feedback`) | `<usa-spinner>` · `<usa-skeleton>` · `<usa-progress>` · `<usa-toaster>` + `toast()` · `<usa-check>` |
41
41
  | **背景・装飾**(`/components/background`) | `<usa-aurora>` · `<usa-particles>` · `<usa-grain>` · `<usa-marquee>` · `<usa-acrylic>`(Acrylic / Mica) · `<usa-grid-glow>` · `<usa-blobs>` · `<usa-water-ripple>` · `<usa-dot-network>` · `fluentPreset()` |
42
- | **トランジション**(`/components/transitions`) | `<usa-dialog>` · `<usa-accordion>` · `<usa-flip-list>` · `<usa-view-switch>` · `viewTransition()` · `flip()` · `connectedAnimation()` |
42
+ | **トランジション**(`/components/transitions`) | `<usa-dialog>` · `<usa-accordion>` · `<usa-view-switch>` · `viewTransition()` · `flip()` |
43
43
  | **スプリング・物理**(`/components/physics`) | `<usa-spring>`(bounce-in · pop · drop · jelly · rubber-band)· `<usa-draggable>` · `<usa-overscroll>` · `spring()` · `createSpring()` |
44
44
  | **カード効果**(`/components/cards`) | `<usa-card>`(flip · holo · glass · border-glow · conic-border · lift · spotlight · sheen · parallax-layers · expand)· `<usa-card-stack>` · `<usa-sticky-stack>` · `<usa-carousel-3d>` |
45
45
  | **クリック・タップ**(`/components/click`) | `<usa-button>`(squash · wobble · gooey · dent · shape morph · submit)· `<usa-icon-morph>` · `<usa-click>` · `<usa-like>` · `<usa-hold>` · `<usa-double-tap>` · `<usa-checkbox>` |
@@ -51,6 +51,7 @@ defineComponents(); // カテゴリ単位: import { defineTextComponents } from
51
51
  | **Canvas / WebGL** (`/components/webgl`) | `<usa-shader>`(gradient · plasma · waves · aurora · カスタム GLSL)· `<usa-distort>` · `<usa-liquid>` · `glQuad()` |
52
52
  | **3D / 奥行き** (`/components/depth`) | `<usa-cube>` · `<usa-depth>`(ポインター · ジャイロ · スクロール視差)· `deviceTilt()` |
53
53
  | **レイアウト** (`/components/layout`) | `<usa-auto-animate>` / `autoAnimate()` · `<usa-masonry>` · `sharedTransition()`(共有要素) |
54
+ | **エフェクトパック** (`/components/packs`) | `<usa-pack>` (`name="ecommerce \| portfolio \| dashboard \| game \| landing"`) · `applyPack()` · `flyToCart()` |
54
55
 
55
56
  ## ドキュメント
56
57
 
@@ -92,7 +93,7 @@ const sa = createScrollAnimate({ defaultEngine: 'auto' });
92
93
 
93
94
  - `'auto'`:**2.0 からのデフォルト**。対応ブラウザではネイティブ、非対応なら JS。要素が `duration`・`delay`・`offset`・`stagger` を自分で指定した場合も JS。`'css'`:対応時は常にネイティブ。`'js'`:1.x の動作(`defaultEngine: 'js'` で全体に適用)。
94
95
  - ネイティブエンジンでは `duration`・`delay`・`threshold`・`offset`・`stagger` は無効で、範囲は `viewRange`(デフォルト `['entry 0%', 'entry 100%']`)。`easing` は有効。HTML:`data-sa-engine`、`data-sa-view-range`。
95
- - `once`(デフォルト)は完了時に最終状態を固定、`repeat: true` ではスクロールに双方向で追従。クラス名モード・reduced motion・`animate()`・`sequence()`・`staggerChildren()` は常に JS エンジン。`supportsScrollTimeline()` もエクスポート。
96
+ - `once`(デフォルト)は完了時に最終状態を固定、`repeat: true` ではスクロールに双方向で追従。クラス名モード・reduced motion・`animate()`・`timeline()`・`staggerChildren()` は常に JS エンジン。`supportsScrollTimeline()` もエクスポート。
96
97
 
97
98
  ## v1.4.0 の新機能 ✨
98
99
 
@@ -112,16 +113,15 @@ const sa = createScrollAnimate({ defaultEngine: 'auto' });
112
113
  const stop = staggerChildren(document.querySelector('#feed'), { stagger: 60, observeChildren: true });
113
114
  ```
114
115
 
115
- - **タイムライン `sequence()`**:複数要素のアニメーションを連結。各ステップは前のステップの終了後に開始し、`gap` で間隔(負の値で重ね合わせ)、`at` で絶対開始時刻を指定できます。`trigger` を指定するとその要素が表示されたときに一度だけ自動再生します。
116
+ - **タイムライン `timeline()`**:1 つの再生ヘッドで複数要素のアニメーションを連結。既定では前のステップの終了後に開始し、`at` で重ね(`'-=300'`)、待機(`'+=200'`)、前と同時(`'<'`)、ラベル・絶対時刻を指定。再生・逆再生・シーク・スクロール連動(scrub)に対応。(4.0 で削除された `sequence()` の後継。[upgrading-4.md](./docs/upgrading-4.md) 参照。)
116
117
 
117
118
  ```js
118
- import { sequence } from 'use-scroll-animate';
119
- const tl = sequence([
120
- { target: '.hero h1', animation: 'fade-in-up', duration: 700 },
121
- { target: '.hero p', animation: 'blur-in', gap: -300 },
122
- { target: '.hero .btn', animation: 'scale-up', stagger: 80 },
123
- ], { trigger: '.hero' });
124
- await tl.play(); // すべて完了すると resolve。tl.cancel() で停止し要素は表示されたまま
119
+ import { timeline } from 'use-scroll-animate';
120
+ const tl = timeline({ defaults: { duration: 700 } })
121
+ .to('.hero h1', 'fade-up')
122
+ .to('.hero p', 'blur', { at: '-=300' })
123
+ .to('.hero .btn', 'scale', { stagger: 80 });
124
+ await tl.play(); // 完了で resolve。tl.scrub(hero) でスクロール連動
125
125
  ```
126
126
 
127
127
  - **新しいプリセット**:`scale-up`、`blur-in-up`、`flip-up`、`flip-down`、`rotate-left`、`rotate-right`、clip-path による `clip-up`、`clip-down`、`clip-left`、`clip-right`、`clip-circle`。
package/README_zh.md CHANGED
@@ -21,7 +21,7 @@
21
21
  `use-scroll-animate` 的设计初衷截然不同:
22
22
  - ⚡ **零依赖**:纯原生 JS/TypeScript 编写。
23
23
  - 🚀 **高性能**:由 `IntersectionObserver` 和原生 `Web Animations API` 驱动。默认不监听滚动事件(可选的滚动进度模式仅在被追踪元素可见时使用一个 passive、rAF 节流的监听器),无布局抖动。
24
- - 🪶 **极轻量**:Gzip 后核心约 4.8KB(含 `sequence`、`staggerChildren` 与 React/Vue 辅助在内全部约 6.1KB)。
24
+ - 🪶 **极轻量**:Gzip 后核心约 4.8KB(含 `timeline`、`staggerChildren` 与 React/Vue 辅助在内全部约 6.1KB)。
25
25
  - 🧩 **框架无关**:完美支持原生 JS、React、Vue、Svelte 等。内置一流的 React Hooks 和 Vue Composables。
26
26
  - ♿ **无障碍**:原生支持 `prefers-reduced-motion`。
27
27
 
@@ -36,7 +36,7 @@ defineComponents(); // 或按分类:import { defineTextComponents } from 'use-
36
36
 
37
37
  ```html
38
38
  <!-- 或免构建直接使用 -->
39
- <script src="https://unpkg.com/use-scroll-animate@3/dist/components.umd.js"></script>
39
+ <script src="https://unpkg.com/use-scroll-animate@4/dist/components.umd.js"></script>
40
40
  <usa-typewriter words="你好,Windows。|你好,Web。"></usa-typewriter>
41
41
  <usa-spinner kind="fluent"></usa-spinner>
42
42
  ```
@@ -48,7 +48,7 @@ defineComponents(); // 或按分类:import { defineTextComponents } from 'use-
48
48
  | **交互反馈**(`/components/interaction`) | `<usa-ripple>` 水波纹 · `<usa-magnetic>` 磁吸按钮 · `<usa-tilt>` 3D 倾斜卡片 · `<usa-spotlight>` Fluent 光照高亮 · `<usa-press>` 按压反馈 · `<usa-toggle>` 切换开关 |
49
49
  | **加载与反馈**(`/components/feedback`) | `<usa-spinner>`(WinUI 进度环、Windows 圆点等 6 种)· `<usa-skeleton>` 骨架屏 · `<usa-progress>` 进度条 · `<usa-toaster>` + `toast()` 通知 · `<usa-check>` 结果图标 |
50
50
  | **背景与装饰**(`/components/background`) | `<usa-aurora>` 极光 · `<usa-particles>` 粒子 · `<usa-grain>` 胶片颗粒 · `<usa-marquee>` 无限跑马灯 · `<usa-acrylic>` 亚克力 / 云母材质 · `<usa-grid-glow>` 网格光晕 · `<usa-blobs>` 流体色块 · `<usa-water-ripple>` 水波 · `<usa-dot-network>` 点阵 · `fluentPreset()` Fluent 预设 |
51
- | **过渡动画**(`/components/transitions`) | `<usa-dialog>` 弹窗 / 抽屉 / 底部面板 · `<usa-accordion>` 手风琴 · `<usa-flip-list>` FLIP 列表 · `<usa-view-switch>` 视图切换 · `viewTransition()` · `flip()` · `connectedAnimation()` |
51
+ | **过渡动画**(`/components/transitions`) | `<usa-dialog>` 弹窗 / 抽屉 / 底部面板 · `<usa-accordion>` 手风琴 · `<usa-view-switch>` 视图切换 · `viewTransition()` · `flip()` |
52
52
  | **弹簧与物理**(`/components/physics`) | `<usa-spring>` 弹入 / 弹出 / 掉落 / 果冻 / 橡皮筋 · `<usa-draggable>` 拖拽回弹、惯性、吸附 · `<usa-overscroll>` 弹性越界 · `spring()` · `createSpring()` · 预设 gentle / wobbly / stiff / bouncy |
53
53
  | **卡片效果**(`/components/cards`) | `<usa-card>` 翻转 · 全息 · 玻璃 · 边框光晕 · 流光边框 · 悬浮 · 聚光 · 扫光 · 视差分层 · 展开详情(可组合)· `<usa-card-stack>` 滑动卡堆 · `<usa-sticky-stack>` 滚动堆叠 · `<usa-carousel-3d>` 3D 轮播 |
54
54
  | **点击与轻触**(`/components/click`) | `<usa-button>` 按钮点击形变(挤压拉伸 · 弹性圆角 · 液态粘滞 · 按压凹陷 · 形状变形 · 提交→加载→成功)· `<usa-icon-morph>` 图标变形 · `<usa-click>` 水波纹 / 迸发 / 彩带 / 抖动 · `<usa-like>` · `<usa-hold>` · `<usa-double-tap>` · `<usa-checkbox>` |
@@ -60,6 +60,7 @@ defineComponents(); // 或按分类:import { defineTextComponents } from 'use-
60
60
  | **Canvas 与 WebGL** (`/components/webgl`) | `<usa-shader>`(gradient · plasma · waves · aurora · 自定义 GLSL)· `<usa-distort>` · `<usa-liquid>` · `glQuad()` —— 优雅降级 |
61
61
  | **3D 与景深** (`/components/depth`) | `<usa-cube>` · `<usa-depth>`(指针 · 陀螺仪 · 滚动景深视差)· `deviceTilt()` ·(另见 cards 中的 `<usa-carousel-3d>`) |
62
62
  | **布局动画** (`/components/layout`) | `<usa-auto-animate>` / `autoAnimate()`(列表与网格重排)· `<usa-masonry>`(瀑布流)· `sharedTransition()`(共享元素) |
63
+ | **效果包** (`/components/packs`) | `<usa-pack>` (`name="ecommerce \| portfolio \| dashboard \| game \| landing"`) · `applyPack()` · `flyToCart()` · `countUp()` |
63
64
 
64
65
  完整包约 22 kB gzip(JS + CSS);单个分类 3.5–6.4 kB;单个组件约 2 kB。下方的滚动动画核心不受影响。
65
66
 
@@ -106,7 +107,7 @@ const sa = createScrollAnimate({ defaultEngine: 'auto' }); // 实例级默认
106
107
  - `'auto'`:**2.0 起的默认值**,支持时使用原生时间线,否则回退 JS;若元素自行设置了 `duration`、`delay`、`offset` 或 `stagger`,则使用 JS。`'css'`:支持时始终使用原生时间线。`'js'`:1.x 的行为(`defaultEngine: 'js'` 可全局恢复)。
107
108
  - 原生引擎下 `duration`、`delay`、`threshold`、`offset`、`stagger` 不生效;动画区间由 `viewRange` 决定(默认 `['entry 0%', 'entry 100%']`),`easing` 仍然有效。HTML:`data-sa-engine`、`data-sa-view-range="entry 0%, cover 40%"`。
108
109
  - `once`(默认)在动画完成后固定最终状态;`repeat: true` 时随滚动双向播放。回调、`onProgress`、`progressVar`、视差照常工作。
109
- - 类名模式、`prefers-reduced-motion`、`animate()`、`sequence()`、`staggerChildren()` 始终使用 JS 引擎。另导出 `supportsScrollTimeline()`。
110
+ - 类名模式、`prefers-reduced-motion`、`animate()`、`timeline()`、`staggerChildren()` 始终使用 JS 引擎。另导出 `supportsScrollTimeline()`。
110
111
 
111
112
  ## v1.4.0 新特性 ✨
112
113
 
@@ -126,16 +127,15 @@ const sa = createScrollAnimate({ defaultEngine: 'auto' }); // 实例级默认
126
127
  const stop = staggerChildren(document.querySelector('#feed'), { stagger: 60, observeChildren: true });
127
128
  ```
128
129
 
129
- - **时间线 `sequence()`**:串联多个元素的动画。每一步在上一步结束后开始;`gap` 设置间隔(负值表示重叠),`at` 设置绝对开始时间;`trigger` 可在元素进入视口时自动播放一次。
130
+ - **时间线 `timeline()`**:在同一播放头上串联多个元素的动画。默认每步在上一步结束后开始;`at` 可重叠(`'-=300'`)、延后(`'+=200'`)、与上一步同时(`'<'`)、对齐标签或绝对时间;支持播放、倒放、跳转与随滚动擦洗。(取代 4.0 中移除的 `sequence()`,见 [upgrading-4.md](./docs/upgrading-4.md)。)
130
131
 
131
132
  ```js
132
- import { sequence } from 'use-scroll-animate';
133
- const tl = sequence([
134
- { target: '.hero h1', animation: 'fade-in-up', duration: 700 },
135
- { target: '.hero p', animation: 'blur-in', gap: -300 },
136
- { target: '.hero .btn', animation: 'scale-up', stagger: 80 },
137
- ], { trigger: '.hero' });
138
- await tl.play(); // 全部完成后 resolve;tl.cancel() 停止并保持元素可见
133
+ import { timeline } from 'use-scroll-animate';
134
+ const tl = timeline({ defaults: { duration: 700 } })
135
+ .to('.hero h1', 'fade-up')
136
+ .to('.hero p', 'blur', { at: '-=300' })
137
+ .to('.hero .btn', 'scale', { stagger: 80 });
138
+ await tl.play(); // 全部完成后 resolve;或 tl.scrub(hero) 随滚动
139
139
  ```
140
140
 
141
141
  - **新预设**:`scale-up`、`blur-in-up`、`flip-up`、`flip-down`、`rotate-left`、`rotate-right`,以及 clip-path 揭示 `clip-up`、`clip-down`、`clip-left`、`clip-right`、`clip-circle`。
@@ -241,5 +241,5 @@ function kindOf(el, valid, fallback) {
241
241
  }
242
242
  const clamp = (v, min, max) => Math.min(max, Math.max(min, v));
243
243
 
244
- export { EASE_SPRING as E, FLUENT_DECELERATE as F, MOTION_SCALE as M, configureComponents as a, clamp as b, canDefine as c, applyFrame as d, caf as e, adoptStyles as f, getMotionIntensity as g, defineElement as h, EASE_OUT as i, srText as j, kindOf as k, motionScale as m, now as n, prefersReducedMotion as p, raf as r, shadowStyles as s };
245
- //# sourceMappingURL=base-BpROOcey.js.map
244
+ export { EASE_SPRING as E, FLUENT_DECELERATE as F, MOTION_SCALE as M, configureComponents as a, caf as b, canDefine as c, clamp as d, applyFrame as e, adoptStyles as f, getMotionIntensity as g, defineElement as h, EASE_OUT as i, srText as j, kindOf as k, motionScale as m, now as n, prefersReducedMotion as p, raf as r, shadowStyles as s };
245
+ //# sourceMappingURL=base-ZARFccur.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"base-BpROOcey.js","sources":["../../src/components/base.ts"],"sourcesContent":["/**\n * use-scroll-animate/components — shared base for the `<usa-*>` custom elements.\n *\n * Everything here is lazy: nothing touches `window`, `document`,\n * `HTMLElement` or `matchMedia` at import time, so the components can be\n * imported during SSR (Next, Nuxt, Astro…) and in Electron/Tauri preload\n * scripts. Classes are created the first time a `define*()` function runs.\n */\n\nexport interface ComponentsConfig {\n /**\n * Inject each component's CSS when it is defined (default `true`). Uses a\n * constructable stylesheet (`document.adoptedStyleSheets`, which a strict\n * `style-src` CSP does not block) and falls back to a `<style>` tag. Set\n * to `false` when you load `use-scroll-animate/components.css` yourself.\n */\n injectStyles?: boolean;\n /**\n * `'user'` (default) follows `prefers-reduced-motion`; `'reduce'` always\n * uses the reduced variants (e.g. a kiosk / battery-saver mode);\n * `'no-preference'` ignores the OS setting (only for demos — respect your users).\n */\n reducedMotion?: 'user' | 'reduce' | 'no-preference';\n /**\n * Global motion intensity (v2.7): `'off'` (same as reduced motion),\n * `'low'` (shorter, calmer), `'normal'` (default) or `'high'`. Scales every\n * component animation's duration and sets `--usa-motion` (0 / 0.6 / 1 /\n * 1.25) on `<html>` for your own CSS. See `setMotionIntensity()`.\n */\n motionIntensity?: MotionIntensity;\n}\n\nexport type MotionIntensity = 'off' | 'low' | 'normal' | 'high';\nexport const MOTION_SCALE: Record<MotionIntensity, number> = { off: 0, low: 0.6, normal: 1, high: 1.25 };\n\nconst config: Required<ComponentsConfig> = { injectStyles: true, reducedMotion: 'user', motionIntensity: 'normal' };\n\n/** Change global component settings (call before `define*()` for `injectStyles`). */\nexport function configureComponents(options: ComponentsConfig): void {\n Object.assign(config, options);\n if (options.motionIntensity && typeof document !== 'undefined') {\n document.documentElement.style.setProperty('--usa-motion', String(MOTION_SCALE[options.motionIntensity] ?? 1));\n document.documentElement.setAttribute('data-usa-motion', options.motionIntensity);\n }\n}\n\n/** The current global motion intensity. */\nexport function getMotionIntensity(): MotionIntensity {\n return config.motionIntensity;\n}\n\n/** Duration multiplier for the current intensity (1 when `normal`). */\nexport function motionScale(): number {\n return MOTION_SCALE[config.motionIntensity] ?? 1;\n}\n\nexport const canDefine = (): boolean => typeof customElements !== 'undefined' && typeof HTMLElement !== 'undefined';\n\n/** `true` when animations should be reduced (OS setting or `configureComponents`). */\nexport function prefersReducedMotion(): boolean {\n if (config.motionIntensity === 'off') return true;\n if (config.reducedMotion !== 'user') return config.reducedMotion === 'reduce';\n return typeof matchMedia === 'function' && !!matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\nconst injected = new Set<string>();\n\n/** Add a component's stylesheet to the document once. */\nexport function adoptStyles(id: string, css: string): void {\n if (!config.injectStyles || !css || injected.has(id) || typeof document === 'undefined') return;\n injected.add(id);\n try {\n if (typeof CSSStyleSheet === 'function' && 'adoptedStyleSheets' in document) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(css);\n document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];\n return;\n }\n } catch {\n /* fall through to <style> */\n }\n const style = document.createElement('style');\n style.setAttribute('data-usa', id);\n style.textContent = css;\n (document.head || document.documentElement).appendChild(style);\n}\n\n/** Attach `css` to a shadow root (constructable sheet where supported, else `<style>`). */\nexport function shadowStyles(root: ShadowRoot, css: string): void {\n try {\n if (typeof CSSStyleSheet === 'function' && 'adoptedStyleSheets' in root) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(css);\n root.adoptedStyleSheets = [sheet];\n return;\n }\n } catch {\n /* fall through */\n }\n const style = document.createElement('style');\n style.textContent = css;\n root.prepend(style);\n}\n\nexport type Cleanup = () => void;\n\n/**\n * Members shared by every `<usa-*>` element. Attribute helpers, a cleanup\n * bag that is emptied on disconnect, and motion helpers that degrade to the\n * final state without WAAPI or under reduced motion.\n */\nexport interface UsaElement extends HTMLElement {\n /** `true` while reduced motion applies to this element. */\n readonly reduced: boolean;\n}\n\nexport interface UsaBase extends UsaElement {\n mount(): void;\n changed(name: string): void;\n unmount(): void;\n str(name: string, fallback?: string): string;\n num(name: string, fallback: number): number;\n flag(name: string): boolean;\n setFlag(name: string, on: boolean): void;\n onCleanup(fn: Cleanup): void;\n listen<K extends keyof HTMLElementEventMap>(\n target: EventTarget,\n type: K | string,\n fn: (e: any) => void,\n options?: AddEventListenerOptions\n ): void;\n inView(cb: (visible: boolean, entry?: IntersectionObserverEntry) => void, init?: IntersectionObserverInit, target?: Element): void;\n motion(el: Element, keyframes: Keyframe[], options: KeyframeAnimationOptions): Animation | null;\n emit(type: string, detail?: unknown): boolean;\n}\n\ntype BaseCtor = new () => UsaBase;\nlet baseClass: BaseCtor | null = null;\n\n/** The lazily created base class (needs `HTMLElement`). */\nexport function getBase(): BaseCtor {\n if (baseClass) return baseClass;\n class Base extends HTMLElement {\n private _cleanups: Cleanup[] = [];\n private _connected = false;\n\n get reduced(): boolean {\n return prefersReducedMotion();\n }\n\n connectedCallback(): void {\n if (this._connected) return;\n this._connected = true;\n // Upgraded while the parser is still inside us (a <script> in <head>\n // defined the element): children/text are not there yet, so wait.\n if (typeof document !== 'undefined' && document.readyState === 'loading' && !this.nextSibling && !this.childNodes.length) {\n const go = () => {\n if (this._connected && this.isConnected) this.mount();\n };\n document.addEventListener('DOMContentLoaded', go, { once: true });\n this._cleanups.push(() => document.removeEventListener('DOMContentLoaded', go));\n return;\n }\n this.mount();\n }\n\n disconnectedCallback(): void {\n this._connected = false;\n this.teardown();\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, value: string | null): void {\n if (!this._connected || oldValue === value) return;\n this.changed(_name);\n }\n\n /** Re-mount on attribute change (override for finer updates). */\n changed(_name: string): void {\n this.teardown();\n this.mount();\n }\n\n private teardown(): void {\n this._cleanups.splice(0).reverse().forEach((fn) => fn());\n this.unmount();\n }\n\n mount(): void {}\n unmount(): void {}\n\n str(name: string, fallback = ''): string {\n const v = this.getAttribute(name);\n return v === null ? fallback : v;\n }\n\n num(name: string, fallback: number): number {\n const v = this.getAttribute(name);\n const n = v === null || v.trim() === '' ? NaN : Number(v);\n return Number.isFinite(n) ? n : fallback;\n }\n\n /** Boolean attribute: present and not `\"false\"`. */\n flag(name: string): boolean {\n const v = this.getAttribute(name);\n return v !== null && v !== 'false';\n }\n\n setFlag(name: string, on: boolean): void {\n if (on) this.setAttribute(name, '');\n else this.removeAttribute(name);\n }\n\n onCleanup(fn: Cleanup): void {\n this._cleanups.push(fn);\n }\n\n listen(target: EventTarget, type: string, fn: (e: any) => void, options?: AddEventListenerOptions): void {\n target.addEventListener(type, fn, options);\n this.onCleanup(() => target.removeEventListener(type, fn, options));\n }\n\n /** Calls `cb(true/false)` as the element enters / leaves the viewport. */\n inView(cb: (visible: boolean, entry?: IntersectionObserverEntry) => void, init?: IntersectionObserverInit, target: Element = this): void {\n if (typeof IntersectionObserver === 'undefined') {\n cb(true);\n return;\n }\n const io = new IntersectionObserver((entries) => {\n for (const e of entries) cb(e.isIntersecting, e);\n }, init);\n io.observe(target);\n this.onCleanup(() => io.disconnect());\n }\n\n /** `el.animate()` that returns `null` (and applies the last frame) without WAAPI. */\n motion(el: Element, keyframes: Keyframe[], options: KeyframeAnimationOptions): Animation | null {\n if (typeof (el as HTMLElement).animate !== 'function') {\n applyFrame(el as HTMLElement, keyframes[keyframes.length - 1]);\n return null;\n }\n const k = motionScale();\n if (k !== 1 && k > 0 && typeof options.duration === 'number') options = { ...options, duration: options.duration * k, delay: (options.delay || 0) * k };\n return (el as HTMLElement).animate(keyframes, options);\n }\n\n emit(type: string, detail?: unknown): boolean {\n return this.dispatchEvent(new CustomEvent(`usa:${type}`, { detail, bubbles: true, cancelable: true }));\n }\n }\n baseClass = Base as unknown as BaseCtor;\n return baseClass;\n}\n\n/** Write a keyframe's properties as inline styles (no-WAAPI fallback). */\nexport function applyFrame(el: HTMLElement, frame?: Keyframe): void {\n if (!frame) return;\n for (const [k, v] of Object.entries(frame)) {\n if (k === 'offset' || k === 'easing' || k === 'composite' || v == null) continue;\n (el.style as any)[k] = String(v);\n }\n}\n\n/**\n * Register `tag` with the class built by `make(Base)`. Returns the\n * constructor, the already registered one, or `undefined` without DOM.\n */\nexport function defineElement(\n tag: string,\n make: (Base: BaseCtor) => CustomElementConstructor,\n css?: { id: string; text: string }\n): CustomElementConstructor | undefined {\n if (!canDefine()) return undefined;\n adoptStyles('base', BASE_CSS);\n if (css) adoptStyles(css.id, css.text);\n const existing = customElements.get(tag);\n if (existing) return existing;\n const ctor = make(getBase());\n customElements.define(tag, ctor);\n return ctor;\n}\n\nconst BASE_CSS = '.usa-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}';\n\n/** A visually hidden copy of `text` for screen readers (the animated copy is `aria-hidden`). */\nexport function srText(text: string): HTMLSpanElement {\n const s = document.createElement('span');\n s.className = 'usa-sr';\n s.textContent = text;\n return s;\n}\n\n/** requestAnimationFrame with a timeout fallback (jsdom / hidden documents). */\nexport const raf = (cb: FrameRequestCallback): number =>\n typeof requestAnimationFrame === 'function' ? requestAnimationFrame(cb) : (setTimeout(() => cb(Date.now()), 16) as unknown as number);\n/** Monotonic time in ms (rAF callback timestamps differ between environments, so loops use this). */\nexport const now = (): number => (typeof performance !== 'undefined' ? performance.now() : Date.now());\nexport const caf = (id: number): void => {\n if (typeof cancelAnimationFrame === 'function') cancelAnimationFrame(id);\n else clearTimeout(id);\n};\n\n/** Spring-ish easing used across the components. */\nexport const EASE_OUT = 'cubic-bezier(0.22, 1, 0.36, 1)';\nexport const EASE_SPRING = 'cubic-bezier(0.34, 1.56, 0.64, 1)';\n/** Windows Fluent \"decelerate\" / \"point-to-point\" curves. */\nexport const FLUENT_DECELERATE = 'cubic-bezier(0.1, 0.9, 0.2, 1)';\n\nconst warned = new Set<string>();\n/** Log a deprecation once per key (console.warn). */\nexport function deprecate(key: string, message: string): void {\n if (warned.has(key)) return;\n warned.add(key);\n if (typeof console !== 'undefined') console.warn(`[use-scroll-animate] ${message}`);\n}\n\n/**\n * The `kind` attribute of `<usa-spinner>`, `<usa-check>`, `<usa-dialog>` and\n * `<usa-acrylic>` (3.0: `variant` only selects a style variant).\n */\nexport function kindOf(el: Element, valid: readonly string[] | Record<string, unknown>, fallback: string): string {\n const k = el.getAttribute('kind');\n return k && (Array.isArray(valid) ? valid.includes(k) : k in (valid as object)) ? k : fallback;\n}\n\nexport const clamp = (v: number, min: number, max: number): number => Math.min(max, Math.max(min, v));\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base-ZARFccur.js","sources":["../../src/components/base.ts"],"sourcesContent":["/**\n * use-scroll-animate/components — shared base for the `<usa-*>` custom elements.\n *\n * Everything here is lazy: nothing touches `window`, `document`,\n * `HTMLElement` or `matchMedia` at import time, so the components can be\n * imported during SSR (Next, Nuxt, Astro…) and in Electron/Tauri preload\n * scripts. Classes are created the first time a `define*()` function runs.\n */\n\nexport interface ComponentsConfig {\n /**\n * Inject each component's CSS when it is defined (default `true`). Uses a\n * constructable stylesheet (`document.adoptedStyleSheets`, which a strict\n * `style-src` CSP does not block) and falls back to a `<style>` tag. Set\n * to `false` when you load `use-scroll-animate/components.css` yourself.\n */\n injectStyles?: boolean;\n /**\n * `'user'` (default) follows `prefers-reduced-motion`; `'reduce'` always\n * uses the reduced variants (e.g. a kiosk / battery-saver mode);\n * `'no-preference'` ignores the OS setting (only for demos — respect your users).\n */\n reducedMotion?: 'user' | 'reduce' | 'no-preference';\n /**\n * Global motion intensity (v2.7): `'off'` (same as reduced motion),\n * `'low'` (shorter, calmer), `'normal'` (default) or `'high'`. Scales every\n * component animation's duration and sets `--usa-motion` (0 / 0.6 / 1 /\n * 1.25) on `<html>` for your own CSS. See `setMotionIntensity()`.\n */\n motionIntensity?: MotionIntensity;\n}\n\nexport type MotionIntensity = 'off' | 'low' | 'normal' | 'high';\nexport const MOTION_SCALE: Record<MotionIntensity, number> = { off: 0, low: 0.6, normal: 1, high: 1.25 };\n\nconst config: Required<ComponentsConfig> = { injectStyles: true, reducedMotion: 'user', motionIntensity: 'normal' };\n\n/** Change global component settings (call before `define*()` for `injectStyles`). */\nexport function configureComponents(options: ComponentsConfig): void {\n Object.assign(config, options);\n if (options.motionIntensity && typeof document !== 'undefined') {\n document.documentElement.style.setProperty('--usa-motion', String(MOTION_SCALE[options.motionIntensity] ?? 1));\n document.documentElement.setAttribute('data-usa-motion', options.motionIntensity);\n }\n}\n\n/** The current global motion intensity. */\nexport function getMotionIntensity(): MotionIntensity {\n return config.motionIntensity;\n}\n\n/** Duration multiplier for the current intensity (1 when `normal`). */\nexport function motionScale(): number {\n return MOTION_SCALE[config.motionIntensity] ?? 1;\n}\n\nexport const canDefine = (): boolean => typeof customElements !== 'undefined' && typeof HTMLElement !== 'undefined';\n\n/** `true` when animations should be reduced (OS setting or `configureComponents`). */\nexport function prefersReducedMotion(): boolean {\n if (config.motionIntensity === 'off') return true;\n if (config.reducedMotion !== 'user') return config.reducedMotion === 'reduce';\n return typeof matchMedia === 'function' && !!matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\nconst injected = new Set<string>();\n\n/** Add a component's stylesheet to the document once. */\nexport function adoptStyles(id: string, css: string): void {\n if (!config.injectStyles || !css || injected.has(id) || typeof document === 'undefined') return;\n injected.add(id);\n try {\n if (typeof CSSStyleSheet === 'function' && 'adoptedStyleSheets' in document) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(css);\n document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];\n return;\n }\n } catch {\n /* fall through to <style> */\n }\n const style = document.createElement('style');\n style.setAttribute('data-usa', id);\n style.textContent = css;\n (document.head || document.documentElement).appendChild(style);\n}\n\n/** Attach `css` to a shadow root (constructable sheet where supported, else `<style>`). */\nexport function shadowStyles(root: ShadowRoot, css: string): void {\n try {\n if (typeof CSSStyleSheet === 'function' && 'adoptedStyleSheets' in root) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(css);\n root.adoptedStyleSheets = [sheet];\n return;\n }\n } catch {\n /* fall through */\n }\n const style = document.createElement('style');\n style.textContent = css;\n root.prepend(style);\n}\n\nexport type Cleanup = () => void;\n\n/**\n * Members shared by every `<usa-*>` element. Attribute helpers, a cleanup\n * bag that is emptied on disconnect, and motion helpers that degrade to the\n * final state without WAAPI or under reduced motion.\n */\nexport interface UsaElement extends HTMLElement {\n /** `true` while reduced motion applies to this element. */\n readonly reduced: boolean;\n}\n\nexport interface UsaBase extends UsaElement {\n mount(): void;\n changed(name: string): void;\n unmount(): void;\n str(name: string, fallback?: string): string;\n num(name: string, fallback: number): number;\n flag(name: string): boolean;\n setFlag(name: string, on: boolean): void;\n onCleanup(fn: Cleanup): void;\n listen<K extends keyof HTMLElementEventMap>(\n target: EventTarget,\n type: K | string,\n fn: (e: any) => void,\n options?: AddEventListenerOptions\n ): void;\n inView(cb: (visible: boolean, entry?: IntersectionObserverEntry) => void, init?: IntersectionObserverInit, target?: Element): void;\n motion(el: Element, keyframes: Keyframe[], options: KeyframeAnimationOptions): Animation | null;\n emit(type: string, detail?: unknown): boolean;\n}\n\ntype BaseCtor = new () => UsaBase;\nlet baseClass: BaseCtor | null = null;\n\n/** The lazily created base class (needs `HTMLElement`). */\nexport function getBase(): BaseCtor {\n if (baseClass) return baseClass;\n class Base extends HTMLElement {\n private _cleanups: Cleanup[] = [];\n private _connected = false;\n\n get reduced(): boolean {\n return prefersReducedMotion();\n }\n\n connectedCallback(): void {\n if (this._connected) return;\n this._connected = true;\n // Upgraded while the parser is still inside us (a <script> in <head>\n // defined the element): children/text are not there yet, so wait.\n if (typeof document !== 'undefined' && document.readyState === 'loading' && !this.nextSibling && !this.childNodes.length) {\n const go = () => {\n if (this._connected && this.isConnected) this.mount();\n };\n document.addEventListener('DOMContentLoaded', go, { once: true });\n this._cleanups.push(() => document.removeEventListener('DOMContentLoaded', go));\n return;\n }\n this.mount();\n }\n\n disconnectedCallback(): void {\n this._connected = false;\n this.teardown();\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, value: string | null): void {\n if (!this._connected || oldValue === value) return;\n this.changed(_name);\n }\n\n /** Re-mount on attribute change (override for finer updates). */\n changed(_name: string): void {\n this.teardown();\n this.mount();\n }\n\n private teardown(): void {\n this._cleanups.splice(0).reverse().forEach((fn) => fn());\n this.unmount();\n }\n\n mount(): void {}\n unmount(): void {}\n\n str(name: string, fallback = ''): string {\n const v = this.getAttribute(name);\n return v === null ? fallback : v;\n }\n\n num(name: string, fallback: number): number {\n const v = this.getAttribute(name);\n const n = v === null || v.trim() === '' ? NaN : Number(v);\n return Number.isFinite(n) ? n : fallback;\n }\n\n /** Boolean attribute: present and not `\"false\"`. */\n flag(name: string): boolean {\n const v = this.getAttribute(name);\n return v !== null && v !== 'false';\n }\n\n setFlag(name: string, on: boolean): void {\n if (on) this.setAttribute(name, '');\n else this.removeAttribute(name);\n }\n\n onCleanup(fn: Cleanup): void {\n this._cleanups.push(fn);\n }\n\n listen(target: EventTarget, type: string, fn: (e: any) => void, options?: AddEventListenerOptions): void {\n target.addEventListener(type, fn, options);\n this.onCleanup(() => target.removeEventListener(type, fn, options));\n }\n\n /** Calls `cb(true/false)` as the element enters / leaves the viewport. */\n inView(cb: (visible: boolean, entry?: IntersectionObserverEntry) => void, init?: IntersectionObserverInit, target: Element = this): void {\n if (typeof IntersectionObserver === 'undefined') {\n cb(true);\n return;\n }\n const io = new IntersectionObserver((entries) => {\n for (const e of entries) cb(e.isIntersecting, e);\n }, init);\n io.observe(target);\n this.onCleanup(() => io.disconnect());\n }\n\n /** `el.animate()` that returns `null` (and applies the last frame) without WAAPI. */\n motion(el: Element, keyframes: Keyframe[], options: KeyframeAnimationOptions): Animation | null {\n if (typeof (el as HTMLElement).animate !== 'function') {\n applyFrame(el as HTMLElement, keyframes[keyframes.length - 1]);\n return null;\n }\n const k = motionScale();\n if (k !== 1 && k > 0 && typeof options.duration === 'number') options = { ...options, duration: options.duration * k, delay: (options.delay || 0) * k };\n return (el as HTMLElement).animate(keyframes, options);\n }\n\n emit(type: string, detail?: unknown): boolean {\n return this.dispatchEvent(new CustomEvent(`usa:${type}`, { detail, bubbles: true, cancelable: true }));\n }\n }\n baseClass = Base as unknown as BaseCtor;\n return baseClass;\n}\n\n/** Write a keyframe's properties as inline styles (no-WAAPI fallback). */\nexport function applyFrame(el: HTMLElement, frame?: Keyframe): void {\n if (!frame) return;\n for (const [k, v] of Object.entries(frame)) {\n if (k === 'offset' || k === 'easing' || k === 'composite' || v == null) continue;\n (el.style as any)[k] = String(v);\n }\n}\n\n/**\n * Register `tag` with the class built by `make(Base)`. Returns the\n * constructor, the already registered one, or `undefined` without DOM.\n */\nexport function defineElement(\n tag: string,\n make: (Base: BaseCtor) => CustomElementConstructor,\n css?: { id: string; text: string }\n): CustomElementConstructor | undefined {\n if (!canDefine()) return undefined;\n adoptStyles('base', BASE_CSS);\n if (css) adoptStyles(css.id, css.text);\n const existing = customElements.get(tag);\n if (existing) return existing;\n const ctor = make(getBase());\n customElements.define(tag, ctor);\n return ctor;\n}\n\nconst BASE_CSS = '.usa-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}';\n\n/** A visually hidden copy of `text` for screen readers (the animated copy is `aria-hidden`). */\nexport function srText(text: string): HTMLSpanElement {\n const s = document.createElement('span');\n s.className = 'usa-sr';\n s.textContent = text;\n return s;\n}\n\n/** requestAnimationFrame with a timeout fallback (jsdom / hidden documents). */\nexport const raf = (cb: FrameRequestCallback): number =>\n typeof requestAnimationFrame === 'function' ? requestAnimationFrame(cb) : (setTimeout(() => cb(Date.now()), 16) as unknown as number);\n/** Monotonic time in ms (rAF callback timestamps differ between environments, so loops use this). */\nexport const now = (): number => (typeof performance !== 'undefined' ? performance.now() : Date.now());\nexport const caf = (id: number): void => {\n if (typeof cancelAnimationFrame === 'function') cancelAnimationFrame(id);\n else clearTimeout(id);\n};\n\n/** Spring-ish easing used across the components. */\nexport const EASE_OUT = 'cubic-bezier(0.22, 1, 0.36, 1)';\nexport const EASE_SPRING = 'cubic-bezier(0.34, 1.56, 0.64, 1)';\n/** Windows Fluent \"decelerate\" / \"point-to-point\" curves. */\nexport const FLUENT_DECELERATE = 'cubic-bezier(0.1, 0.9, 0.2, 1)';\n\nconst warned = new Set<string>();\n/** Log a deprecation once per key (console.warn). */\nexport function deprecate(key: string, message: string): void {\n if (warned.has(key)) return;\n warned.add(key);\n if (typeof console !== 'undefined') console.warn(`[use-scroll-animate] ${message}`);\n}\n\n/**\n * The `kind` attribute of `<usa-spinner>`, `<usa-check>`, `<usa-dialog>` and\n * `<usa-acrylic>` (3.0: `variant` only selects a style variant).\n */\nexport function kindOf(el: Element, valid: readonly string[] | Record<string, unknown>, fallback: string): string {\n const k = el.getAttribute('kind');\n return k && (Array.isArray(valid) ? valid.includes(k) : k in (valid as object)) ? k : fallback;\n}\n\nexport const clamp = (v: number, min: number, max: number): number => Math.min(max, Math.max(min, v));\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,218 @@
1
+ import { p as prefersReducedMotion, b as caf, d as clamp, e as applyFrame, r as raf, m as motionScale, n as now } from './base-ZARFccur.js';
2
+
3
+ /** Keyframe presets usable by name in `to()` and `data-tl`. */
4
+ const TIMELINE_PRESETS = {
5
+ fade: [{ opacity: 0 }, { opacity: 1 }],
6
+ 'fade-up': [{ opacity: 0, transform: 'translateY(24px)' }, { opacity: 1, transform: 'none' }],
7
+ 'fade-down': [{ opacity: 0, transform: 'translateY(-24px)' }, { opacity: 1, transform: 'none' }],
8
+ 'fade-left': [{ opacity: 0, transform: 'translateX(24px)' }, { opacity: 1, transform: 'none' }],
9
+ 'fade-right': [{ opacity: 0, transform: 'translateX(-24px)' }, { opacity: 1, transform: 'none' }],
10
+ scale: [{ opacity: 0, transform: 'scale(0.85)' }, { opacity: 1, transform: 'none' }],
11
+ blur: [{ opacity: 0, filter: 'blur(12px)' }, { opacity: 1, filter: 'blur(0)' }],
12
+ rotate: [{ opacity: 0, transform: 'rotate(-12deg) scale(0.9)' }, { opacity: 1, transform: 'none' }],
13
+ 'clip-up': [{ clipPath: 'inset(100% 0 0 0)' }, { clipPath: 'inset(0 0 0 0)' }],
14
+ 'clip-right': [{ clipPath: 'inset(0 100% 0 0)' }, { clipPath: 'inset(0 0 0 0)' }],
15
+ };
16
+ /** Resolve a position against the previous step and labels (pure). */
17
+ function resolvePosition(pos, end, prevStart, labels = {}) {
18
+ if (pos === undefined || pos === '' || pos === '>')
19
+ return end;
20
+ if (typeof pos === 'number')
21
+ return Math.max(0, pos);
22
+ const s = String(pos).trim();
23
+ if (/^-?\d+(\.\d+)?$/.test(s))
24
+ return Math.max(0, Number(s));
25
+ const m = /^(<|>|[A-Za-z_][\w-]*)?\s*(?:([+-])=\s*(\d+(?:\.\d+)?))?$/.exec(s);
26
+ if (!m)
27
+ return end;
28
+ const base = m[1] === '<' ? prevStart : m[1] === '>' || !m[1] ? end : labels[m[1]] ?? end;
29
+ const delta = m[2] ? (m[2] === '-' ? -1 : 1) * Number(m[3]) : 0;
30
+ return Math.max(0, base + delta);
31
+ }
32
+ const toEls = (t) => typeof t === 'string' ? (typeof document === 'undefined' ? [] : Array.from(document.querySelectorAll(t))) : t instanceof Element ? [t] : Array.from(t);
33
+ /**
34
+ * Choreograph animations on one clock: chain, overlap, label, seek, reverse and
35
+ * scrub them with scroll. Built on WAAPI (paused animations driven by one
36
+ * playhead); without WAAPI or under reduced motion it jumps to the end state.
37
+ *
38
+ * @example
39
+ * const tl = timeline({ defaults: { duration: 500 } })
40
+ * .to('.title', 'fade-up')
41
+ * .label('cards')
42
+ * .to('.card', 'scale', { stagger: 80, at: '-=200' })
43
+ * .to('.cta', [{ opacity: 0 }, { opacity: 1 }], { at: 'cards+=400' });
44
+ * tl.play(); // or tl.scrub(document.querySelector('.hero'))
45
+ */
46
+ function timeline(options = {}) {
47
+ const d = { duration: 600, easing: 'cubic-bezier(0.22, 1, 0.36, 1)', stagger: 0, ...options.defaults };
48
+ const steps = [];
49
+ const cues = [];
50
+ const labels = {};
51
+ let end = 0;
52
+ let prevStart = 0;
53
+ let t = 0;
54
+ let frame = 0;
55
+ let dir = 1;
56
+ let settle;
57
+ let built = false;
58
+ const total = () => Math.max(end, ...cues.map((c) => c.at), 0);
59
+ const build = () => {
60
+ if (built)
61
+ return;
62
+ built = true;
63
+ for (const s of steps) {
64
+ if (typeof s.el.animate !== 'function') {
65
+ s.anim = null;
66
+ continue;
67
+ }
68
+ s.anim = s.el.animate(s.frames, { duration: s.duration, delay: s.start, easing: s.easing, fill: 'both' });
69
+ s.anim.pause?.();
70
+ }
71
+ };
72
+ const render = (to, from) => {
73
+ build();
74
+ t = clamp(to, 0, total());
75
+ for (const s of steps) {
76
+ if (s.anim)
77
+ s.anim.currentTime = t;
78
+ else
79
+ applyFrame(s.el, s.frames[t >= s.start ? s.frames.length - 1 : 0]);
80
+ }
81
+ for (const c of cues)
82
+ if ((from < c.at && t >= c.at) || (from > c.at && t <= c.at))
83
+ c.fn();
84
+ options.onUpdate?.(total() ? t / total() : 1);
85
+ };
86
+ const stop = () => {
87
+ if (frame)
88
+ caf(frame);
89
+ frame = 0;
90
+ };
91
+ const run = (direction) => {
92
+ stop();
93
+ settle?.();
94
+ dir = direction;
95
+ const target = dir > 0 ? total() : 0;
96
+ const k = motionScale();
97
+ if (prefersReducedMotion() || k === 0 || !total()) {
98
+ render(target, t);
99
+ options.onComplete?.();
100
+ return Promise.resolve();
101
+ }
102
+ const rate = (options.speed ?? 1) / k;
103
+ return new Promise((resolve) => {
104
+ settle = () => { settle = undefined; resolve(); };
105
+ let last = now();
106
+ const loop = () => {
107
+ const n = now();
108
+ const next = t + (n - last) * rate * dir;
109
+ last = n;
110
+ render(next, t);
111
+ if ((dir > 0 && t >= target) || (dir < 0 && t <= 0)) {
112
+ frame = 0;
113
+ options.onComplete?.();
114
+ settle?.();
115
+ return;
116
+ }
117
+ frame = raf(loop);
118
+ };
119
+ frame = raf(loop);
120
+ });
121
+ };
122
+ const api = {
123
+ get duration() { return total(); },
124
+ get labels() { return { ...labels }; },
125
+ get time() { return t; },
126
+ to(target, frames, o = {}) {
127
+ const kf = typeof frames === 'string' ? TIMELINE_PRESETS[frames] || TIMELINE_PRESETS.fade : frames;
128
+ const start = resolvePosition(o.at, end, prevStart, labels);
129
+ const duration = o.duration ?? d.duration;
130
+ const stagger = o.stagger ?? d.stagger;
131
+ let last = start;
132
+ toEls(target).forEach((el, i) => {
133
+ const s = start + i * stagger;
134
+ steps.push({ el, frames: kf, start: s, duration, easing: o.easing ?? d.easing });
135
+ last = Math.max(last, s + duration);
136
+ });
137
+ prevStart = start;
138
+ end = Math.max(end, last);
139
+ built = false;
140
+ steps.forEach((s) => s.anim?.cancel?.());
141
+ return api;
142
+ },
143
+ label(name, at) {
144
+ labels[name] = resolvePosition(at, end, prevStart, labels);
145
+ return api;
146
+ },
147
+ call(fn, at) {
148
+ cues.push({ fn, at: resolvePosition(at, end, prevStart, labels) });
149
+ return api;
150
+ },
151
+ play(from) {
152
+ if (from !== undefined)
153
+ render(resolvePosition(from, 0, 0, labels), t);
154
+ else if (t >= total())
155
+ render(0, -1);
156
+ return run(1);
157
+ },
158
+ reverse() {
159
+ return run(-1);
160
+ },
161
+ pause() {
162
+ stop();
163
+ return api;
164
+ },
165
+ seek(to) {
166
+ stop();
167
+ render(resolvePosition(to, 0, 0, labels), t);
168
+ return api;
169
+ },
170
+ progress(p) {
171
+ if (p !== undefined)
172
+ api.seek(clamp(p, 0, 1) * total());
173
+ return total() ? t / total() : 0;
174
+ },
175
+ scrub(source, o = {}) {
176
+ stop();
177
+ if (prefersReducedMotion() || typeof window === 'undefined') {
178
+ render(total(), t);
179
+ return () => { };
180
+ }
181
+ let id = 0;
182
+ let cur = t;
183
+ const update = () => {
184
+ id = 0;
185
+ const r = source.getBoundingClientRect();
186
+ const vh = window.innerHeight || 1;
187
+ const p = clamp((vh + (o.offset ?? 0) - r.top) / (vh + r.height || 1), 0, 1);
188
+ const goal = p * total();
189
+ const sm = clamp(o.smooth ?? 0, 0, 0.95);
190
+ cur = sm ? cur + (goal - cur) * (1 - sm) : goal;
191
+ render(cur, t);
192
+ if (sm && Math.abs(goal - cur) > 0.5)
193
+ id = raf(update);
194
+ };
195
+ const onScroll = () => { if (!id)
196
+ id = raf(update); };
197
+ window.addEventListener('scroll', onScroll, { passive: true });
198
+ window.addEventListener('resize', onScroll, { passive: true });
199
+ update();
200
+ return () => {
201
+ window.removeEventListener('scroll', onScroll);
202
+ window.removeEventListener('resize', onScroll);
203
+ if (id)
204
+ caf(id);
205
+ };
206
+ },
207
+ cancel() {
208
+ stop();
209
+ settle?.();
210
+ steps.forEach((s) => s.anim?.cancel?.());
211
+ built = false;
212
+ },
213
+ };
214
+ return api;
215
+ }
216
+
217
+ export { TIMELINE_PRESETS as T, resolvePosition as r, timeline as t };
218
+ //# sourceMappingURL=core-Co-6AL0h.js.map