@wix/interact 2.2.2 → 2.4.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 (55) hide show
  1. package/README.md +322 -246
  2. package/dist/cjs/index.js +1 -1
  3. package/dist/cjs/react.js +1 -1
  4. package/dist/cjs/web.js +1 -1
  5. package/dist/es/index.js +1 -1
  6. package/dist/es/react.js +2 -2
  7. package/dist/es/web.js +2 -2
  8. package/dist/index-C6u4q815.mjs +3291 -0
  9. package/dist/index-C6u4q815.mjs.map +1 -0
  10. package/dist/index-Qg46rn0Y.js +21 -0
  11. package/dist/index-Qg46rn0Y.js.map +1 -0
  12. package/dist/tsconfig.build.tsbuildinfo +1 -1
  13. package/dist/types/core/add.d.ts.map +1 -1
  14. package/dist/types/core/css.d.ts +17 -2
  15. package/dist/types/core/css.d.ts.map +1 -1
  16. package/dist/types/core/cssUtils.d.ts +8 -0
  17. package/dist/types/core/cssUtils.d.ts.map +1 -0
  18. package/dist/types/core/resolvers.d.ts +4 -0
  19. package/dist/types/core/resolvers.d.ts.map +1 -0
  20. package/dist/types/core/utilities.d.ts +6 -0
  21. package/dist/types/core/utilities.d.ts.map +1 -1
  22. package/dist/types/handlers/animationEnd.d.ts +1 -1
  23. package/dist/types/handlers/animationEnd.d.ts.map +1 -1
  24. package/dist/types/handlers/viewProgress.d.ts.map +1 -1
  25. package/dist/types/types/config.d.ts +23 -2
  26. package/dist/types/types/config.d.ts.map +1 -1
  27. package/dist/types/types/css.d.ts +26 -0
  28. package/dist/types/types/css.d.ts.map +1 -0
  29. package/dist/types/types/effects.d.ts +12 -0
  30. package/dist/types/types/effects.d.ts.map +1 -1
  31. package/dist/types/types/external.d.ts +3 -3
  32. package/dist/types/types/external.d.ts.map +1 -1
  33. package/dist/types/types/handlers.d.ts +2 -1
  34. package/dist/types/types/handlers.d.ts.map +1 -1
  35. package/dist/types/types/index.d.ts +1 -0
  36. package/dist/types/types/index.d.ts.map +1 -1
  37. package/dist/types/types/internal.d.ts +1 -1
  38. package/dist/types/types/internal.d.ts.map +1 -1
  39. package/dist/types/utils.d.ts +11 -2
  40. package/dist/types/utils.d.ts.map +1 -1
  41. package/docs/README.md +1 -1
  42. package/docs/api/README.md +4 -4
  43. package/docs/api/functions.md +157 -42
  44. package/docs/examples/entrance-animations.md +7 -5
  45. package/docs/guides/getting-started.md +1 -1
  46. package/docs/integration/react.md +8 -8
  47. package/package.json +6 -3
  48. package/rules/full-lean.md +24 -15
  49. package/rules/integration.md +23 -17
  50. package/rules/viewenter.md +4 -2
  51. package/rules/viewprogress.md +52 -0
  52. package/dist/index-A2Q0e94t.js +0 -18
  53. package/dist/index-A2Q0e94t.js.map +0 -1
  54. package/dist/index-HeFaJMEX.mjs +0 -2839
  55. package/dist/index-HeFaJMEX.mjs.map +0 -1
package/README.md CHANGED
@@ -1,383 +1,459 @@
1
+ <!-- AI: full docs index at https://wix.github.io/interact/llms.txt -->
2
+
1
3
  # @wix/interact
2
4
 
