@wix/interact 1.93.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.
Files changed (179) hide show
  1. package/dist/cjs/index.js +2 -23
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/react.js +15 -0
  4. package/dist/cjs/react.js.map +1 -0
  5. package/dist/cjs/web.js +2 -0
  6. package/dist/cjs/web.js.map +1 -0
  7. package/dist/es/index.js +8 -0
  8. package/dist/es/index.js.map +1 -0
  9. package/dist/es/react.js +650 -0
  10. package/dist/es/react.js.map +1 -0
  11. package/dist/es/web.js +56 -0
  12. package/dist/es/web.js.map +1 -0
  13. package/dist/index-C8QxOkui.mjs +7940 -0
  14. package/dist/index-C8QxOkui.mjs.map +1 -0
  15. package/dist/index-DEPRHaUt.js +18 -0
  16. package/dist/index-DEPRHaUt.js.map +1 -0
  17. package/dist/tsconfig.build.tsbuildinfo +1 -0
  18. package/dist/types/core/Interact.d.ts +17 -7
  19. package/dist/types/core/Interact.d.ts.map +1 -0
  20. package/dist/types/core/InteractionController.d.ts +19 -0
  21. package/dist/types/core/InteractionController.d.ts.map +1 -0
  22. package/dist/types/core/add.d.ts +4 -3
  23. package/dist/types/core/add.d.ts.map +1 -0
  24. package/dist/types/core/css.d.ts +3 -0
  25. package/dist/types/core/css.d.ts.map +1 -0
  26. package/dist/types/core/remove.d.ts +3 -1
  27. package/dist/types/core/remove.d.ts.map +1 -0
  28. package/dist/types/core/utilities.d.ts +1 -0
  29. package/dist/types/core/utilities.d.ts.map +1 -0
  30. package/dist/types/dom/api.d.ts +3 -0
  31. package/dist/types/dom/api.d.ts.map +1 -0
  32. package/dist/types/handlers/animationEnd.d.ts +3 -2
  33. package/dist/types/handlers/animationEnd.d.ts.map +1 -0
  34. package/dist/types/handlers/click.d.ts +3 -2
  35. package/dist/types/handlers/click.d.ts.map +1 -0
  36. package/dist/types/handlers/hover.d.ts +3 -2
  37. package/dist/types/handlers/hover.d.ts.map +1 -0
  38. package/dist/types/handlers/index.d.ts +1 -0
  39. package/dist/types/handlers/index.d.ts.map +1 -0
  40. package/dist/types/handlers/pointerMove.d.ts +3 -2
  41. package/dist/types/handlers/pointerMove.d.ts.map +1 -0
  42. package/dist/types/handlers/utilities.d.ts +1 -0
  43. package/dist/types/handlers/utilities.d.ts.map +1 -0
  44. package/dist/types/handlers/viewEnter.d.ts +3 -2
  45. package/dist/types/handlers/viewEnter.d.ts.map +1 -0
  46. package/dist/types/handlers/viewProgress.d.ts +4 -3
  47. package/dist/types/handlers/viewProgress.d.ts.map +1 -0
  48. package/dist/types/index.d.ts +3 -2
  49. package/dist/types/index.d.ts.map +1 -0
  50. package/dist/types/react/Interaction.d.ts +10 -0
  51. package/dist/types/react/Interaction.d.ts.map +1 -0
  52. package/dist/types/react/index.d.ts +8 -0
  53. package/dist/types/react/index.d.ts.map +1 -0
  54. package/dist/types/react/interactRef.d.ts +3 -0
  55. package/dist/types/react/interactRef.d.ts.map +1 -0
  56. package/dist/types/types.d.ts +23 -10
  57. package/dist/types/types.d.ts.map +1 -0
  58. package/dist/types/utils.d.ts +2 -1
  59. package/dist/types/utils.d.ts.map +1 -0
  60. package/dist/types/{InteractElement.d.ts → web/InteractElement.d.ts} +115 -77
  61. package/dist/types/web/InteractElement.d.ts.map +1 -0
  62. package/dist/types/web/defineInteractElement.d.ts +2 -0
  63. package/dist/types/web/defineInteractElement.d.ts.map +1 -0
  64. package/dist/types/web/index.d.ts +6 -0
  65. package/dist/types/web/index.d.ts.map +1 -0
  66. package/docs/README.md +211 -0
  67. package/docs/advanced/README.md +164 -0
  68. package/docs/api/README.md +157 -0
  69. package/docs/api/element-selection.md +607 -0
  70. package/docs/api/functions.md +638 -0
  71. package/docs/api/interact-class.md +663 -0
  72. package/docs/api/interact-element.md +565 -0
  73. package/docs/api/interaction-controller.md +450 -0
  74. package/docs/api/types.md +957 -0
  75. package/docs/examples/README.md +212 -0
  76. package/docs/examples/click-interactions.md +977 -0
  77. package/docs/examples/entrance-animations.md +935 -0
  78. package/docs/examples/hover-effects.md +930 -0
  79. package/docs/examples/list-patterns.md +737 -0
  80. package/docs/guides/README.md +49 -0
  81. package/docs/guides/conditions-and-media-queries.md +1068 -0
  82. package/docs/guides/configuration-structure.md +726 -0
  83. package/docs/guides/custom-elements.md +327 -0
  84. package/docs/guides/effects-and-animations.md +634 -0
  85. package/docs/guides/getting-started.md +379 -0
  86. package/docs/guides/lists-and-dynamic-content.md +713 -0
  87. package/docs/guides/state-management.md +747 -0
  88. package/docs/guides/understanding-triggers.md +690 -0
  89. package/docs/integration/README.md +264 -0
  90. package/docs/integration/react.md +605 -0
  91. package/package.json +73 -56
  92. package/rules/Integration.md +255 -0
  93. package/rules/click-rules.md +533 -0
  94. package/rules/full-lean.md +346 -0
  95. package/rules/hover-rules.md +593 -0
  96. package/rules/pointermove-rules.md +1341 -0
  97. package/rules/scroll-list-rules.md +900 -0
  98. package/rules/viewenter-rules.md +1015 -0
  99. package/rules/viewprogress-rules.md +1044 -0
  100. package/dist/cjs/InteractElement.js +0 -163
  101. package/dist/cjs/InteractElement.js.map +0 -1
  102. package/dist/cjs/__tests__/interact.spec.js +0 -2094
  103. package/dist/cjs/__tests__/interact.spec.js.map +0 -1
  104. package/dist/cjs/__tests__/viewEnter.spec.js +0 -207
  105. package/dist/cjs/__tests__/viewEnter.spec.js.map +0 -1
  106. package/dist/cjs/core/Interact.js +0 -257
  107. package/dist/cjs/core/Interact.js.map +0 -1
  108. package/dist/cjs/core/add.js +0 -250
  109. package/dist/cjs/core/add.js.map +0 -1
  110. package/dist/cjs/core/remove.js +0 -35
  111. package/dist/cjs/core/remove.js.map +0 -1
  112. package/dist/cjs/core/utilities.js +0 -16
  113. package/dist/cjs/core/utilities.js.map +0 -1
  114. package/dist/cjs/external-types.d.js +0 -2
  115. package/dist/cjs/external-types.d.js.map +0 -1
  116. package/dist/cjs/handlers/animationEnd.js +0 -37
  117. package/dist/cjs/handlers/animationEnd.js.map +0 -1
  118. package/dist/cjs/handlers/click.js +0 -122
  119. package/dist/cjs/handlers/click.js.map +0 -1
  120. package/dist/cjs/handlers/hover.js +0 -147
  121. package/dist/cjs/handlers/hover.js.map +0 -1
  122. package/dist/cjs/handlers/index.js +0 -32
  123. package/dist/cjs/handlers/index.js.map +0 -1
  124. package/dist/cjs/handlers/pointerMove.js +0 -49
  125. package/dist/cjs/handlers/pointerMove.js.map +0 -1
  126. package/dist/cjs/handlers/utilities.js +0 -49
  127. package/dist/cjs/handlers/utilities.js.map +0 -1
  128. package/dist/cjs/handlers/viewEnter.js +0 -131
  129. package/dist/cjs/handlers/viewEnter.js.map +0 -1
  130. package/dist/cjs/handlers/viewProgress.js +0 -79
  131. package/dist/cjs/handlers/viewProgress.js.map +0 -1
  132. package/dist/cjs/test-types.d.js +0 -2
  133. package/dist/cjs/test-types.d.js.map +0 -1
  134. package/dist/cjs/types.js +0 -2
  135. package/dist/cjs/types.js.map +0 -1
  136. package/dist/cjs/utils.js +0 -98
  137. package/dist/cjs/utils.js.map +0 -1
  138. package/dist/esm/InteractElement.js +0 -157
  139. package/dist/esm/InteractElement.js.map +0 -1
  140. package/dist/esm/__tests__/interact.spec.js +0 -2102
  141. package/dist/esm/__tests__/interact.spec.js.map +0 -1
  142. package/dist/esm/__tests__/viewEnter.spec.js +0 -210
  143. package/dist/esm/__tests__/viewEnter.spec.js.map +0 -1
  144. package/dist/esm/core/Interact.js +0 -251
  145. package/dist/esm/core/Interact.js.map +0 -1
  146. package/dist/esm/core/add.js +0 -245
  147. package/dist/esm/core/add.js.map +0 -1
  148. package/dist/esm/core/remove.js +0 -30
  149. package/dist/esm/core/remove.js.map +0 -1
  150. package/dist/esm/core/utilities.js +0 -14
  151. package/dist/esm/core/utilities.js.map +0 -1
  152. package/dist/esm/external-types.d.js +0 -2
  153. package/dist/esm/external-types.d.js.map +0 -1
  154. package/dist/esm/handlers/animationEnd.js +0 -33
  155. package/dist/esm/handlers/animationEnd.js.map +0 -1
  156. package/dist/esm/handlers/click.js +0 -122
  157. package/dist/esm/handlers/click.js.map +0 -1
  158. package/dist/esm/handlers/hover.js +0 -147
  159. package/dist/esm/handlers/hover.js.map +0 -1
  160. package/dist/esm/handlers/index.js +0 -27
  161. package/dist/esm/handlers/index.js.map +0 -1
  162. package/dist/esm/handlers/pointerMove.js +0 -48
  163. package/dist/esm/handlers/pointerMove.js.map +0 -1
  164. package/dist/esm/handlers/utilities.js +0 -43
  165. package/dist/esm/handlers/utilities.js.map +0 -1
  166. package/dist/esm/handlers/viewEnter.js +0 -133
  167. package/dist/esm/handlers/viewEnter.js.map +0 -1
  168. package/dist/esm/handlers/viewProgress.js +0 -75
  169. package/dist/esm/handlers/viewProgress.js.map +0 -1
  170. package/dist/esm/index.js +0 -5
  171. package/dist/esm/index.js.map +0 -1
  172. package/dist/esm/test-types.d.js +0 -2
  173. package/dist/esm/test-types.d.js.map +0 -1
  174. package/dist/esm/types.js +0 -2
  175. package/dist/esm/types.js.map +0 -1
  176. package/dist/esm/utils.js +0 -92
  177. package/dist/esm/utils.js.map +0 -1
  178. package/dist/types/__tests__/interact.spec.d.ts +0 -1
  179. package/dist/types/__tests__/viewEnter.spec.d.ts +0 -0
