react-voodoo 2.5.16 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +150 -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.0",
|
|
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.1.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,94 @@
|
|
|
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
|
+
This unlocks a set of features that are unique to the delta model:
|
|
47
32
|
|
|
48
|
-
|
|
33
|
+
| Feature | How |
|
|
34
|
+
|---|---|
|
|
35
|
+
| **Additive multi-axis composition** | Each axis contributes a delta; they stack without coordination code. |
|
|
36
|
+
| **Swipeable / draggable animations** | Drag gestures are mapped directly to axis positions with realistic momentum. |
|
|
37
|
+
| **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. |
|
|
38
|
+
| **SSR with correct initial styles** | Axes have a `defaultPosition`; styles are computed server-side and rendered inline — no flash on first paint. |
|
|
39
|
+
| **DOM writes bypass React** | Style updates go straight to `node.style` via direct DOM writes, never triggering a re-render. |
|
|
40
|
+
| **Multi-unit CSS via `calc()`** | Mix `%`, `px`, `vw`, `bw`/`bh` (box-relative units) in a single value — compiled to `calc()` automatically. |
|
|
49
41
|
|
|
50
|
-
|
|
42
|
+
---
|
|
51
43
|
|
|
52
|
-
|
|
44
|
+
## Comparison
|
|
45
|
+
|
|
46
|
+
### Feature matrix
|
|
47
|
+
|
|
48
|
+
| | **react-voodoo** | Framer Motion | GSAP + ScrollTrigger | react-spring | Motion One | anime.js |
|
|
49
|
+
|---|:---:|:---:|:---:|:---:|:---:|:---:|
|
|
50
|
+
| Scroll-linked animation | ✅ | ✅ `useScroll` | ✅ | ⚠️ manual | ✅ | ⚠️ manual |
|
|
51
|
+
| Drag-linked animation | ✅ native | ✅ `drag` | ⚠️ manual | ✅ `@use-gesture` | ⚠️ manual | ❌ |
|
|
52
|
+
| **Additive multi-axis composition** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
53
|
+
| Physics / momentum inertia | ✅ predictive | ✅ spring | ❌ | ✅ spring | ❌ | ❌ |
|
|
54
|
+
| **Predictive snap target** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
55
|
+
| **SSR — correct initial styles** | ✅ | ⚠️ flash | ⚠️ flash | ⚠️ flash | ⚠️ flash | ❌ |
|
|
56
|
+
| Bypasses React render loop | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
57
|
+
| Transform layer composition | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
58
|
+
| SVG geometry attributes | ✅ | ⚠️ limited | ✅ | ❌ | ⚠️ | ✅ |
|
|
59
|
+
| Multitouch (drag multiple axes) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
60
|
+
| Bundle size (approx. gzip) | ~18 kB | ~50 kB | ~75 kB | ~30 kB | ~18 kB | ~14 kB |
|
|
61
|
+
| React dependency | ≥ 16 | ≥ 18 | none | ≥ 16 | none | none |
|
|
62
|
+
|
|
63
|
+
### When to pick react-voodoo
|
|
64
|
+
|
|
65
|
+
- Swipeable carousels and full-page scroll scenes where drag, inertia, and animation must be one system
|
|
66
|
+
- Any UI where **multiple animation "tracks"** compose onto the same elements (parallax, pinned sequences, overlapping effects)
|
|
67
|
+
- **SSR-first** projects where the initial paint must already reflect the animated state
|
|
68
|
+
- Scenarios requiring **predictive callbacks** — e.g. preloading slide N+1 before the swipe animation finishes
|
|
53
69
|
|
|
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>
|
|
70
|
+
### When to look elsewhere
|
|
56
71
|
|
|
57
|
-
|
|
72
|
+
- Simple enter/exit transitions → **Framer Motion** (`AnimatePresence` is excellent for this)
|
|
73
|
+
- Complex GSAP-style timeline sequencing without scroll/drag → **GSAP**
|
|
74
|
+
- Spring-physics micro-interactions → **react-spring** or **Framer Motion**
|
|
75
|
+
- Lightweight imperative animation on non-React pages → **anime.js** or **Motion One**
|
|
58
76
|
|
|
59
|
-
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm install react-voodoo
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Peer dependencies:** `react >= 16`, `react-dom >= 16`
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## All-in-one example
|
|
90
|
+
|
|
91
|
+
Every major feature in a single component, with comments explaining each part.
|
|
60
92
|
|
|
61
93
|
```jsx harmony
|
|
62
94
|
import React from "react";
|
|
@@ -68,13 +100,13 @@ const styleSample = {
|
|
|
68
100
|
* Voodoo.Node style property and the tween descriptors use classic CSS-in-JS declaration
|
|
69
101
|
* exept we can specify values using the "box" unit which is a [0-1] ratio of the parent ViewBox height / width
|
|
70
102
|
*/
|
|
71
|
-
|
|
103
|
+
|
|
72
104
|
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
|
|
105
|
+
|
|
106
|
+
// the tweener deal with multiple units
|
|
107
|
+
// it will use css calc fn to add them if there's more than 1 unit used
|
|
76
108
|
width: ["50%", "10vw", "-50px", ".2box"],
|
|
77
|
-
|
|
109
|
+
|
|
78
110
|
// transform can use multiple "layers"
|
|
79
111
|
transform: [
|
|
80
112
|
{
|
|
@@ -85,7 +117,7 @@ const styleSample = {
|
|
|
85
117
|
translateZ: "-.2box"
|
|
86
118
|
}
|
|
87
119
|
],
|
|
88
|
-
|
|
120
|
+
|
|
89
121
|
filter:
|
|
90
122
|
{
|
|
91
123
|
blur: "5px"
|
|
@@ -97,8 +129,8 @@ const axisSample = [// Examples of tween descriptors
|
|
|
97
129
|
from : 0, // tween start position
|
|
98
130
|
duration: 100, // tween duration
|
|
99
131
|
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
|
|
132
|
+
|
|
133
|
+
apply: {// relative css values to be applied
|
|
102
134
|
// Same syntax as the styles
|
|
103
135
|
transform: [{}, {
|
|
104
136
|
translateZ: "-.2box"
|
|
@@ -108,16 +140,16 @@ const axisSample = [// Examples of tween descriptors
|
|
|
108
140
|
{
|
|
109
141
|
from : 40,
|
|
110
142
|
duration: 20,
|
|
111
|
-
|
|
112
|
-
// triggered when axis has scrolled in the Event period
|
|
143
|
+
|
|
144
|
+
// triggered when axis has scrolled in the Event period
|
|
113
145
|
// delta : a float value between [-1,1] is the update inside the Event period
|
|
114
146
|
entering: ( delta ) => false,
|
|
115
|
-
|
|
147
|
+
|
|
116
148
|
// triggered when axis has scrolled in the Event period
|
|
117
149
|
// newPos, precPos : float values between [0,1] position inside the Event period
|
|
118
150
|
// delta : a float value between [-1,1] is the update inside the Event period
|
|
119
151
|
moving: ( newPos, precPos, delta ) => false,
|
|
120
|
-
|
|
152
|
+
|
|
121
153
|
// triggered when axis has scrolled out the Event period
|
|
122
154
|
// delta : a float value between [-1,1] is the update inside the Event period
|
|
123
155
|
leaving: ( delta ) => false
|
|
@@ -125,7 +157,7 @@ const axisSample = [// Examples of tween descriptors
|
|
|
125
157
|
];
|
|
126
158
|
|
|
127
159
|
const Sample = ( {} ) => {
|
|
128
|
-
|
|
160
|
+
|
|
129
161
|
/**
|
|
130
162
|
* Voodoo tweener instanciation
|
|
131
163
|
*/
|
|
@@ -142,86 +174,86 @@ const Sample = ( {} ) => {
|
|
|
142
174
|
maxClickTm: 200,
|
|
143
175
|
// max drag offset in px before a click become a drag
|
|
144
176
|
maxClickOffset: 100,
|
|
145
|
-
// lock to only 1 drag direction
|
|
177
|
+
// lock to only 1 drag direction
|
|
146
178
|
dragDirectionLock: false,
|
|
147
179
|
// allow dragging with mouse
|
|
148
180
|
enableMouseDrag: false
|
|
149
181
|
}
|
|
150
182
|
);
|
|
151
|
-
// get a named parent tweener
|
|
183
|
+
// get a named parent tweener
|
|
152
184
|
const [nammedParentTweener] = Voodoo.hook("root")
|
|
153
|
-
|
|
185
|
+
|
|
154
186
|
/**
|
|
155
187
|
* once first render done, axes expose the following values & functions :
|
|
156
188
|
*/
|
|
157
189
|
// Theirs actual position in :
|
|
158
190
|
// tweener.axes.(axisId).scrollPos
|
|
159
|
-
|
|
191
|
+
|
|
160
192
|
// The "scrollTo" function allowing to manually move the axes positions :
|
|
161
193
|
// tweener.axes.(axisId).scrollTo(targetPos, duration, easeFn)
|
|
162
194
|
// tweener.scrollTo(targetPos, duration, axisId, easeFn)
|
|
163
|
-
|
|
195
|
+
|
|
164
196
|
// They can also be watched using the "watchAxis" function;
|
|
165
197
|
// When called, the returned function will disable the listener if executed :
|
|
166
198
|
React.useEffect(
|
|
167
199
|
e => tweener?.watchAxis("scrollY", ( pos ) => doSomething()),
|
|
168
200
|
[tweener]
|
|
169
201
|
)
|
|
170
|
-
|
|
202
|
+
|
|
171
203
|
return <ViewBox className={"container"}>
|
|
172
204
|
<Voodoo.Axis
|
|
173
|
-
|
|
205
|
+
|
|
174
206
|
id={"scrollY"} // Tween axis Id
|
|
175
207
|
defaultPosition={100} // optional initial position ( default : 0 )
|
|
176
|
-
|
|
208
|
+
|
|
177
209
|
// optional Array of tween descriptors with theirs Voodoo.Node target ids ( see axisSample )
|
|
178
210
|
items={tweenArrayWithTargets}
|
|
179
|
-
|
|
211
|
+
|
|
180
212
|
// optional size of the scrollable window for drag synchronisation
|
|
181
213
|
scrollableWindow={200}
|
|
182
|
-
|
|
183
|
-
// optional length of this scrollable axis (default to last tween desciptor position+duration)
|
|
214
|
+
|
|
215
|
+
// optional length of this scrollable axis (default to last tween desciptor position+duration)
|
|
184
216
|
size={1000}
|
|
185
|
-
|
|
217
|
+
|
|
186
218
|
// optional bounds ( inertia will target them if target pos is out )
|
|
187
219
|
bounds={{ min: 100, max: 900 }}
|
|
188
|
-
|
|
220
|
+
|
|
189
221
|
// optional inertia cfg ( false to disable it )
|
|
190
222
|
inertia={
|
|
191
223
|
{
|
|
192
224
|
// called when inertia is updated
|
|
193
225
|
// should return instantaneous move to do if wanted
|
|
194
226
|
shouldLoop: ( currentPos ) => (currentPos > 500 ? -500 : null),
|
|
195
|
-
|
|
227
|
+
|
|
196
228
|
// called when inertia know where it will end ( when the user stop dragging )
|
|
197
229
|
willEnd: ( targetPos, targetDelta, duration ) => {
|
|
198
230
|
},
|
|
199
|
-
|
|
231
|
+
|
|
200
232
|
// called when inertia know where it will snap ( when the user stop dragging )
|
|
201
233
|
willSnap: ( currentSnapIndex, targetWayPointObj ) => {
|
|
202
234
|
},
|
|
203
|
-
|
|
235
|
+
|
|
204
236
|
// called when inertia end
|
|
205
237
|
onStop: ( pos, targetWayPointObj ) => {
|
|
206
238
|
},
|
|
207
|
-
|
|
239
|
+
|
|
208
240
|
// called when inertia end on a snap
|
|
209
241
|
onSnap: ( snapIndex, targetWayPointObj ) => {
|
|
210
242
|
},
|
|
211
|
-
|
|
243
|
+
|
|
212
244
|
// list of waypoints object ( only support auto snap 50/50 for now )
|
|
213
245
|
wayPoints: [{ at: 100 }, { at: 200 }]
|
|
214
246
|
}
|
|
215
247
|
}
|
|
216
248
|
/>
|
|
217
|
-
|
|
249
|
+
|
|
218
250
|
<Voodoo.Node
|
|
219
251
|
id={"testItem"} // optional id
|
|
220
|
-
|
|
252
|
+
|
|
221
253
|
style={styleSample}// optional styles applied before any style coming from axes : css syntax + voodoo tweener units & transform management
|
|
222
|
-
|
|
254
|
+
|
|
223
255
|
axes={{ scrollY: axisSample }} // optional Array of tween by axis Id with no target node id required ( it will be ignored )
|
|
224
|
-
|
|
256
|
+
|
|
225
257
|
onClick={// all unknow props are passed to the child node
|
|
226
258
|
( e ) => {
|
|
227
259
|
// start playing an anim ( prefer scrolling Axes )
|
|
@@ -239,23 +271,23 @@ const Sample = ( {} ) => {
|
|
|
239
271
|
<Voodoo.Draggable
|
|
240
272
|
// make drag y move the scrollAnAxis axis
|
|
241
273
|
// xAxis={ "scrollAnAxis" }
|
|
242
|
-
|
|
274
|
+
|
|
243
275
|
// 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
|
-
|
|
276
|
+
// xHook={(delta)=>modify(delta)}
|
|
277
|
+
|
|
278
|
+
// React ref to the box, default to the parent ViewBox
|
|
279
|
+
// scale is as follow : (delta / ((xBoxRef||ViewBox).offsetWidth)) * ( axis.scrollableWindow || axis.duration )
|
|
280
|
+
// xBoxRef={ref}
|
|
281
|
+
|
|
250
282
|
yAxis={"scrollY"}// make drag y move the scrollY axis
|
|
251
283
|
// yHook={(delta)=>modify(delta)}
|
|
252
|
-
// yBoxRef={ref}
|
|
253
|
-
|
|
284
|
+
// yBoxRef={ref}
|
|
285
|
+
|
|
254
286
|
// mouseDrag={true} // listen for mouse drag ( default to false )
|
|
255
287
|
// touchDrag={false} // listen for touch drag ( default to true )
|
|
256
|
-
|
|
288
|
+
|
|
257
289
|
// button={1-3} // limit mouse drag to the specified event.button === ( default to 1; the left btn )
|
|
258
|
-
|
|
290
|
+
|
|
259
291
|
// * actually Draggable create it's own div node
|
|
260
292
|
>
|
|
261
293
|
<div>
|
|
@@ -267,11 +299,40 @@ const Sample = ( {} ) => {
|
|
|
267
299
|
}
|
|
268
300
|
```
|
|
269
301
|
|
|
270
|
-
|
|
302
|
+
For a more complete annotated example with inertia callbacks, `watchAxis`, and programmatic scrolling, see the [full documentation](doc/readme.md).
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Core concepts in 30 seconds
|
|
307
|
+
|
|
308
|
+
**Axis** — a virtual number line. Move its position (by drag, scroll, or code) and it drives CSS animations on any number of nodes.
|
|
309
|
+
|
|
310
|
+
**Node** — a React element whose styles are controlled by one or more axes. Style updates go straight to `node.style`, no re-renders.
|
|
311
|
+
|
|
312
|
+
**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.
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
axis position ──► tween engine ──► Δ per property ──► node.style (direct DOM write)
|
|
316
|
+
▲
|
|
317
|
+
other axes add their Δ here
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## License
|
|
271
323
|
|
|
272
|
-
|
|
273
|
-
Using AGPL, you can distribute modified versions but theses versions must be AGPL too.
|
|
324
|
+
React-voodoo is dual-licensed:
|
|
274
325
|
|
|
326
|
+
- **[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.
|
|
327
|
+
- **[AGPL v3](http://www.gnu.org/licenses/agpl-3.0)** — distribute modified versions under the same open-source license.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Support the project
|
|
332
|
+
|
|
333
|
+
If react-voodoo saved you a day of work, consider supporting it:
|
|
275
334
|
|
|
276
335
|
[](#)
|
|
277
|
-
|
|
336
|
+
|
|
337
|
+
**BTC** — `bc1qh43j8jh6dr8v3f675jwqq3nqymtsj8pyq0kh5a`
|
|
338
|
+
**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>
|