@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,726 @@
1
+ # Configuration Structure
2
+
3
+ The `InteractConfig` object is the heart of `@wix/interact`. This guide explains how to organize and structure complex interactions efficiently.
4
+
5
+ ## Basic Configuration Structure
6
+
7
+ ```typescript
8
+ import type { InteractConfig } from '@wix/interact';
9
+
10
+ const config: InteractConfig = {
11
+ effects: {
12
+ // Reusable effect definitions
13
+ },
14
+ conditions: {
15
+ // Reusable condition definitions
16
+ },
17
+ interactions: [
18
+ // Array of interaction definitions
19
+ ]
20
+ };
21
+ ```
22
+
23
+ ## Anatomy of an Interaction
24
+
25
+ Each interaction defines a complete cause-and-effect relationship:
26
+
27
+ ```typescript
28
+ {
29
+ key: 'trigger-element', // What element triggers the interaction
30
+ selector: '.clickable-area', // Optional: Custom selector within source
31
+ trigger: 'hover', // What user action starts it
32
+ params: { // Optional trigger parameters
33
+ type: 'alternate'
34
+ },
35
+ conditions: ['desktop-only'], // Optional conditions to check
36
+ effects: [ // Array of effects to apply
37
+ {
38
+ key: 'animated-element',
39
+ selector: '.animation-target', // Optional: Custom selector within target
40
+ namedEffect: 'FadeIn',
41
+ duration: 300
42
+ }
43
+ ]
44
+ }
45
+ ```
46
+
47
+ ## Element Selection with Selectors
48
+
49
+ The `selector` property allows you to specify exactly which element should be used for interactions, instead of being limited to the first child element.
50
+
51
+ ### How Element Selection Works
52
+
53
+ Note that while `Interaction.key` defaults to `Effect.key` if it's missing, `selector` and `listContainer` are not inherited from the Interaction's config to the Effect's config.
54
+
55
+ The system follows this priority order for selecting elements:
56
+
57
+ 1. **List Container** (if specified): `listContainer: '.item-list'`. Matches child elements of the selected container using `selector`, or all its immediate children if not specified.
58
+ 2. **Custom Selector** (if specified): `selector: '.my-element'`.
59
+ 3. **First Child** (fallback): The first child element of the interact-element.
60
+
61
+ ### Basic Selector Usage
62
+
63
+ ```typescript
64
+ const config: InteractConfig = {
65
+ interactions: [
66
+ {
67
+ key: 'card-container',
68
+ selector: '.card-image', // Select the image within the card
69
+ trigger: 'hover',
70
+ effects: [
71
+ {
72
+ key: 'card-container',
73
+ selector: '.card-overlay', // Select the overlay within the card
74
+ namedEffect: 'FadeIn',
75
+ duration: 300
76
+ }
77
+ ]
78
+ }
79
+ ]
80
+ };
81
+ ```
82
+
83
+ ### Selector vs ListContainer
84
+
85
+ - **`selector`**: Selects a single element using CSS selector
86
+ - **`listContainer`**: Selects a container for targeting its child elements for list-based interactions
87
+ - **Combined**: Use both to select elements within list items
88
+
89
+ ```typescript
90
+ // Using selector with listContainer
91
+ {
92
+ key: 'product-grid',
93
+ listContainer: '.product-item', // Each product item
94
+ selector: '.product-image', // Image within each item
95
+ trigger: 'hover',
96
+ effects: [
97
+ {
98
+ key: 'product-grid',
99
+ listContainer: '.product-item',
100
+ selector: '.product-overlay', // Overlay within each item
101
+ namedEffect: {
102
+ type: 'FadeIn'
103
+ },
104
+ duration: 200
105
+ }
106
+ ]
107
+ }
108
+ ```
109
+
110
+ ## Organizing Simple Interactions
111
+
112
+ ### Inline Effects (Small Projects)
113
+ For simple interactions, define effects directly:
114
+
115
+ ```typescript
116
+ const simpleConfig: InteractConfig = {
117
+ interactions: [
118
+ {
119
+ key: 'button-1',
120
+ trigger: 'hover',
121
+ effects: [
122
+ {
123
+ key: 'button-1',
124
+ namedEffect: {
125
+ type: 'Scale'
126
+ },
127
+ duration: 200,
128
+ easing: 'ease-out'
129
+ }
130
+ ]
131
+ },
132
+ {
133
+ key: 'button-2',
134
+ trigger: 'click',
135
+ effects: [
136
+ {
137
+ key: 'modal',
138
+ keyframeEffect: {
139
+ name: 'scale-button',
140
+ keyframes: [
141
+ { opacity: '0', transform: 'scale(0.9)' },
142
+ { opacity: '1', transform: 'scale(1)' }
143
+ ]
144
+ },
145
+ duration: 300
146
+ }
147
+ ]
148
+ }
149
+ ]
150
+ };
151
+ ```
152
+
153
+ ## Organizing Complex Interactions
154
+
155
+ ### Reusable Effects
156
+ For larger projects, define effects separately and reference them:
157
+
158
+ ```typescript
159
+ const complexConfig: InteractConfig = {
160
+ effects: {
161
+ // Reusable effect definitions
162
+ 'button-hover': {
163
+ keyframeEffect: {
164
+ name: 'button-hover',
165
+ keyframes: [
166
+ { transform: 'scale(1)', boxShadow: '0 2px 4px rgba(0,0,0,0.1)' },
167
+ { transform: 'scale(1.05)', boxShadow: '0 8px 16px rgba(0,0,0,0.15)' }
168
+ ]
169
+ },
170
+ duration: 200,
171
+ easing: 'ease-out'
172
+ },
173
+ 'card-entrance': {
174
+ keyframeEffect: {
175
+ name: 'card-entrance',
176
+ keyframes: [
177
+ { opacity: '0', transform: 'translateY(30px)' },
178
+ { opacity: '1', transform: 'translateY(0)' }
179
+ ]
180
+ },
181
+ duration: 600,
182
+ easing: 'cubic-bezier(0.16, 1, 0.3, 1)'
183
+ },
184
+ 'modal-open': {
185
+ keyframeEffect: {
186
+ name: 'modal-open',
187
+ keyframes: [
188
+ { opacity: '0', transform: 'scale(0.95)' },
189
+ { opacity: '1', transform: 'scale(1)' }
190
+ ]
191
+ },
192
+ duration: 300,
193
+ easing: 'ease-out'
194
+ }
195
+ },
196
+
197
+ interactions: [
198
+ {
199
+ key: 'btn-primary',
200
+ trigger: 'hover',
201
+ effects: [
202
+ {
203
+ key: 'btn-primary',
204
+ effectId: 'button-hover' // Reference to reusable effect
205
+ }
206
+ ]
207
+ },
208
+ {
209
+ key: 'product-card',
210
+ trigger: 'viewEnter',
211
+ params: { type: 'once', threshold: 0.3 },
212
+ effects: [
213
+ {
214
+ key: 'product-card',
215
+ effectId: 'card-entrance'
216
+ }
217
+ ]
218
+ }
219
+ ]
220
+ };
221
+ ```
222
+
223
+ ## Conditional Interactions
224
+
225
+ ### Defining Conditions
226
+ Create reusable conditions for responsive design:
227
+
228
+ ```typescript
229
+ const responsiveConfig: InteractConfig = {
230
+ conditions: {
231
+ 'desktop-only': {
232
+ type: 'media',
233
+ predicate: '(min-width: 768px)'
234
+ },
235
+ 'mobile-only': {
236
+ type: 'media',
237
+ predicate: '(max-width: 767px)'
238
+ },
239
+ 'prefers-motion': {
240
+ type: 'media',
241
+ predicate: '(prefers-reduced-motion: no-preference)'
242
+ },
243
+ 'large-container': {
244
+ type: 'container',
245
+ predicate: '(min-width: 600px)'
246
+ }
247
+ },
248
+
249
+ interactions: [
250
+ // Desktop hover effects
251
+ {
252
+ key: 'hero-image',
253
+ trigger: 'hover',
254
+ conditions: ['desktop-only', 'prefers-motion'],
255
+ effects: [
256
+ {
257
+ key: 'hero-image',
258
+ namedEffect: {
259
+ type: 'Scale'
260
+ },
261
+ duration: 400
262
+ }
263
+ ]
264
+ },
265
+
266
+ // Mobile tap effects
267
+ {
268
+ key: 'hero-image',
269
+ trigger: 'click',
270
+ conditions: ['mobile-only'],
271
+ effects: [
272
+ {
273
+ key: 'hero-image',
274
+ namedEffect: {
275
+ type: 'Pulse'
276
+ },
277
+ duration: 300
278
+ }
279
+ ]
280
+ }
281
+ ]
282
+ };
283
+ ```
284
+
285
+ ### Using Conditions in Effects
286
+ Apply conditions at the effect level:
287
+
288
+ ```typescript
289
+ {
290
+ key: 'animated-section',
291
+ trigger: 'viewEnter',
292
+ effects: [
293
+ // Basic fade for all devices
294
+ {
295
+ key: 'animated-section',
296
+ namedEffect: {
297
+ type: 'FadeIn'
298
+ },
299
+ duration: 600
300
+ },
301
+ // Enhanced animation only on desktop
302
+ {
303
+ key: 'animated-section',
304
+ selector: ' .particles',
305
+ namedEffect: {
306
+ type: 'SlideUp'
307
+ },
308
+ duration: 800,
309
+ delay: 200,
310
+ conditions: ['desktop-only', 'prefers-motion']
311
+ }
312
+ ]
313
+ }
314
+ ```
315
+
316
+ ## Modular Configuration Patterns
317
+
318
+ ### Feature-Based Organization
319
+ Organize by features or components:
320
+
321
+ ```typescript
322
+ // buttons.ts
323
+ export const buttonInteractions = [
324
+ {
325
+ key: 'btn-primary',
326
+ trigger: 'hover',
327
+ effects: [{ key: 'btn-primary', effectId: 'button-hover' }]
328
+ },
329
+ {
330
+ key: 'btn-secondary',
331
+ trigger: 'hover',
332
+ effects: [{ key: 'btn-secondary', effectId: 'button-hover-secondary' }]
333
+ }
334
+ ];
335
+
336
+ // cards.ts
337
+ export const cardInteractions = [
338
+ {
339
+ key: 'card',
340
+ trigger: 'viewEnter',
341
+ params: { type: 'once' },
342
+ effects: [{ key: 'card', effectId: 'card-entrance' }]
343
+ }
344
+ ];
345
+
346
+ // main.ts
347
+ import { buttonInteractions } from './buttons';
348
+ import { cardInteractions } from './cards';
349
+ import { commonEffects } from './effects';
350
+ import { mediaConditions } from './conditions';
351
+
352
+ const config: InteractConfig = {
353
+ effects: commonEffects,
354
+ conditions: mediaConditions,
355
+ interactions: [
356
+ ...buttonInteractions,
357
+ ...cardInteractions
358
+ ]
359
+ };
360
+ ```
361
+
362
+ ### Component-Specific Configurations
363
+ Create configurations for specific components:
364
+
365
+ ```typescript
366
+ // NavbarConfig.ts
367
+ export const createNavbarConfig = (navbarId: string): InteractConfig => ({
368
+ effects: {
369
+ 'nav-slide': {
370
+ keyframeEffect: {
371
+ name: 'nav-slide',
372
+ keyframes: [
373
+ { transform: 'translateY(-100%)' },
374
+ { transform: 'translateY(0)' }
375
+ ]
376
+ },
377
+ duration: 300,
378
+ easing: 'ease-out'
379
+ }
380
+ },
381
+ interactions: [
382
+ {
383
+ key: navbarId,
384
+ selector: '.nav-toggle',
385
+ trigger: 'click',
386
+ effects: [
387
+ {
388
+ key: navbarId,
389
+ selector: '.nav-menu',
390
+ effectId: 'nav-slide'
391
+ }
392
+ ]
393
+ }
394
+ ]
395
+ });
396
+
397
+ // Usage
398
+ const navConfig = createNavbarConfig('main-nav');
399
+ Interact.create(navConfig);
400
+ ```
401
+
402
+ ## Advanced Configuration Patterns
403
+
404
+ TBD
405
+
406
+ ## Performance Considerations
407
+
408
+ ### Lazy Loading Configurations
409
+ Load configurations on demand:
410
+
411
+ ```typescript
412
+ const loadFeatureConfig = async (featureName: string): Promise<InteractConfig> => {
413
+ const module = await import(`./features/${featureName}/interactions.js`);
414
+ return module.default;
415
+ };
416
+
417
+ // Usage
418
+ const heroConfig = await loadFeatureConfig('hero');
419
+ Interact.create(heroConfig);
420
+ ```
421
+
422
+ ## Real-World Example: E-commerce Product Page
423
+
424
+ ```typescript
425
+ const productPageConfig: InteractConfig = {
426
+ effects: {
427
+ 'product-image-zoom': {
428
+ keyframeEffect: {
429
+ name: 'product-image-zoom',
430
+ keyframes: [
431
+ { transform: 'scale(1)' },
432
+ { transform: 'scale(1.1)' }
433
+ ]
434
+ },
435
+ duration: 300,
436
+ easing: 'ease-out'
437
+ },
438
+ 'add-to-cart-success': {
439
+ keyframeEffect: {
440
+ name: 'add-to-cart-success',
441
+ keyframes: [
442
+ { backgroundColor: '#ef4444', transform: 'scale(1)' },
443
+ { transform: 'scale(1.05)' },
444
+ { backgroundColor: '#10b981', transform: 'scale(1)' }
445
+ ]
446
+ },
447
+ duration: 600,
448
+ easing: 'ease-in-out'
449
+ },
450
+ 'review-entrance': {
451
+ keyframeEffect: {
452
+ name: 'review-entrance',
453
+ keyframes: [
454
+ { opacity: '0', transform: 'translateY(20px)' },
455
+ { opacity: '1', transform: 'translateY(0)' }
456
+ ]
457
+ },
458
+ duration: 500,
459
+ easing: 'ease-out'
460
+ }
461
+ },
462
+
463
+ conditions: {
464
+ 'desktop': {
465
+ type: 'media',
466
+ predicate: '(min-width: 1024px)'
467
+ },
468
+ 'touch-device': {
469
+ type: 'media',
470
+ predicate: '(hover: none)'
471
+ }
472
+ },
473
+
474
+ interactions: [
475
+ // Product image hover (desktop only)
476
+ {
477
+ key: 'product-image',
478
+ trigger: 'hover',
479
+ conditions: ['desktop'],
480
+ effects: [
481
+ {
482
+ key: 'product-image',
483
+ selector: 'img',
484
+ effectId: 'product-image-zoom'
485
+ }
486
+ ]
487
+ },
488
+
489
+ // Add to cart success animation
490
+ {
491
+ key: 'add-to-cart-btn',
492
+ trigger: 'click',
493
+ effects: [
494
+ {
495
+ key: 'add-to-cart-btn',
496
+ effectId: 'add-to-cart-success'
497
+ }
498
+ ]
499
+ },
500
+
501
+ // Staggered review animations
502
+ {
503
+ key: 'review-1',
504
+ trigger: 'viewEnter',
505
+ params: { type: 'once', threshold: 0.2 },
506
+ effects: [
507
+ {
508
+ key: 'review-1',
509
+ effectId: 'review-entrance',
510
+ delay: 0
511
+ }
512
+ ]
513
+ },
514
+ {
515
+ key: 'review-2',
516
+ trigger: 'viewEnter',
517
+ params: { type: 'once', threshold: 0.2 },
518
+ effects: [
519
+ {
520
+ key: 'review-2',
521
+ effectId: 'review-entrance',
522
+ delay: 100
523
+ }
524
+ ]
525
+ }
526
+ ]
527
+ };
528
+ ```
529
+
530
+ ## Advanced Selector Examples
531
+
532
+ ### Card Component with Multiple Interactive Areas
533
+
534
+ ```typescript
535
+ const cardConfig: InteractConfig = {
536
+ effects: {
537
+ 'card-lift': {
538
+ keyframeEffect: {
539
+ name: 'card-lift',
540
+ keyframes: [
541
+ { transform: 'translateY(0px)', boxShadow: '0 2px 4px rgba(0,0,0,0.1)' },
542
+ { transform: 'translateY(-4px)', boxShadow: '0 8px 16px rgba(0,0,0,0.15)' }
543
+ ]
544
+ },
545
+ duration: 200,
546
+ easing: 'ease-out'
547
+ },
548
+ 'image-zoom': {
549
+ keyframeEffect: {
550
+ name: 'image-zoom',
551
+ keyframes: [
552
+ { transform: 'scale(1)' },
553
+ { transform: 'scale(1.05)' }
554
+ ]
555
+ },
556
+ duration: 300,
557
+ easing: 'ease-out'
558
+ },
559
+ 'button-pulse': {
560
+ keyframeEffect: {
561
+ name: 'button-pulse',
562
+ keyframes: [
563
+ { transform: 'scale(1)' },
564
+ { transform: 'scale(1.1)' },
565
+ { transform: 'scale(1)' }
566
+ ]
567
+ },
568
+ duration: 400,
569
+ easing: 'ease-in-out'
570
+ }
571
+ },
572
+
573
+ interactions: [
574
+ // Hover on card image triggers card lift
575
+ {
576
+ key: 'product-card',
577
+ selector: '.card-image', // Trigger area: just the image
578
+ trigger: 'hover',
579
+ effects: [
580
+ {
581
+ key: 'product-card',
582
+ selector: '.card-container', // Effect target: entire card
583
+ effectId: 'card-lift'
584
+ },
585
+ {
586
+ key: 'product-card',
587
+ selector: '.card-image img', // Effect target: image itself
588
+ effectId: 'image-zoom'
589
+ }
590
+ ]
591
+ },
592
+
593
+ // Click on CTA button
594
+ {
595
+ key: 'product-card',
596
+ selector: '.cta-button', // Trigger area: CTA button
597
+ trigger: 'click',
598
+ effects: [
599
+ {
600
+ key: 'product-card',
601
+ selector: '.cta-button', // Effect target: button itself
602
+ effectId: 'button-pulse'
603
+ }
604
+ ]
605
+ }
606
+ ]
607
+ };
608
+ ```
609
+
610
+ ### Navigation Menu with Nested Selectors
611
+
612
+ ```typescript
613
+ const navConfig: InteractConfig = {
614
+ effects: {
615
+ 'dropdown-slide': {
616
+ keyframeEffect: {
617
+ name: 'dropdown-slide',
618
+ keyframes: [
619
+ { opacity: '0', transform: 'translateY(-10px)' },
620
+ { opacity: '1', transform: 'translateY(0)' }
621
+ ]
622
+ },
623
+ duration: 250,
624
+ easing: 'ease-out'
625
+ },
626
+ 'menu-item-highlight': {
627
+ keyframeEffect: {
628
+ name: 'menu-item-highlight',
629
+ keyframes: [
630
+ { backgroundColor: 'transparent' },
631
+ { backgroundColor: 'rgba(0, 123, 255, 0.1)' }
632
+ ]
633
+ },
634
+ duration: 150,
635
+ easing: 'ease-out'
636
+ }
637
+ },
638
+
639
+ interactions: [
640
+ // Hover on main menu items
641
+ {
642
+ key: 'main-nav',
643
+ listContainer: 'nav',
644
+ selector: '.nav-item[data-has-dropdown]', // Only items with dropdowns
645
+ trigger: 'hover',
646
+ effects: [
647
+ {
648
+ key: 'main-nav',
649
+ listContainer: 'nav',
650
+ selector: '.nav-item[data-has-dropdown] .dropdown-menu',
651
+ effectId: 'dropdown-slide'
652
+ },
653
+ {
654
+ key: 'main-nav',
655
+ listContainer: 'nav',
656
+ selector: '.nav-item[data-has-dropdown]',
657
+ effectId: 'menu-item-highlight'
658
+ }
659
+ ]
660
+ }
661
+ ]
662
+ };
663
+ ```
664
+
665
+ ### Gallery with Dynamic Item Selection
666
+
667
+ ```typescript
668
+ const galleryConfig: InteractConfig = {
669
+ effects: {
670
+ 'image-overlay': {
671
+ keyframeEffect: {
672
+ name: 'image-overlay',
673
+ keyframes: [
674
+ { opacity: '0' },
675
+ { opacity: '1' }
676
+ ]
677
+ },
678
+ duration: 300,
679
+ easing: 'ease-in-out'
680
+ }
681
+ },
682
+
683
+ interactions: [
684
+ // Gallery items with list container and selector
685
+ {
686
+ key: 'image-gallery',
687
+ listContainer: '.gallery-grid', // Container with multiple items
688
+ selector: '.gallery-item img', // Image within each item
689
+ trigger: 'hover',
690
+ effects: [
691
+ {
692
+ key: 'image-gallery',
693
+ listContainer: '.gallery-grid',
694
+ selector: '.gallery-item .overlay', // Overlay within each item
695
+ effectId: 'image-overlay'
696
+ }
697
+ ]
698
+ }
699
+ ]
700
+ };
701
+ ```
702
+
703
+ ## Best Practices
704
+
705
+ ### Configuration Organization
706
+ 1. **Start simple** - Use inline effects for prototypes
707
+ 2. **Extract reusable effects** as your project grows
708
+ 3. **Group by feature** rather than by type
709
+
710
+ ### Accessibility
711
+ 1. **Use `activate` instead of `click`** for keyboard accessibility (Enter/Space)
712
+ 2. **Use `interest` instead of `hover`** for keyboard accessibility (Focus)
713
+ 3. **Or enable `allowA11yTriggers` globally** to make existing triggers accessible
714
+
715
+ ### Performance Tips
716
+ 1. **Reuse effects** instead of duplicating them
717
+ 2. **Use conditions** to avoid unnecessary animations
718
+ 3. **Lazy load** configurations for large applications
719
+ 4. **Validate in development** to catch errors early
720
+
721
+ ## Next Steps
722
+
723
+ Now that you understand configuration structure:
724
+ - **[Custom Elements](./custom-elements.md)** - Learn about `<interact-element>`
725
+ - **[State Management](./state-management.md)** - Advanced state handling
726
+ - **[Conditions and Media Queries](./conditions-and-media-queries.md)** - Responsive interactions