react-voodoo 2.5.16 → 2.6.1
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/README.md +274 -0
- package/babel.config.js +6 -0
- package/dist/react-voodoo.js +1 -1
- package/dist/react-voodoo.js.map +1 -1
- package/jest.config.js +16 -0
- package/package.json +10 -4
- package/readme.md +152 -89
package/jest.config.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
testEnvironment: 'jest-environment-jsdom',
|
|
3
|
+
|
|
4
|
+
setupFilesAfterEnv: ['<rootDir>/etc/tests/jest.setup.js'],
|
|
5
|
+
|
|
6
|
+
transform: {
|
|
7
|
+
'^.+\\.[jt]sx?$': 'babel-jest',
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
testMatch: ['<rootDir>/etc/tests/**/*.test.{js,jsx}'],
|
|
11
|
+
|
|
12
|
+
// tween-axis ships a CJS dist — no transformation needed.
|
|
13
|
+
// d3-ease and color-rgba expose CJS-compatible builds.
|
|
14
|
+
// The local dist/ bundle is already compiled CJS — skip babel on it too.
|
|
15
|
+
transformIgnorePatterns: ['/node_modules/', '/dist/'],
|
|
16
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-voodoo",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
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>",
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "lpack",
|
|
11
11
|
"devLib": "lpack :staging -w",
|
|
12
|
-
"test": "
|
|
13
|
-
"
|
|
12
|
+
"test": "jest",
|
|
13
|
+
"test:watch": "jest --watch",
|
|
14
|
+
"testAuto": "nodemon --watch ./src --watch ./etc/tests --exec \"npm test\"",
|
|
14
15
|
"setupLayers": "lpack-setup"
|
|
15
16
|
},
|
|
16
17
|
"peerDependencies": {
|
|
@@ -25,13 +26,18 @@
|
|
|
25
26
|
"fast-deep-equal": "^3.1.3",
|
|
26
27
|
"is": "^3.3.0",
|
|
27
28
|
"shortid": "^2.2.16",
|
|
28
|
-
"tween-axis": "^2.0
|
|
29
|
+
"tween-axis": "^2.2.0"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
32
|
+
"@babel/preset-env": "^7.24.0",
|
|
33
|
+
"@babel/preset-react": "^7.24.0",
|
|
31
34
|
"@babel/register": "^7.24.6",
|
|
32
35
|
"@testing-library/jest-dom": "^6.4.6",
|
|
33
36
|
"@testing-library/react": "^16.0.0",
|
|
37
|
+
"babel-jest": "^29.0.0",
|
|
34
38
|
"docdash": "^2.0.2",
|
|
39
|
+
"jest": "^29.0.0",
|
|
40
|
+
"jest-environment-jsdom": "^29.0.0",
|
|
35
41
|
"jsdoc": "^4.0.3",
|
|
36
42
|
"layer-pack": "^3.0.7",
|
|
37
43
|
"lpack-react": "^2.2.0",
|
package/readme.md
CHANGED
|
@@ -1,62 +1,96 @@
|
|
|
1
1
|
<h1 align="center">react-voodoo</h1>
|
|
2
|
-
<p align="center">
|
|
3
|
-
|
|
4
|
-
___
|
|
5
|
-
<p align="center"><img width="192" src ="https://github.com/react-voodoo/react-voodoo/raw/master/doc/assets/logo-v0.png?sanitize=true" /></p>
|
|
2
|
+
<p align="center"><b>Additive · Swipeable · SSR-ready · Physics-based</b><br/>A delta-driven tween composition engine for React</p>
|
|
6
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>
|
|
7
5
|
|
|
8
6
|
<p align="center">
|
|
9
|
-
<a href="https://www.npmjs.com/package/react-voodoo">
|
|
10
|
-
<img src="https://
|
|
11
|
-
<a href="https://travis-ci.org/react-voodoo/react-voodoo">
|
|
12
|
-
<img src="https://travis-ci.org/react-voodoo/react-voodoo.svg?branch=master" alt="Build Status" /></a>
|
|
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>
|
|
13
9
|
<img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" />
|
|
14
10
|
<br/>
|
|
15
|
-
<a href="http://creativecommons.org/licenses/by-nd/4.0">
|
|
16
|
-
<img src="https://img.shields.io/badge/License-
|
|
17
|
-
<a href="http://www.gnu.org/licenses/agpl-3.0">
|
|
18
|
-
<img src="https://img.shields.io/badge/License-AGPL%20v3-blue.svg" alt="License: AGPL v3" /></a>
|
|
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>
|
|
19
13
|
</p>
|
|
20
14
|
|
|
21
|
-
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="doc/readme.md"><b>Full documentation</b></a> ·
|
|
17
|
+
<a href="https://react-voodoo.github.io/react-voodoo-samples/"><b>Live demos & CodeSandbox</b></a> ·
|
|
18
|
+
<a href="https://github.com/react-voodoo/react-voodoo-samples"><b>Sample sources</b></a>
|
|
19
|
+
</p>
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
gradually compose values from multiple sources (e.g. when merging multiple animations based on user drag interactions )
|
|
25
|
-
.<br/>
|
|
21
|
+
<p align="center"><img src="https://github.com/react-voodoo/react-voodoo/raw/master/doc/assets/demo.gif?sanitize=true" /></p>
|
|
26
22
|
|
|
27
|
-
|
|
23
|
+
---
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
- Swipeable complex animations ( like Android & iOS )
|
|
31
|
-
- Fast & direct DOM updates ( not bound to the React rendering loop )
|
|
32
|
-
- Server Side Rendering of any scroll / swipe position
|
|
33
|
-
- Easily connect sensors / gestures to complex animations
|
|
34
|
-
- Hot switching scrollable anims ( responsive )
|
|
35
|
-
- Predictive inertia ( knowing where inertia will stop while animating )
|
|
36
|
-
- Multitouch dragging ( drag multiple things at once )
|
|
37
|
-
- Intuitive & flexible animation system
|
|
38
|
-
- Cool ( & performant ) React integration
|
|
39
|
-
- Automatically deal with multiple units using css "calc( ... )"
|
|
40
|
-
- etc...
|
|
25
|
+
## Why react-voodoo?
|
|
41
26
|
|
|
42
|
-
|
|
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.
|
|
43
28
|
|
|
44
|
-
|
|
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.
|
|
45
30
|
|
|
46
|
-
|
|
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.
|
|
47
32
|
|
|
48
|
-
|
|
33
|
+
This unlocks a set of features that are unique to the delta model:
|
|
49
34
|
|
|
50
|
-
|
|
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. |
|
|
51
43
|
|
|
52
|
-
|
|
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
|
|
53
71
|
|
|
54
|
-
|
|
55
|
-
Paypal : <span class="badge-paypal"><a href="https://www.paypal.com/donate/?hosted_button_id=ECHYGKY3GR7CN" title="Donate to this project using Paypal"><img src="https://img.shields.io/badge/paypal-donate-yellow.svg" alt="PayPal donate button" /></a></span>
|
|
72
|
+
### When to look elsewhere
|
|
56
73
|
|
|
57
|
-
|
|
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**
|
|
58
78
|
|
|
59
|
-
|
|
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.
|
|
60
94
|
|
|
61
95
|
```jsx harmony
|
|
62
96
|
import React from "react";
|
|
@@ -68,13 +102,13 @@ const styleSample = {
|
|
|
68
102
|
* Voodoo.Node style property and the tween descriptors use classic CSS-in-JS declaration
|
|
69
103
|
* exept we can specify values using the "box" unit which is a [0-1] ratio of the parent ViewBox height / width
|
|
70
104
|
*/
|
|
71
|
-
|
|
105
|
+
|
|
72
106
|
height: "50%",
|
|
73
|
-
|
|
74
|
-
// the tweener deal with multiple units
|
|
75
|
-
// it will use css calc fn to add them if there's more than 1 unit used
|
|
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
|
|
76
110
|
width: ["50%", "10vw", "-50px", ".2box"],
|
|
77
|
-
|
|
111
|
+
|
|
78
112
|
// transform can use multiple "layers"
|
|
79
113
|
transform: [
|
|
80
114
|
{
|
|
@@ -85,7 +119,7 @@ const styleSample = {
|
|
|
85
119
|
translateZ: "-.2box"
|
|
86
120
|
}
|
|
87
121
|
],
|
|
88
|
-
|
|
122
|
+
|
|
89
123
|
filter:
|
|
90
124
|
{
|
|
91
125
|
blur: "5px"
|
|
@@ -97,8 +131,8 @@ const axisSample = [// Examples of tween descriptors
|
|
|
97
131
|
from : 0, // tween start position
|
|
98
132
|
duration: 100, // tween duration
|
|
99
133
|
easeFn : "easeCircleIn", // function or easing fn id from [d3-ease](https://github.com/d3/d3-ease)
|
|
100
|
-
|
|
101
|
-
apply: {// relative css values to be applied
|
|
134
|
+
|
|
135
|
+
apply: {// relative css values to be applied
|
|
102
136
|
// Same syntax as the styles
|
|
103
137
|
transform: [{}, {
|
|
104
138
|
translateZ: "-.2box"
|
|
@@ -108,16 +142,16 @@ const axisSample = [// Examples of tween descriptors
|
|
|
108
142
|
{
|
|
109
143
|
from : 40,
|
|
110
144
|
duration: 20,
|
|
111
|
-
|
|
112
|
-
// triggered when axis has scrolled in the Event period
|
|
145
|
+
|
|
146
|
+
// triggered when axis has scrolled in the Event period
|
|
113
147
|
// delta : a float value between [-1,1] is the update inside the Event period
|
|
114
148
|
entering: ( delta ) => false,
|
|
115
|
-
|
|
149
|
+
|
|
116
150
|
// triggered when axis has scrolled in the Event period
|
|
117
151
|
// newPos, precPos : float values between [0,1] position inside the Event period
|
|
118
152
|
// delta : a float value between [-1,1] is the update inside the Event period
|
|
119
153
|
moving: ( newPos, precPos, delta ) => false,
|
|
120
|
-
|
|
154
|
+
|
|
121
155
|
// triggered when axis has scrolled out the Event period
|
|
122
156
|
// delta : a float value between [-1,1] is the update inside the Event period
|
|
123
157
|
leaving: ( delta ) => false
|
|
@@ -125,7 +159,7 @@ const axisSample = [// Examples of tween descriptors
|
|
|
125
159
|
];
|
|
126
160
|
|
|
127
161
|
const Sample = ( {} ) => {
|
|
128
|
-
|
|
162
|
+
|
|
129
163
|
/**
|
|
130
164
|
* Voodoo tweener instanciation
|
|
131
165
|
*/
|
|
@@ -142,86 +176,86 @@ const Sample = ( {} ) => {
|
|
|
142
176
|
maxClickTm: 200,
|
|
143
177
|
// max drag offset in px before a click become a drag
|
|
144
178
|
maxClickOffset: 100,
|
|
145
|
-
// lock to only 1 drag direction
|
|
179
|
+
// lock to only 1 drag direction
|
|
146
180
|
dragDirectionLock: false,
|
|
147
181
|
// allow dragging with mouse
|
|
148
182
|
enableMouseDrag: false
|
|
149
183
|
}
|
|
150
184
|
);
|
|
151
|
-
// get a named parent tweener
|
|
185
|
+
// get a named parent tweener
|
|
152
186
|
const [nammedParentTweener] = Voodoo.hook("root")
|
|
153
|
-
|
|
187
|
+
|
|
154
188
|
/**
|
|
155
189
|
* once first render done, axes expose the following values & functions :
|
|
156
190
|
*/
|
|
157
191
|
// Theirs actual position in :
|
|
158
192
|
// tweener.axes.(axisId).scrollPos
|
|
159
|
-
|
|
193
|
+
|
|
160
194
|
// The "scrollTo" function allowing to manually move the axes positions :
|
|
161
195
|
// tweener.axes.(axisId).scrollTo(targetPos, duration, easeFn)
|
|
162
196
|
// tweener.scrollTo(targetPos, duration, axisId, easeFn)
|
|
163
|
-
|
|
197
|
+
|
|
164
198
|
// They can also be watched using the "watchAxis" function;
|
|
165
199
|
// When called, the returned function will disable the listener if executed :
|
|
166
200
|
React.useEffect(
|
|
167
201
|
e => tweener?.watchAxis("scrollY", ( pos ) => doSomething()),
|
|
168
202
|
[tweener]
|
|
169
203
|
)
|
|
170
|
-
|
|
204
|
+
|
|
171
205
|
return <ViewBox className={"container"}>
|
|
172
206
|
<Voodoo.Axis
|
|
173
|
-
|
|
207
|
+
|
|
174
208
|
id={"scrollY"} // Tween axis Id
|
|
175
209
|
defaultPosition={100} // optional initial position ( default : 0 )
|
|
176
|
-
|
|
210
|
+
|
|
177
211
|
// optional Array of tween descriptors with theirs Voodoo.Node target ids ( see axisSample )
|
|
178
212
|
items={tweenArrayWithTargets}
|
|
179
|
-
|
|
213
|
+
|
|
180
214
|
// optional size of the scrollable window for drag synchronisation
|
|
181
215
|
scrollableWindow={200}
|
|
182
|
-
|
|
183
|
-
// optional length of this scrollable axis (default to last tween desciptor position+duration)
|
|
216
|
+
|
|
217
|
+
// optional length of this scrollable axis (default to last tween desciptor position+duration)
|
|
184
218
|
size={1000}
|
|
185
|
-
|
|
219
|
+
|
|
186
220
|
// optional bounds ( inertia will target them if target pos is out )
|
|
187
221
|
bounds={{ min: 100, max: 900 }}
|
|
188
|
-
|
|
222
|
+
|
|
189
223
|
// optional inertia cfg ( false to disable it )
|
|
190
224
|
inertia={
|
|
191
225
|
{
|
|
192
226
|
// called when inertia is updated
|
|
193
227
|
// should return instantaneous move to do if wanted
|
|
194
228
|
shouldLoop: ( currentPos ) => (currentPos > 500 ? -500 : null),
|
|
195
|
-
|
|
229
|
+
|
|
196
230
|
// called when inertia know where it will end ( when the user stop dragging )
|
|
197
231
|
willEnd: ( targetPos, targetDelta, duration ) => {
|
|
198
232
|
},
|
|
199
|
-
|
|
233
|
+
|
|
200
234
|
// called when inertia know where it will snap ( when the user stop dragging )
|
|
201
235
|
willSnap: ( currentSnapIndex, targetWayPointObj ) => {
|
|
202
236
|
},
|
|
203
|
-
|
|
237
|
+
|
|
204
238
|
// called when inertia end
|
|
205
239
|
onStop: ( pos, targetWayPointObj ) => {
|
|
206
240
|
},
|
|
207
|
-
|
|
241
|
+
|
|
208
242
|
// called when inertia end on a snap
|
|
209
243
|
onSnap: ( snapIndex, targetWayPointObj ) => {
|
|
210
244
|
},
|
|
211
|
-
|
|
245
|
+
|
|
212
246
|
// list of waypoints object ( only support auto snap 50/50 for now )
|
|
213
247
|
wayPoints: [{ at: 100 }, { at: 200 }]
|
|
214
248
|
}
|
|
215
249
|
}
|
|
216
250
|
/>
|
|
217
|
-
|
|
251
|
+
|
|
218
252
|
<Voodoo.Node
|
|
219
253
|
id={"testItem"} // optional id
|
|
220
|
-
|
|
254
|
+
|
|
221
255
|
style={styleSample}// optional styles applied before any style coming from axes : css syntax + voodoo tweener units & transform management
|
|
222
|
-
|
|
256
|
+
|
|
223
257
|
axes={{ scrollY: axisSample }} // optional Array of tween by axis Id with no target node id required ( it will be ignored )
|
|
224
|
-
|
|
258
|
+
|
|
225
259
|
onClick={// all unknow props are passed to the child node
|
|
226
260
|
( e ) => {
|
|
227
261
|
// start playing an anim ( prefer scrolling Axes )
|
|
@@ -239,23 +273,23 @@ const Sample = ( {} ) => {
|
|
|
239
273
|
<Voodoo.Draggable
|
|
240
274
|
// make drag y move the scrollAnAxis axis
|
|
241
275
|
// xAxis={ "scrollAnAxis" }
|
|
242
|
-
|
|
276
|
+
|
|
243
277
|
// scale / inverse dispatched delta
|
|
244
|
-
// xHook={(delta)=>modify(delta)}
|
|
245
|
-
|
|
246
|
-
// React ref to the box, default to the parent ViewBox
|
|
247
|
-
// scale is as follow : (delta / ((xBoxRef||ViewBox).offsetWidth)) * ( axis.scrollableWindow || axis.duration )
|
|
248
|
-
// xBoxRef={ref}
|
|
249
|
-
|
|
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
|
+
|
|
250
284
|
yAxis={"scrollY"}// make drag y move the scrollY axis
|
|
251
285
|
// yHook={(delta)=>modify(delta)}
|
|
252
|
-
// yBoxRef={ref}
|
|
253
|
-
|
|
286
|
+
// yBoxRef={ref}
|
|
287
|
+
|
|
254
288
|
// mouseDrag={true} // listen for mouse drag ( default to false )
|
|
255
289
|
// touchDrag={false} // listen for touch drag ( default to true )
|
|
256
|
-
|
|
290
|
+
|
|
257
291
|
// button={1-3} // limit mouse drag to the specified event.button === ( default to 1; the left btn )
|
|
258
|
-
|
|
292
|
+
|
|
259
293
|
// * actually Draggable create it's own div node
|
|
260
294
|
>
|
|
261
295
|
<div>
|
|
@@ -267,11 +301,40 @@ const Sample = ( {} ) => {
|
|
|
267
301
|
}
|
|
268
302
|
```
|
|
269
303
|
|
|
270
|
-
|
|
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
|
|
271
325
|
|
|
272
|
-
|
|
273
|
-
Using AGPL, you can distribute modified versions but theses versions must be AGPL too.
|
|
326
|
+
React-voodoo is dual-licensed:
|
|
274
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:
|
|
275
336
|
|
|
276
337
|
[](#)
|
|
277
|
-
|
|
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>
|