3
- A powerful, declarative interaction library for creating engaging web animations and effects. Built on top of `@wix/motion`, it provides a configuration-driven approach to adding triggers, animations, and state transitions to web applications.
5
+ Declarative, configuration-driven interaction library web-native, AI-ready, and framework-agnostic.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@wix/interact.svg)](https://www.npmjs.com/package/@wix/interact)
8
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/@wix/interact)](https://bundlephobia.com/package/@wix/interact)
9
+ [![license](https://img.shields.io/npm/l/@wix/interact.svg)](https://github.com/wix/interact/blob/master/LICENSE)
10
+ [![downloads](https://img.shields.io/npm/dm/@wix/interact.svg)](https://www.npmjs.com/package/@wix/interact)
4
11
 
5
- ## Features
12
+ ## Why Interact?
6
13
 
7
- - 🎯 **Declarative Configuration** - Define complex interactions through simple JSON configuration
8
- - 🎨 **Rich Animation Support** - Integration with `@wix/motion` for high-performance animations
9
- - 🖱️ **Multiple Trigger Types** - Support for hover, click, scroll, viewport, and custom triggers
10
- - 📱 **Responsive Conditions** - Media query and container-based conditional interactions
11
- - 🔧 **Custom Elements** - Web Components API for easy framework integration
12
- - **Performance Optimized** - Efficient event handling and animation management
13
- - 🧩 **Framework Agnostic** - Works with React, vanilla JS, and other frameworks
14
+ - **Declarative** Define trigger-to-effect bindings in JSON; no imperative event wiring
15
+ - **Web-native** Built on CSS, WAAPI, ViewTimeline, and DOM APIs; supports DOM management via Custom Elements
16
+ - **Framework-agnostic** Web Components and vanilla JS integrations; React integration included
17
+ - **AI-ready** — JSON configs are machine-readable and provide guardrails; LLMs can generate and agents can validate them
18
+ - **CSS generation** `generate(config)` emits complete CSS for the whole config (`@keyframes`, `view-timeline`, transitions, FOUC rules)
19
+ - **Preset ecosystem** Plug in [`@wix/motion-presets`](https://github.com/wix/interact/tree/master/packages/motion-presets) for 75+ ready-made effects.
20
+ - **Accessible** — Built-in `activate` (click + keyboard) and `interest` (hover + focus) trigger variants
14
21
 
15
- ## Installation
22
+ ## Install
16
23
 
17
24
  ```bash
18
25
  npm install @wix/interact
19
26
  ```
20
27
 
28
+ ### Use pre-made presets
29
+
30
+ ```bash
31
+ npm install @wix/motion-presets
32
+ ```
33
+
34
+ `@wix/motion-presets` is optional but recommended — it provides the `namedEffect` library used in most examples below.
35
+
21
36
  ## Quick Start
22
37
 
23
- ### Using Custom Elements
38
+ ### Using Web Components (recommended)
24
39
 
25
- #### 1. Basic Setup
40
+ **Web Components** wrap the target element with `<interact-element>`:
26
41
 
27
- ```typescript
28
- import { Interact } from '@wix/interact/web';
42
+ ```ts
43
+ import { Interact, generate, type InteractConfig } from '@wix/interact/web';
44
+ import * as presets from '@wix/motion-presets'; // required when using namedEffect
29
45
 
30
- // Define your interaction configuration
31
- const config = {
46
+ Interact.registerEffects(presets); // required when using namedEffect
47
+
48
+ const config: InteractConfig = {
32
49
  interactions: [
33
50
  {
51
+ key: 'hero',
34
52
  trigger: 'viewEnter',
35
- key: '#my-element',
36
- effects: [
37
- {
38
- effectId: 'fade-in',
39
- },
40
- ],
53
+ effects: [{ effectId: 'hero-in' }],
41
54
  },
42
55
  ],
43
56
  effects: {
44
- 'fade-in': {
45
- duration: 1000,
46
- keyframeEffect: {
47
- name: 'fade',
48
- keyframes: { opacity: [0, 1] },
49
- },
57
+ 'hero-in': {
58
+ duration: 800,
59
+ easing: 'ease-out',
60
+ namedEffect: { type: 'FadeIn' }, // requires motion-presets
61
+ triggerType: 'once',
50
62
  },
51
63
  },
52
64
  };
53
65
 
54
- // Initialize the interact instance
55
- const interact = Interact.create(config);
66
+ // render styles - e.g. for SSR
67
+ const interactCSS = generate(config, true);
68
+
69
+ // run on client - e.g. on pagereveal event
70
+ const instance = Interact.create(config);
71
+ ```
72
+
73
+ In `<head>` add:
74
+
75
+ ```html
76
+ <style>
77
+ ${interactCSS}
78
+ /* Optional — keep the custom element from affecting layout */
79
+ interact-element {
80
+ display: contents;
81
+ }
82
+ </style>
56
83
  ```
57
84
 
58
- #### 2. HTML Setup
85
+ In the `<body>` add:
59
86
 
60
87
  ```html
61
- <!-- Wrap your target element with interact-element -->
62
- <interact-element data-interact-key="my-element">
63
- <div>This will fade in when it enters the viewport!</div>
88
+ <interact-element data-interact-key="hero">
89
+ <section class="hero">Hello, animated world!</section>
64
90
  </interact-element>
65
91
  ```
66
92
 
67
93
  ### Using React
68
94
 
69
- #### 1. Basic Setup
95
+ A complete React example: register presets, generate CSS, mount the component, clean up on unmount.
70
96
 
71
- ```typescript
72
- import { Interact } from '@wix/interact/react';
97
+ ```tsx
98
+ import { useEffect } from 'react';
99
+ import type { InteractConfig } from '@wix/interact';
100
+ import { Interact, Interaction, generate } from '@wix/interact/react';
101
+ import * as presets from '@wix/motion-presets'; // optional
73
102
 
74
- // Define your interaction configuration
75
- const config = {
76
- interactions: [
77
- {
78
- trigger: 'viewEnter',
79
- key: '#my-element',
80
- effects: [
81
- {
82
- effectId: 'fade-in',
83
- },
84
- ],
85
- },
86
- ],
87
- effects: {
88
- 'fade-in': {
89
- duration: 1000,
90
- keyframeEffect: {
91
- name: 'fade',
92
- keyframes: { opacity: [0, 1] },
93
- },
94
- },
95
- },
103
+ Interact.registerEffects(presets); // optional
104
+
105
+ const config: InteractConfig = {
106
+ //...
96
107
  };
97
108
 
98
- // Initialize the interact instance
99
- const interact = Interact.create(config);
100
- ```
109
+ export function App () {
110
+ const interactCSS = generate(config, false);
111
+ // rest of App logic ...
101
112
 
102
- #### 2. HTML Setup
113
+ useEffect(() => {
114
+ const instance = Interact.create(config);
115
+ return () => instance.destroy();
116
+ }, []);
103
117
 
104
- ```tsx
105
- import { Interaction } from '@wix/interact/react';
118
+ return (
119
+ // can go to <head>
120
+ <style>{interactCSS}</style>
121
+ // ...
122
+ <Hero/>
123
+ // ...
124
+ )
125
+ }
106
126
 
107
- function MyComponent() {
127
+ // in components/Hero.jsx
128
+ export function Hero() {
108
129
  return (
109
- <Interaction tagName="div" interactKey="my-element" className="animated-content">
130
+ <Interaction tagName="section" interactKey="hero">
110
131
  Hello, animated world!
111
132
  </Interaction>
112
133
  );
113
134
  }
114
135
  ```
115
136
 
116
- ### Vanilla usage
137
+ ### Using Vanilla JS (you manage element lifecycle)
117
138
 
118
- #### 1. Basic Setup
139
+ **Vanilla JS** bind elements after they exist in the DOM:
119
140
 
120
- ```typescript
141
+ ```ts
142
+ import type { InteractConfig } from '@wix/interact';
121
143
  import { Interact, add } from '@wix/interact';
122
144
 
123
- // Define your interaction configuration
124
- const config = {
125
- interactions: [
126
- {
127
- trigger: 'viewEnter',
128
- key: '#my-element',
129
- effects: [
130
- {
131
- effectId: 'fade-in',
132
- },
133
- ],
134
- },
135
- ],
136
- effects: {
137
- 'fade-in': {
138
- duration: 1000,
139
- keyframeEffect: {
140
- name: 'fade',
141
- keyframes: { opacity: [0, 1] },
142
- },
143
- },
144
- },
145
+ const config: InteractConfig = {
146
+ //...
145
147
  };
146
148
 
147
- // add element
148
- add(document.querySelector('[data-interact-key="my-element"]'), 'my-element');
149
+ const instance = Interact.create(config);
149
150
 
150
- // Initialize the interact instance
151
- const interact = Interact.create(config);
151
+ add(document.querySelector('#hero'), 'hero');
152
152
  ```
153
153
 
154
- #### 2. HTML Setup
154
+ ## Entry Points
155
155
 
156
- ```html
157
- <div data-interact-key="my-element" class="animated-content">Hello, animated world!</div>
158
- ```
159
-
160
- ## Core Concepts
161
-
162
- ### Triggers
163
-
164
- Define when interactions should occur:
156
+ | Import | Use When |
157
+ | --------------------- | ----------------------------------------------------------- |
158
+ | `@wix/interact` | Vanilla JS — manual element binding via `add()`/`remove()`. |
159
+ | `@wix/interact/web` | Web Components — `<interact-element>` custom element. |
160
+ | `@wix/interact/react` | React — `<Interaction>` component with lifecycle. |
165
161
 
166
- - `viewEnter` - When element enters viewport
167
- - `click` - On element click
168
- - `hover` - On element hover
169
- - `viewProgress` - Scroll-driven animations based on progress of element in viewport
170
- - `pointerMove` - On pointer/mouse movement over an element or viewport
171
- - `animationEnd` - When another animation completes
162
+ All three entry points export the same `Interact` class, `generate()` function, and types.
172
163
 
173
- ### Effects
164
+ ## How It Works
174
165
 
175
- Define what should happen:
166
+ ```
167
+ Config ─┬─► Interact.create() ─► Trigger Observers ─► Effect Engine ─► Animation (via @wix/motion)
168
+ └─► generate() ────────► CSS (@keyframes, view-timeline, animations, transitions) ─► <head>
169
+ ```
176
170
 
177
- - **Time-based animations** - Duration-based effects with easing
178
- - **Scroll-driven animations** - Progress-based effects tied to scroll
179
- - **Pointer-driven animations** - Progress-based effects linked to pointer position
180
- - **CSS transitions** - Style property transitions
181
- - **Custom effects** - Integration with `@wix/motion`
171
+ `generate(config)` runs at build time or on the server to emit complete CSS for the entire config — maximizing offload of effect creation, binding, and running to the browser.
172
+ Interact also generates native `view-timeline` CSS declarations, so browsers that support it can drive scroll animations entirely without JS.
182
173
 
183
- ### Configuration Structure
174
+ The `InteractConfig` shape:
184
175
 
185
- ```typescript
186
- {
187
- interactions: [ // Define trigger → effect relationships
188
- {
189
- trigger: 'viewEnter',
190
- key: 'source-element',
191
- effects: [{ effectId: 'my-effect' }]
192
- }
193
- ],
194
- effects: { // Define reusable effect definitions
195
- 'my-effect': {
196
- duration: 1000,
197
- keyframeEffect: {
198
- name: 'fade',
199
- keyframes: { opacity: [0, 1] }
200
- }
201
- }
202
- },
203
- conditions: { // Define conditional logic
204
- 'mobile-only': {
205
- type: 'media',
206
- predicate: '(max-width: 768px)'
207
- }
208
- }
209
- }
176
+ ```ts
177
+ type InteractConfig = {
178
+ interactions: Interaction[]; // trigger → effect bindings
179
+ effects?: Record<string, Effect>; // reusable effect definitions
180
+ sequences?: Record<string, SequenceConfig>; // staggered multi-effect timelines
181
+ conditions?: Record<string, Condition>; // media / selector gates
182
+ };
210
183
  ```
211
184
 
212
- ## Basic API Reference
185
+ ## Triggers
213
186
 
214
- ### Interact Class
187
+ | Trigger | Fires On | Params |
188
+ | -------------- | -------------------------------------------- | --------------------------------------- |
189
+ | `viewEnter` | Element enters viewport | `threshold?`, `inset?` |
190
+ | `viewProgress` | While element scrolls through viewport | (use `rangeStart`/`rangeEnd` on effect) |
191
+ | `hover` | Pointer enters/leaves element | — |
192
+ | `click` | Element is clicked | — |
193
+ | `activate` | Click + keyboard (a11y variant of `click`) | — |
194
+ | `interest` | Hover + focus (a11y variant of `hover`) | — |
195
+ | `pointerMove` | While pointer moves over element or viewport | `hitArea?`, `axis?` |
196
+ | `animationEnd` | Another specified effect is finished | `effectId` |
215
197
 
216
- #### Static Methods
198
+ ## Effects
217
199
 
218
- ```typescript
219
- // Create a new instance with configuration
220
- Interact.create(config: InteractConfig): Interact
221
- ```
200
+ | Effect Type | Use For |
201
+ | ------------------------------------- | -------------------------------------------------------------------------- |
202
+ | `keyframeEffect` | Inline keyframes — self-contained, no preset needed. |
203
+ | `namedEffect` | Registered presets from `@wix/motion-presets` (e.g. `{ type: 'FadeIn' }`). |
204
+ | `customEffect` | Programmatic `(element, progress) => void` callback. |
205
+ | `transition` / `transitionProperties` | CSS state changes driven by `stateAction` (`add`/`remove`/`toggle`). |
222
206
 
223
- ### Standalone Functions
207
+ ## Recipes
224
208
 
225
- ```typescript
226
- // Add interactions to an element
227
- add(element: IInteractElement, key: string): boolean
209
+ Each example is a complete `InteractConfig` — pass it to `Interact.create(config)`.
228
210
 
229
- // Remove all interactions from an element
230
- remove(key: string): void
231
- ```
211
+ ### Entrance animation
232
212
 
233
- ## Examples
234
-
235
- ### Entrance Animation
236
-
237
- ```typescript
213
+ ```ts
238
214
  {
239
215
  interactions: [{
240
- trigger: 'viewEnter',
241
216
  key: 'hero',
242
- effects: [{ effectId: 'slide-up' }]
217
+ trigger: 'viewEnter',
218
+ effects: [{ effectId: 'float-in' }],
243
219
  }],
244
220
  effects: {
245
- 'slide-up': {
221
+ 'float-in': {
246
222
  duration: 800,
247
223
  easing: 'ease-out',
248
- keyframeEffect: {
249
- name: 'slide-up',
250
- keyframes: {
251
- transform: ['translateY(20px)', 'translateY(0)'],
252
- opacity: [0, 1]
253
- }
254
- }
255
- }
256
- }
224
+ namedEffect: { type: 'FloatIn', direction: 'bottom' },
225
+ },
226
+ },
257
227
  }
258
228
  ```
259
229
 
260
- ### Click Interaction
230
+ ### Click effect
261
231
 
262
- ```typescript
232
+ ```ts
263
233
  {
264
234
  interactions: [{
235
+ key: 'cta',
265
236
  trigger: 'click',
266
- key: 'button',
267
- effects: [{ effectId: 'bounce' }]
237
+ effects: [{ effectId: 'pulse' }],
268
238
  }],
269
239
  effects: {
270
- 'bounce': {
271
- duration: 600,
272
- namedEffect: {
273
- type: 'Bounce'
274
- }
275
- }
276
- }
240
+ 'pulse': {
241
+ duration: 300,
242
+ keyframeEffect: {
243
+ name: 'pulse',
244
+ keyframes: [
245
+ { transform: 'scale(1.08)', offset: 0.5 }
246
+ ],
247
+ },
248
+ triggerType: 'repeat',
249
+ },
250
+ },
277
251
  }
278
252
  ```
279
253
 
280
- ### Scroll-driven Animation
254
+ ### Scroll-driven animations
281
255
 
282
- ```typescript
256
+ ```ts
283
257
  {
284
258
  interactions: [{
259
+ key: 'card',
285
260
  trigger: 'viewProgress',
286
- key: 'parallax-card',
287
- effects: [{ effectId: 'parallax-scroll' }]
261
+ effects: [{ effectId: 'parallax' }],
288
262
  }],
289
263
  effects: {
290
- 'parallax-scroll': {
264
+ 'parallax': {
291
265
  keyframeEffect: {
292
- name: 'parallax-1',
266
+ name: 'parallax',
293
267
  keyframes: [
294
- { transform: 'translateY(200px)' },
295
- { transform: 'translateY(-200px)' }
296
- ]
268
+ { transform: 'translateY(-120px)' },
269
+ { transform: 'translateY(120px)' },
270
+ ],
297
271
  },
298
272
  rangeStart: { name: 'cover', offset: { value: 0, unit: 'percentage' } },
299
273
  rangeEnd: { name: 'cover', offset: { value: 100, unit: 'percentage' } },
300
274
  fill: 'both',
301
- easing: 'linear'
302
- }
303
- }
275
+ easing: 'linear',
276
+ },
277
+ },
304
278
  }
305
279
  ```
306
280
 
307
- ### Responsive Interactions
281
+ ### Hover toggle
282
+
283
+ #### CSS transition
308
284
 
309
- ```typescript
285
+ ```ts
310
286
  {
311
287
  interactions: [{
312
- trigger: 'hover',
313
288
  key: 'card',
314
- conditions: ['desktop-only'],
315
- effects: [{ effectId: 'lift' }]
289
+ trigger: 'hover',
290
+ effects: [{ effectId: 'lift', selector: '.card-figure' }],
316
291
  }],
317
- conditions: {
318
- 'desktop-only': {
319
- type: 'media',
320
- predicate: '(min-width: 1024px)'
321
- }
292
+ effects: {
293
+ 'lift': {
294
+ transition: {
295
+ duration: 200,
296
+ easing: 'ease-out',
297
+ styleProperties: [
298
+ { name: 'transform', value: 'scale(1.08)' },
299
+ { name: 'box-shadow', value: '0 8px 16px rgb(0 0 0 / 0.15)' },
300
+ ],
301
+ },
302
+ },
322
303
  },
304
+ }
305
+ ```
306
+
307
+ #### CSS Animation
308
+
309
+ ```ts
310
+ {
311
+ interactions: [{
312
+ key: 'card',
313
+ trigger: 'hover',
314
+ effects: [{ effectId: 'lift', selector: '.card-figure' }],
315
+ }],
323
316
  effects: {
324
317
  'lift': {
325
- duration: 200,
326
318
  keyframeEffect: {
327
319
  name: 'lift',
328
- keyframes: {
329
- transform: ['translateY(0)', 'translateY(-8px)'],
330
- boxShadow: ['0 2px 4px rgb(0 0 0 / 0.1)', '0 8px 16px rgb(0 0 0 / 0.15)']
331
- }
332
- }
333
- }
334
- }
320
+ keyframes: [
321
+ { transform: 'translateY(-80px)', boxShadow: '0 8px 16px rgb(0 0 0 / 0.15)' },
322
+ ],
323
+ },
324
+ duration: 200,
325
+ easing: 'ease-out',
326
+ },
327
+ },
335
328
  }
336
329
  ```
337
330
 
338
- ## Documentation
331
+ ### Pointer-tracking
339
332
 
340
- - [Full API Documentation](https://wix.github.io/interact/docs/api)
341
- - [Guides and Tutorials](https://wix.github.io/interact/docs/guides)
342
- - [Examples and Patterns](https://wix.github.io/interact/docs/examples)
343
- - [Integration Guides](https://wix.github.io/interact/docs/integration)
333
+ #### Keyframe effect
344
334
 
345
- ## AI Support
335
+ ```ts
336
+ {
337
+ interactions: [{
338
+ key: 'card-wrapper',
339
+ trigger: 'pointerMove',
340
+ params: { hitArea: 'root', axis: 'x' },
341
+ effects: [{ effectId: 'follow-x', key: 'card' }],
342
+ }, {
343
+ key: 'card-wrapper',
344
+ trigger: 'pointerMove',
345
+ params: { hitArea: 'root', axis: 'y' },
346
+ effects: [{ effectId: 'follow-y', key: 'card' }],
347
+ }],
348
+ effects: {
349
+ 'follow-x': {
350
+ keyframeEffect: {
351
+ name: 'follow-x',
352
+ keyframes: [
353
+ { transform: 'rotateY(-45deg)' },
354
+ { transform: 'rotateY(0px)' },
355
+ { transform: 'rotateY(45deg)' },
356
+ ],
357
+ },
358
+ easing: 'linear',
359
+ centeredToTarget: true,
360
+ },
361
+ 'follow-y': {
362
+ keyframeEffect: {
363
+ name: 'follow-y',
364
+ keyframes: [
365
+ { transform: 'rotateX(45deg)' },
366
+ { transform: 'rotateX(0px)' },
367
+ { transform: 'rotateX(-45deg)' },
368
+ ],
369
+ },
370
+ easing: 'linear',
371
+ composite: 'add',
372
+ centeredToTarget: true,
373
+ },
374
+ },
375
+ }
376
+ ```
346
377
 
347
- - [Full-flow, lean rules](https://wix.github.io/interact/rules/full-lean.md)
348
- - [Rules for integration](https://wix.github.io/interact/rules/integration.md)
349
- - [Rules for view entrance interactions](https://wix.github.io/interact/rules/viewenter.md)
350
- - [Rules for click interactions](https://wix.github.io/interact/rules/click.md)
351
- - [Rules for hover interactions](https://wix.github.io/interact/rules/click.md)
352
- - [Rules for scroll interactions](https://wix.github.io/interact/rules/viewprogress.md)
353
- - [Rules for pointer-move interactions](https://wix.github.io/interact/rules/pointermove.md)
378
+ #### Custom effect
354
379
 
355
- ## Development
380
+ ```ts
381
+ {
382
+ interactions: [{
383
+ key: 'spotlight',
384
+ trigger: 'pointerMove',
385
+ params: { hitArea: 'root' },
386
+ effects: [{ effectId: 'follow' }],
387
+ }],
388
+ effects: {
389
+ 'follow': {
390
+ customEffect: (element: HTMLElement, progress: { x: number, y: number }) => {
391
+ element.style.setProperty('--x', `${progress.x * 100}%`);
392
+ element.style.setProperty('--y', `${progress.y * 100}%`);
393
+ },
394
+ },
395
+ },
396
+ }
397
+ ```
356
398
 
357
- ```bash
358
- # Install dependencies
359
- yarn install
399
+ ## Common Pitfalls
360
400
 
361
- # Run tests
362
- yarn test
401
+ - **`overflow: hidden` breaks `viewProgress`** — Use `overflow: clip` on all ancestors between the source and the scroll container.
402
+ - **Same element as source and target with `viewEnter`** — Must use `triggerType: 'once'`. Other types cause re-entry loops.
403
+ - **Hit-area shift on `hover` / `pointerMove`** — Animating size/position of the hovered element shifts the hit area and causes jitter. Instead, animate a child via `selector` or a different `key`.
404
+ - **`registerEffects()` must run before `Interact.create()`/`generate()`** when using `namedEffect`.
405
+ - **FOUC prevention** — requires injecting the output of `generate(config)` into `<head>`.
406
+ - **`generate(config, useFirstChild)`** — Pass `true` for `<interact-element>` (web), `false` for vanilla and React `<Interaction>`.
407
+ - **`<interact-element>` must wrap exactly one child** — the library targets `:first-child` by default.
363
408
 
364
- # Run playground
365
- yarn playground
409
+ ## AI & Agent Support
366
410
 
367
- # Build package
368
- yarn build
369
- ```
411
+ Interact's JSON-config surface is the differentiator: configs are serializable, schema-typed, and validate-able (guardrails) — no imperative DOM logic for an LLM to hallucinate.
412
+
413
+ AI agents can discover @wix/interact documentation through:
414
+
415
+ - **[llms.txt](https://wix.github.io/interact/llms.txt)** — structured docs index ([llms.txt standard](https://llmstxt.org/))
416
+ - **[llms-full.txt](https://wix.github.io/interact/llms-full.txt)** — all rules in a single file
417
+
418
+ **Rules files** ship with the package under [`rules/`](https://github.com/wix/interact/tree/master/packages/interact/rules) — point your agent at them:
419
+
420
+ - [`rules/full-lean.md`](https://wix.github.io/interact/rules/full-lean.md) — complete config spec, pitfalls, and constraints
421
+ - [`rules/integration.md`](https://wix.github.io/interact/rules/integration.md) — integration entry points, lifecycle, style generation
422
+ - [`rules/viewenter.md`](https://wix.github.io/interact/rules/viewenter.md) — viewport entrance triggers (scroll-triggered animations)
423
+ - [`rules/viewprogress.md`](https://wix.github.io/interact/rules/viewprogress.md) — scroll-driven animations
424
+ - [`rules/click.md`](https://wix.github.io/interact/rules/click.md) — click and activate triggers
425
+ - [`rules/hover.md`](https://wix.github.io/interact/rules/hover.md) — hover and interest triggers
426
+ - [`rules/pointermove.md`](https://wix.github.io/interact/rules/pointermove.md) — pointer-driven animations
427
+
428
+ **Generation constraints** for agents producing configs:
429
+
430
+ - Do not invent `namedEffect` types — use only registered presets.
431
+ - Do not attach DOM event listeners manually — use triggers.
432
+ - Do not use `overflow: hidden` on scroll-tracked ancestors — use `overflow: clip`.
433
+ - Always pre-render CSS with `generate(config)` and inject into `<head>`.
434
+ - Always call `Interact.registerEffects(presets)` before `generate()` and `Interact.create()` when using `namedEffect`.
370
435
 
371
436
  ## Browser Support
372
437
 
373
- - Modern browsers with Web Components support
374
- - ⚠️ If using setting styles via JS in `transition` or `transitionProerties` - which use `adoptedStyleSheets`, browser support is: Chrome 73+, Firefox 101+, Safari 16.4+, Edge 79+
438
+ - Modern browsers with the Web Animations API (Baseline).
439
+ - `adoptedStyleSheets` (used by `transition` / `transitionProperties`): Chrome 73+, Firefox 101+, Safari 16.4+, Edge 79+.
440
+ - ViewTimeline: Chrome 115+; polyfilled via [`fizban`](https://github.com/wix-incubator/fizban) elsewhere.
375
441
 
376
442
  ## Related Packages
377
443
 
378
- - [`@wix/motion`](../motion/README.md) - Core animation engine
379
- - [`fizban`](https://github.com/wix/fizban) - For polyfilling scroll-driven animations
380
- - [`kuliso`](https://github.com/wix/kuliso) - For polyfilling pointer-driven animations
444
+ - [`@wix/motion`](https://github.com/wix/interact/tree/master/packages/motion) — low-level animation engine underneath Interact.
445
+ - [`@wix/motion-presets`](https://github.com/wix/interact/tree/master/packages/motion-presets) — ready-made effect catalog (entrance, scroll, hover, pointer).
446
+ - [`fizban`](https://github.com/wix-incubator/fizban) — scroll-driven animation polyfill (bundled dependency).
447
+ - [`kuliso`](https://github.com/wix-incubator/kuliso) — pointer-driven animation polyfill (bundled dependency).
448
+
449
+ ## Documentation
450
+
451
+ - [**Getting Started**](https://wix.github.io/interact/docs/#/guides/getting-started)
452
+ - [**API Reference**](https://wix.github.io/interact/docs/#/api) — `Interact` class, `InteractionController`, standalone functions, types
453
+ - [**Guides**](https://wix.github.io/interact/docs/#/guides) — triggers, effects, configuration, state, conditions, sequences
454
+ - [**Examples**](https://wix.github.io/interact/docs/#/examples) — entrance, click, hover, list patterns
455
+ - [**Web Components**](https://wix.github.io/interact/docs/#/guides/custom-elements) — integration via custom elements
456
+ - [**React Integration**](https://wix.github.io/interact/docs/#/integration/react) — React integration
381
457
 
382
458
  ## License
383
459