@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.
- package/dist/cjs/index.js +2 -23
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react.js +15 -0
- package/dist/cjs/react.js.map +1 -0
- package/dist/cjs/web.js +2 -0
- package/dist/cjs/web.js.map +1 -0
- package/dist/es/index.js +8 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/react.js +650 -0
- package/dist/es/react.js.map +1 -0
- package/dist/es/web.js +56 -0
- package/dist/es/web.js.map +1 -0
- package/dist/index-C8QxOkui.mjs +7940 -0
- package/dist/index-C8QxOkui.mjs.map +1 -0
- package/dist/index-DEPRHaUt.js +18 -0
- package/dist/index-DEPRHaUt.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/types/core/Interact.d.ts +17 -7
- package/dist/types/core/Interact.d.ts.map +1 -0
- package/dist/types/core/InteractionController.d.ts +19 -0
- package/dist/types/core/InteractionController.d.ts.map +1 -0
- package/dist/types/core/add.d.ts +4 -3
- package/dist/types/core/add.d.ts.map +1 -0
- package/dist/types/core/css.d.ts +3 -0
- package/dist/types/core/css.d.ts.map +1 -0
- package/dist/types/core/remove.d.ts +3 -1
- package/dist/types/core/remove.d.ts.map +1 -0
- package/dist/types/core/utilities.d.ts +1 -0
- package/dist/types/core/utilities.d.ts.map +1 -0
- package/dist/types/dom/api.d.ts +3 -0
- package/dist/types/dom/api.d.ts.map +1 -0
- package/dist/types/handlers/animationEnd.d.ts +3 -2
- package/dist/types/handlers/animationEnd.d.ts.map +1 -0
- package/dist/types/handlers/click.d.ts +3 -2
- package/dist/types/handlers/click.d.ts.map +1 -0
- package/dist/types/handlers/hover.d.ts +3 -2
- package/dist/types/handlers/hover.d.ts.map +1 -0
- package/dist/types/handlers/index.d.ts +1 -0
- package/dist/types/handlers/index.d.ts.map +1 -0
- package/dist/types/handlers/pointerMove.d.ts +3 -2
- package/dist/types/handlers/pointerMove.d.ts.map +1 -0
- package/dist/types/handlers/utilities.d.ts +1 -0
- package/dist/types/handlers/utilities.d.ts.map +1 -0
- package/dist/types/handlers/viewEnter.d.ts +3 -2
- package/dist/types/handlers/viewEnter.d.ts.map +1 -0
- package/dist/types/handlers/viewProgress.d.ts +4 -3
- package/dist/types/handlers/viewProgress.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/react/Interaction.d.ts +10 -0
- package/dist/types/react/Interaction.d.ts.map +1 -0
- package/dist/types/react/index.d.ts +8 -0
- package/dist/types/react/index.d.ts.map +1 -0
- package/dist/types/react/interactRef.d.ts +3 -0
- package/dist/types/react/interactRef.d.ts.map +1 -0
- package/dist/types/types.d.ts +23 -10
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/utils.d.ts +2 -1
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/{InteractElement.d.ts → web/InteractElement.d.ts} +115 -77
- package/dist/types/web/InteractElement.d.ts.map +1 -0
- package/dist/types/web/defineInteractElement.d.ts +2 -0
- package/dist/types/web/defineInteractElement.d.ts.map +1 -0
- package/dist/types/web/index.d.ts +6 -0
- package/dist/types/web/index.d.ts.map +1 -0
- package/docs/README.md +211 -0
- package/docs/advanced/README.md +164 -0
- package/docs/api/README.md +157 -0
- package/docs/api/element-selection.md +607 -0
- package/docs/api/functions.md +638 -0
- package/docs/api/interact-class.md +663 -0
- package/docs/api/interact-element.md +565 -0
- package/docs/api/interaction-controller.md +450 -0
- package/docs/api/types.md +957 -0
- package/docs/examples/README.md +212 -0
- package/docs/examples/click-interactions.md +977 -0
- package/docs/examples/entrance-animations.md +935 -0
- package/docs/examples/hover-effects.md +930 -0
- package/docs/examples/list-patterns.md +737 -0
- package/docs/guides/README.md +49 -0
- package/docs/guides/conditions-and-media-queries.md +1068 -0
- package/docs/guides/configuration-structure.md +726 -0
- package/docs/guides/custom-elements.md +327 -0
- package/docs/guides/effects-and-animations.md +634 -0
- package/docs/guides/getting-started.md +379 -0
- package/docs/guides/lists-and-dynamic-content.md +713 -0
- package/docs/guides/state-management.md +747 -0
- package/docs/guides/understanding-triggers.md +690 -0
- package/docs/integration/README.md +264 -0
- package/docs/integration/react.md +605 -0
- package/package.json +73 -56
- package/rules/Integration.md +255 -0
- package/rules/click-rules.md +533 -0
- package/rules/full-lean.md +346 -0
- package/rules/hover-rules.md +593 -0
- package/rules/pointermove-rules.md +1341 -0
- package/rules/scroll-list-rules.md +900 -0
- package/rules/viewenter-rules.md +1015 -0
- package/rules/viewprogress-rules.md +1044 -0
- package/dist/cjs/InteractElement.js +0 -163
- package/dist/cjs/InteractElement.js.map +0 -1
- package/dist/cjs/__tests__/interact.spec.js +0 -2094
- package/dist/cjs/__tests__/interact.spec.js.map +0 -1
- package/dist/cjs/__tests__/viewEnter.spec.js +0 -207
- package/dist/cjs/__tests__/viewEnter.spec.js.map +0 -1
- package/dist/cjs/core/Interact.js +0 -257
- package/dist/cjs/core/Interact.js.map +0 -1
- package/dist/cjs/core/add.js +0 -250
- package/dist/cjs/core/add.js.map +0 -1
- package/dist/cjs/core/remove.js +0 -35
- package/dist/cjs/core/remove.js.map +0 -1
- package/dist/cjs/core/utilities.js +0 -16
- package/dist/cjs/core/utilities.js.map +0 -1
- package/dist/cjs/external-types.d.js +0 -2
- package/dist/cjs/external-types.d.js.map +0 -1
- package/dist/cjs/handlers/animationEnd.js +0 -37
- package/dist/cjs/handlers/animationEnd.js.map +0 -1
- package/dist/cjs/handlers/click.js +0 -122
- package/dist/cjs/handlers/click.js.map +0 -1
- package/dist/cjs/handlers/hover.js +0 -147
- package/dist/cjs/handlers/hover.js.map +0 -1
- package/dist/cjs/handlers/index.js +0 -32
- package/dist/cjs/handlers/index.js.map +0 -1
- package/dist/cjs/handlers/pointerMove.js +0 -49
- package/dist/cjs/handlers/pointerMove.js.map +0 -1
- package/dist/cjs/handlers/utilities.js +0 -49
- package/dist/cjs/handlers/utilities.js.map +0 -1
- package/dist/cjs/handlers/viewEnter.js +0 -131
- package/dist/cjs/handlers/viewEnter.js.map +0 -1
- package/dist/cjs/handlers/viewProgress.js +0 -79
- package/dist/cjs/handlers/viewProgress.js.map +0 -1
- package/dist/cjs/test-types.d.js +0 -2
- package/dist/cjs/test-types.d.js.map +0 -1
- package/dist/cjs/types.js +0 -2
- package/dist/cjs/types.js.map +0 -1
- package/dist/cjs/utils.js +0 -98
- package/dist/cjs/utils.js.map +0 -1
- package/dist/esm/InteractElement.js +0 -157
- package/dist/esm/InteractElement.js.map +0 -1
- package/dist/esm/__tests__/interact.spec.js +0 -2102
- package/dist/esm/__tests__/interact.spec.js.map +0 -1
- package/dist/esm/__tests__/viewEnter.spec.js +0 -210
- package/dist/esm/__tests__/viewEnter.spec.js.map +0 -1
- package/dist/esm/core/Interact.js +0 -251
- package/dist/esm/core/Interact.js.map +0 -1
- package/dist/esm/core/add.js +0 -245
- package/dist/esm/core/add.js.map +0 -1
- package/dist/esm/core/remove.js +0 -30
- package/dist/esm/core/remove.js.map +0 -1
- package/dist/esm/core/utilities.js +0 -14
- package/dist/esm/core/utilities.js.map +0 -1
- package/dist/esm/external-types.d.js +0 -2
- package/dist/esm/external-types.d.js.map +0 -1
- package/dist/esm/handlers/animationEnd.js +0 -33
- package/dist/esm/handlers/animationEnd.js.map +0 -1
- package/dist/esm/handlers/click.js +0 -122
- package/dist/esm/handlers/click.js.map +0 -1
- package/dist/esm/handlers/hover.js +0 -147
- package/dist/esm/handlers/hover.js.map +0 -1
- package/dist/esm/handlers/index.js +0 -27
- package/dist/esm/handlers/index.js.map +0 -1
- package/dist/esm/handlers/pointerMove.js +0 -48
- package/dist/esm/handlers/pointerMove.js.map +0 -1
- package/dist/esm/handlers/utilities.js +0 -43
- package/dist/esm/handlers/utilities.js.map +0 -1
- package/dist/esm/handlers/viewEnter.js +0 -133
- package/dist/esm/handlers/viewEnter.js.map +0 -1
- package/dist/esm/handlers/viewProgress.js +0 -75
- package/dist/esm/handlers/viewProgress.js.map +0 -1
- package/dist/esm/index.js +0 -5
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/test-types.d.js +0 -2
- package/dist/esm/test-types.d.js.map +0 -1
- package/dist/esm/types.js +0 -2
- package/dist/esm/types.js.map +0 -1
- package/dist/esm/utils.js +0 -92
- package/dist/esm/utils.js.map +0 -1
- package/dist/types/__tests__/interact.spec.d.ts +0 -1
- package/dist/types/__tests__/viewEnter.spec.d.ts +0 -0
|
@@ -0,0 +1,713 @@
|
|
|
1
|
+
# Lists and Dynamic Content
|
|
2
|
+
|
|
3
|
+
Working with dynamic lists is one of the most powerful features of `@wix/interact`. This guide explains how to create animations for lists, handle dynamic content, and optimize performance for large datasets.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
When working with lists, you have two main approaches:
|
|
8
|
+
|
|
9
|
+
1. **Individual Elements** - Treat each list item as a separate interaction
|
|
10
|
+
2. **List Container** - Use `listContainer` to target all items in a collection
|
|
11
|
+
|
|
12
|
+
The `listContainer` approach is **highly recommended** for:
|
|
13
|
+
- Dynamic lists that change (items added/removed)
|
|
14
|
+
- Large lists (100+ items)
|
|
15
|
+
- Staggered animations
|
|
16
|
+
- Consistent behavior across all items
|
|
17
|
+
|
|
18
|
+
## Basic List Animations
|
|
19
|
+
|
|
20
|
+
### Using listContainer
|
|
21
|
+
|
|
22
|
+
The `listContainer` property tells `@wix/interact` to:
|
|
23
|
+
1. Find the container element
|
|
24
|
+
2. Automatically track all its child elements
|
|
25
|
+
3. Apply interactions to each child
|
|
26
|
+
4. Watch for DOM additions/removals of direct children
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { Interact } from '@wix/interact';
|
|
30
|
+
|
|
31
|
+
const config = {
|
|
32
|
+
interactions: [{
|
|
33
|
+
key: 'product-grid',
|
|
34
|
+
listContainer: '.grid', // Container selector
|
|
35
|
+
trigger: 'viewEnter',
|
|
36
|
+
params: { type: 'once', threshold: 0.1 },
|
|
37
|
+
effects: [{
|
|
38
|
+
key: 'product-grid',
|
|
39
|
+
listContainer: '.grid', // Target the same container
|
|
40
|
+
keyframeEffect: {
|
|
41
|
+
name: 'fade-slide',
|
|
42
|
+
keyframes: [
|
|
43
|
+
{ opacity: '0', transform: 'translateY(20px)' },
|
|
44
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
duration: 600,
|
|
48
|
+
easing: 'ease-out'
|
|
49
|
+
}]
|
|
50
|
+
}]
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
Interact.create(config);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```html
|
|
57
|
+
<interact-element data-interact-key="product-grid">
|
|
58
|
+
<div class="grid">
|
|
59
|
+
<div class="item">Product 1</div>
|
|
60
|
+
<div class="item">Product 2</div>
|
|
61
|
+
<div class="item">Product 3</div>
|
|
62
|
+
<!-- More items... -->
|
|
63
|
+
</div>
|
|
64
|
+
</interact-element>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Combining listContainer with selector
|
|
68
|
+
|
|
69
|
+
Use both properties to target specific elements within each list item:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
{
|
|
73
|
+
key: 'gallery',
|
|
74
|
+
listContainer: '.gallery-grid', // Container with items
|
|
75
|
+
selector: '.gallery-item img', // Image in each item
|
|
76
|
+
trigger: 'hover',
|
|
77
|
+
effects: [{
|
|
78
|
+
key: 'gallery',
|
|
79
|
+
listContainer: '.gallery-grid',
|
|
80
|
+
selector: '.gallery-item .overlay', // Different target within item
|
|
81
|
+
keyframeEffect: {
|
|
82
|
+
name: 'reveal-overlay',
|
|
83
|
+
keyframes: [
|
|
84
|
+
{ opacity: '0', transform: 'translateY(100%)' },
|
|
85
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
duration: 300
|
|
89
|
+
}]
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```html
|
|
94
|
+
<interact-element data-interact-key="gallery">
|
|
95
|
+
<div class="gallery-grid">
|
|
96
|
+
<div class="gallery-item">
|
|
97
|
+
<img src="image1.jpg" />
|
|
98
|
+
<div class="overlay">View Details</div>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="gallery-item">
|
|
101
|
+
<img src="image2.jpg" />
|
|
102
|
+
<div class="overlay">View Details</div>
|
|
103
|
+
</div>
|
|
104
|
+
<!-- More items... -->
|
|
105
|
+
</div>
|
|
106
|
+
</interact-element>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Staggered Animations
|
|
110
|
+
|
|
111
|
+
Create sequential entrance animations for list items using delays:
|
|
112
|
+
|
|
113
|
+
### CSS-Based Stagger
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
{
|
|
117
|
+
key: 'feature-list',
|
|
118
|
+
listContainer: '.features',
|
|
119
|
+
trigger: 'viewEnter',
|
|
120
|
+
params: { type: 'once', threshold: 0.2 },
|
|
121
|
+
effects: [{
|
|
122
|
+
key: 'feature-list',
|
|
123
|
+
listContainer: '.features',
|
|
124
|
+
keyframeEffect: {
|
|
125
|
+
name: 'stagger-fade',
|
|
126
|
+
keyframes: [
|
|
127
|
+
{ opacity: '0', transform: 'translateX(-30px)' },
|
|
128
|
+
{ opacity: '1', transform: 'translateX(0)' }
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
duration: 500,
|
|
132
|
+
easing: 'ease-out'
|
|
133
|
+
}]
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```css
|
|
138
|
+
/* Add stagger delay via CSS */
|
|
139
|
+
.features > *:nth-child(1) { animation-delay: 0ms; }
|
|
140
|
+
.features > *:nth-child(2) { animation-delay: 100ms; }
|
|
141
|
+
.features > *:nth-child(3) { animation-delay: 200ms; }
|
|
142
|
+
.features > *:nth-child(4) { animation-delay: 300ms; }
|
|
143
|
+
.features > *:nth-child(5) { animation-delay: 400ms; }
|
|
144
|
+
|
|
145
|
+
/* Or use a formula for unlimited items */
|
|
146
|
+
.features > * {
|
|
147
|
+
animation-delay: calc(var(--stagger-index, 0) * 100ms);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Programmatic Stagger
|
|
152
|
+
|
|
153
|
+
For more control, use data attributes:
|
|
154
|
+
|
|
155
|
+
```html
|
|
156
|
+
<interact-element data-interact-key="animated-list">
|
|
157
|
+
<ul class="list">
|
|
158
|
+
<li data-delay="0">Item 1</li>
|
|
159
|
+
<li data-delay="100">Item 2</li>
|
|
160
|
+
<li data-delay="200">Item 3</li>
|
|
161
|
+
</ul>
|
|
162
|
+
</interact-element>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
{
|
|
167
|
+
key: 'animated-list',
|
|
168
|
+
listContainer: '.list',
|
|
169
|
+
trigger: 'viewEnter',
|
|
170
|
+
effects: [{
|
|
171
|
+
key: 'animated-list',
|
|
172
|
+
listContainer: '.list',
|
|
173
|
+
customEffect: (element) => {
|
|
174
|
+
const delay = parseInt(element.dataset.delay || '0');
|
|
175
|
+
return element.animate([
|
|
176
|
+
{ opacity: 0, transform: 'scale(0.8)' },
|
|
177
|
+
{ opacity: 1, transform: 'scale(1)' }
|
|
178
|
+
], {
|
|
179
|
+
duration: 400,
|
|
180
|
+
delay,
|
|
181
|
+
fill: 'both',
|
|
182
|
+
easing: 'cubic-bezier(0.16, 1, 0.3, 1)'
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}]
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Dynamic List Management
|
|
190
|
+
|
|
191
|
+
### Automatic Mutation Tracking
|
|
192
|
+
|
|
193
|
+
`@wix/interact` automatically watches for changes in list containers:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// Configuration
|
|
197
|
+
const config = {
|
|
198
|
+
interactions: [{
|
|
199
|
+
key: 'todo-list',
|
|
200
|
+
listContainer: '.todos',
|
|
201
|
+
trigger: 'viewEnter',
|
|
202
|
+
effects: [{
|
|
203
|
+
key: 'todo-list',
|
|
204
|
+
listContainer: '.todos',
|
|
205
|
+
keyframeEffect: {
|
|
206
|
+
name: 'slide-in',
|
|
207
|
+
keyframes: [
|
|
208
|
+
{ opacity: '0', transform: 'translateX(-20px)' },
|
|
209
|
+
{ opacity: '1', transform: 'translateX(0)' }
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
duration: 300
|
|
213
|
+
}]
|
|
214
|
+
}]
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
Interact.create(config);
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
// Add new item - animation applies automatically
|
|
222
|
+
function addTodoItem(text) {
|
|
223
|
+
const todoList = document.querySelector('.todos');
|
|
224
|
+
const newItem = document.createElement('div');
|
|
225
|
+
newItem.className = 'todo-item';
|
|
226
|
+
newItem.textContent = text;
|
|
227
|
+
|
|
228
|
+
todoList.appendChild(newItem); // Automatically triggers animation
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Remove item - cleanup happens automatically
|
|
232
|
+
function removeTodoItem(item) {
|
|
233
|
+
item.remove(); // Automatically cleaned up
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Manual List Item Management
|
|
238
|
+
|
|
239
|
+
For advanced use cases, use the list management API:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import { addListItems, removeListItems } from '@wix/interact';
|
|
243
|
+
|
|
244
|
+
// Add specific items
|
|
245
|
+
function addItems(containerElement, items) {
|
|
246
|
+
const root = document.querySelector('interact-element[data-interact-key="my-list"]');
|
|
247
|
+
addListItems(root, 'my-list', '.list-container', items);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Remove specific items
|
|
251
|
+
function removeItems(items) {
|
|
252
|
+
removeListItems(items);
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### watchChildList Method
|
|
257
|
+
|
|
258
|
+
The custom element's `watchChildList` method sets up mutation observers:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
const element = document.querySelector('interact-element');
|
|
262
|
+
|
|
263
|
+
// Start watching for changes in a container
|
|
264
|
+
element.watchChildList('.dynamic-list');
|
|
265
|
+
|
|
266
|
+
// Now any DOM changes in .dynamic-list will be tracked
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**How it works:**
|
|
270
|
+
1. Creates a `MutationObserver` for the container
|
|
271
|
+
2. Tracks `childList` mutations (additions/removals)
|
|
272
|
+
3. Automatically calls `addListItems` for new elements
|
|
273
|
+
4. Automatically calls `removeListItems` for removed elements
|
|
274
|
+
5. Applies interactions to new items
|
|
275
|
+
6. Cleans up removed items
|
|
276
|
+
|
|
277
|
+
## List Animation Patterns
|
|
278
|
+
|
|
279
|
+
### Entrance Animations
|
|
280
|
+
|
|
281
|
+
#### Fade In Sequence
|
|
282
|
+
```typescript
|
|
283
|
+
{
|
|
284
|
+
key: 'cards',
|
|
285
|
+
listContainer: '.card-grid',
|
|
286
|
+
trigger: 'viewEnter',
|
|
287
|
+
params: { type: 'once', threshold: 0.1 },
|
|
288
|
+
effects: [{
|
|
289
|
+
key: 'cards',
|
|
290
|
+
listContainer: '.card-grid',
|
|
291
|
+
keyframeEffect: {
|
|
292
|
+
name: 'fade-in',
|
|
293
|
+
keyframes: [
|
|
294
|
+
{ opacity: '0' },
|
|
295
|
+
{ opacity: '1' }
|
|
296
|
+
]
|
|
297
|
+
},
|
|
298
|
+
duration: 600,
|
|
299
|
+
easing: 'ease-out'
|
|
300
|
+
}]
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
#### Slide Up Cascade
|
|
305
|
+
```typescript
|
|
306
|
+
{
|
|
307
|
+
key: 'features',
|
|
308
|
+
listContainer: '.feature-list',
|
|
309
|
+
trigger: 'viewEnter',
|
|
310
|
+
params: { type: 'once', threshold: 0.2 },
|
|
311
|
+
effects: [{
|
|
312
|
+
key: 'features',
|
|
313
|
+
listContainer: '.feature-list',
|
|
314
|
+
keyframeEffect: {
|
|
315
|
+
name: 'slide-up',
|
|
316
|
+
keyframes: [
|
|
317
|
+
{ opacity: '0', transform: 'translateY(40px)' },
|
|
318
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
319
|
+
]
|
|
320
|
+
},
|
|
321
|
+
duration: 700,
|
|
322
|
+
easing: 'cubic-bezier(0.16, 1, 0.3, 1)'
|
|
323
|
+
}]
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
#### Scale and Rotate
|
|
328
|
+
```typescript
|
|
329
|
+
{
|
|
330
|
+
key: 'photos',
|
|
331
|
+
listContainer: '.photo-grid',
|
|
332
|
+
trigger: 'viewEnter',
|
|
333
|
+
params: { type: 'once', threshold: 0.15 },
|
|
334
|
+
effects: [{
|
|
335
|
+
key: 'photos',
|
|
336
|
+
listContainer: '.photo-grid',
|
|
337
|
+
keyframeEffect: {
|
|
338
|
+
name: 'scale-rotate',
|
|
339
|
+
keyframes: [
|
|
340
|
+
{ opacity: '0', transform: 'scale(0.5) rotate(-10deg)' },
|
|
341
|
+
{ opacity: '1', transform: 'scale(1) rotate(0deg)' }
|
|
342
|
+
]
|
|
343
|
+
},
|
|
344
|
+
duration: 800,
|
|
345
|
+
easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)' // Elastic
|
|
346
|
+
}]
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Hover Effects on Lists
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
{
|
|
354
|
+
key: 'product-grid',
|
|
355
|
+
listContainer: '.products',
|
|
356
|
+
trigger: 'hover',
|
|
357
|
+
effects: [
|
|
358
|
+
// Lift the product card
|
|
359
|
+
{
|
|
360
|
+
key: 'product-grid',
|
|
361
|
+
listContainer: '.products',
|
|
362
|
+
keyframeEffect: {
|
|
363
|
+
name: 'lift',
|
|
364
|
+
keyframes: [
|
|
365
|
+
{ transform: 'translateY(0)', boxShadow: '0 2px 8px rgb(0 0 0 / 0.1)' },
|
|
366
|
+
{ transform: 'translateY(-8px)', boxShadow: '0 12px 24px rgb(0 0 0 / 0.15)' }
|
|
367
|
+
]
|
|
368
|
+
},
|
|
369
|
+
duration: 250
|
|
370
|
+
},
|
|
371
|
+
// Zoom the image
|
|
372
|
+
{
|
|
373
|
+
key: 'product-grid',
|
|
374
|
+
listContainer: '.products',
|
|
375
|
+
selector: '.product-image img',
|
|
376
|
+
keyframeEffect: {
|
|
377
|
+
name: 'zoom',
|
|
378
|
+
keyframes: [
|
|
379
|
+
{ transform: 'scale(1)' },
|
|
380
|
+
{ transform: 'scale(1.1)' }
|
|
381
|
+
]
|
|
382
|
+
},
|
|
383
|
+
duration: 300
|
|
384
|
+
}
|
|
385
|
+
]
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Infinite Scroll Integration
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
{
|
|
393
|
+
key: 'infinite-list',
|
|
394
|
+
listContainer: '.items',
|
|
395
|
+
trigger: 'viewEnter',
|
|
396
|
+
params: { type: 'repeat', threshold: 0.1 },
|
|
397
|
+
effects: [{
|
|
398
|
+
key: 'infinite-list',
|
|
399
|
+
listContainer: '.items',
|
|
400
|
+
keyframeEffect: {
|
|
401
|
+
name: 'fade-slide',
|
|
402
|
+
keyframes: [
|
|
403
|
+
{ opacity: '0', transform: 'translateY(30px)' },
|
|
404
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
405
|
+
]
|
|
406
|
+
},
|
|
407
|
+
duration: 500
|
|
408
|
+
}]
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
```javascript
|
|
413
|
+
// Infinite scroll implementation
|
|
414
|
+
const observer = new IntersectionObserver((entries) => {
|
|
415
|
+
entries.forEach(entry => {
|
|
416
|
+
if (entry.isIntersecting) {
|
|
417
|
+
loadMoreItems(); // New items automatically get animations
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
observer.observe(document.querySelector('.loading-sentinel'));
|
|
423
|
+
|
|
424
|
+
function loadMoreItems() {
|
|
425
|
+
const container = document.querySelector('.items');
|
|
426
|
+
|
|
427
|
+
// Fetch and add new items
|
|
428
|
+
fetchItems().then(items => {
|
|
429
|
+
items.forEach(item => {
|
|
430
|
+
const element = createItemElement(item);
|
|
431
|
+
container.appendChild(element);
|
|
432
|
+
// Animation triggers automatically via mutation observer
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
## Performance Optimization
|
|
439
|
+
|
|
440
|
+
### When to Use listContainer
|
|
441
|
+
|
|
442
|
+
**✅ Use listContainer for:**
|
|
443
|
+
- Lists with 2+ items
|
|
444
|
+
- Dynamic lists (items added/removed)
|
|
445
|
+
- Consistent interactions across all items
|
|
446
|
+
- Staggered entrance effects
|
|
447
|
+
- Lists that grow (infinite scroll, pagination)
|
|
448
|
+
|
|
449
|
+
### Performance Best Practices
|
|
450
|
+
|
|
451
|
+
#### Efficient Animations
|
|
452
|
+
```typescript
|
|
453
|
+
// ✅ Good - GPU-accelerated properties
|
|
454
|
+
{
|
|
455
|
+
keyframeEffect: {
|
|
456
|
+
name: 'efficient',
|
|
457
|
+
keyframes: [
|
|
458
|
+
{ opacity: '0', transform: 'translateY(20px)' },
|
|
459
|
+
{ opacity: '1', transform: 'translateY(0)' }
|
|
460
|
+
]
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// ❌ Avoid - causes reflows
|
|
465
|
+
{
|
|
466
|
+
keyframeEffect: {
|
|
467
|
+
name: 'inefficient',
|
|
468
|
+
keyframes: [
|
|
469
|
+
{ height: '0px', marginTop: '0px' },
|
|
470
|
+
{ height: '200px', marginTop: '20px' }
|
|
471
|
+
]
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
#### Limit Active Observers
|
|
477
|
+
```typescript
|
|
478
|
+
// ✅ Good - One container for all items
|
|
479
|
+
{
|
|
480
|
+
listContainer: '.products' // One observer
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// ❌ Avoid - Multiple containers
|
|
484
|
+
{
|
|
485
|
+
listContainer: '.product-1' // Creates many observers
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Advanced Patterns
|
|
490
|
+
|
|
491
|
+
### Grid-to-List Layout Transitions
|
|
492
|
+
|
|
493
|
+
```typescript
|
|
494
|
+
const layoutConfig = {
|
|
495
|
+
conditions: {
|
|
496
|
+
'grid-view': {
|
|
497
|
+
type: 'media',
|
|
498
|
+
predicate: '(min-width: 768px)'
|
|
499
|
+
},
|
|
500
|
+
'list-view': {
|
|
501
|
+
type: 'media',
|
|
502
|
+
predicate: '(max-width: 767px)'
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
interactions: [
|
|
506
|
+
{
|
|
507
|
+
key: 'adaptive-items',
|
|
508
|
+
listContainer: '.items',
|
|
509
|
+
trigger: 'viewEnter',
|
|
510
|
+
conditions: ['grid-view'],
|
|
511
|
+
effects: [{
|
|
512
|
+
key: 'adaptive-items',
|
|
513
|
+
listContainer: '.items',
|
|
514
|
+
keyframeEffect: {
|
|
515
|
+
name: 'grid-fade',
|
|
516
|
+
keyframes: [
|
|
517
|
+
{ opacity: '0', transform: 'scale(0.9)' },
|
|
518
|
+
{ opacity: '1', transform: 'scale(1)' }
|
|
519
|
+
]
|
|
520
|
+
},
|
|
521
|
+
duration: 500
|
|
522
|
+
}]
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
key: 'adaptive-items',
|
|
526
|
+
listContainer: '.items',
|
|
527
|
+
trigger: 'viewEnter',
|
|
528
|
+
conditions: ['list-view'],
|
|
529
|
+
effects: [{
|
|
530
|
+
key: 'adaptive-items',
|
|
531
|
+
listContainer: '.items',
|
|
532
|
+
keyframeEffect: {
|
|
533
|
+
name: 'list-slide',
|
|
534
|
+
keyframes: [
|
|
535
|
+
{ opacity: '0', transform: 'translateX(-20px)' },
|
|
536
|
+
{ opacity: '1', transform: 'translateX(0)' }
|
|
537
|
+
]
|
|
538
|
+
},
|
|
539
|
+
duration: 400
|
|
540
|
+
}]
|
|
541
|
+
}
|
|
542
|
+
]
|
|
543
|
+
};
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
## Real-World Examples
|
|
547
|
+
|
|
548
|
+
### E-commerce Product Grid
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
const productGridConfig = {
|
|
552
|
+
interactions: [
|
|
553
|
+
// Entrance animation
|
|
554
|
+
{
|
|
555
|
+
key: 'products',
|
|
556
|
+
listContainer: '.product-grid',
|
|
557
|
+
trigger: 'viewEnter',
|
|
558
|
+
params: { type: 'once', threshold: 0.1 },
|
|
559
|
+
effects: [{
|
|
560
|
+
key: 'products',
|
|
561
|
+
listContainer: '.product-grid',
|
|
562
|
+
keyframeEffect: {
|
|
563
|
+
name: 'product-entrance',
|
|
564
|
+
keyframes: [
|
|
565
|
+
{ opacity: '0', transform: 'translateY(40px) scale(0.95)' },
|
|
566
|
+
{ opacity: '1', transform: 'translateY(0) scale(1)' }
|
|
567
|
+
]
|
|
568
|
+
},
|
|
569
|
+
duration: 700,
|
|
570
|
+
easing: 'cubic-bezier(0.16, 1, 0.3, 1)'
|
|
571
|
+
}]
|
|
572
|
+
},
|
|
573
|
+
// Hover effect
|
|
574
|
+
{
|
|
575
|
+
key: 'products',
|
|
576
|
+
listContainer: '.product-grid',
|
|
577
|
+
selector: '.product-card',
|
|
578
|
+
trigger: 'hover',
|
|
579
|
+
effects: [
|
|
580
|
+
{
|
|
581
|
+
key: 'products',
|
|
582
|
+
listContainer: '.product-grid',
|
|
583
|
+
selector: '.product-card',
|
|
584
|
+
keyframeEffect: {
|
|
585
|
+
name: 'card-lift',
|
|
586
|
+
keyframes: [
|
|
587
|
+
{ transform: 'translateY(0)', boxShadow: '0 4px 12px rgb(0 0 0 / 0.1)' },
|
|
588
|
+
{ transform: 'translateY(-8px)', boxShadow: '0 16px 32px rgb(0 0 0 / 0.15)' }
|
|
589
|
+
]
|
|
590
|
+
},
|
|
591
|
+
duration: 250
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
key: 'products',
|
|
595
|
+
listContainer: '.product-grid',
|
|
596
|
+
selector: '.product-image img',
|
|
597
|
+
keyframeEffect: {
|
|
598
|
+
name: 'image-zoom',
|
|
599
|
+
keyframes: [
|
|
600
|
+
{ transform: 'scale(1)' },
|
|
601
|
+
{ transform: 'scale(1.05)' }
|
|
602
|
+
]
|
|
603
|
+
},
|
|
604
|
+
duration: 300
|
|
605
|
+
}
|
|
606
|
+
]
|
|
607
|
+
}
|
|
608
|
+
]
|
|
609
|
+
};
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
### Dynamic To-Do List
|
|
613
|
+
|
|
614
|
+
```typescript
|
|
615
|
+
const todoConfig = {
|
|
616
|
+
interactions: [
|
|
617
|
+
// New item animation
|
|
618
|
+
{
|
|
619
|
+
key: 'todos',
|
|
620
|
+
listContainer: '.todo-list',
|
|
621
|
+
trigger: 'viewEnter',
|
|
622
|
+
params: { type: 'repeat' },
|
|
623
|
+
effects: [{
|
|
624
|
+
key: 'todos',
|
|
625
|
+
listContainer: '.todo-list',
|
|
626
|
+
keyframeEffect: {
|
|
627
|
+
name: 'todo-add',
|
|
628
|
+
keyframes: [
|
|
629
|
+
{ opacity: '0', transform: 'translateX(-30px) scale(0.9)' },
|
|
630
|
+
{ opacity: '1', transform: 'translateX(0) scale(1)' }
|
|
631
|
+
]
|
|
632
|
+
},
|
|
633
|
+
duration: 400,
|
|
634
|
+
easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)'
|
|
635
|
+
}]
|
|
636
|
+
},
|
|
637
|
+
// Complete animation
|
|
638
|
+
{
|
|
639
|
+
key: 'todos',
|
|
640
|
+
listContainer: '.todo-list',
|
|
641
|
+
selector: '.todo-checkbox',
|
|
642
|
+
trigger: 'click',
|
|
643
|
+
effects: [{
|
|
644
|
+
key: 'todos',
|
|
645
|
+
listContainer: '.todo-list',
|
|
646
|
+
selector: '.todo-item',
|
|
647
|
+
transition: {
|
|
648
|
+
duration: 300,
|
|
649
|
+
styleProperties: [
|
|
650
|
+
{ name: 'opacity', value: '0.5' },
|
|
651
|
+
{ name: 'text-decoration', value: 'line-through' }
|
|
652
|
+
]
|
|
653
|
+
}
|
|
654
|
+
}]
|
|
655
|
+
}
|
|
656
|
+
]
|
|
657
|
+
};
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
### Image Gallery with Lightbox
|
|
661
|
+
|
|
662
|
+
```typescript
|
|
663
|
+
const galleryConfig = {
|
|
664
|
+
interactions: [
|
|
665
|
+
// Grid entrance
|
|
666
|
+
{
|
|
667
|
+
key: 'gallery',
|
|
668
|
+
listContainer: '.gallery-grid',
|
|
669
|
+
trigger: 'viewEnter',
|
|
670
|
+
params: { type: 'once', threshold: 0.1 },
|
|
671
|
+
effects: [{
|
|
672
|
+
key: 'gallery',
|
|
673
|
+
listContainer: '.gallery-grid',
|
|
674
|
+
keyframeEffect: {
|
|
675
|
+
name: 'gallery-fade',
|
|
676
|
+
keyframes: [
|
|
677
|
+
{ opacity: '0', filter: 'blur(10px)' },
|
|
678
|
+
{ opacity: '1', filter: 'blur(0)' }
|
|
679
|
+
]
|
|
680
|
+
},
|
|
681
|
+
duration: 800
|
|
682
|
+
}]
|
|
683
|
+
},
|
|
684
|
+
// Hover overlay
|
|
685
|
+
{
|
|
686
|
+
key: 'gallery',
|
|
687
|
+
listContainer: '.gallery-grid',
|
|
688
|
+
selector: '.gallery-item',
|
|
689
|
+
trigger: 'hover',
|
|
690
|
+
effects: [{
|
|
691
|
+
key: 'gallery',
|
|
692
|
+
listContainer: '.gallery-grid',
|
|
693
|
+
selector: '.gallery-overlay',
|
|
694
|
+
keyframeEffect: {
|
|
695
|
+
name: 'overlay-reveal',
|
|
696
|
+
keyframes: [
|
|
697
|
+
{ opacity: '0' },
|
|
698
|
+
{ opacity: '1' }
|
|
699
|
+
]
|
|
700
|
+
},
|
|
701
|
+
duration: 250
|
|
702
|
+
}]
|
|
703
|
+
}
|
|
704
|
+
]
|
|
705
|
+
};
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
## Next Steps
|
|
709
|
+
|
|
710
|
+
- **[Element Selection](../api/element-selection.md)** - Understand selector priority
|
|
711
|
+
- **[Performance Guide](./performance.md)** - Optimize animations
|
|
712
|
+
- **[API Reference](../api/functions.md)** - List management functions
|
|
713
|
+
- **[Examples](../examples/list-patterns.md)** - More list patterns
|