@wix/interact 1.92.0 → 2.0.0-rc.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/dist/cjs/index.js +2 -23
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react.js +15 -0
- package/dist/cjs/react.js.map +1 -0
- package/dist/cjs/web.js +2 -0
- package/dist/cjs/web.js.map +1 -0
- package/dist/es/index.js +8 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/react.js +650 -0
- package/dist/es/react.js.map +1 -0
- package/dist/es/web.js +56 -0
- package/dist/es/web.js.map +1 -0
- package/dist/index-C8QxOkui.mjs +7940 -0
- package/dist/index-C8QxOkui.mjs.map +1 -0
- package/dist/index-DEPRHaUt.js +18 -0
- package/dist/index-DEPRHaUt.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/types/core/Interact.d.ts +17 -7
- package/dist/types/core/Interact.d.ts.map +1 -0
- package/dist/types/core/InteractionController.d.ts +19 -0
- package/dist/types/core/InteractionController.d.ts.map +1 -0
- package/dist/types/core/add.d.ts +4 -3
- package/dist/types/core/add.d.ts.map +1 -0
- package/dist/types/core/css.d.ts +3 -0
- package/dist/types/core/css.d.ts.map +1 -0
- package/dist/types/core/remove.d.ts +3 -1
- package/dist/types/core/remove.d.ts.map +1 -0
- package/dist/types/core/utilities.d.ts +1 -0
- package/dist/types/core/utilities.d.ts.map +1 -0
- package/dist/types/dom/api.d.ts +3 -0
- package/dist/types/dom/api.d.ts.map +1 -0
- package/dist/types/handlers/animationEnd.d.ts +3 -2
- package/dist/types/handlers/animationEnd.d.ts.map +1 -0
- package/dist/types/handlers/click.d.ts +3 -2
- package/dist/types/handlers/click.d.ts.map +1 -0
- package/dist/types/handlers/hover.d.ts +3 -2
- package/dist/types/handlers/hover.d.ts.map +1 -0
- package/dist/types/handlers/index.d.ts +1 -0
- package/dist/types/handlers/index.d.ts.map +1 -0
- package/dist/types/handlers/pointerMove.d.ts +3 -2
- package/dist/types/handlers/pointerMove.d.ts.map +1 -0
- package/dist/types/handlers/utilities.d.ts +1 -0
- package/dist/types/handlers/utilities.d.ts.map +1 -0
- package/dist/types/handlers/viewEnter.d.ts +3 -2
- package/dist/types/handlers/viewEnter.d.ts.map +1 -0
- package/dist/types/handlers/viewProgress.d.ts +4 -3
- package/dist/types/handlers/viewProgress.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/react/Interaction.d.ts +10 -0
- package/dist/types/react/Interaction.d.ts.map +1 -0
- package/dist/types/react/index.d.ts +8 -0
- package/dist/types/react/index.d.ts.map +1 -0
- package/dist/types/react/interactRef.d.ts +3 -0
- package/dist/types/react/interactRef.d.ts.map +1 -0
- package/dist/types/types.d.ts +25 -10
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/utils.d.ts +4 -2
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/{InteractElement.d.ts → web/InteractElement.d.ts} +115 -77
- package/dist/types/web/InteractElement.d.ts.map +1 -0
- package/dist/types/web/defineInteractElement.d.ts +2 -0
- package/dist/types/web/defineInteractElement.d.ts.map +1 -0
- package/dist/types/web/index.d.ts +6 -0
- package/dist/types/web/index.d.ts.map +1 -0
- package/docs/README.md +211 -0
- package/docs/advanced/README.md +164 -0
- package/docs/api/README.md +157 -0
- package/docs/api/element-selection.md +607 -0
- package/docs/api/functions.md +638 -0
- package/docs/api/interact-class.md +663 -0
- package/docs/api/interact-element.md +565 -0
- package/docs/api/interaction-controller.md +450 -0
- package/docs/api/types.md +957 -0
- package/docs/examples/README.md +212 -0
- package/docs/examples/click-interactions.md +977 -0
- package/docs/examples/entrance-animations.md +935 -0
- package/docs/examples/hover-effects.md +930 -0
- package/docs/examples/list-patterns.md +737 -0
- package/docs/guides/README.md +49 -0
- package/docs/guides/conditions-and-media-queries.md +1068 -0
- package/docs/guides/configuration-structure.md +726 -0
- package/docs/guides/custom-elements.md +327 -0
- package/docs/guides/effects-and-animations.md +634 -0
- package/docs/guides/getting-started.md +379 -0
- package/docs/guides/lists-and-dynamic-content.md +713 -0
- package/docs/guides/state-management.md +747 -0
- package/docs/guides/understanding-triggers.md +690 -0
- package/docs/integration/README.md +264 -0
- package/docs/integration/react.md +605 -0
- package/package.json +73 -56
- package/rules/Integration.md +255 -0
- package/rules/click-rules.md +533 -0
- package/rules/full-lean.md +346 -0
- package/rules/hover-rules.md +593 -0
- package/rules/pointermove-rules.md +1341 -0
- package/rules/scroll-list-rules.md +900 -0
- package/rules/viewenter-rules.md +1015 -0
- package/rules/viewprogress-rules.md +1044 -0
- package/dist/cjs/InteractElement.js +0 -162
- package/dist/cjs/InteractElement.js.map +0 -1
- package/dist/cjs/__tests__/interact.spec.js +0 -1930
- package/dist/cjs/__tests__/interact.spec.js.map +0 -1
- package/dist/cjs/__tests__/viewEnter.spec.js +0 -207
- package/dist/cjs/__tests__/viewEnter.spec.js.map +0 -1
- package/dist/cjs/core/Interact.js +0 -257
- package/dist/cjs/core/Interact.js.map +0 -1
- package/dist/cjs/core/add.js +0 -246
- package/dist/cjs/core/add.js.map +0 -1
- package/dist/cjs/core/remove.js +0 -35
- package/dist/cjs/core/remove.js.map +0 -1
- package/dist/cjs/core/utilities.js +0 -16
- package/dist/cjs/core/utilities.js.map +0 -1
- package/dist/cjs/external-types.d.js +0 -2
- package/dist/cjs/external-types.d.js.map +0 -1
- package/dist/cjs/handlers/animationEnd.js +0 -33
- package/dist/cjs/handlers/animationEnd.js.map +0 -1
- package/dist/cjs/handlers/click.js +0 -116
- package/dist/cjs/handlers/click.js.map +0 -1
- package/dist/cjs/handlers/hover.js +0 -141
- package/dist/cjs/handlers/hover.js.map +0 -1
- package/dist/cjs/handlers/index.js +0 -32
- package/dist/cjs/handlers/index.js.map +0 -1
- package/dist/cjs/handlers/pointerMove.js +0 -49
- package/dist/cjs/handlers/pointerMove.js.map +0 -1
- package/dist/cjs/handlers/utilities.js +0 -49
- package/dist/cjs/handlers/utilities.js.map +0 -1
- package/dist/cjs/handlers/viewEnter.js +0 -127
- package/dist/cjs/handlers/viewEnter.js.map +0 -1
- package/dist/cjs/handlers/viewProgress.js +0 -65
- package/dist/cjs/handlers/viewProgress.js.map +0 -1
- package/dist/cjs/test-types.d.js +0 -2
- package/dist/cjs/test-types.d.js.map +0 -1
- package/dist/cjs/types.js +0 -2
- package/dist/cjs/types.js.map +0 -1
- package/dist/cjs/utils.js +0 -68
- package/dist/cjs/utils.js.map +0 -1
- package/dist/esm/InteractElement.js +0 -156
- package/dist/esm/InteractElement.js.map +0 -1
- package/dist/esm/__tests__/interact.spec.js +0 -1937
- package/dist/esm/__tests__/interact.spec.js.map +0 -1
- package/dist/esm/__tests__/viewEnter.spec.js +0 -210
- package/dist/esm/__tests__/viewEnter.spec.js.map +0 -1
- package/dist/esm/core/Interact.js +0 -251
- package/dist/esm/core/Interact.js.map +0 -1
- package/dist/esm/core/add.js +0 -241
- package/dist/esm/core/add.js.map +0 -1
- package/dist/esm/core/remove.js +0 -30
- package/dist/esm/core/remove.js.map +0 -1
- package/dist/esm/core/utilities.js +0 -14
- package/dist/esm/core/utilities.js.map +0 -1
- package/dist/esm/external-types.d.js +0 -2
- package/dist/esm/external-types.d.js.map +0 -1
- package/dist/esm/handlers/animationEnd.js +0 -29
- package/dist/esm/handlers/animationEnd.js.map +0 -1
- package/dist/esm/handlers/click.js +0 -116
- package/dist/esm/handlers/click.js.map +0 -1
- package/dist/esm/handlers/hover.js +0 -141
- package/dist/esm/handlers/hover.js.map +0 -1
- package/dist/esm/handlers/index.js +0 -27
- package/dist/esm/handlers/index.js.map +0 -1
- package/dist/esm/handlers/pointerMove.js +0 -48
- package/dist/esm/handlers/pointerMove.js.map +0 -1
- package/dist/esm/handlers/utilities.js +0 -43
- package/dist/esm/handlers/utilities.js.map +0 -1
- package/dist/esm/handlers/viewEnter.js +0 -129
- package/dist/esm/handlers/viewEnter.js.map +0 -1
- package/dist/esm/handlers/viewProgress.js +0 -61
- package/dist/esm/handlers/viewProgress.js.map +0 -1
- package/dist/esm/index.js +0 -5
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/test-types.d.js +0 -2
- package/dist/esm/test-types.d.js.map +0 -1
- package/dist/esm/types.js +0 -2
- package/dist/esm/types.js.map +0 -1
- package/dist/esm/utils.js +0 -63
- package/dist/esm/utils.js.map +0 -1
- package/dist/types/__tests__/interact.spec.d.ts +0 -1
- package/dist/types/__tests__/viewEnter.spec.d.ts +0 -0
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
# React Integration
|
|
2
|
+
|
|
3
|
+
This guide covers how to use `@wix/interact` with React applications. The library provides a dedicated React entry point with components and utilities designed for seamless React integration.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @wix/interact @wix/motion
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Import
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Interact, Interaction, createInteractRef } from '@wix/interact/react';
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The `@wix/interact/react` entry point exports:
|
|
18
|
+
- `Interact` - Main interaction manager class
|
|
19
|
+
- `Interaction` - React component for interactive elements
|
|
20
|
+
- `createInteractRef` - Function to create interact-aware refs
|
|
21
|
+
- `add`, `remove` - DOM API functions
|
|
22
|
+
- All types from the main package
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import React, { useEffect } from 'react';
|
|
28
|
+
import { Interact, Interaction } from '@wix/interact/react';
|
|
29
|
+
|
|
30
|
+
const config = {
|
|
31
|
+
interactions: [{
|
|
32
|
+
key: 'my-button',
|
|
33
|
+
trigger: 'hover',
|
|
34
|
+
effects: [{
|
|
35
|
+
keyframeEffect: {
|
|
36
|
+
name: 'scale-up',
|
|
37
|
+
keyframes: [{ transform: 'scale(1.1)' }]
|
|
38
|
+
},
|
|
39
|
+
duration: 200
|
|
40
|
+
}]
|
|
41
|
+
}]
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
function Button() {
|
|
45
|
+
return (
|
|
46
|
+
<Interaction tagName="button" interactKey="my-button">
|
|
47
|
+
Hover me!
|
|
48
|
+
</Interaction>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function App() {
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
const instance = Interact.create(config);
|
|
55
|
+
return () => instance.destroy();
|
|
56
|
+
}, []);
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<Button />
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## The `Interaction` Component
|
|
67
|
+
|
|
68
|
+
The `Interaction` component is a wrapper that automatically manages interaction lifecycle for React components.
|
|
69
|
+
|
|
70
|
+
### Props
|
|
71
|
+
|
|
72
|
+
| Prop | Type | Required | Description |
|
|
73
|
+
|------|------|----------|-------------|
|
|
74
|
+
| `tagName` | `keyof JSX.IntrinsicElements` | Yes | The HTML element to render (e.g., `'div'`, `'button'`, `'span'`) |
|
|
75
|
+
| `interactKey` | `string` | Yes | Unique identifier matching the interaction configuration |
|
|
76
|
+
| `children` | `React.ReactNode` | No | Child elements to render |
|
|
77
|
+
| `ref` | `React.Ref<any>` | No | Forwarded ref to the underlying DOM element |
|
|
78
|
+
| `...rest` | `JSX.IntrinsicElements[T]` | No | Any valid props for the specified `tagName` |
|
|
79
|
+
|
|
80
|
+
### Basic Usage
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { Interaction } from '@wix/interact/react';
|
|
84
|
+
|
|
85
|
+
// Render as a div
|
|
86
|
+
<Interaction tagName="div" interactKey="card" className="card">
|
|
87
|
+
<h2>Card Title</h2>
|
|
88
|
+
<p>Card content</p>
|
|
89
|
+
</Interaction>
|
|
90
|
+
|
|
91
|
+
// Render as a button
|
|
92
|
+
<Interaction tagName="button" interactKey="cta-button" onClick={handleClick}>
|
|
93
|
+
Click me
|
|
94
|
+
</Interaction>
|
|
95
|
+
|
|
96
|
+
// Render as an image container
|
|
97
|
+
<Interaction tagName="figure" interactKey="image-hover">
|
|
98
|
+
<img src="photo.jpg" alt="Photo" />
|
|
99
|
+
</Interaction>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### With Forwarded Refs
|
|
103
|
+
|
|
104
|
+
The `Interaction` component supports ref forwarding, allowing you to access the underlying DOM element:
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
import React, { useRef, useEffect } from 'react';
|
|
108
|
+
import { Interaction } from '@wix/interact/react';
|
|
109
|
+
|
|
110
|
+
function AnimatedCard() {
|
|
111
|
+
const cardRef = useRef<HTMLDivElement>(null);
|
|
112
|
+
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
if (cardRef.current) {
|
|
115
|
+
console.log('Card element:', cardRef.current);
|
|
116
|
+
}
|
|
117
|
+
}, []);
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<Interaction
|
|
121
|
+
tagName="div"
|
|
122
|
+
interactKey="card"
|
|
123
|
+
ref={cardRef}
|
|
124
|
+
className="card"
|
|
125
|
+
>
|
|
126
|
+
<h2>Interactive Card</h2>
|
|
127
|
+
</Interaction>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### TypeScript Support
|
|
133
|
+
|
|
134
|
+
The component is fully typed and provides type inference for the `tagName` prop:
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import { Interaction } from '@wix/interact/react';
|
|
138
|
+
|
|
139
|
+
// TypeScript knows these are valid button props
|
|
140
|
+
<Interaction
|
|
141
|
+
tagName="button"
|
|
142
|
+
interactKey="btn"
|
|
143
|
+
type="submit"
|
|
144
|
+
disabled={false}
|
|
145
|
+
onClick={(e) => console.log(e.currentTarget)} // e is MouseEvent<HTMLButtonElement>
|
|
146
|
+
>
|
|
147
|
+
Submit
|
|
148
|
+
</Interaction>
|
|
149
|
+
|
|
150
|
+
// TypeScript knows these are valid anchor props
|
|
151
|
+
<Interaction
|
|
152
|
+
tagName="a"
|
|
153
|
+
interactKey="link"
|
|
154
|
+
href="/about"
|
|
155
|
+
target="_blank"
|
|
156
|
+
>
|
|
157
|
+
About Us
|
|
158
|
+
</Interaction>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## The `createInteractRef` Function
|
|
164
|
+
|
|
165
|
+
For more control over ref management, use `createInteractRef` to create a ref callback that handles interaction lifecycle.
|
|
166
|
+
|
|
167
|
+
### Signature
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
function createInteractRef(interactKey: string): InteractRef
|
|
171
|
+
|
|
172
|
+
type InteractRef = (node: Element | null) => () => void;
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Basic Usage
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
import React, { useRef, useCallback, useEffect } from 'react';
|
|
179
|
+
import { Interact, createInteractRef } from '@wix/interact/react';
|
|
180
|
+
|
|
181
|
+
function CustomComponent() {
|
|
182
|
+
const interactRef = useRef(createInteractRef('my-element'));
|
|
183
|
+
|
|
184
|
+
useEffect(() => {
|
|
185
|
+
Interact.create(config);
|
|
186
|
+
}, []);
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<div ref={interactRef.current} data-interact-key="my-element">
|
|
190
|
+
<span>Interactive content</span>
|
|
191
|
+
</div>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### React 18 vs React 19 Compatibility
|
|
197
|
+
|
|
198
|
+
The `createInteractRef` function is designed to work with both React 18 and React 19's different cleanup patterns:
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
// React 18: Cleanup happens when ref receives null
|
|
202
|
+
// React 19: Cleanup happens via returned cleanup function
|
|
203
|
+
|
|
204
|
+
const interactRef = createInteractRef('my-key');
|
|
205
|
+
|
|
206
|
+
// The ref callback handles both patterns automatically:
|
|
207
|
+
// - When node is null (React 18 unmount), it calls remove()
|
|
208
|
+
// - Returns a cleanup function for React 19+
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Combining with Other Refs
|
|
212
|
+
|
|
213
|
+
When you need to combine the interact ref with other refs:
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
import React, { useRef, useCallback } from 'react';
|
|
217
|
+
import { createInteractRef } from '@wix/interact/react';
|
|
218
|
+
|
|
219
|
+
function CombinedRefExample() {
|
|
220
|
+
const localRef = useRef<HTMLDivElement>(null);
|
|
221
|
+
const interactRef = useRef(createInteractRef('combined'));
|
|
222
|
+
|
|
223
|
+
const combinedRef = useCallback((node: HTMLDivElement | null) => {
|
|
224
|
+
// Set local ref
|
|
225
|
+
localRef.current = node;
|
|
226
|
+
|
|
227
|
+
// Call interact ref
|
|
228
|
+
const cleanup = interactRef.current(node);
|
|
229
|
+
|
|
230
|
+
// Return cleanup for React 19+
|
|
231
|
+
return cleanup;
|
|
232
|
+
}, []);
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<div ref={combinedRef} data-interact-key="combined">
|
|
236
|
+
Content
|
|
237
|
+
</div>
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Configuration Patterns
|
|
245
|
+
|
|
246
|
+
### Basic Setup with useEffect
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
import React, { useEffect } from 'react';
|
|
250
|
+
import { Interact, Interaction, InteractConfig } from '@wix/interact/react';
|
|
251
|
+
|
|
252
|
+
const config: InteractConfig = {
|
|
253
|
+
interactions: [
|
|
254
|
+
{
|
|
255
|
+
key: 'fade-card',
|
|
256
|
+
trigger: 'viewEnter',
|
|
257
|
+
effects: [{
|
|
258
|
+
keyframeEffect: {
|
|
259
|
+
name: 'fade-in',
|
|
260
|
+
keyframes: [
|
|
261
|
+
{ opacity: 0, transform: 'translateY(20px)' },
|
|
262
|
+
{ opacity: 1, transform: 'translateY(0)' }
|
|
263
|
+
]
|
|
264
|
+
},
|
|
265
|
+
duration: 600,
|
|
266
|
+
easing: 'ease-out'
|
|
267
|
+
}]
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
function App() {
|
|
273
|
+
useEffect(() => {
|
|
274
|
+
const instance = Interact.create(config);
|
|
275
|
+
|
|
276
|
+
// Cleanup on unmount
|
|
277
|
+
return () => {
|
|
278
|
+
instance.destroy();
|
|
279
|
+
};
|
|
280
|
+
}, []);
|
|
281
|
+
|
|
282
|
+
return (
|
|
283
|
+
<Interaction tagName="div" interactKey="fade-card" className="card">
|
|
284
|
+
<h2>Animated Card</h2>
|
|
285
|
+
<p>This card fades in when it enters the viewport.</p>
|
|
286
|
+
</Interaction>
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Custom Hook for Reusability
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
import { useEffect, useRef } from 'react';
|
|
295
|
+
import { Interact, InteractConfig } from '@wix/interact/react';
|
|
296
|
+
|
|
297
|
+
export function useInteract(config: InteractConfig) {
|
|
298
|
+
const instanceRef = useRef<Interact | null>(null);
|
|
299
|
+
|
|
300
|
+
useEffect(() => {
|
|
301
|
+
instanceRef.current = Interact.create(config);
|
|
302
|
+
|
|
303
|
+
return () => {
|
|
304
|
+
instanceRef.current?.destroy();
|
|
305
|
+
instanceRef.current = null;
|
|
306
|
+
};
|
|
307
|
+
}, [config]);
|
|
308
|
+
|
|
309
|
+
return instanceRef;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Usage
|
|
313
|
+
function MyComponent() {
|
|
314
|
+
useInteract(config);
|
|
315
|
+
|
|
316
|
+
return (
|
|
317
|
+
<Interaction tagName="div" interactKey="my-element">
|
|
318
|
+
Content
|
|
319
|
+
</Interaction>
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Multiple Instances
|
|
325
|
+
|
|
326
|
+
```tsx
|
|
327
|
+
import React, { useEffect } from 'react';
|
|
328
|
+
import { Interact, Interaction } from '@wix/interact/react';
|
|
329
|
+
|
|
330
|
+
const heroConfig = {
|
|
331
|
+
interactions: [{
|
|
332
|
+
key: 'hero',
|
|
333
|
+
trigger: 'viewEnter',
|
|
334
|
+
effects: [/* ... */]
|
|
335
|
+
}]
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
const cardsConfig = {
|
|
339
|
+
interactions: [{
|
|
340
|
+
key: 'card',
|
|
341
|
+
trigger: 'hover',
|
|
342
|
+
effects: [/* ... */]
|
|
343
|
+
}]
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
function App() {
|
|
347
|
+
useEffect(() => {
|
|
348
|
+
const heroInstance = Interact.create(heroConfig);
|
|
349
|
+
const cardsInstance = Interact.create(cardsConfig);
|
|
350
|
+
|
|
351
|
+
return () => {
|
|
352
|
+
heroInstance.destroy();
|
|
353
|
+
cardsInstance.destroy();
|
|
354
|
+
};
|
|
355
|
+
}, []);
|
|
356
|
+
|
|
357
|
+
return (
|
|
358
|
+
<>
|
|
359
|
+
<Interaction tagName="section" interactKey="hero">
|
|
360
|
+
<h1>Welcome</h1>
|
|
361
|
+
</Interaction>
|
|
362
|
+
|
|
363
|
+
<Interaction tagName="article" interactKey="card">
|
|
364
|
+
<h2>Card 1</h2>
|
|
365
|
+
</Interaction>
|
|
366
|
+
|
|
367
|
+
<Interaction tagName="article" interactKey="card">
|
|
368
|
+
<h2>Card 2</h2>
|
|
369
|
+
</Interaction>
|
|
370
|
+
</>
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## State-Based Interactions
|
|
378
|
+
|
|
379
|
+
### Click Toggle Effects
|
|
380
|
+
|
|
381
|
+
```tsx
|
|
382
|
+
import React, { useEffect } from 'react';
|
|
383
|
+
import { Interact, Interaction, InteractConfig } from '@wix/interact/react';
|
|
384
|
+
|
|
385
|
+
const config: InteractConfig = {
|
|
386
|
+
effects: {
|
|
387
|
+
'expanded': {
|
|
388
|
+
transitionEffect: {
|
|
389
|
+
properties: ['max-height', 'padding'],
|
|
390
|
+
from: { maxHeight: '0px', padding: '0' },
|
|
391
|
+
to: { maxHeight: '200px', padding: '16px' }
|
|
392
|
+
},
|
|
393
|
+
duration: 300
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
interactions: [{
|
|
397
|
+
key: 'accordion',
|
|
398
|
+
trigger: 'click',
|
|
399
|
+
selector: '.accordion-header',
|
|
400
|
+
effects: [{ effectId: 'expanded', method: 'toggle' }]
|
|
401
|
+
}]
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
function Accordion() {
|
|
405
|
+
useEffect(() => {
|
|
406
|
+
const instance = Interact.create(config);
|
|
407
|
+
return () => instance.destroy();
|
|
408
|
+
}, []);
|
|
409
|
+
|
|
410
|
+
return (
|
|
411
|
+
<Interaction tagName="div" interactKey="accordion" className="accordion">
|
|
412
|
+
<button className="accordion-header">Toggle</button>
|
|
413
|
+
<div className="accordion-content">
|
|
414
|
+
<p>Expandable content here</p>
|
|
415
|
+
</div>
|
|
416
|
+
</Interaction>
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### Accessing Active Effects
|
|
422
|
+
|
|
423
|
+
```tsx
|
|
424
|
+
import React, { useRef, useEffect } from 'react';
|
|
425
|
+
import { Interact, Interaction } from '@wix/interact/react';
|
|
426
|
+
|
|
427
|
+
function EffectAwareComponent() {
|
|
428
|
+
const elementRef = useRef<HTMLDivElement>(null);
|
|
429
|
+
|
|
430
|
+
const checkEffects = () => {
|
|
431
|
+
const controller = Interact.getController('my-element');
|
|
432
|
+
if (controller) {
|
|
433
|
+
const activeEffects = controller.getActiveEffects();
|
|
434
|
+
console.log('Active effects:', activeEffects);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
return (
|
|
439
|
+
<Interaction
|
|
440
|
+
tagName="div"
|
|
441
|
+
interactKey="my-element"
|
|
442
|
+
ref={elementRef}
|
|
443
|
+
onClick={checkEffects}
|
|
444
|
+
>
|
|
445
|
+
Click to check effects
|
|
446
|
+
</Interaction>
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Lists and Dynamic Content
|
|
454
|
+
|
|
455
|
+
### Animated Lists
|
|
456
|
+
|
|
457
|
+
```tsx
|
|
458
|
+
import React, { useEffect, useState } from 'react';
|
|
459
|
+
import { Interact, Interaction, InteractConfig } from '@wix/interact/react';
|
|
460
|
+
|
|
461
|
+
const config: InteractConfig = {
|
|
462
|
+
interactions: [{
|
|
463
|
+
key: 'product-list',
|
|
464
|
+
trigger: 'viewEnter',
|
|
465
|
+
listContainer: '.products',
|
|
466
|
+
effects: [{
|
|
467
|
+
keyframeEffect: {
|
|
468
|
+
name: 'slide-up',
|
|
469
|
+
keyframes: [
|
|
470
|
+
{ opacity: 0, transform: 'translateY(30px)' },
|
|
471
|
+
{ opacity: 1, transform: 'translateY(0)' }
|
|
472
|
+
]
|
|
473
|
+
},
|
|
474
|
+
duration: 400,
|
|
475
|
+
stagger: 100 // Stagger animation for list items
|
|
476
|
+
}]
|
|
477
|
+
}]
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
function ProductList() {
|
|
481
|
+
const [products, setProducts] = useState([
|
|
482
|
+
{ id: 1, name: 'Product A' },
|
|
483
|
+
{ id: 2, name: 'Product B' },
|
|
484
|
+
{ id: 3, name: 'Product C' }
|
|
485
|
+
]);
|
|
486
|
+
|
|
487
|
+
useEffect(() => {
|
|
488
|
+
const instance = Interact.create(config);
|
|
489
|
+
return () => instance.destroy();
|
|
490
|
+
}, []);
|
|
491
|
+
|
|
492
|
+
const addProduct = () => {
|
|
493
|
+
setProducts(prev => [...prev, {
|
|
494
|
+
id: Date.now(),
|
|
495
|
+
name: `Product ${prev.length + 1}`
|
|
496
|
+
}]);
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
return (
|
|
500
|
+
<Interaction tagName="div" interactKey="product-list">
|
|
501
|
+
<button onClick={addProduct}>Add Product</button>
|
|
502
|
+
<div className="products">
|
|
503
|
+
{products.map(product => (
|
|
504
|
+
<div key={product.id} className="product-card">
|
|
505
|
+
{product.name}
|
|
506
|
+
</div>
|
|
507
|
+
))}
|
|
508
|
+
</div>
|
|
509
|
+
</Interaction>
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
## Server-Side Rendering (SSR)
|
|
517
|
+
|
|
518
|
+
### Next.js App Router
|
|
519
|
+
|
|
520
|
+
```tsx
|
|
521
|
+
// app/components/InteractiveCard.tsx
|
|
522
|
+
'use client';
|
|
523
|
+
|
|
524
|
+
import { useEffect } from 'react';
|
|
525
|
+
import { Interact, Interaction } from '@wix/interact/react';
|
|
526
|
+
|
|
527
|
+
const config = {/* ... */};
|
|
528
|
+
|
|
529
|
+
export function InteractiveCard({ children }: { children: React.ReactNode }) {
|
|
530
|
+
useEffect(() => {
|
|
531
|
+
const instance = Interact.create(config);
|
|
532
|
+
return () => instance.destroy();
|
|
533
|
+
}, []);
|
|
534
|
+
|
|
535
|
+
return (
|
|
536
|
+
<Interaction tagName="div" interactKey="card">
|
|
537
|
+
{children}
|
|
538
|
+
</Interaction>
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### Next.js Pages Router
|
|
544
|
+
|
|
545
|
+
```tsx
|
|
546
|
+
// pages/index.tsx
|
|
547
|
+
import { useEffect } from 'react';
|
|
548
|
+
import { Interact, Interaction } from '@wix/interact/react';
|
|
549
|
+
|
|
550
|
+
const config = {/* ... */};
|
|
551
|
+
|
|
552
|
+
export default function Home() {
|
|
553
|
+
useEffect(() => {
|
|
554
|
+
// Only runs on client
|
|
555
|
+
const instance = Interact.create(config);
|
|
556
|
+
return () => instance.destroy();
|
|
557
|
+
}, []);
|
|
558
|
+
|
|
559
|
+
return (
|
|
560
|
+
<Interaction tagName="main" interactKey="hero">
|
|
561
|
+
<h1>Welcome</h1>
|
|
562
|
+
</Interaction>
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
## Troubleshooting
|
|
568
|
+
|
|
569
|
+
### React StrictMode
|
|
570
|
+
|
|
571
|
+
React's StrictMode double-invokes effects in development. The library handles this gracefully:
|
|
572
|
+
|
|
573
|
+
```tsx
|
|
574
|
+
// This works correctly even in StrictMode
|
|
575
|
+
useEffect(() => {
|
|
576
|
+
const instance = Interact.create(config);
|
|
577
|
+
return () => instance.destroy();
|
|
578
|
+
}, []);
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### Memory leaks
|
|
582
|
+
|
|
583
|
+
Always clean up instances:
|
|
584
|
+
|
|
585
|
+
```tsx
|
|
586
|
+
useEffect(() => {
|
|
587
|
+
const instance = Interact.create(config);
|
|
588
|
+
|
|
589
|
+
// Always return cleanup function
|
|
590
|
+
return () => {
|
|
591
|
+
instance.destroy();
|
|
592
|
+
};
|
|
593
|
+
}, []);
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
---
|
|
597
|
+
|
|
598
|
+
## See Also
|
|
599
|
+
|
|
600
|
+
- [Getting Started](../guides/getting-started.md) - Basic concepts and setup
|
|
601
|
+
- [Interact Class](../api/interact-class.md) - Main class API
|
|
602
|
+
- [InteractionController](../api/interaction-controller.md) - Controller API
|
|
603
|
+
- [Configuration Guide](../guides/configuration-structure.md) - Configuration options
|
|
604
|
+
- [Type Definitions](../api/types.md) - TypeScript types
|
|
605
|
+
|