@@ -0,0 +1,1341 @@
1
+ # PointerMove Trigger Rules for @wix/interact
2
+
3
+ These rules help generate pointer-driven interactions using the `@wix/interact` library. PointerMove triggers create real-time animations that respond to mouse movement over elements, perfect for 3D effects, cursor followers, and interactive cards.
4
+
5
+ ## Core Concepts
6
+
7
+ ### Effect Types for PointerMove
8
+
9
+ **IMPORTANT**: The `pointerMove` trigger provides 2D progress (x and y coordinates), which is incompatible with linear `keyframeEffect` animations. Only use:
10
+
11
+ 1. **`namedEffect`** (Preferred): Pre-built mouse presets from `@wix/motion` that handle 2D progress internally
12
+ 2. **`customEffect`** (Advanced): Custom function receiving the 2D progress object for full control
13
+
14
+ **Never use `keyframeEffect` with `pointerMove`** - keyframes require linear 0-1 progress and cannot handle 2D coordinates.
15
+
16
+ ### Hit Area Configuration (`hitArea`)
17
+
18
+ The `hitArea` parameter determines where mouse movement is tracked:
19
+
20
+ | Value | Behavior | Best For |
21
+ |-------|----------|----------|
22
+ | `'self'` | Tracks mouse within the source element's bounds only | Local hover effects, card interactions |
23
+ | `'root'` | Tracks mouse anywhere in the viewport (document root) | Global cursor followers, ambient effects |
24
+
25
+ ### Progress Object Structure (for `customEffect`)
26
+
27
+ When using `customEffect` with `pointerMove`, the progress parameter is an object:
28
+
29
+ ```typescript
30
+ type Progress = {
31
+ x: number; // 0-1: horizontal position (0 = left edge, 1 = right edge)
32
+ y: number; // 0-1: vertical position (0 = top edge, 1 = bottom edge)
33
+ v?: { // Velocity (optional)
34
+ x: number; // Horizontal velocity
35
+ y: number; // Vertical velocity
36
+ };
37
+ active?: boolean; // Whether mouse is currently in the hit area
38
+ };
39
+ ```
40
+
41
+ ### Centering with `centeredToTarget`
42
+
43
+ Controls how the progress range is calculated:
44
+
45
+ | Value | Behavior | Use When |
46
+ |-------|----------|----------|
47
+ | `true` | Centers the coordinate range at the target element | Source and target are different elements |
48
+ | `false` | Uses source element bounds for calculations | Cursor followers, global effects |
49
+
50
+ ## Rule 1: Single Element Pointer Effects with 3D Named Effects
51
+
52
+ **Use Case**: Interactive 3D transformations on individual elements that respond to mouse position (e.g., card tilting, 3D product showcases, interactive buttons)
53
+
54
+ **When to Apply**:
55
+ - For interactive card hover effects
56
+ - When creating 3D product showcases
57
+ - For engaging button interactions
58
+ - When building interactive UI elements that respond to mouse movement
59
+
60
+ **Pattern**:
61
+ ```typescript
62
+ {
63
+ key: '[SOURCE_KEY]',
64
+ trigger: 'pointerMove',
65
+ params: {
66
+ hitArea: '[HIT_AREA]'
67
+ },
68
+ effects: [
69
+ {
70
+ key: '[TARGET_KEY]',
71
+ namedEffect: {
72
+ type: '[3D_EFFECT_TYPE]',
73
+ [EFFECT_PROPERTIES]
74
+ },
75
+ centeredToTarget: [CENTERED_TO_TARGET],
76
+ effectId: '[UNIQUE_EFFECT_ID]'
77
+ }
78
+ ]
79
+ }
80
+ ```
81
+
82
+ **Variables**:
83
+ - `[SOURCE_KEY]`: Unique identifier for source element that tracks mouse movement
84
+ - `[TARGET_KEY]`: Unique identifier for target element to animate (can be same as source or different)
85
+ - `[HIT_AREA]`: 'self' (mouse within source element) or 'root' (mouse anywhere in viewport)
86
+ - `[3D_EFFECT_TYPE]`: 'Tilt3DMouse', 'Track3DMouse', 'SwivelMouse'
87
+ - `[EFFECT_PROPERTIES]`: Named effect specific properties (angle, perspective, power, etc.)
88
+ - `[CENTERED_TO_TARGET]`: true (center range at target) or false (use source element bounds)
89
+ - `[UNIQUE_EFFECT_ID]`: Optional unique identifier
90
+
91
+ **Example - Interactive Product Card**:
92
+ ```typescript
93
+ {
94
+ key: 'product-card',
95
+ trigger: 'pointerMove',
96
+ params: {
97
+ hitArea: 'self'
98
+ },
99
+ effects: [
100
+ {
101
+ key: 'product-card',
102
+ namedEffect: {
103
+ type: 'Tilt3DMouse',
104
+ angle: 15,
105
+ perspective: 1000,
106
+ power: 'medium'
107
+ }
108
+ }
109
+ ]
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Rule 2: Single Element Pointer Effects with Movement Named Effects
116
+
117
+ **Use Case**: Cursor-following and position-tracking effects on individual elements (e.g., floating elements, cursor followers, responsive decorations)
118
+
119
+ **When to Apply**:
120
+ - For cursor-following elements
121
+ - When creating floating responsive decorations
122
+ - For interactive element positioning
123
+ - When building mouse-aware UI components
124
+
125
+ **Pattern**:
126
+ ```typescript
127
+ {
128
+ key: '[SOURCE_KEY]',
129
+ trigger: 'pointerMove',
130
+ params: {
131
+ hitArea: '[HIT_AREA]'
132
+ },
133
+ effects: [
134
+ {
135
+ key: '[TARGET_KEY]',
136
+ namedEffect: {
137
+ type: '[MOVEMENT_EFFECT_TYPE]',
138
+ distance: { value: [DISTANCE_VALUE], type: '[DISTANCE_UNIT]' },
139
+ axis: '[AXIS_CONSTRAINT]',
140
+ power: '[POWER_LEVEL]'
141
+ },
142
+ centeredToTarget: [CENTERED_TO_TARGET],
143
+ effectId: '[UNIQUE_EFFECT_ID]'
144
+ }
145
+ ]
146
+ }
147
+ ```
148
+
149
+ **Variables**:
150
+ - `[MOVEMENT_EFFECT_TYPE]`: 'TrackMouse', 'AiryMouse', 'BounceMouse'
151
+ - `[DISTANCE_VALUE]`: Numeric value for movement distance
152
+ - `[DISTANCE_UNIT]`: 'px', 'percentage', 'vw', 'vh'
153
+ - `[AXIS_CONSTRAINT]`: 'both', 'horizontal', 'vertical'
154
+ - `[POWER_LEVEL]`: 'soft', 'medium', 'hard'
155
+ - Other variables same as Rule 1
156
+
157
+ **Example - Cursor Follower Element**:
158
+ ```typescript
159
+ {
160
+ key: 'cursor-follower',
161
+ trigger: 'pointerMove',
162
+ params: {
163
+ hitArea: 'root'
164
+ },
165
+ effects: [
166
+ {
167
+ namedEffect: {
168
+ type: 'TrackMouse',
169
+ distance: { value: 50, type: 'percentage' },
170
+ axis: 'both',
171
+ power: 'medium'
172
+ },
173
+ centeredToTarget: false
174
+ }
175
+ ]
176
+ }
177
+ ```
178
+
179
+ **Example - Floating Decoration**:
180
+ ```typescript
181
+ {
182
+ key: 'hero-section',
183
+ trigger: 'pointerMove',
184
+ params: {
185
+ hitArea: 'self'
186
+ },
187
+ effects: [
188
+ {
189
+ key: 'floating-element',
190
+ namedEffect: {
191
+ type: 'AiryMouse',
192
+ distance: { value: 30, type: 'px' },
193
+ axis: 'both',
194
+ power: 'soft'
195
+ },
196
+ centeredToTarget: true,
197
+ effectId: 'hero-float'
198
+ }
199
+ ]
200
+ }
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Rule 3: Single Element Pointer Effects with Scale Named Effects
206
+
207
+ **Use Case**: Dynamic scaling and deformation effects on individual elements based on mouse position (e.g., interactive scaling, organic transformations, blob effects)
208
+
209
+ **When to Apply**:
210
+ - For interactive scaling buttons
211
+ - When creating organic blob-like interactions
212
+ - For dynamic size responsive elements
213
+ - When building creative morphing interfaces
214
+
215
+ **Pattern**:
216
+ ```typescript
217
+ {
218
+ key: '[SOURCE_KEY]',
219
+ trigger: 'pointerMove',
220
+ params: {
221
+ hitArea: '[HIT_AREA]'
222
+ },
223
+ effects: [
224
+ {
225
+ key: '[TARGET_KEY]',
226
+ namedEffect: {
227
+ type: '[SCALE_EFFECT_TYPE]',
228
+ [SCALE_PROPERTIES]
229
+ },
230
+ centeredToTarget: [CENTERED_TO_TARGET],
231
+ effectId: '[UNIQUE_EFFECT_ID]'
232
+ }
233
+ ]
234
+ }
235
+ ```
236
+
237
+ **Variables**:
238
+ - `[SCALE_EFFECT_TYPE]`: 'ScaleMouse', 'BlobMouse', 'SkewMouse'
239
+ - `[SCALE_PROPERTIES]`: Effect-specific properties (scale, distance, axis, power)
240
+ - Other variables same as Rule 1
241
+
242
+ **Example - Interactive Scale Button**:
243
+ ```typescript
244
+ {
245
+ key: 'scale-button',
246
+ trigger: 'pointerMove',
247
+ params: {
248
+ hitArea: 'self'
249
+ },
250
+ effects: [
251
+ {
252
+ key: 'scale-button',
253
+ namedEffect: {
254
+ type: 'ScaleMouse',
255
+ scale: 1.1,
256
+ distance: { value: 100, type: 'px' },
257
+ axis: 'both',
258
+ power: 'medium'
259
+ },
260
+ centeredToTarget: true
261
+ }
262
+ ]
263
+ }
264
+ ```
265
+
266
+ **Example - Organic Blob Effect**:
267
+ ```typescript
268
+ {
269
+ key: 'blob-container',
270
+ trigger: 'pointerMove',
271
+ params: {
272
+ hitArea: 'self'
273
+ },
274
+ effects: [
275
+ {
276
+ key: 'blob-shape',
277
+ namedEffect: {
278
+ type: 'BlobMouse',
279
+ intensity: 0.8,
280
+ smoothness: 0.6,
281
+ power: 'medium'
282
+ },
283
+ effectId: 'blob-morph'
284
+ }
285
+ ]
286
+ }
287
+ ```
288
+
289
+ ---
290
+
291
+ ## Rule 4: Single Element Pointer Effects with Visual Named Effects
292
+
293
+ **Use Case**: Visual effect transformations on individual elements based on mouse position (e.g., motion blur, rotation effects, visual filters)
294
+
295
+ **When to Apply**:
296
+ - For creative visual interfaces
297
+ - When adding motion blur to interactions
298
+ - For rotation-based mouse effects
299
+ - When creating dynamic visual feedback
300
+
301
+ **Pattern**:
302
+ ```typescript
303
+ {
304
+ key: '[SOURCE_KEY]',
305
+ trigger: 'pointerMove',
306
+ params: {
307
+ hitArea: '[HIT_AREA]'
308
+ },
309
+ effects: [
310
+ {
311
+ key: '[TARGET_KEY]',
312
+ namedEffect: {
313
+ type: '[VISUAL_EFFECT_TYPE]',
314
+ [VISUAL_PROPERTIES]
315
+ },
316
+ centeredToTarget: [CENTERED_TO_TARGET],
317
+ effectId: '[UNIQUE_EFFECT_ID]'
318
+ }
319
+ ]
320
+ }
321
+ ```
322
+
323
+ **Variables**:
324
+ - `[VISUAL_EFFECT_TYPE]`: 'BlurMouse', 'SpinMouse'
325
+ - `[VISUAL_PROPERTIES]`: Effect-specific properties (blur amount, rotation speed, power)
326
+ - Other variables same as Rule 1
327
+
328
+ **Example - Motion Blur Card**:
329
+ ```typescript
330
+ {
331
+ key: 'motion-card',
332
+ trigger: 'pointerMove',
333
+ params: {
334
+ hitArea: 'self'
335
+ },
336
+ effects: [
337
+ {
338
+ key: 'motion-card',
339
+ namedEffect: {
340
+ type: 'BlurMouse',
341
+ blurAmount: 5,
342
+ motionIntensity: 0.7,
343
+ power: 'medium'
344
+ },
345
+ centeredToTarget: true
346
+ }
347
+ ]
348
+ }
349
+ ```
350
+
351
+ **Example - Spinning Element**:
352
+ ```typescript
353
+ {
354
+ key: 'spin-trigger',
355
+ trigger: 'pointerMove',
356
+ params: {
357
+ hitArea: 'self'
358
+ },
359
+ effects: [
360
+ {
361
+ key: 'spinning-icon',
362
+ namedEffect: {
363
+ type: 'SpinMouse',
364
+ rotationSpeed: 0.5,
365
+ direction: 'clockwise',
366
+ power: 'soft'
367
+ },
368
+ centeredToTarget: false,
369
+ effectId: 'icon-spin'
370
+ }
371
+ ]
372
+ }
373
+ ```
374
+
375
+ ---
376
+
377
+ ## Rule 5: Multi-Element Pointer Parallax Effects with Named Effects
378
+
379
+ **Use Case**: Coordinated pointer-driven animations across multiple elements creating layered parallax effects (e.g., multi-layer backgrounds, depth effects, coordinated element responses)
380
+
381
+ **When to Apply**:
382
+ - For multi-layer background effects
383
+ - When creating depth and parallax interactions
384
+ - For coordinated UI element responses
385
+ - When building immersive pointer-driven experiences
386
+
387
+ **Pattern**:
388
+ ```typescript
389
+ {
390
+ key: '[CONTAINER_KEY]',
391
+ trigger: 'pointerMove',
392
+ params: {
393
+ hitArea: '[HIT_AREA]'
394
+ },
395
+ effects: [
396
+ {
397
+ key: '[BACKGROUND_LAYER_KEY]',
398
+ namedEffect: {
399
+ type: '[BACKGROUND_EFFECT_TYPE]',
400
+ distance: { value: [BACKGROUND_DISTANCE], type: '[DISTANCE_UNIT]' },
401
+ power: '[BACKGROUND_POWER]'
402
+ },
403
+ centeredToTarget: [CENTERED_TO_TARGET]
404
+ },
405
+ {
406
+ key: '[MIDGROUND_LAYER_KEY]',
407
+ namedEffect: {
408
+ type: '[MIDGROUND_EFFECT_TYPE]',
409
+ distance: { value: [MIDGROUND_DISTANCE], type: '[DISTANCE_UNIT]' },
410
+ power: '[MIDGROUND_POWER]'
411
+ },
412
+ centeredToTarget: [CENTERED_TO_TARGET]
413
+ },
414
+ {
415
+ key: '[FOREGROUND_LAYER_KEY]',
416
+ namedEffect: {
417
+ type: '[FOREGROUND_EFFECT_TYPE]',
418
+ distance: { value: [FOREGROUND_DISTANCE], type: '[DISTANCE_UNIT]' },
419
+ power: '[FOREGROUND_POWER]'
420
+ },
421
+ centeredToTarget: [CENTERED_TO_TARGET]
422
+ }
423
+ ]
424
+ }
425
+ ```
426
+
427
+ **Variables**:
428
+ - `[CONTAINER_KEY]`: Unique identifier for container element tracking mouse
429
+ - `[*_LAYER_KEY]`: Unique identifier for different layer elements
430
+ - `[*_EFFECT_TYPE]`: Named effects for each layer (typically movement effects)
431
+ - `[*_DISTANCE]`: Movement distance for each layer (creating depth)
432
+ - `[*_POWER]`: Power level for each layer response
433
+ - Other variables same as previous rules
434
+
435
+ **Example - Parallax Card Layers**:
436
+ ```typescript
437
+ {
438
+ key: 'parallax-card',
439
+ trigger: 'pointerMove',
440
+ params: {
441
+ hitArea: 'self'
442
+ },
443
+ effects: [
444
+ {
445
+ key: 'bg-layer',
446
+ namedEffect: {
447
+ type: 'AiryMouse',
448
+ distance: { value: 15, type: 'px' },
449
+ axis: 'both',
450
+ power: 'soft'
451
+ },
452
+ centeredToTarget: true
453
+ },
454
+ {
455
+ key: 'mid-layer',
456
+ namedEffect: {
457
+ type: 'TrackMouse',
458
+ distance: { value: 25, type: 'px' },
459
+ axis: 'both',
460
+ power: 'medium'
461
+ },
462
+ centeredToTarget: true
463
+ },
464
+ {
465
+ key: 'fg-layer',
466
+ namedEffect: {
467
+ type: 'BounceMouse',
468
+ distance: { value: 35, type: 'px' },
469
+ axis: 'both',
470
+ power: 'medium'
471
+ },
472
+ centeredToTarget: true
473
+ }
474
+ ]
475
+ }
476
+ ```
477
+
478
+ **Example - Multi-Layer Hero Section**:
479
+ ```typescript
480
+ {
481
+ key: 'hero-container',
482
+ trigger: 'pointerMove',
483
+ params: {
484
+ hitArea: 'self'
485
+ },
486
+ effects: [
487
+ {
488
+ key: 'hero-bg',
489
+ namedEffect: {
490
+ type: 'AiryMouse',
491
+ distance: { value: 20, type: 'px' },
492
+ axis: 'both',
493
+ power: 'soft'
494
+ },
495
+ centeredToTarget: true
496
+ },
497
+ {
498
+ key: 'hero-content',
499
+ namedEffect: {
500
+ type: 'TrackMouse',
501
+ distance: { value: 40, type: 'px' },
502
+ axis: 'horizontal',
503
+ power: 'medium'
504
+ },
505
+ centeredToTarget: true
506
+ },
507
+ {
508
+ key: 'hero-decorations',
509
+ namedEffect: {
510
+ type: 'ScaleMouse',
511
+ scale: 1.05,
512
+ distance: { value: 60, type: 'px' },
513
+ power: 'medium'
514
+ },
515
+ centeredToTarget: true
516
+ }
517
+ ]
518
+ }
519
+ ```
520
+
521
+ ---
522
+
523
+ ## Rule 6: Coordinated Group Pointer Effects with Named Effects
524
+
525
+ **Use Case**: Synchronized pointer-driven animations across related elements with different responses (e.g., card grids, navigation menus, interactive galleries)
526
+
527
+ **When to Apply**:
528
+ - For interactive card grids
529
+ - When building responsive navigation systems
530
+ - For gallery hover effects
531
+ - When creating coordinated interface responses
532
+
533
+ **Pattern**:
534
+ ```typescript
535
+ {
536
+ key: '[CONTAINER_KEY]',
537
+ trigger: 'pointerMove',
538
+ params: {
539
+ hitArea: '[HIT_AREA]'
540
+ },
541
+ effects: [
542
+ {
543
+ key: '[PRIMARY_ELEMENTS_KEY]',
544
+ namedEffect: {
545
+ type: '[PRIMARY_EFFECT_TYPE]',
546
+ [PRIMARY_EFFECT_PROPERTIES]
547
+ },
548
+ centeredToTarget: [PRIMARY_CENTERED]
549
+ },
550
+ {
551
+ key: '[SECONDARY_ELEMENTS_KEY]',
552
+ namedEffect: {
553
+ type: '[SECONDARY_EFFECT_TYPE]',
554
+ [SECONDARY_EFFECT_PROPERTIES]
555
+ },
556
+ centeredToTarget: [SECONDARY_CENTERED]
557
+ }
558
+ ]
559
+ }
560
+ ```
561
+
562
+ **Variables**:
563
+ - `[PRIMARY_ELEMENTS_KEY]`: Unique identifier for primary responsive elements
564
+ - `[SECONDARY_ELEMENTS_KEY]`: Unique identifier for secondary responsive elements
565
+ - `[PRIMARY_EFFECT_TYPE]`: Named effect for primary elements
566
+ - `[SECONDARY_EFFECT_TYPE]`: Named effect for secondary elements
567
+ - `[*_EFFECT_PROPERTIES]`: Properties specific to each effect type
568
+ - `[*_CENTERED]`: Centering configuration for each element group
569
+ - Other variables same as previous rules
570
+
571
+ **Example - Interactive Card Grid**:
572
+ ```typescript
573
+ {
574
+ key: 'card-grid',
575
+ trigger: 'pointerMove',
576
+ params: {
577
+ hitArea: 'self'
578
+ },
579
+ effects: [
580
+ {
581
+ key: 'grid-card',
582
+ namedEffect: {
583
+ type: 'Tilt3DMouse',
584
+ angle: 12,
585
+ perspective: 1000,
586
+ power: 'soft'
587
+ },
588
+ centeredToTarget: true
589
+ },
590
+ {
591
+ key: 'card-shadow',
592
+ namedEffect: {
593
+ type: 'AiryMouse',
594
+ distance: { value: 20, type: 'px' },
595
+ axis: 'both',
596
+ power: 'soft'
597
+ },
598
+ centeredToTarget: true
599
+ }
600
+ ]
601
+ }
602
+ ```
603
+
604
+ **Example - Navigation Menu Response**:
605
+ ```typescript
606
+ {
607
+ key: 'nav-container',
608
+ trigger: 'pointerMove',
609
+ params: {
610
+ hitArea: 'self'
611
+ },
612
+ effects: [
613
+ {
614
+ key: 'nav-item',
615
+ namedEffect: {
616
+ type: 'ScaleMouse',
617
+ scale: 1.05,
618
+ distance: { value: 80, type: 'px' },
619
+ power: 'medium'
620
+ },
621
+ centeredToTarget: true
622
+ },
623
+ {
624
+ key: 'nav-indicator',
625
+ namedEffect: {
626
+ type: 'TrackMouse',
627
+ distance: { value: 15, type: 'px' },
628
+ axis: 'horizontal',
629
+ power: 'hard'
630
+ },
631
+ centeredToTarget: false
632
+ }
633
+ ]
634
+ }
635
+ ```
636
+
637
+ ---
638
+
639
+ ## Rule 7: Global Cursor Follower Effects with Named Effects
640
+
641
+ **Use Case**: Page-wide cursor following elements that respond to mouse movement anywhere (e.g., custom cursors, global decorative followers, interactive overlays)
642
+
643
+ **When to Apply**:
644
+ - For custom cursor implementations
645
+ - When creating global interactive overlays
646
+ - For page-wide decorative followers
647
+ - When building immersive cursor experiences
648
+
649
+ **Pattern**:
650
+ ```typescript
651
+ {
652
+ key: '[FOLLOWER_KEY]',
653
+ trigger: 'pointerMove',
654
+ params: {
655
+ hitArea: 'root'
656
+ },
657
+ effects: [
658
+ {
659
+ namedEffect: {
660
+ type: '[FOLLOWER_EFFECT_TYPE]',
661
+ distance: { value: [FOLLOWER_DISTANCE], type: '[DISTANCE_UNIT]' },
662
+ [FOLLOWER_PROPERTIES]
663
+ },
664
+ centeredToTarget: false,
665
+ effectId: '[FOLLOWER_EFFECT_ID]'
666
+ }
667
+ ]
668
+ }
669
+ ```
670
+
671
+ **Variables**:
672
+ - `[FOLLOWER_KEY]`: Unique identifier for cursor follower element
673
+ - `[FOLLOWER_EFFECT_TYPE]`: 'TrackMouse', 'AiryMouse', 'BounceMouse'
674
+ - `[FOLLOWER_DISTANCE]`: Distance/lag for follower (0 for perfect following)
675
+ - `[FOLLOWER_PROPERTIES]`: Additional effect properties
676
+ - `[FOLLOWER_EFFECT_ID]`: Unique identifier for the follower effect
677
+ - Other variables same as previous rules
678
+
679
+ **Example - Custom Cursor Follower**:
680
+ ```typescript
681
+ {
682
+ key: 'custom-cursor',
683
+ trigger: 'pointerMove',
684
+ params: {
685
+ hitArea: 'root'
686
+ },
687
+ effects: [
688
+ {
689
+ namedEffect: {
690
+ type: 'TrackMouse',
691
+ distance: { value: 0, type: 'px' },
692
+ axis: 'both',
693
+ power: 'hard'
694
+ },
695
+ centeredToTarget: false,
696
+ effectId: 'global-cursor'
697
+ }
698
+ ]
699
+ }
700
+ ```
701
+
702
+ **Example - Floating Decoration Follower**:
703
+ ```typescript
704
+ {
705
+ key: 'floating-decoration',
706
+ trigger: 'pointerMove',
707
+ params: {
708
+ hitArea: 'root'
709
+ },
710
+ effects: [
711
+ {
712
+ namedEffect: {
713
+ type: 'AiryMouse',
714
+ distance: { value: 50, type: 'px' },
715
+ axis: 'both',
716
+ power: 'soft'
717
+ },
718
+ centeredToTarget: false,
719
+ effectId: 'decoration-follower'
720
+ }
721
+ ]
722
+ }
723
+ ```
724
+
725
+ ---
726
+
727
+ ## Rule 8: Custom Pointer Effects with customEffect
728
+
729
+ **Use Case**: When you need full control over pointer-driven animations that cannot be achieved with named effects, such as custom physics, complex multi-property animations, or unique visual transformations.
730
+
731
+ **When to Apply**:
732
+ - For custom physics-based animations
733
+ - When creating unique visual effects not covered by named effects
734
+ - When controlling WebGL/WebGPU effects or other JavaScript controlled effects
735
+ - For complex DOM manipulations based on mouse position
736
+ - When implementing grid-based or particle effects
737
+ - For animations requiring access to velocity data
738
+
739
+ **IMPORTANT**: Only use `customEffect` when `namedEffect` cannot achieve the desired result. Named effects are optimized and GPU-friendly.
740
+
741
+ **Pattern - Basic customEffect**:
742
+ ```typescript
743
+ {
744
+ key: '[SOURCE_KEY]',
745
+ trigger: 'pointerMove',
746
+ params: {
747
+ hitArea: '[HIT_AREA]'
748
+ },
749
+ effects: [
750
+ {
751
+ key: '[TARGET_KEY]',
752
+ customEffect: (element, progress) => {
753
+ // progress.x: 0-1 horizontal position
754
+ // progress.y: 0-1 vertical position
755
+ // progress.v: { x, y } velocity (optional)
756
+ // progress.active: boolean (optional)
757
+
758
+ [CUSTOM_ANIMATION_LOGIC]
759
+ },
760
+ centeredToTarget: [CENTERED_TO_TARGET]
761
+ }
762
+ ]
763
+ }
764
+ ```
765
+
766
+ **Variables**:
767
+ - `[SOURCE_KEY]`: Unique identifier for source element tracking mouse movement
768
+ - `[TARGET_KEY]`: Unique identifier for target element to animate
769
+ - `[HIT_AREA]`: 'self' or 'root'
770
+ - `[CUSTOM_ANIMATION_LOGIC]`: Your custom animation code using the progress object
771
+ - `[CENTERED_TO_TARGET]`: true or false
772
+
773
+ **Example - Custom Rotation Based on Mouse Position**:
774
+ ```typescript
775
+ {
776
+ key: 'rotation-container',
777
+ trigger: 'pointerMove',
778
+ params: {
779
+ hitArea: 'self'
780
+ },
781
+ effects: [
782
+ {
783
+ customEffect: (element, progress) => {
784
+ // Convert progress to angle (0-360 degrees)
785
+ const angle = Math.atan2(
786
+ progress.y - 0.5,
787
+ progress.x - 0.5
788
+ ) * (180 / Math.PI);
789
+
790
+ element.style.transform = `rotate(${angle}deg)`;
791
+ },
792
+ centeredToTarget: true
793
+ }
794
+ ]
795
+ }
796
+ ```
797
+
798
+ **Example - Magnetic Effect with Distance Calculation**:
799
+ ```typescript
800
+ {
801
+ key: 'magnetic-button',
802
+ trigger: 'pointerMove',
803
+ params: {
804
+ hitArea: 'self'
805
+ },
806
+ effects: [
807
+ {
808
+ customEffect: (element, progress) => {
809
+ // Calculate distance from center (0.5, 0.5)
810
+ const dx = (progress.x - 0.5) * 2; // -1 to 1
811
+ const dy = (progress.y - 0.5) * 2; // -1 to 1
812
+
813
+ // Apply magnetic pull effect
814
+ const maxMove = 20; // pixels
815
+ const moveX = dx * maxMove;
816
+ const moveY = dy * maxMove;
817
+
818
+ element.style.transform = `translate(${moveX}px, ${moveY}px)`;
819
+ },
820
+ centeredToTarget: true
821
+ }
822
+ ]
823
+ }
824
+ ```
825
+
826
+ **Example - Velocity-Based Motion Blur**:
827
+ ```typescript
828
+ {
829
+ key: 'velocity-element',
830
+ trigger: 'pointerMove',
831
+ params: {
832
+ hitArea: 'root'
833
+ },
834
+ effects: [
835
+ {
836
+ customEffect: (element, progress) => {
837
+ // Use velocity for motion blur intensity
838
+ const velocity = progress.v || { x: 0, y: 0 };
839
+ const speed = Math.sqrt(velocity.x ** 2 + velocity.y ** 2);
840
+
841
+ // Apply blur based on speed
842
+ const blurAmount = Math.min(speed * 0.5, 10);
843
+ element.style.filter = `blur(${blurAmount}px)`;
844
+
845
+ // Move element towards mouse
846
+ const offsetX = (progress.x - 0.5) * 100;
847
+ const offsetY = (progress.y - 0.5) * 100;
848
+ element.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
849
+ },
850
+ centeredToTarget: false
851
+ }
852
+ ]
853
+ }
854
+ ```
855
+
856
+ **Example - Grid Cell Rotation Effect**:
857
+ ```typescript
858
+ // First, cache grid cell positions for performance
859
+ const cellCache = new Map();
860
+ // Cache viewport size
861
+ const windowWidth = window.innerWidth;
862
+ const windowHeight = window.innerHeight;
863
+ // ... populate cache with cell center positions
864
+ // ... update `windowWidth/height` on window `resize` event
865
+
866
+ {
867
+ key: 'interactive-grid',
868
+ trigger: 'pointerMove',
869
+ params: {
870
+ hitArea: 'root'
871
+ },
872
+ effects: [
873
+ {
874
+ customEffect: (element, progress) => {
875
+ // Convert progress to viewport coordinates
876
+ const mouseX = progress.x * windowWidth;
877
+ const mouseY = progress.y * windowHeight;
878
+
879
+ // Iterate through cached grid cells
880
+ for (const [cell, cache] of cellCache) {
881
+ const deltaX = mouseX - cache.x;
882
+ const deltaY = mouseY - cache.y;
883
+
884
+ // Calculate angle pointing towards mouse
885
+ const angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 90;
886
+
887
+ // Calculate distance-based intensity
888
+ const dist = Math.sqrt(deltaX ** 2 + deltaY ** 2);
889
+ const intensity = Math.max(0, 1 - dist / 500);
890
+
891
+ cell.style.transform = `rotate(${angle}deg) scale(${1 + intensity * 0.2})`;
892
+ }
893
+ },
894
+ centeredToTarget: false
895
+ }
896
+ ]
897
+ }
898
+ ```
899
+
900
+ **Example - Active State Handling**:
901
+ ```typescript
902
+ {
903
+ key: 'active-aware-element',
904
+ trigger: 'pointerMove',
905
+ params: {
906
+ hitArea: 'self'
907
+ },
908
+ effects: [
909
+ {
910
+ customEffect: (element, progress) => {
911
+ if (!progress.active) {
912
+ // Mouse left the hit area - reset or animate out
913
+ element.style.transform = 'scale(1)';
914
+ element.style.opacity = '0.7';
915
+ return;
916
+ }
917
+
918
+ // Mouse is active in hit area
919
+ const scale = 1 + (1 - Math.abs(progress.x - 0.5) * 2) * 0.1;
920
+ element.style.transform = `scale(${scale})`;
921
+ element.style.opacity = '1';
922
+ },
923
+ centeredToTarget: true
924
+ }
925
+ ]
926
+ }
927
+ ```
928
+
929
+ ### customEffect with Transition Smoothing
930
+
931
+ For smoother animations, you can use `transitionDuration` and `transitionEasing`:
932
+
933
+ ```typescript
934
+ {
935
+ key: 'smooth-custom',
936
+ trigger: 'pointerMove',
937
+ params: {
938
+ hitArea: 'self'
939
+ },
940
+ effects: [
941
+ {
942
+ customEffect: (element, progress) => {
943
+ const x = (progress.x - 0.5) * 50;
944
+ const y = (progress.y - 0.5) * 50;
945
+ element.style.transform = `translate(${x}px, ${y}px)`;
946
+ },
947
+ transitionDuration: 100,
948
+ transitionEasing: 'easeOut',
949
+ centeredToTarget: true
950
+ }
951
+ ]
952
+ }
953
+ ```
954
+
955
+ ---
956
+
957
+ ## Rule 9: Multi-Element Custom Parallax with customEffect
958
+
959
+ **Use Case**: Complex parallax effects with custom physics or non-standard transformations across multiple layers.
960
+
961
+ **When to Apply**:
962
+ - For parallax with custom easing or physics
963
+ - When layers need different calculation methods
964
+ - For effects combining multiple CSS properties
965
+
966
+ **Pattern**:
967
+ ```typescript
968
+ {
969
+ key: '[CONTAINER_KEY]',
970
+ trigger: 'pointerMove',
971
+ params: {
972
+ hitArea: '[HIT_AREA]'
973
+ },
974
+ effects: [
975
+ {
976
+ key: '[LAYER_1_KEY]',
977
+ customEffect: (element, progress) => {
978
+ [LAYER_1_CUSTOM_LOGIC]
979
+ },
980
+ centeredToTarget: true
981
+ },
982
+ {
983
+ key: '[LAYER_2_KEY]',
984
+ customEffect: (element, progress) => {
985
+ [LAYER_2_CUSTOM_LOGIC]
986
+ },
987
+ centeredToTarget: true
988
+ }
989
+ ]
990
+ }
991
+ ```
992
+
993
+ **Example - Depth-Based Custom Parallax**:
994
+ ```typescript
995
+ {
996
+ key: 'parallax-scene',
997
+ trigger: 'pointerMove',
998
+ params: {
999
+ hitArea: 'self'
1000
+ },
1001
+ effects: [
1002
+ {
1003
+ key: 'bg-stars',
1004
+ customEffect: (element, progress) => {
1005
+ // Background: subtle movement, inverted direction
1006
+ const x = (0.5 - progress.x) * 10;
1007
+ const y = (0.5 - progress.y) * 10;
1008
+ element.style.transform = `translate(${x}px, ${y}px)`;
1009
+ },
1010
+ centeredToTarget: true
1011
+ },
1012
+ {
1013
+ key: 'mid-clouds',
1014
+ customEffect: (element, progress) => {
1015
+ // Midground: moderate movement with rotation
1016
+ const x = (progress.x - 0.5) * 30;
1017
+ const y = (progress.y - 0.5) * 20;
1018
+ const rotation = (progress.x - 0.5) * 5;
1019
+ element.style.transform = `translate(${x}px, ${y}px) rotate(${rotation}deg)`;
1020
+ },
1021
+ centeredToTarget: true
1022
+ },
1023
+ {
1024
+ key: 'fg-elements',
1025
+ customEffect: (element, progress) => {
1026
+ // Foreground: strong movement with scale
1027
+ const x = (progress.x - 0.5) * 60;
1028
+ const y = (progress.y - 0.5) * 40;
1029
+ const scale = 1 + Math.abs(progress.x - 0.5) * 0.1;
1030
+ element.style.transform = `translate(${x}px, ${y}px) scale(${scale})`;
1031
+ },
1032
+ centeredToTarget: true
1033
+ }
1034
+ ]
1035
+ }
1036
+ ```
1037
+
1038
+ ---
1039
+
1040
+ ## Advanced Patterns and Combinations
1041
+
1042
+ ### Responsive Pointer Effects
1043
+ Adjusting pointer sensitivity based on device capabilities:
1044
+
1045
+ ```typescript
1046
+ {
1047
+ key: 'responsive-element',
1048
+ trigger: 'pointerMove',
1049
+ conditions: ['supports-hover', 'desktop-only'],
1050
+ params: {
1051
+ hitArea: 'self'
1052
+ },
1053
+ effects: [
1054
+ {
1055
+ key: 'responsive-element',
1056
+ namedEffect: {
1057
+ type: 'Tilt3DMouse',
1058
+ angle: 20,
1059
+ perspective: 800,
1060
+ power: 'medium'
1061
+ },
1062
+ centeredToTarget: true
1063
+ }
1064
+ ]
1065
+ },
1066
+ // Simplified version for touch devices
1067
+ {
1068
+ key: 'responsive-element',
1069
+ trigger: 'pointerMove',
1070
+ conditions: ['touch-device'],
1071
+ params: {
1072
+ hitArea: 'self'
1073
+ },
1074
+ effects: [
1075
+ {
1076
+ key: 'responsive-element',
1077
+ namedEffect: {
1078
+ type: 'ScaleMouse',
1079
+ scale: 1.02,
1080
+ power: 'soft'
1081
+ },
1082
+ centeredToTarget: true
1083
+ }
1084
+ ]
1085
+ }
1086
+ ```
1087
+
1088
+ ### Contextual Hit Areas
1089
+ Different hit areas for different interaction contexts:
1090
+
1091
+ ```typescript
1092
+ // Local interaction - mouse must be over element
1093
+ {
1094
+ key: 'local-card',
1095
+ trigger: 'pointerMove',
1096
+ params: {
1097
+ hitArea: 'self'
1098
+ },
1099
+ effects: [
1100
+ {
1101
+ key: 'local-card',
1102
+ namedEffect: {
1103
+ type: 'Tilt3DMouse',
1104
+ angle: 15,
1105
+ power: 'medium'
1106
+ },
1107
+ centeredToTarget: true
1108
+ }
1109
+ ]
1110
+ },
1111
+ // Global interaction - responds to mouse anywhere
1112
+ {
1113
+ key: 'global-background',
1114
+ trigger: 'pointerMove',
1115
+ params: {
1116
+ hitArea: 'root'
1117
+ },
1118
+ effects: [
1119
+ {
1120
+ key: 'ambient-element',
1121
+ namedEffect: {
1122
+ type: 'AiryMouse',
1123
+ distance: { value: 30, type: 'px' },
1124
+ power: 'soft'
1125
+ },
1126
+ centeredToTarget: false
1127
+ }
1128
+ ]
1129
+ }
1130
+ ```
1131
+
1132
+ ### Axis-Constrained Effects
1133
+ Controlling movement direction for specific design needs:
1134
+
1135
+ ```typescript
1136
+ {
1137
+ key: 'constrained-container',
1138
+ trigger: 'pointerMove',
1139
+ params: {
1140
+ hitArea: 'self'
1141
+ },
1142
+ effects: [
1143
+ {
1144
+ key: 'horizontal-slider',
1145
+ namedEffect: {
1146
+ type: 'TrackMouse',
1147
+ distance: { value: 100, type: 'px' },
1148
+ axis: 'horizontal',
1149
+ power: 'medium'
1150
+ },
1151
+ centeredToTarget: true
1152
+ },
1153
+ {
1154
+ key: 'vertical-indicator',
1155
+ namedEffect: {
1156
+ type: 'ScaleMouse',
1157
+ scale: 1.2,
1158
+ distance: { value: 150, type: 'px' },
1159
+ axis: 'vertical',
1160
+ power: 'medium'
1161
+ },
1162
+ centeredToTarget: true
1163
+ }
1164
+ ]
1165
+ }
1166
+ ```
1167
+
1168
+ ---
1169
+
1170
+ ## Best Practices for PointerMove Interactions
1171
+
1172
+ ### Effect Type Selection Guidelines
1173
+
1174
+ **When to use `namedEffect` (Preferred)**:
1175
+ 1. For standard mouse-tracking effects (tilt, track, scale, blur)
1176
+ 2. When GPU-optimized performance is critical
1177
+ 3. For effects that match preset behavior (3D tilt, elastic following)
1178
+ 4. When you don't need custom physics or calculations
1179
+
1180
+ **When to use `customEffect`**:
1181
+ 1. For custom physics-based animations (springs, gravity)
1182
+ 2. When you need access to velocity data (`progress.v`)
1183
+ 3. For complex DOM manipulations (updating multiple elements)
1184
+ 4. When creating effects not covered by named presets
1185
+ 5. For grid/particle systems with many elements
1186
+ 6. For controlling WebGL/WebGPU effects
1187
+
1188
+ **Never use `keyframeEffect`** with `pointerMove` - pointer progress is 2D and cannot map to linear keyframes.
1189
+
1190
+ ### Performance Guidelines
1191
+ 1. **Use hardware-accelerated properties** - prefer transforms over position changes
1192
+ 2. **Limit simultaneous pointer effects** - too many can cause performance issues
1193
+ 3. **Test on various devices** - pointer sensitivity varies across hardware
1194
+ 4. **Cache DOM queries in customEffect** - avoid repeated `querySelector` calls
1195
+ 5. **Use `requestAnimationFrame` sparingly** - the library already handles frame timing
1196
+ 6. **Prefer `namedEffect` over `customEffect`** - named effects are optimized for GPU acceleration
1197
+
1198
+ ### Hit Area Guidelines
1199
+ 1. **Use `hitArea: 'self'`** for local element interactions (cards, buttons, hover effects)
1200
+ 2. **Use `hitArea: 'root'`** for global cursor followers and ambient effects
1201
+ 3. **Consider container boundaries** when choosing hit areas
1202
+ 4. **Test hit area responsiveness** across different screen sizes
1203
+ 5. **`'self'`** is more performant than `'root'` - use when possible
1204
+
1205
+ ### Centering Guidelines
1206
+ 1. **Set `centeredToTarget: true`** when target differs from source (e.g., animating child element from parent)
1207
+ 2. **Use `centeredToTarget: false`** for cursor followers and global effects
1208
+ 3. **Test centering behavior** with different element sizes
1209
+ 4. **Consider responsive design** when setting centering
1210
+ 5. **Centering affects how progress.x/y map to element position**
1211
+
1212
+ ### User Experience Guidelines
1213
+ 1. **Keep pointer effects subtle** to avoid overwhelming users
1214
+ 2. **Ensure effects enhance rather than distract** from content
1215
+ 3. **Provide visual feedback** that feels natural and responsive
1216
+ 4. **Test with actual users** to validate interaction quality
1217
+
1218
+ ### Accessibility Considerations
1219
+ 1. **Respect `prefers-reduced-motion`** for all pointer animations
1220
+ 2. **Ensure touch device compatibility** with appropriate alternatives
1221
+ 3. **Don't rely solely on pointer effects** for important interactions
1222
+ 4. **Provide keyboard alternatives** for interactive elements
1223
+
1224
+ ### Common Use Cases by Pattern
1225
+
1226
+ **Single Element 3D Effects (Rule 1)** - `namedEffect`:
1227
+ - Interactive product cards
1228
+ - 3D showcase elements
1229
+ - Immersive button interactions
1230
+ - Portfolio item presentations
1231
+
1232
+ **Movement Followers (Rule 2)** - `namedEffect`:
1233
+ - Cursor follower elements
1234
+ - Floating decorative elements
1235
+ - Responsive UI indicators
1236
+ - Interactive overlays
1237
+
1238
+ **Scale & Deformation (Rule 3)** - `namedEffect`:
1239
+ - Organic interface elements
1240
+ - Interactive morphing shapes
1241
+ - Creative scaling buttons
1242
+ - Blob-like interactions
1243
+
1244
+ **Visual Effects (Rule 4)** - `namedEffect`:
1245
+ - Creative interface elements
1246
+ - Motion blur interactions
1247
+ - Spinning decorative elements
1248
+ - Dynamic visual feedback
1249
+
1250
+ **Multi-Element Parallax (Rule 5)** - `namedEffect`:
1251
+ - Layered background effects
1252
+ - Depth-based interactions
1253
+ - Immersive hero sections
1254
+ - Complex scene responses
1255
+
1256
+ **Group Coordination (Rule 6)** - `namedEffect`:
1257
+ - Interactive card grids
1258
+ - Navigation menu systems
1259
+ - Gallery hover effects
1260
+ - Coordinated UI responses
1261
+
1262
+ **Global Followers (Rule 7)** - `namedEffect`:
1263
+ - Custom cursor implementations
1264
+ - Page-wide decorative elements
1265
+ - Global interactive overlays
1266
+ - Immersive cursor experiences
1267
+
1268
+ **Custom Pointer Effects (Rule 8)** - `customEffect`:
1269
+ - Grid-based rotation systems
1270
+ - Magnetic pull/push effects
1271
+ - Physics-based animations
1272
+ - Velocity-reactive effects
1273
+ - Complex DOM manipulations
1274
+ - Particle systems
1275
+
1276
+ **Multi-Element Custom Parallax (Rule 9)** - `customEffect`:
1277
+ - Non-linear parallax physics
1278
+ - Layers with different calculation methods
1279
+ - Combined transform effects per layer
1280
+ - Custom easing per element
1281
+
1282
+ ### Troubleshooting Common Issues
1283
+
1284
+ **Poor pointer responsiveness**:
1285
+ - Check `power` settings (soft/medium/hard) for namedEffect
1286
+ - Verify `hitArea` configuration
1287
+ - Test `centeredToTarget` settings
1288
+ - Ensure target elements are properly positioned
1289
+
1290
+ **Performance issues**:
1291
+ - Reduce number of simultaneous effects
1292
+ - Use simpler named effects
1293
+ - Check for CSS conflicts
1294
+ - Test on lower-end devices
1295
+ - In customEffect: cache DOM queries outside the callback
1296
+ - Avoid creating objects inside customEffect callbacks
1297
+
1298
+ **customEffect not updating smoothly**:
1299
+ - Add `transitionDuration` and `transitionEasing` for smoother transitions
1300
+ - Ensure style changes use transform/opacity for GPU acceleration
1301
+ - Avoid expensive calculations inside the callback
1302
+ - Consider debouncing complex logic
1303
+
1304
+ **customEffect progress values unexpected**:
1305
+ - Remember x/y are 0-1 normalized (not pixel values)
1306
+ - Check `centeredToTarget` setting affects coordinate mapping
1307
+ - Verify `hitArea` matches expected tracking area
1308
+ - Use `progress.active` to handle edge cases
1309
+
1310
+ **Unexpected behavior on touch devices**:
1311
+ - Implement appropriate conditions for touch vs. mouse
1312
+ - Provide touch-friendly alternatives
1313
+ - Test pointer events on mobile devices
1314
+ - Consider disabling complex effects on touch
1315
+
1316
+ **Effects not triggering**:
1317
+ - Verify source element exists and is visible
1318
+ - Check `data-interact-key` matches CSS selector
1319
+ - Ensure proper hit area configuration
1320
+ - Test mouse event propagation
1321
+
1322
+ **keyframeEffect not working with pointerMove**:
1323
+ - This is expected! `keyframeEffect` requires linear 0-1 progress
1324
+ - `pointerMove` provides 2D progress (x, y object)
1325
+ - Use `namedEffect` or `customEffect` instead
1326
+
1327
+ ---
1328
+
1329
+ ## Quick Reference: Effect Type Selection
1330
+
1331
+ | Requirement | Use This | Why |
1332
+ |-------------|----------|-----|
1333
+ | Standard 3D tilt | `namedEffect: { type: 'Tilt3DMouse' }` | GPU-optimized, battle-tested |
1334
+ | Cursor following | `namedEffect: { type: 'TrackMouse' }` | Built-in physics |
1335
+ | Custom physics | `customEffect` | Full control over calculations |
1336
+ | Velocity-based effects | `customEffect` | Access to `progress.v` |
1337
+ | Grid/particle systems | `customEffect` | Can manipulate many elements |
1338
+
1339
+ ---
1340
+
1341
+ These rules provide comprehensive coverage for PointerMove trigger interactions in `@wix/interact`, supporting all hit area configurations, centering options, named effect types, and custom effect patterns as outlined in the development plan Stage 1.5.