react-voodoo 2.6.1 → 2.6.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-voodoo",
3
- "version": "2.6.1",
3
+ "version": "2.6.2",
4
4
  "license": "(CC-BY-ND-4.0 OR AGPL-3.0-only)",
5
5
  "main": "./dist/react-voodoo.js",
6
6
  "author": "Nathan Braun <n8tz.js@gmail.com>",
package/readme.md DELETED
@@ -1,340 +0,0 @@
1
- <h1 align="center">react-voodoo</h1>
2
- <p align="center"><b>Additive · Swipeable · SSR-ready · Physics-based</b><br/>A delta-driven tween composition engine for React</p>
3
-
4
- <p align="center"><img width="192" src="https://github.com/react-voodoo/react-voodoo/raw/master/doc/assets/logo-v0.png?sanitize=true" /></p>
5
-
6
- <p align="center">
7
- <a href="https://www.npmjs.com/package/react-voodoo"><img src="https://img.shields.io/npm/v/react-voodoo.svg" alt="npm version" /></a>
8
- <a href="https://travis-ci.org/react-voodoo/react-voodoo"><img src="https://travis-ci.org/react-voodoo/react-voodoo.svg?branch=master" alt="Build Status" /></a>
9
- <img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" />
10
- <br/>
11
- <a href="http://creativecommons.org/licenses/by-nd/4.0"><img src="https://img.shields.io/badge/License-CC%20BY--ND%204.0-lightgrey.svg" alt="License: CC BY-ND 4.0" /></a>
12
- <a href="http://www.gnu.org/licenses/agpl-3.0"><img src="https://img.shields.io/badge/License-AGPL%20v3-blue.svg" alt="License: AGPL v3" /></a>
13
- </p>
14
-
15
- <p align="center">
16
- <a href="doc/readme.md"><b>Full documentation</b></a> &nbsp;·&nbsp;
17
- <a href="https://react-voodoo.github.io/react-voodoo-samples/"><b>Live demos & CodeSandbox</b></a> &nbsp;·&nbsp;
18
- <a href="https://github.com/react-voodoo/react-voodoo-samples"><b>Sample sources</b></a>
19
- </p>
20
-
21
- <p align="center"><img src="https://github.com/react-voodoo/react-voodoo/raw/master/doc/assets/demo.gif?sanitize=true" /></p>
22
-
23
- ---
24
-
25
- ## Why react-voodoo?
26
-
27
- Most animation libraries output **absolute values** — they own a CSS property and write a number to it each frame. That works fine for isolated transitions, but breaks down the moment you need to combine sources: a scroll position driving `translateY`, a drag gesture adding to the same `translateY`, and a parallax offset stacking on top. The libraries fight each other and you end up writing glue code.
28
-
29
- React-voodoo takes a different approach: its engine computes **deltas** — the *change* from the previous frame — and accumulates them additively across any number of axes. Multiple animations on the same property simply add together. No ownership, no conflicts.
30
-
31
- The engine is built on [tween-axis](../tween-axis/README.md) and uses its WebAssembly backend for hot-path property accumulation with zero JS-boundary crossings per frame.
32
-
33
- This unlocks a set of features that are unique to the delta model:
34
-
35
- | Feature | How |
36
- |---|---|
37
- | **Additive multi-axis composition** | Each axis contributes a delta; they stack without coordination code. |
38
- | **Swipeable / draggable animations** | Drag gestures are mapped directly to axis positions with realistic momentum. |
39
- | **Predictive inertia** | The engine computes the final snap target *at the moment of release*, before the animation plays out — useful for preloading the next slide. |
40
- | **SSR with correct initial styles** | Axes have a `defaultPosition`; styles are computed server-side and rendered inline — no flash on first paint. |
41
- | **DOM writes bypass React** | Style updates go straight to `node.style` via direct DOM writes, never triggering a re-render. |
42
- | **Multi-unit CSS via `calc()`** | Mix `%`, `px`, `vw`, `bw`/`bh` (box-relative units) in a single value — compiled to `calc()` automatically. |
43
-
44
- ---
45
-
46
- ## Comparison
47
-
48
- ### Feature matrix
49
-
50
- | | **react-voodoo** | Framer Motion | GSAP + ScrollTrigger | react-spring | Motion One | anime.js |
51
- |---|:---:|:---:|:---:|:---:|:---:|:---:|
52
- | Scroll-linked animation | ✅ | ✅ `useScroll` | ✅ | ⚠️ manual | ✅ | ⚠️ manual |
53
- | Drag-linked animation | ✅ native | ✅ `drag` | ⚠️ manual | ✅ `@use-gesture` | ⚠️ manual | ❌ |
54
- | **Additive multi-axis composition** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
55
- | Physics / momentum inertia | ✅ predictive | ✅ spring | ❌ | ✅ spring | ❌ | ❌ |
56
- | **Predictive snap target** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
57
- | **SSR — correct initial styles** | ✅ | ⚠️ flash | ⚠️ flash | ⚠️ flash | ⚠️ flash | ❌ |
58
- | Bypasses React render loop | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
59
- | Transform layer composition | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
60
- | SVG geometry attributes | ✅ | ⚠️ limited | ✅ | ❌ | ⚠️ | ✅ |
61
- | Multitouch (drag multiple axes) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
62
- | Bundle size (approx. gzip) | ~18 kB | ~50 kB | ~75 kB | ~30 kB | ~18 kB | ~14 kB |
63
- | React dependency | ≥ 16 | ≥ 18 | none | ≥ 16 | none | none |
64
-
65
- ### When to pick react-voodoo
66
-
67
- - Swipeable carousels and full-page scroll scenes where drag, inertia, and animation must be one system
68
- - Any UI where **multiple animation "tracks"** compose onto the same elements (parallax, pinned sequences, overlapping effects)
69
- - **SSR-first** projects where the initial paint must already reflect the animated state
70
- - Scenarios requiring **predictive callbacks** — e.g. preloading slide N+1 before the swipe animation finishes
71
-
72
- ### When to look elsewhere
73
-
74
- - Simple enter/exit transitions → **Framer Motion** (`AnimatePresence` is excellent for this)
75
- - Complex GSAP-style timeline sequencing without scroll/drag → **GSAP**
76
- - Spring-physics micro-interactions → **react-spring** or **Framer Motion**
77
- - Lightweight imperative animation on non-React pages → **anime.js** or **Motion One**
78
-
79
- ---
80
-
81
- ## Installation
82
-
83
- ```bash
84
- npm install react-voodoo
85
- ```
86
-
87
- **Peer dependencies:** `react >= 16`, `react-dom >= 16`
88
-
89
- ---
90
-
91
- ## All-in-one example
92
-
93
- Every major feature in a single component, with comments explaining each part.
94
-
95
- ```jsx harmony
96
- import React from "react";
97
- import Voodoo from "react-voodoo";
98
- import {itemTweenAxis, tweenArrayWithTargets} from "./somewhere";
99
-
100
- const styleSample = {
101
- /**
102
- * Voodoo.Node style property and the tween descriptors use classic CSS-in-JS declaration
103
- * exept we can specify values using the "box" unit which is a [0-1] ratio of the parent ViewBox height / width
104
- */
105
-
106
- height: "50%",
107
-
108
- // the tweener deal with multiple units
109
- // it will use css calc fn to add them if there's more than 1 unit used
110
- width: ["50%", "10vw", "-50px", ".2box"],
111
-
112
- // transform can use multiple "layers"
113
- transform: [
114
- {
115
- // use rotate(X|Y|Z) & translate(X|Y|Z)
116
- rotateX: "25deg"
117
- },
118
- {
119
- translateZ: "-.2box"
120
- }
121
- ],
122
-
123
- filter:
124
- {
125
- blur: "5px"
126
- }
127
- };
128
- const axisSample = [// Examples of tween descriptors
129
- {
130
- target : "someTweenRefId", // target Voodoo.Node id ( optional if used as parameter on a Voodoo.Node as it will target it )
131
- from : 0, // tween start position
132
- duration: 100, // tween duration
133
- easeFn : "easeCircleIn", // function or easing fn id from [d3-ease](https://github.com/d3/d3-ease)
134
-
135
- apply: {// relative css values to be applied
136
- // Same syntax as the styles
137
- transform: [{}, {
138
- translateZ: "-.2box"
139
- }]
140
- }
141
- },
142
- {
143
- from : 40,
144
- duration: 20,
145
-
146
- // triggered when axis has scrolled in the Event period
147
- // delta : a float value between [-1,1] is the update inside the Event period
148
- entering: ( delta ) => false,
149
-
150
- // triggered when axis has scrolled in the Event period
151
- // newPos, precPos : float values between [0,1] position inside the Event period
152
- // delta : a float value between [-1,1] is the update inside the Event period
153
- moving: ( newPos, precPos, delta ) => false,
154
-
155
- // triggered when axis has scrolled out the Event period
156
- // delta : a float value between [-1,1] is the update inside the Event period
157
- leaving: ( delta ) => false
158
- }
159
- ];
160
-
161
- const Sample = ( {} ) => {
162
-
163
- /**
164
- * Voodoo tweener instanciation
165
- */
166
- // Classic minimal method
167
- const [tweener, ViewBox] = Voodoo.hook();
168
- // get the first tweener in parents
169
- const [parentTweener] = Voodoo.hook(true);
170
- // Create a tweener with options
171
- const [twenerWithNameAndOptions, ViewBox2] = Voodoo.hook(
172
- {
173
- // Give an id to this tweener so we can access it's axes in the childs components
174
- name: "root",
175
- // max click tm in ms before a click become a drag
176
- maxClickTm: 200,
177
- // max drag offset in px before a click become a drag
178
- maxClickOffset: 100,
179
- // lock to only 1 drag direction
180
- dragDirectionLock: false,
181
- // allow dragging with mouse
182
- enableMouseDrag: false
183
- }
184
- );
185
- // get a named parent tweener
186
- const [nammedParentTweener] = Voodoo.hook("root")
187
-
188
- /**
189
- * once first render done, axes expose the following values & functions :
190
- */
191
- // Theirs actual position in :
192
- // tweener.axes.(axisId).scrollPos
193
-
194
- // The "scrollTo" function allowing to manually move the axes positions :
195
- // tweener.axes.(axisId).scrollTo(targetPos, duration, easeFn)
196
- // tweener.scrollTo(targetPos, duration, axisId, easeFn)
197
-
198
- // They can also be watched using the "watchAxis" function;
199
- // When called, the returned function will disable the listener if executed :
200
- React.useEffect(
201
- e => tweener?.watchAxis("scrollY", ( pos ) => doSomething()),
202
- [tweener]
203
- )
204
-
205
- return <ViewBox className={"container"}>
206
- <Voodoo.Axis
207
-
208
- id={"scrollY"} // Tween axis Id
209
- defaultPosition={100} // optional initial position ( default : 0 )
210
-
211
- // optional Array of tween descriptors with theirs Voodoo.Node target ids ( see axisSample )
212
- items={tweenArrayWithTargets}
213
-
214
- // optional size of the scrollable window for drag synchronisation
215
- scrollableWindow={200}
216
-
217
- // optional length of this scrollable axis (default to last tween desciptor position+duration)
218
- size={1000}
219
-
220
- // optional bounds ( inertia will target them if target pos is out )
221
- bounds={{ min: 100, max: 900 }}
222
-
223
- // optional inertia cfg ( false to disable it )
224
- inertia={
225
- {
226
- // called when inertia is updated
227
- // should return instantaneous move to do if wanted
228
- shouldLoop: ( currentPos ) => (currentPos > 500 ? -500 : null),
229
-
230
- // called when inertia know where it will end ( when the user stop dragging )
231
- willEnd: ( targetPos, targetDelta, duration ) => {
232
- },
233
-
234
- // called when inertia know where it will snap ( when the user stop dragging )
235
- willSnap: ( currentSnapIndex, targetWayPointObj ) => {
236
- },
237
-
238
- // called when inertia end
239
- onStop: ( pos, targetWayPointObj ) => {
240
- },
241
-
242
- // called when inertia end on a snap
243
- onSnap: ( snapIndex, targetWayPointObj ) => {
244
- },
245
-
246
- // list of waypoints object ( only support auto snap 50/50 for now )
247
- wayPoints: [{ at: 100 }, { at: 200 }]
248
- }
249
- }
250
- />
251
-
252
- <Voodoo.Node
253
- id={"testItem"} // optional id
254
-
255
- style={styleSample}// optional styles applied before any style coming from axes : css syntax + voodoo tweener units & transform management
256
-
257
- axes={{ scrollY: axisSample }} // optional Array of tween by axis Id with no target node id required ( it will be ignored )
258
-
259
- onClick={// all unknow props are passed to the child node
260
- ( e ) => {
261
- // start playing an anim ( prefer scrolling Axes )
262
- tweener.pushAnim(
263
- // make all tween target "testItem"
264
- Voodoo.tools.target(pushIn, "testItem")
265
- ).then(
266
- ( tweenAxis ) => {
267
- // doSomething next
268
- }
269
- );
270
- }
271
- }
272
- >
273
- <Voodoo.Draggable
274
- // make drag y move the scrollAnAxis axis
275
- // xAxis={ "scrollAnAxis" }
276
-
277
- // scale / inverse dispatched delta
278
- // xHook={(delta)=>modify(delta)}
279
-
280
- // React ref to the box, default to the parent ViewBox
281
- // scale is as follow : (delta / ((xBoxRef||ViewBox).offsetWidth)) * ( axis.scrollableWindow || axis.duration )
282
- // xBoxRef={ref}
283
-
284
- yAxis={"scrollY"}// make drag y move the scrollY axis
285
- // yHook={(delta)=>modify(delta)}
286
- // yBoxRef={ref}
287
-
288
- // mouseDrag={true} // listen for mouse drag ( default to false )
289
- // touchDrag={false} // listen for touch drag ( default to true )
290
-
291
- // button={1-3} // limit mouse drag to the specified event.button === ( default to 1; the left btn )
292
-
293
- // * actually Draggable create it's own div node
294
- >
295
- <div>
296
- Some content to tween
297
- </div>
298
- </Voodoo.Draggable>
299
- </Voodoo.Node>
300
- </ViewBox>;
301
- }
302
- ```
303
-
304
- For a more complete annotated example with inertia callbacks, `watchAxis`, and programmatic scrolling, see the [full documentation](doc/readme.md).
305
-
306
- ---
307
-
308
- ## Core concepts in 30 seconds
309
-
310
- **Axis** — a virtual number line. Move its position (by drag, scroll, or code) and it drives CSS animations on any number of nodes.
311
-
312
- **Node** — a React element whose styles are controlled by one or more axes. Style updates go straight to `node.style`, no re-renders.
313
-
314
- **Delta composition** — each axis contributes a *change* per frame. Stack a horizontal drag axis and a parallax axis on the same `translateX` and they simply add together. No ownership, no conflicts.
315
-
316
- ```
317
- axis position ──► tween engine ──► Δ per property ──► node.style (direct DOM write)
318
-
319
- other axes add their Δ here
320
- ```
321
-
322
- ---
323
-
324
- ## License
325
-
326
- React-voodoo is dual-licensed:
327
-
328
- - **[CC BY-ND 4.0](http://creativecommons.org/licenses/by-nd/4.0)** — use freely in commercial projects; distribution of modified versions is not permitted.
329
- - **[AGPL v3](http://www.gnu.org/licenses/agpl-3.0)** — distribute modified versions under the same open-source license.
330
-
331
- ---
332
-
333
- ## Support the project
334
-
335
- If react-voodoo saved you a day of work, consider supporting it:
336
-
337
- [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#)
338
-
339
- **BTC** — `bc1qh43j8jh6dr8v3f675jwqq3nqymtsj8pyq0kh5a`
340
- **PayPal** — <a href="https://www.paypal.com/donate/?hosted_button_id=ECHYGKY3GR7CN"><img src="https://img.shields.io/badge/paypal-donate-yellow.svg" alt="PayPal donate" /></a>