vlist 1.8.3 → 1.9.1
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/README.github.md +41 -12
- package/README.md +12 -10
- package/dist/builder/data.d.ts +1 -0
- package/dist/builder/types.d.ts +4 -0
- package/dist/features/async/manager.d.ts +2 -0
- package/dist/features/async/sparse.d.ts +5 -1
- package/dist/features/groups/async-bridge.d.ts +2 -0
- package/dist/features/transition/feature.d.ts +30 -0
- package/dist/features/transition/index.d.ts +9 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/internals.js +1 -1
- package/dist/size.json +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/vlist.css +1 -1
- package/package.json +1 -1
package/README.github.md
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
# vlist
|
|
2
2
|
|
|
3
|
-
The virtual list library for every framework. Accessible by default, batteries-included, with composable features — in 11.
|
|
3
|
+
The virtual list library for every framework. Accessible by default, batteries-included, with composable features — in 11.2 KB.
|
|
4
4
|
|
|
5
|
-
**v1.
|
|
5
|
+
**v1.9.1** — [Changelog](./CHANGELOG.md)
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/vlist)
|
|
8
|
+
[](https://bundlephobia.com/package/vlist)
|
|
8
9
|
[](https://github.com/floor/vlist/actions/workflows/ci.yml)
|
|
9
10
|
[](https://github.com/floor/vlist/blob/main/LICENSE)
|
|
10
11
|
|
|
11
|
-
- **New:
|
|
12
|
+
- **New: `withTransition()`** — FLIP-based enter/exit animations for insert and remove, with batch `removeItems()` for simultaneous multi-item transitions
|
|
12
13
|
- **Accessible** — WAI-ARIA, 2D keyboard navigation, focus recovery, screen-reader DOM ordering, ARIA live region
|
|
13
14
|
- **Zero dependencies** — framework-agnostic core with tiny adapters for Vue, Svelte, Solid, React
|
|
14
|
-
- **11.
|
|
15
|
+
- **11.2 KB gzipped** — composable features with perfect tree-shaking
|
|
15
16
|
- **Constant memory** — ~0.1 MB overhead at any scale, from 10K to 1M+ items
|
|
16
|
-
- **Grid, masonry, table, groups, async, selection, sortable, scale** — all opt-in
|
|
17
|
+
- **Grid, masonry, table, groups, async, selection, sortable, transition, scale** — all opt-in
|
|
17
18
|
- **Vertical & horizontal** — single axis-neutral code path, every feature works in both orientations
|
|
18
19
|
|
|
19
20
|
**18 interactive examples, docs & benchmarks → [vlist.io](https://vlist.io)**
|
|
@@ -94,19 +95,20 @@ const list = vlist({
|
|
|
94
95
|
|
|
95
96
|
| Feature | Size | Description |
|
|
96
97
|
|---------|------|-------------|
|
|
97
|
-
| **Base** | 11.
|
|
98
|
-
| `withAsync()` | +4.
|
|
99
|
-
| `withSelection()` | +
|
|
98
|
+
| **Base** | 11.2 KB | Virtualization, ARIA, keyboard nav, gap, padding |
|
|
99
|
+
| `withAsync()` | +4.6 KB | Lazy loading with velocity-aware fetching |
|
|
100
|
+
| `withSelection()` | +2.7 KB | Single/multiple selection with 2D keyboard nav |
|
|
100
101
|
| `withScale()` | +3.6 KB | 1M+ items via scroll compression |
|
|
101
|
-
| `withGroups()` | +4.
|
|
102
|
+
| `withGroups()` | +4.7 KB | Sticky/inline headers with async group discovery |
|
|
102
103
|
| `withAutoSize()` | +0.9 KB | Auto-measure items via ResizeObserver |
|
|
103
|
-
| `withScrollbar()` | +1.
|
|
104
|
+
| `withScrollbar()` | +1.8 KB | Custom scrollbar UI |
|
|
104
105
|
| `withGrid()` | +4.1 KB | 2D grid layout |
|
|
105
|
-
| `withMasonry()` | +3.
|
|
106
|
+
| `withMasonry()` | +3.4 KB | Pinterest-style masonry with lane-aware keyboard nav |
|
|
106
107
|
| `withTable()` | +5.8 KB | Data table with columns, resize, sort |
|
|
107
108
|
| `withPage()` | +0.7 KB | Window-level scrolling |
|
|
108
109
|
| `withSortable()` | +2.9 KB | Drag-and-drop reordering with auto-scroll |
|
|
109
110
|
| `withSnapshots()` | +1.2 KB | Scroll position save/restore |
|
|
111
|
+
| `withTransition()` | +2.1 KB | FLIP-based enter/exit animations for insert & remove |
|
|
110
112
|
|
|
111
113
|
## Examples
|
|
112
114
|
|
|
@@ -163,6 +165,30 @@ const gallery = vlist({
|
|
|
163
165
|
.build()
|
|
164
166
|
```
|
|
165
167
|
|
|
168
|
+
### Animated Insert & Remove
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { vlist, withTransition, withSelection } from 'vlist'
|
|
172
|
+
|
|
173
|
+
const list = vlist({
|
|
174
|
+
container: '#playlist',
|
|
175
|
+
items: tracks,
|
|
176
|
+
item: { height: 64, template: renderTrack },
|
|
177
|
+
})
|
|
178
|
+
.use(withTransition({ duration: 200 }))
|
|
179
|
+
.use(withSelection({ mode: 'multiple' }))
|
|
180
|
+
.build()
|
|
181
|
+
|
|
182
|
+
// Single item — collapses with fade-out, siblings slide up
|
|
183
|
+
list.removeItem(trackId)
|
|
184
|
+
|
|
185
|
+
// Batch — all items animate simultaneously
|
|
186
|
+
list.removeItems(list.getSelected())
|
|
187
|
+
|
|
188
|
+
// Insert — expands in, siblings slide down
|
|
189
|
+
list.insertItem({ id: 42, title: 'New Track' }, 0)
|
|
190
|
+
```
|
|
191
|
+
|
|
166
192
|
### Async Loading
|
|
167
193
|
|
|
168
194
|
```typescript
|
|
@@ -217,7 +243,9 @@ const list = vlist(config).use(...features).build()
|
|
|
217
243
|
| `list.appendItems(items)` | Add to end (auto-scrolls in reverse mode) |
|
|
218
244
|
| `list.prependItems(items)` | Add to start (preserves scroll position) |
|
|
219
245
|
| `list.updateItem(index, partial)` | Update a single item by index |
|
|
220
|
-
| `list.
|
|
246
|
+
| `list.insertItem(item, index?)` | Insert at index (animated with `withTransition`) |
|
|
247
|
+
| `list.removeItem(id)` | Remove by ID (animated with `withTransition`) |
|
|
248
|
+
| `list.removeItems(ids)` | Batch remove (simultaneous animations) |
|
|
221
249
|
| `list.getItemAt(index)` | Get item at index |
|
|
222
250
|
| `list.getIndexById(id)` | Get index by item ID |
|
|
223
251
|
| `list.reload()` | Re-fetch from adapter (async) |
|
|
@@ -282,6 +310,7 @@ withTable({ columns, rowHeight, headerHeight?, resizable? })
|
|
|
282
310
|
withAutoSize() // auto-measure items (requires estimatedHeight)
|
|
283
311
|
withScale() // auto-activates at 16.7M px
|
|
284
312
|
withScrollbar({ autoHide?, autoHideDelay?, minThumbSize? })
|
|
313
|
+
withTransition({ duration?: 200, insert?: timing, remove?: timing })
|
|
285
314
|
withSortable({ handle?: '.drag-handle' }) // drag-and-drop reordering
|
|
286
315
|
withPage() // no config — uses document scroll
|
|
287
316
|
withSnapshots({ autoSave: 'key' }) // automatic sessionStorage save/restore
|
package/README.md
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
# vlist
|
|
2
2
|
|
|
3
|
-
The virtual list library for every framework. Accessible by default, batteries-included, with composable features — in 11.
|
|
3
|
+
The virtual list library for every framework. Accessible by default, batteries-included, with composable features — in 11.2 KB.
|
|
4
4
|
|
|
5
|
-
**v1.
|
|
5
|
+
**v1.9.1** — [Changelog](https://github.com/floor/vlist/blob/main/CHANGELOG.md)
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/vlist)
|
|
8
|
+
[](https://bundlephobia.com/package/vlist)
|
|
8
9
|
[](https://github.com/floor/vlist/actions/workflows/ci.yml)
|
|
9
10
|
[](https://github.com/floor/vlist/blob/main/LICENSE)
|
|
10
11
|
|
|
11
|
-
- **New:
|
|
12
|
+
- **New: `withTransition()`** — FLIP-based enter/exit animations for insert and remove
|
|
12
13
|
- **Zero dependencies** — framework-agnostic core, tiny adapters for Vue, Svelte, Solid, React
|
|
13
14
|
- **Accessible** — WAI-ARIA, 2D keyboard navigation, focus recovery, screen-reader DOM ordering
|
|
14
|
-
- **11.
|
|
15
|
+
- **11.2 KB gzipped** — composable features with perfect tree-shaking
|
|
15
16
|
- **Constant memory** — ~0.1 MB overhead at any scale, from 10K to 1M+ items
|
|
16
17
|
- **Vertical & horizontal** — single axis-neutral code path, every feature works in both orientations
|
|
17
18
|
|
|
@@ -56,19 +57,20 @@ const list = vlist({ container: '#app', items, item: { height: 200, template: re
|
|
|
56
57
|
|
|
57
58
|
| Feature | Size | Description |
|
|
58
59
|
|---------|------|-------------|
|
|
59
|
-
| **Base** | 11.
|
|
60
|
-
| `withAsync()` | +4.
|
|
61
|
-
| `withSelection()` | +
|
|
60
|
+
| **Base** | 11.2 KB | Virtualization, ARIA, keyboard nav, gap, padding |
|
|
61
|
+
| `withAsync()` | +4.6 KB | Lazy loading with velocity-aware fetching |
|
|
62
|
+
| `withSelection()` | +2.7 KB | Single/multiple selection with 2D keyboard nav |
|
|
62
63
|
| `withScale()` | +3.6 KB | 1M+ items via scroll compression |
|
|
63
|
-
| `withGroups()` | +4.
|
|
64
|
+
| `withGroups()` | +4.7 KB | Sticky/inline headers with async group discovery |
|
|
64
65
|
| `withAutoSize()` | +0.9 KB | Auto-measure items via ResizeObserver |
|
|
65
|
-
| `withScrollbar()` | +1.
|
|
66
|
+
| `withScrollbar()` | +1.8 KB | Custom scrollbar UI |
|
|
66
67
|
| `withGrid()` | +4.1 KB | 2D grid layout |
|
|
67
|
-
| `withMasonry()` | +3.
|
|
68
|
+
| `withMasonry()` | +3.4 KB | Pinterest-style masonry with lane-aware keyboard nav |
|
|
68
69
|
| `withTable()` | +5.8 KB | Data table with columns, resize, sort |
|
|
69
70
|
| `withPage()` | +0.7 KB | Window-level scrolling |
|
|
70
71
|
| `withSortable()` | +2.9 KB | Drag-and-drop reordering with auto-scroll |
|
|
71
72
|
| `withSnapshots()` | +1.2 KB | Scroll position save/restore |
|
|
73
|
+
| `withTransition()` | +2.1 KB | FLIP-based enter/exit animations for insert & remove |
|
|
72
74
|
|
|
73
75
|
## Framework Adapters
|
|
74
76
|
|
package/dist/builder/data.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export interface SimpleDataManager<T extends VListItem = VListItem> {
|
|
|
42
42
|
setTotal: (total: number) => void;
|
|
43
43
|
setItems: (items: T[], offset?: number, total?: number) => void;
|
|
44
44
|
updateItem: (index: number, updates: Partial<T>) => boolean;
|
|
45
|
+
insertItem: (item: T, index: number) => void;
|
|
45
46
|
removeItem: (id: string | number) => boolean;
|
|
46
47
|
loadRange: (start: number, end: number) => Promise<void>;
|
|
47
48
|
ensureRange: (start: number, end: number) => Promise<void>;
|
package/dist/builder/types.d.ts
CHANGED
|
@@ -481,7 +481,11 @@ export interface VList<T extends VListItem = VListItem> {
|
|
|
481
481
|
appendItems: (items: T[]) => void;
|
|
482
482
|
prependItems: (items: T[]) => void;
|
|
483
483
|
updateItem: (id: string | number, updates: Partial<T>) => void;
|
|
484
|
+
insertItem: (item: T, index?: number) => void;
|
|
485
|
+
/** @deprecated Use `insertItem` instead. */
|
|
486
|
+
addItem: (item: T, index?: number) => void;
|
|
484
487
|
removeItem: (id: string | number) => void;
|
|
488
|
+
removeItems: (ids: ReadonlyArray<string | number>) => number;
|
|
485
489
|
getItemAt: (index: number) => T | undefined;
|
|
486
490
|
getIndexById: (id: string | number) => number;
|
|
487
491
|
reload: (options?: ReloadOptions) => Promise<void>;
|
|
@@ -75,6 +75,8 @@ export interface DataManager<T extends VListItem = VListItem> {
|
|
|
75
75
|
setItems: (items: T[], offset?: number, total?: number) => void;
|
|
76
76
|
/** Update item at index */
|
|
77
77
|
updateItem: (index: number, updates: Partial<T>) => boolean;
|
|
78
|
+
/** Insert item at index */
|
|
79
|
+
insertItem: (item: T, index: number) => void;
|
|
78
80
|
/** Remove item by ID */
|
|
79
81
|
removeItem: (id: string | number) => boolean;
|
|
80
82
|
/** Load items for a range */
|
|
@@ -45,6 +45,8 @@ export interface SparseStorage<T extends VListItem = VListItem> {
|
|
|
45
45
|
set: (index: number, item: T) => void;
|
|
46
46
|
/** Set multiple items starting at offset */
|
|
47
47
|
setRange: (offset: number, items: T[]) => void;
|
|
48
|
+
/** Insert item at index, shifting subsequent items up by 1 */
|
|
49
|
+
insert: (index: number, item: T) => void;
|
|
48
50
|
/** Delete item at index */
|
|
49
51
|
delete: (index: number) => boolean;
|
|
50
52
|
/** Get items in range (includes undefined for unloaded) */
|
|
@@ -57,8 +59,10 @@ export interface SparseStorage<T extends VListItem = VListItem> {
|
|
|
57
59
|
findUnloadedRanges: (start: number, end: number) => Range[];
|
|
58
60
|
/** Get chunk index for item index */
|
|
59
61
|
getChunkIndex: (itemIndex: number) => number;
|
|
60
|
-
/** Check if chunk is loaded */
|
|
62
|
+
/** Check if chunk is loaded (has any items) */
|
|
61
63
|
isChunkLoaded: (chunkIndex: number) => boolean;
|
|
64
|
+
/** Check if chunk has all expected items (count matches expected for total) */
|
|
65
|
+
isChunkFullyLoaded: (chunkIndex: number) => boolean;
|
|
62
66
|
/** Mark chunk as accessed (for LRU) */
|
|
63
67
|
touchChunk: (chunkIndex: number) => void;
|
|
64
68
|
/** Mark all chunks in a range as accessed with a single Date.now() call */
|
|
@@ -48,6 +48,8 @@ export interface AsyncGroupBridge {
|
|
|
48
48
|
getGroupAtLayoutIndex(layoutIndex: number): GroupBoundary;
|
|
49
49
|
/** Get the group boundary at a data index */
|
|
50
50
|
getGroupAtDataIndex(dataIndex: number): GroupBoundary;
|
|
51
|
+
/** Insert item at data index — shifts group keys up and rebuilds */
|
|
52
|
+
insertAt(dataIndex: number, item: VListItem): void;
|
|
51
53
|
/** Remove item at data index — shifts group keys and rebuilds */
|
|
52
54
|
removeAt(dataIndex: number): void;
|
|
53
55
|
/** Reset all state (e.g. on reload) */
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* withTransition — FLIP-based enter/exit animations for insertItem and removeItem.
|
|
3
|
+
*
|
|
4
|
+
* Opt-in feature that replaces the immediate insert/remove with animated versions:
|
|
5
|
+
* - removeItem: clone collapses via scaleY(0), siblings slide up
|
|
6
|
+
* - insertItem: new element expands in, siblings slide down
|
|
7
|
+
*
|
|
8
|
+
* Without this feature, insert/remove are instantaneous.
|
|
9
|
+
*/
|
|
10
|
+
import type { VListItem } from "../../types";
|
|
11
|
+
import type { VListFeature } from "../../builder/types";
|
|
12
|
+
/** Per-animation timing overrides. */
|
|
13
|
+
export interface TransitionTiming {
|
|
14
|
+
/** Duration in ms */
|
|
15
|
+
duration?: number;
|
|
16
|
+
/** CSS easing function */
|
|
17
|
+
easing?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface TransitionConfig {
|
|
20
|
+
/** Shared duration in ms (default: 200). Overridden by add/remove sub-configs. */
|
|
21
|
+
duration?: number;
|
|
22
|
+
/** Shared CSS easing (default: MD3 emphasized). Overridden by add/remove sub-configs. */
|
|
23
|
+
easing?: string;
|
|
24
|
+
/** Insert animation config, or `false` to disable. */
|
|
25
|
+
insert?: TransitionTiming | false;
|
|
26
|
+
/** Remove animation config, or `false` to disable. */
|
|
27
|
+
remove?: TransitionTiming | false;
|
|
28
|
+
}
|
|
29
|
+
export declare function withTransition<T extends VListItem = VListItem>(config?: TransitionConfig): VListFeature<T>;
|
|
30
|
+
//# sourceMappingURL=feature.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vlist/transition — FLIP-based enter/exit animations
|
|
3
|
+
* Opt-in animated add/remove for smooth list transitions
|
|
4
|
+
*
|
|
5
|
+
* Usage: import { withTransition } from 'vlist'
|
|
6
|
+
*/
|
|
7
|
+
export { withTransition } from "./feature";
|
|
8
|
+
export type { TransitionConfig, TransitionTiming } from "./feature";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export { withTable } from "./features/table";
|
|
|
24
24
|
export { withSortable } from "./features/sortable";
|
|
25
25
|
export type { SortableConfig } from "./features/sortable";
|
|
26
26
|
export { withAutoSize } from "./features/autosize";
|
|
27
|
+
export { withTransition } from "./features/transition";
|
|
28
|
+
export type { TransitionConfig, TransitionTiming } from "./features/transition";
|
|
27
29
|
export { createStats } from "./utils/stats";
|
|
28
30
|
export type { Stats, StatsConfig, StatsState } from "./utils/stats";
|
|
29
31
|
export type { VListItem, VListEvents, ItemConfig, ItemTemplate, ItemState, SelectionMode, SelectionConfig, SelectionState, ScrollbarConfig, ScrollbarPadding, ScrollbarOptions, ScrollConfig, ScrollToOptions, ScrollSnapshot, VListAdapter, AdapterParams, AdapterResponse, Range, ViewportState, EventHandler, Unsubscribe, GridConfig, MasonryConfig, GroupsConfig, GroupHeaderConfig, GridSizeContext, GridHeightContext, } from "./types";
|