@wix/interact 1.93.0 → 2.0.0-rc.4

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-BoEj_7uB.js +18 -0
  14. package/dist/index-BoEj_7uB.js.map +1 -0
  15. package/dist/index-DUTdIvfw.mjs +7969 -0
  16. package/dist/index-DUTdIvfw.mjs.map +1 -0
  17. package/dist/tsconfig.build.tsbuildinfo +1 -0
  18. package/dist/types/core/Interact.d.ts +25 -10
  19. package/dist/types/core/Interact.d.ts.map +1 -0
  20. package/dist/types/core/InteractionController.d.ts +24 -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 +31 -12
  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} +117 -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,900 @@
1
+ # Scroll List Animation Rules for @wix/interact
2
+
3
+ These rules help generate scroll-driven list animations using the `@wix/interact` library. List animations encompass sticky containers, sticky items, and their content animations, providing comprehensive patterns for modern scroll-driven list interactions including parallax effects, staggered reveals, and progressive content disclosure.
4
+
5
+ ## Rule 1: Sticky Container List Animations with Named Effects
6
+
7
+ **Use Case**: Animations applied to list containers that are sticky-positioned within their wrapper, using pre-built named effects for smooth scroll-driven transformations (e.g., horizontal sliding galleries, parallax backgrounds, container reveals)
8
+
9
+ **When to Apply**:
10
+ - For sticky container horizontal sliding during scroll
11
+ - When creating parallax container effects
12
+ - For container-level background transformations
13
+ - When using pre-built motion effects for container animations
14
+
15
+ **Pattern**:
16
+ ```typescript
17
+ {
18
+ key: '[CONTAINER_SELECTOR]',
19
+ trigger: 'viewProgress',
20
+ effects: [
21
+ {
22
+ key: '[CONTAINER_KEY]',
23
+ namedEffect: {
24
+ type: '[CONTAINER_NAMED_EFFECT]'
25
+ },
26
+ rangeStart: { name: 'contain', offset: { type: 'percentage', value: [START_PERCENTAGE] } },
27
+ rangeEnd: { name: 'contain', offset: { type: 'percentage', value: [END_PERCENTAGE] } },
28
+ easing: 'linear',
29
+ effectId: '[UNIQUE_EFFECT_ID]'
30
+ }
31
+ ]
32
+ }
33
+ ```
34
+
35
+ **Variables**:
36
+ - `[CONTAINER_KEY]`: Unique identifier for sticky list container
37
+ - `[CONTAINER_NAMED_EFFECT]`: Container-level scroll effects ('BgParallax', 'PanScroll', 'MoveScroll', 'ParallaxScroll') or background effects ('BgPan', 'BgZoom', 'BgFade', 'BgReveal')
38
+ - `[START_PERCENTAGE]`: Start point in contain range (typically 0)
39
+ - `[END_PERCENTAGE]`: End point in contain range (typically 100)
40
+ - `[UNIQUE_EFFECT_ID]`: Optional unique identifier
41
+
42
+ **Example - Horizontal Sliding Gallery Container**:
43
+ ```typescript
44
+ {
45
+ key: 'gallery-container',
46
+ trigger: 'viewProgress',
47
+ effects: [
48
+ {
49
+ key: 'gallery-container',
50
+ namedEffect: {
51
+ type: 'PanScroll'
52
+ },
53
+ rangeStart: { name: 'contain', offset: { type: 'percentage', value: 0 } },
54
+ rangeEnd: { name: 'contain', offset: { type: 'percentage', value: 100 } },
55
+ easing: 'linear',
56
+ effectId: 'gallery-slide'
57
+ }
58
+ ]
59
+ }
60
+ ```
61
+
62
+ **Example - Parallax Container Background**:
63
+ ```typescript
64
+ {
65
+ key: 'sticky-list-wrapper',
66
+ trigger: 'viewProgress',
67
+ effects: [
68
+ {
69
+ key: 'list-background',
70
+ namedEffect: {
71
+ type: 'BgParallax'
72
+ },
73
+ rangeStart: { name: 'contain', offset: { type: 'percentage', value: 0 } },
74
+ rangeEnd: { name: 'contain', offset: { type: 'percentage', value: 100 } },
75
+ easing: 'linear',
76
+ effectId: 'bg-parallax'
77
+ }
78
+ ]
79
+ }
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Rule 2: Sticky Item List Animations with Named Effects
85
+
86
+ **Use Case**: Animations on individual list items that are sticky-positioned within the container, using named effects for entrance/exit animations as items enter sticky positioning (e.g., progressive item reveals, item transformation sequences)
87
+
88
+ **When to Apply**:
89
+ - For item entrance/exit animations during sticky phases
90
+ - When creating progressive item reveals
91
+ - For individual item transformations
92
+ - When using pre-built item-level effects
93
+
94
+ **Pattern**:
95
+ ```typescript
96
+ {
97
+ key: '[ITEM_KEY]',
98
+ trigger: 'viewProgress',
99
+ effects: [
100
+ {
101
+ key: '[ITEM_KEY]',
102
+ namedEffect: {
103
+ type: '[ITEM_NAMED_EFFECT]'
104
+ },
105
+ rangeStart: { name: '[RANGE_TYPE]', offset: { type: 'percentage', value: [START_PERCENTAGE] } },
106
+ rangeEnd: { name: '[RANGE_TYPE]', offset: { type: 'percentage', value: [END_PERCENTAGE] } },
107
+ easing: '[EASING_FUNCTION]',
108
+ effectId: '[UNIQUE_EFFECT_ID]'
109
+ }
110
+ ]
111
+ }
112
+ ```
113
+
114
+ **Variables**:
115
+ - `[ITEM_KEY]`: Unique identifier for individual list items
116
+ - `[ITEM_NAMED_EFFECT]`: Item-level scroll effects from @wix/motion scroll animations:
117
+ - **Reveal/Fade**: 'FadeScroll', 'BlurScroll', 'RevealScroll', 'ShapeScroll', 'ShuttersScroll'
118
+ - **Movement**: 'MoveScroll', 'SlideScroll', 'PanScroll', 'SkewPanScroll'
119
+ - **Scale**: 'GrowScroll', 'ShrinkScroll', 'StretchScroll'
120
+ - **Rotation**: 'SpinScroll', 'FlipScroll', 'TiltScroll', 'TurnScroll'
121
+ - **3D**: 'ArcScroll', 'Spin3dScroll'
122
+ - `[RANGE_TYPE]`: 'entry' for entrance, 'exit' for exit, 'contain' for during sticky, 'cover' for full scroll range
123
+ - `[START_PERCENTAGE]`: Range start percentage (0-100)
124
+ - `[END_PERCENTAGE]`: Range end percentage (0-100)
125
+ - `[EASING_FUNCTION]`: Timing function
126
+
127
+ **Example - Item Entrance Reveal**:
128
+ ```typescript
129
+ {
130
+ key: 'list-item',
131
+ trigger: 'viewProgress',
132
+ effects: [
133
+ {
134
+ key: 'list-item',
135
+ namedEffect: {
136
+ type: 'RevealScroll',
137
+ direction: 'bottom'
138
+ },
139
+ rangeStart: { name: 'entry', offset: { type: 'percentage', value: 0 } },
140
+ rangeEnd: { name: 'entry', offset: { type: 'percentage', value: 60 } },
141
+ easing: 'ease-out',
142
+ effectId: 'item-reveal'
143
+ }
144
+ ]
145
+ }
146
+ ```
147
+
148
+ **Example - Item Scale During Sticky**:
149
+ ```typescript
150
+ {
151
+ key: 'sticky-list-item',
152
+ trigger: 'viewProgress',
153
+ effects: [
154
+ {
155
+ key: 'sticky-list-item',
156
+ namedEffect: {
157
+ type: 'GrowScroll'
158
+ },
159
+ rangeStart: { name: 'contain', offset: { type: 'percentage', value: 0 } },
160
+ rangeEnd: { name: 'contain', offset: { type: 'percentage', value: 50 } },
161
+ easing: 'ease-in-out',
162
+ effectId: 'item-grow'
163
+ }
164
+ ]
165
+ }
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Rule 3: Sticky Item List Content Animations with Named Effects
171
+
172
+ **Use Case**: Animations on content within sticky list items, using named effects with each individual item being the viewProgress trigger (e.g., text reveals within cards, image animations within items, progressive content disclosure)
173
+
174
+ **When to Apply**:
175
+ - For content animations within sticky items
176
+ - When creating staggered content reveals
177
+ - For text/image animations inside list items
178
+ - When coordinating multiple content elements
179
+
180
+ **Pattern**:
181
+ ```typescript
182
+ {
183
+ key: '[ITEM_CONTAINER_SELECTOR]',
184
+ trigger: 'viewProgress',
185
+ effects: [
186
+ {
187
+ key: '[CONTENT_SELECTOR]',
188
+ namedEffect: {
189
+ type: '[CONTENT_NAMED_EFFECT]'
190
+ },
191
+ rangeStart: { name: '[RANGE_TYPE]', offset: { type: 'percentage', value: [START_PERCENTAGE] } },
192
+ rangeEnd: { name: '[RANGE_TYPE]', offset: { type: 'percentage', value: [END_PERCENTAGE] } },
193
+ easing: '[EASING_FUNCTION]',
194
+ effectId: '[UNIQUE_EFFECT_ID]'
195
+ }
196
+ ]
197
+ }
198
+ ```
199
+
200
+ **Variables**:
201
+ - `[ITEM_CONTAINER_SELECTOR]`: CSS selector for the containing list item
202
+ - `[CONTENT_SELECTOR]`: CSS selector for content within the item
203
+ - `[CONTENT_NAMED_EFFECT]`: Content-level scroll effects from @wix/motion:
204
+ - **Opacity/Visibility**: 'FadeScroll', 'BlurScroll'
205
+ - **Reveal**: 'RevealScroll', 'ShapeScroll', 'ShuttersScroll'
206
+ - **3D Transforms**: 'TiltScroll', 'FlipScroll', 'ArcScroll', 'TurnScroll', 'Spin3dScroll'
207
+ - **Movement**: 'MoveScroll', 'SlideScroll'
208
+ - **Scale**: 'GrowScroll', 'ShrinkScroll'
209
+ - Other variables same as Rule 2
210
+
211
+ **Example - Staggered Text Content Reveal**:
212
+ ```typescript
213
+ {
214
+ key: 'list-item-1',
215
+ trigger: 'viewProgress',
216
+ effects: [
217
+ {
218
+ key: 'list-item-1',
219
+ selector: '.content-text',
220
+ namedEffect: {
221
+ type: 'FadeScroll'
222
+ },
223
+ rangeStart: { name: 'entry', offset: { type: 'percentage', value: 20 } },
224
+ rangeEnd: { name: 'entry', offset: { type: 'percentage', value: 80 } },
225
+ easing: 'ease-out',
226
+ effectId: 'text-reveal-1'
227
+ }
228
+ ]
229
+ },
230
+ {
231
+ key: 'list-item-2',
232
+ trigger: 'viewProgress',
233
+ effects: [
234
+ {
235
+ key: 'list-item-2',
236
+ selector: '.content-text',
237
+ namedEffect: {
238
+ type: 'FadeScroll'
239
+ },
240
+ rangeStart: { name: 'entry', offset: { type: 'percentage', value: 20 } },
241
+ rangeEnd: { name: 'entry', offset: { type: 'percentage', value: 80 } },
242
+ easing: 'ease-out',
243
+ effectId: 'text-reveal-2'
244
+ }
245
+ ]
246
+ }
247
+ ```
248
+
249
+ **Example - Image Animation Within List Item**:
250
+ ```typescript
251
+ {
252
+ key: 'product-card',
253
+ trigger: 'viewProgress',
254
+ effects: [
255
+ {
256
+ key: 'product-card',
257
+ selector: ' .hero-image',
258
+ namedEffect: {
259
+ type: 'RevealScroll'
260
+ },
261
+ rangeStart: { name: 'entry', offset: { type: 'percentage', value: 0 } },
262
+ rangeEnd: { name: 'entry', offset: { type: 'percentage', value: 50 } },
263
+ easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
264
+ effectId: 'product-image-reveal'
265
+ }
266
+ ]
267
+ }
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Rule 4: List Container Keyframe Animations
273
+
274
+ **Use Case**: Custom scroll-driven container animations using keyframe effects for precise control over sticky container behaviors (e.g., multi-property container transformations, responsive container animations, complex background effects)
275
+
276
+ **When to Apply**:
277
+ - For custom container effects not available in named effects
278
+ - When combining multiple CSS properties in container animations
279
+ - For responsive container behaviors
280
+ - When creating unique container visual effects
281
+
282
+ **Pattern**:
283
+ ```typescript
284
+ {
285
+ key: '[CONTAINER_SELECTOR]',
286
+ trigger: 'viewProgress',
287
+ effects: [
288
+ {
289
+ key: '[CONTAINER_KEY]',
290
+ keyframeEffect: {
291
+ name: '[UNIQUE_KEYFRAME_EFFECT_NAME]',
292
+ keyframes: [
293
+ { [CSS_PROPERTY_1]: '[START_VALUE_1]', [CSS_PROPERTY_2]: '[START_VALUE_2]', [CSS_PROPERTY_3]: '[START_VALUE_3]' },
294
+ { [CSS_PROPERTY_1]: '[MID_VALUE_1]' },
295
+ { [CSS_PROPERTY_1]: '[END_VALUE_1]', [CSS_PROPERTY_2]: '[END_VALUE_2]', [CSS_PROPERTY_3]: '[END_VALUE_3]' }
296
+ ]
297
+ },
298
+ rangeStart: { name: 'contain', offset: { type: 'percentage', value: [START_PERCENTAGE] } },
299
+ rangeEnd: { name: 'contain', offset: { type: 'percentage', value: [END_PERCENTAGE] } },
300
+ easing: 'linear',
301
+ fill: 'both',
302
+ effectId: '[UNIQUE_EFFECT_ID]'
303
+ }
304
+ ]
305
+ }
306
+ ```
307
+
308
+ **Variables**:
309
+ - `[CONTAINER_KEY]`: Unique identifier for list container
310
+ - `[UNIQUE_KEYFRAME_EFFECT_NAME]`: unique name for the CSS keyframe effect (can equal `[UNIQUE_EFFECT_ID]` if provided)
311
+ - `[CSS_PROPERTY_N]`: CSS property names ('transform', 'filter', 'opacity', 'backgroundColor')
312
+ - `[START/MID/END_VALUE_N]`: Keyframe values for each property
313
+ - Other variables same as Rule 1
314
+
315
+ **Example - Multi-Property Container Animation**:
316
+ ```typescript
317
+ {
318
+ key: 'feature-list-container',
319
+ trigger: 'viewProgress',
320
+ effects: [
321
+ {
322
+ key: 'feature-list-container',
323
+ keyframeEffect: {
324
+ name: 'container-slide',
325
+ keyframes: [
326
+ { transform: 'translateX(0)', filter: 'brightness(1)', backgroundColor: 'rgb(255 255 255 / 0)' },
327
+ { transform: 'translateX(-50%)', filter: 'brightness(1.2)', backgroundColor: 'rgb(255 255 255 / 0.1)' },
328
+ { transform: 'translateX(-100%)', filter: 'brightness(1)', backgroundColor: 'rgb(255 255 255 / 0)' }
329
+ ]
330
+ },
331
+ rangeStart: { name: 'contain', offset: { type: 'percentage', value: 0 } },
332
+ rangeEnd: { name: 'contain', offset: { type: 'percentage', value: 100 } },
333
+ easing: 'linear',
334
+ fill: 'both',
335
+ effectId: 'container-slide'
336
+ }
337
+ ]
338
+ }
339
+ ```
340
+
341
+ **Example - Container Background Transformation**:
342
+ ```typescript
343
+ {
344
+ key: 'gallery-wrapper',
345
+ trigger: 'viewProgress',
346
+ effects: [
347
+ {
348
+ key: 'gallery-background',
349
+ keyframeEffect: {
350
+ name: 'bg-transform',
351
+ keyframes: [
352
+ { transform: 'scale(1.1) rotate(6deg)', opacity: '0.8', filter: 'hue-rotate(30deg)' },
353
+ { transform: 'scale(1) rotate(0deg)', opacity: '1', filter: 'hue-rotate(0deg)' }
354
+ ]
355
+ },
356
+ rangeStart: { name: 'contain', offset: { type: 'percentage', value: 0 } },
357
+ rangeEnd: { name: 'contain', offset: { type: 'percentage', value: 100 } },
358
+ easing: 'linear',
359
+ fill: 'both',
360
+ effectId: 'bg-transform'
361
+ }
362
+ ]
363
+ }
364
+ ```
365
+
366
+ ---
367
+
368
+ ## Rule 5: List Item Keyframe Entrance/Exit Animations
369
+
370
+ **Use Case**: Custom entrance and exit animations for list items using keyframe effects for precise control over item reveals and dismissals (e.g., complex item entrances, item position flow, responsive item animations)
371
+
372
+ **When to Apply**:
373
+ - For complex item entrance effects beyond named effects
374
+ - When creating unique item position flows
375
+ - For multi-stage item animations
376
+ - When coordinating item wrapper with content animations
377
+
378
+ **Pattern**:
379
+ ```typescript
380
+ {
381
+ key: '[ITEM_KEY]',
382
+ trigger: 'viewProgress',
383
+ effects: [
384
+ {
385
+ key: '[ITEM_KEY]',
386
+ keyframeEffect: {
387
+ name: '[UNIQUE_KEYFRAME_EFFECT_NAME]',
388
+ keyframes: [
389
+ { [CSS_PROPERTY_1]: '[START_VALUE_1]', [CSS_PROPERTY_2]: '[START_VALUE_2]' },
390
+ { [CSS_PROPERTY_1]: '[MID_VALUE_1]' },
391
+ { [CSS_PROPERTY_1]: '[END_VALUE_1]', [CSS_PROPERTY_2]: '[END_VALUE_2]' }
392
+ ]
393
+ },
394
+ rangeStart: { name: '[RANGE_TYPE]', offset: { type: 'percentage', value: [START_PERCENTAGE] } },
395
+ rangeEnd: { name: '[RANGE_TYPE]', offset: { type: 'percentage', value: [END_PERCENTAGE] } },
396
+ easing: '[EASING_FUNCTION]',
397
+ fill: 'both',
398
+ effectId: '[UNIQUE_EFFECT_ID]'
399
+ }
400
+ ]
401
+ }
402
+ ```
403
+
404
+ **Variables**:
405
+ - `[ITEM_KEY]`: Unique identifier for individual list items
406
+ - `[RANGE_TYPE]`: 'entry', 'exit', or 'contain' depending on animation phase
407
+ - `[EASING_FUNCTION]`: Easing function to use
408
+ - Other variables same as Rule 4
409
+
410
+ **Example - Complex Item Entrance**:
411
+ ```typescript
412
+ {
413
+ key: 'timeline-item',
414
+ trigger: 'viewProgress',
415
+ effects: [
416
+ {
417
+ key: 'timeline-item',
418
+ keyframeEffect: {
419
+ name: 'timeline-entrance',
420
+ keyframes: [
421
+ { opacity: '0', transform: 'translateY(100px) scale(0.8) rotate(5deg)', filter: 'blur(10px)', boxShadow: '0 0 0 rgb(0 0 0 / 0)' },
422
+ { opacity: '0.5', transform: 'translateY(20px) scale(0.95) rotate(1deg)', filter: 'blur(2px)', boxShadow: '0 10px 20px rgb(0 0 0 / 0.1)' },
423
+ { opacity: '1', transform: 'translateY(0) scale(1) rotate(0deg)', filter: 'blur(0)', boxShadow: '0 20px 40px rgb(0 0 0 / 0.15)' }
424
+ ]
425
+ },
426
+ rangeStart: { name: 'entry', offset: { type: 'percentage', value: 0 } },
427
+ rangeEnd: { name: 'entry', offset: { type: 'percentage', value: 80 } },
428
+ easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
429
+ fill: 'both',
430
+ effectId: 'timeline-entrance'
431
+ }
432
+ ]
433
+ }
434
+ ```
435
+
436
+ **Example - Item Exit Sequence**:
437
+ ```typescript
438
+ {
439
+ key: 'card-item',
440
+ trigger: 'viewProgress',
441
+ effects: [
442
+ {
443
+ key: 'card-item',
444
+ keyframeEffect: {
445
+ name: 'card-exit-6',
446
+ keyframes: [
447
+ { opacity: '1', transform: 'scale(1) rotate(0deg)', filter: 'brightness(1)' },
448
+ { opacity: '0.7', transform: 'scale(0.9) rotate(-2deg)', filter: 'brightness(0.8)' },
449
+ { opacity: '0', transform: 'scale(0.8) rotate(-5deg)', filter: 'brightness(0.6)' }
450
+ ]
451
+ },
452
+ rangeStart: { name: 'exit', offset: { type: 'percentage', value: 20 } },
453
+ rangeEnd: { name: 'exit', offset: { type: 'percentage', value: 100 } },
454
+ easing: 'ease-in',
455
+ fill: 'both',
456
+ effectId: 'card-exit'
457
+ }
458
+ ]
459
+ }
460
+ ```
461
+
462
+ ---
463
+
464
+ ## Rule 6: Staggered List Animations with Custom Timing
465
+
466
+ **Use Case**: Coordinated animations across multiple list items with each individual item used as the viewProgress trigger and custom timing patterns (e.g., wave animations, linear stagger, exponential stagger, reverse stagger)
467
+
468
+ **When to Apply**:
469
+ - For creating wave-like animation propagation
470
+ - When implementing linear or exponential stagger patterns
471
+ - For reverse-order animations (exit effects)
472
+
473
+ **Pattern**:
474
+ ```typescript
475
+ {
476
+ effects: {
477
+ [EFFECT_ID]: {
478
+ [EFFECT_TYPE]: [EFFECT_DEFINITION],
479
+ rangeStart: { name: '[RANGE_TYPE]', offset: { type: 'percentage', value: [START_PERCENTAGE] } },
480
+ rangeEnd: { name: '[RANGE_TYPE]', offset: { type: 'percentage', value: [END_PERCENTAGE] } },
481
+ easing: '[EASING_FUNCTION]'
482
+ }
483
+ },
484
+ interactions: [
485
+ {
486
+ key: '[ITEM_SELECTOR_N]',
487
+ trigger: 'viewProgress',
488
+ effects: [
489
+ {
490
+ effectId: '[EFFECT_ID]'
491
+ }
492
+ ]
493
+ },
494
+ // ... repeat for each item
495
+ ]
496
+ }
497
+ ```
498
+
499
+ **Example - Linear Staggered Card Entrance**:
500
+ ```typescript
501
+ {
502
+ effects: {
503
+ 'card-entrance': {
504
+ namedEffect: {
505
+ type: 'SlideScroll'
506
+ },
507
+ rangeStart: { name: 'entry', offset: { type: 'percentage', value: 0 } },
508
+ rangeEnd: { name: 'entry', offset: { type: 'percentage', value: 60 } },
509
+ easing: 'linear'
510
+ }
511
+ },
512
+ interactions: [
513
+ {
514
+ key: 'card-1',
515
+ trigger: 'viewProgress',
516
+ effects: [
517
+ {
518
+ effectId: 'card-entrance'
519
+ }
520
+ ]
521
+ },
522
+ {
523
+ key: 'card-2',
524
+ trigger: 'viewProgress',
525
+ effects: [
526
+ {
527
+ effectId: 'card-entrance'
528
+ }
529
+ ]
530
+ },
531
+ {
532
+ key: 'card-3',
533
+ trigger: 'viewProgress',
534
+ effects: [
535
+ {
536
+ effectId: 'card-entrance'
537
+ }
538
+ ]
539
+ },
540
+ ]
541
+ }
542
+ ```
543
+
544
+ **Example - Exponential Stagger for Dramatic Effect**:
545
+ ```typescript
546
+ {
547
+ effects: {
548
+ 'feature-entrance': {
549
+ keyframeEffect: {
550
+ name: 'feature-entrance',
551
+ keyframes: [
552
+ { opacity: '0', transform: 'translateY(50px) scale(0.9)' },
553
+ { opacity: '1', transform: 'translateY(0) scale(1)' }
554
+ ]
555
+ },
556
+ rangeStart: { name: 'entry', offset: { type: 'percentage', value: 0 } },
557
+ rangeEnd: { name: 'entry', offset: { type: 'percentage', value: 100 } },
558
+ easing: 'expoOut',
559
+ fill: 'both'
560
+ }
561
+ },
562
+ interactions: [
563
+ {
564
+ key: 'feature-1',
565
+ trigger: 'viewProgress',
566
+ effects: [
567
+ {
568
+ effectId: 'feature-entrance'
569
+ }
570
+ ]
571
+ },
572
+ {
573
+ key: 'feature-2',
574
+ trigger: 'viewProgress',
575
+ effects: [
576
+ {
577
+ effectId: 'feature-entrance'
578
+ }
579
+ ]
580
+ },
581
+ {
582
+ key: 'feature-3',
583
+ trigger: 'viewProgress',
584
+ effects: [
585
+ {
586
+ effectId: 'feature-entrance'
587
+ }
588
+ ]
589
+ },
590
+ ]
591
+ }
592
+ ```
593
+
594
+ ---
595
+
596
+ ## Rule 7: Dynamic Content Animations with Custom Effects
597
+
598
+ **Use Case**: JavaScript-powered list animations with custom effects for complex interactions that require calculations or dynamic content updates (e.g., scroll counters, progress tracking, data visualization, dynamic text updates)
599
+
600
+ **When to Apply**:
601
+ - For animations requiring complex calculations
602
+ - When integrating with data visualization
603
+ - For dynamic content updates based on scroll
604
+ - When creating interactive scroll-driven counters
605
+
606
+ **Pattern**:
607
+ ```typescript
608
+ {
609
+ key: '[LIST_CONTAINER_SELECTOR]',
610
+ trigger: 'viewProgress',
611
+ effects: [
612
+ {
613
+ key: '[DYNAMIC_CONTENT_SELECTOR]',
614
+ customEffect: (element, progress, params) => {
615
+ // progress is 0-1 representing scroll position within range
616
+ [CUSTOM_CALCULATION_LOGIC]
617
+ [DYNAMIC_CONTENT_UPDATE]
618
+ [VISUAL_PROPERTY_UPDATES]
619
+ },
620
+ rangeStart: { name: '[RANGE_TYPE]', offset: { type: 'percentage', value: [START_PERCENTAGE] } },
621
+ rangeEnd: { name: '[RANGE_TYPE]', offset: { type: 'percentage', value: [END_PERCENTAGE] } },
622
+ fill: 'both',
623
+ effectId: '[UNIQUE_EFFECT_ID]'
624
+ }
625
+ ]
626
+ }
627
+ ```
628
+
629
+ **Variables**:
630
+ - `[LIST_CONTAINER_KEY]`: Unique identifier for list or section containing dynamic content
631
+ - `[DYNAMIC_CONTENT_KEY]`: Unique identifier for elements that will be dynamically updated
632
+ - `[CUSTOM_CALCULATION_LOGIC]`: JavaScript calculations based on progress
633
+ - `[DYNAMIC_CONTENT_UPDATE]`: Code to update element content
634
+ - `[VISUAL_PROPERTY_UPDATES]`: Code to update visual properties
635
+
636
+ **Example - Scroll-Driven Counter in List**:
637
+ ```typescript
638
+ {
639
+ key: 'stats-list-container',
640
+ trigger: 'viewProgress',
641
+ effects: [
642
+ {
643
+ key: 'stat-counter',
644
+ customEffect: (element, progress) => {
645
+ const targetValue = parseInt(element.dataset.targetValue) || 100;
646
+ const currentValue = Math.floor(targetValue * progress);
647
+ const percentage = Math.floor(progress * 100);
648
+
649
+ // Update counter text
650
+ element.textContent = currentValue.toLocaleString();
651
+
652
+ // Update visual properties based on progress
653
+ element.style.color = `hsl(${progress * 120}, 70%, 50%)`; // Green to red progression
654
+ element.style.transform = `scale(${0.8 + progress * 0.2})`; // Subtle scale effect
655
+
656
+ // Update progress bar if exists
657
+ const progressBar = element.querySelector('.progress-bar');
658
+ if (progressBar) {
659
+ progressBar.style.width = `${percentage}%`;
660
+ }
661
+ },
662
+ rangeStart: { name: 'entry', offset: { type: 'percentage', value: 0 } },
663
+ rangeEnd: { name: 'exit', offset: { type: 'percentage', value: 100 } },
664
+ fill: 'both',
665
+ effectId: 'stats-counter'
666
+ }
667
+ ]
668
+ }
669
+ ```
670
+
671
+ **Example - Interactive List Progress Tracking**:
672
+ ```typescript
673
+ {
674
+ key: 'task-list',
675
+ trigger: 'viewProgress',
676
+ effects: [
677
+ {
678
+ key: 'task-item',
679
+ customEffect: (element, progress) => {
680
+ const items = element.closest('interact-element')?.querySelectorAll('.task-item') || [];
681
+ const totalItems = items.length;
682
+ const elementIndex = Array.from(items).indexOf(element);
683
+
684
+ // Calculate staggered progress for each item
685
+ const itemStartProgress = elementIndex / totalItems;
686
+ const itemEndProgress = (elementIndex + 1) / totalItems;
687
+
688
+ // Calculate individual item progress
689
+ let itemProgress = 0;
690
+ if (progress > itemStartProgress) {
691
+ itemProgress = Math.min(1, (progress - itemStartProgress) / (itemEndProgress - itemStartProgress));
692
+ }
693
+
694
+ // Update visual state
695
+ const checkbox = element.querySelector('.task-checkbox');
696
+ const taskText = element.querySelector('.task-text');
697
+
698
+ if (itemProgress > 0.5) {
699
+ element.classList.add('active');
700
+ checkbox.style.transform = `scale(${0.8 + itemProgress * 0.4})`;
701
+ checkbox.style.opacity = itemProgress;
702
+ }
703
+
704
+ if (itemProgress > 0.8) {
705
+ element.classList.add('completed');
706
+ taskText.style.textDecoration = 'line-through';
707
+ taskText.style.opacity = '0.7';
708
+ }
709
+
710
+ // Update overall progress indicator
711
+ const progressIndicator = document.querySelector('#overall-progress');
712
+ if (progressIndicator && elementIndex === 0) {
713
+ progressIndicator.style.width = `${progress * 100}%`;
714
+ progressIndicator.textContent = `${Math.floor(progress * 100)}% Complete`;
715
+ }
716
+ },
717
+ rangeStart: { name: 'cover', offset: { type: 'percentage', value: 0 } },
718
+ rangeEnd: { name: 'cover', offset: { type: 'percentage', value: 100 } },
719
+ fill: 'both',
720
+ effectId: 'task-progress'
721
+ }
722
+ ]
723
+ }
724
+ ```
725
+
726
+ ---
727
+
728
+ ## Advanced Patterns and Combinations
729
+
730
+ ### Multi-Layer List Coordination
731
+ Coordinating container, items, and content simultaneously:
732
+
733
+ ```typescript
734
+ {
735
+ key: 'complex-list-section',
736
+ trigger: 'viewProgress',
737
+ effects: [
738
+ // Background layer
739
+ {
740
+ key: 'list-background',
741
+ keyframeEffect: {
742
+ name: 'background-parallax',
743
+ keyframes: [
744
+ { transform: 'scale(1.1) translateY(0)', filter: 'blur(0)' },
745
+ { transform: 'scale(1) translateY(-50px)', filter: 'blur(2px)' }
746
+ ]
747
+ },
748
+ rangeStart: { name: 'cover', offset: { type: 'percentage', value: 0 } },
749
+ rangeEnd: { name: 'cover', offset: { type: 'percentage', value: 100 } },
750
+ easing: 'linear',
751
+ fill: 'both'
752
+ },
753
+ // Container layer
754
+ {
755
+ key: 'list-container',
756
+ keyframeEffect: {
757
+ name: 'container-slide',
758
+ keyframes: [
759
+ { transform: 'translateX(0)' },
760
+ { transform: 'translateX(-50%)' }
761
+ ]
762
+ },
763
+ rangeStart: { name: 'contain', offset: { type: 'percentage', value: 0 } },
764
+ rangeEnd: { name: 'contain', offset: { type: 'percentage', value: 100 } },
765
+ easing: 'linear',
766
+ fill: 'both'
767
+ },
768
+ // Foreground decorations
769
+ {
770
+ key: 'list-decorations',
771
+ keyframeEffect: {
772
+ name: 'decorations-parallax',
773
+ keyframes: [
774
+ { transform: 'translateY(0)', opacity: '0.8' },
775
+ { transform: 'translateY(-100px)', opacity: '1' }
776
+ ]
777
+ },
778
+ rangeStart: { name: 'cover', offset: { type: 'percentage', value: 0 } },
779
+ rangeEnd: { name: 'cover', offset: { type: 'percentage', value: 100 } },
780
+ easing: 'linear',
781
+ fill: 'both'
782
+ }
783
+ ]
784
+ }
785
+ ```
786
+
787
+ ### Responsive List Animations
788
+ Adaptive patterns based on screen size and device capabilities:
789
+
790
+ ```typescript
791
+ // Desktop version with complex effects
792
+ {
793
+ key: 'responsive-list',
794
+ trigger: 'viewProgress',
795
+ conditions: ['desktop-only', 'prefers-motion'],
796
+ effects: [
797
+ {
798
+ key: 'list-item',
799
+ keyframeEffect: {
800
+ name: 'list-item-complex',
801
+ keyframes: [
802
+ { transform: 'translateY(-20px) rotateY(5deg)', boxShadow: '0 20px 40px rgb(0 0 0 / 0.15)' },
803
+ { transform: 'translateY(0) rotateY(0deg)', boxShadow: '0 0 0 rgb(0 0 0 / 0)' }
804
+ ]
805
+ },
806
+ rangeStart: { name: 'entry', offset: { type: 'percentage', value: 0 } },
807
+ rangeEnd: { name: 'entry', offset: { type: 'percentage', value: 80 } },
808
+ easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
809
+ fill: 'both'
810
+ }
811
+ ]
812
+ },
813
+ // Mobile version with simplified effects
814
+ {
815
+ key: 'responsive-list',
816
+ trigger: 'viewProgress',
817
+ conditions: ['mobile-only'],
818
+ effects: [
819
+ {
820
+ key: 'list-item',
821
+ keyframeEffect: {
822
+ name: 'list-item-simple',
823
+ keyframes: [
824
+ { opacity: '0', transform: 'translateY(30px)' },
825
+ { opacity: '1', transform: 'translateY(0)' }
826
+ ]
827
+ },
828
+ rangeStart: { name: 'entry', offset: { type: 'percentage', value: 0 } },
829
+ rangeEnd: { name: 'entry', offset: { type: 'percentage', value: 60 } },
830
+ easing: 'ease-out',
831
+ fill: 'both'
832
+ }
833
+ ]
834
+ }
835
+ ```
836
+
837
+ ---
838
+
839
+ ## Best Practices for List Scroll Animations
840
+
841
+ ### Performance Guidelines
842
+ 1. **Use hardware-accelerated properties**: `transform`, `opacity`, `filter` for smooth animations
843
+ 2. **Limit concurrent animations**: Avoid animating too many items simultaneously
844
+ 3. **Use position:sticky for scrolling effects**: Animate elements while they're stuck in position and not scrolling with the page
845
+ 4. **Consider `will-change` property**: When doing complex style animations inside custom effects that the browser can not predict automatically
846
+
847
+ ### Range Selection Guidelines
848
+ 1. **Container animations**: Use `contain` range for sticky container effects
849
+ 2. **Item entrance**: Use `entry` range (0-60%) for natural reveals
850
+ 3. **Item exit**: Use `exit` range (20-100%) for smooth dismissals
851
+ 4. **Content coordination**: Use same timeline with `cover`/`contain` range and staggered offsets, or use a different timeline per item with same range and offsets
852
+
853
+ ### User Experience Guidelines
854
+ 1. **Keep animations subtle**: Avoid overwhelming users with excessive motion
855
+ 2. **Maintain content readability**: Ensure text remains legible during animations
856
+ 3. **Provide reduced motion alternatives**: Respect `prefers-reduced-motion` setting
857
+
858
+ ### Accessibility Considerations
859
+ 1. **Respect motion preferences**: Include `prefers-motion` conditions
860
+ 2. **Provide keyboard navigation**: Ensure list remains navigable during animations
861
+ 3. **Maintain focus management**: Don't break focus states with animations
862
+ 4. **Ensure content accessibility**: Keep content accessible throughout animation states
863
+
864
+ ### Common Use Cases by Pattern
865
+
866
+ **Sticky Container (Rule 1)**:
867
+ - Horizontal scrolling galleries
868
+ - Timeline navigation
869
+ - Product showcase carousels
870
+ - Feature comparison tables
871
+
872
+ **Sticky Items (Rule 2)**:
873
+ - Progressive story reveals
874
+ - Step-by-step processes
875
+ - Card-based layouts
876
+ - Interactive portfolios
877
+
878
+ **Content Animations (Rule 3)**:
879
+ - Text reveals within cards
880
+ - Image animations in galleries
881
+ - Icon animations in feature lists
882
+ - Progressive data visualization
883
+
884
+ **Keyframe Effects (Rules 4-5)**:
885
+ - Complex brand animations
886
+ - Multi-property transformations
887
+ - Responsive design adaptations
888
+ - Advanced visual effects
889
+
890
+ **Staggered Animations (Rule 6)**:
891
+ - Team member introductions
892
+ - Product grid reveals
893
+ - Feature list presentations
894
+ - Testimonial carousels
895
+
896
+ **Dynamic Content (Rule 7)**:
897
+ - Statistics counters
898
+ - Progress tracking
899
+ - Data visualization
900
+ - Interactive dashboards