vlist 1.7.0 → 1.7.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/README.github.md CHANGED
@@ -2,18 +2,19 @@
2
2
 
3
3
  The virtual list library for every framework. Accessible by default, batteries-included, with composable features — in 10.5 KB.
4
4
 
5
- **v1.7.0** — [Changelog](./changelog.txt)
5
+ **v1.7.1** — [Changelog](./changelog.txt)
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/vlist.svg)](https://www.npmjs.com/package/vlist)
8
8
  [![CI](https://github.com/floor/vlist/actions/workflows/ci.yml/badge.svg)](https://github.com/floor/vlist/actions/workflows/ci.yml)
9
9
  [![license](https://img.shields.io/npm/l/vlist.svg)](https://github.com/floor/vlist/blob/main/LICENSE)
10
10
 
11
+ - **New: `withSortable()`** — drag-and-drop reordering with auto-scroll, keyboard support, and ARIA announcements
11
12
  - **Accessible** — WAI-ARIA, 2D keyboard navigation, focus recovery, screen-reader DOM ordering, ARIA live region
12
13
  - **Zero dependencies** — framework-agnostic core with tiny adapters for Vue, Svelte, Solid, React
13
14
  - **10.6 KB gzipped** — composable features with perfect tree-shaking
14
15
  - **Constant memory** — ~0.1 MB overhead at any scale, from 10K to 1M+ items
15
- - **Grid, masonry, table, groups, async, selection, scale** — all opt-in
16
- - **Vertical & horizontal** — dimension-agnostic API, every layout mode works in both orientations
16
+ - **Grid, masonry, table, groups, async, selection, sortable, scale** — all opt-in
17
+ - **Vertical & horizontal** — single axis-neutral code path, every feature works in both orientations
17
18
 
18
19
  **18 interactive examples, docs & benchmarks → [vlist.io](https://vlist.io)**
19
20
 
@@ -95,7 +96,7 @@ const list = vlist({
95
96
  |---------|------|-------------|
96
97
  | **Base** | 10.6 KB | Virtualization, ARIA, keyboard nav, gap, padding |
97
98
  | `withAsync()` | +4.6 KB | Lazy loading with velocity-aware fetching |
98
- | `withSelection()` | +2.7 KB | Single/multiple selection with 2D keyboard nav |
99
+ | `withSelection()` | +2.9 KB | Single/multiple selection with 2D keyboard nav |
99
100
  | `withScale()` | +3.7 KB | 1M+ items via scroll compression |
100
101
  | `withGroups()` | +2.7 KB | Sticky/inline headers |
101
102
  | `withAutoSize()` | +0.9 KB | Auto-measure items via ResizeObserver |
@@ -104,6 +105,7 @@ const list = vlist({
104
105
  | `withMasonry()` | +3.4 KB | Pinterest-style masonry with lane-aware keyboard nav |
105
106
  | `withTable()` | +5.5 KB | Data table with columns, resize, sort |
106
107
  | `withPage()` | +0.8 KB | Window-level scrolling |
108
+ | `withSortable()` | +2.9 KB | Drag-and-drop reordering with auto-scroll |
107
109
  | `withSnapshots()` | +0.8 KB | Scroll position save/restore |
108
110
 
109
111
  ## Examples
@@ -253,6 +255,8 @@ list.on('selection:change', ({ selectedIds, selectedItems }) => {})
253
255
  list.on('load:start', ({ offset, limit }) => {})
254
256
  list.on('load:end', ({ items, offset, total }) => {})
255
257
  list.on('load:error', ({ error, offset, limit }) => {})
258
+ list.on('sort:end', ({ fromIndex, toIndex }) => {})
259
+ list.on('sort:cancel', ({ originalItems }) => {})
256
260
  ```
257
261
 
258
262
  ### Properties
@@ -278,6 +282,7 @@ withTable({ columns, rowHeight, headerHeight?, resizable? })
278
282
  withAutoSize() // auto-measure items (requires estimatedHeight)
279
283
  withScale() // auto-activates at 16.7M px
280
284
  withScrollbar({ autoHide?, autoHideDelay?, minThumbSize? })
285
+ withSortable({ handle?: '.drag-handle' }) // drag-and-drop reordering
281
286
  withPage() // no config — uses document scroll
282
287
  withSnapshots({ autoSave: 'key' }) // automatic sessionStorage save/restore
283
288
  ```
package/README.md CHANGED
@@ -6,10 +6,12 @@ The virtual list library for every framework. Accessible by default, batteries-i
6
6
  [![CI](https://github.com/floor/vlist/actions/workflows/ci.yml/badge.svg)](https://github.com/floor/vlist/actions/workflows/ci.yml)
7
7
  [![license](https://img.shields.io/npm/l/vlist.svg)](https://github.com/floor/vlist/blob/main/LICENSE)
8
8
 
9
+ - **New: `withSortable()`** — drag-and-drop reordering with auto-scroll, keyboard support, and ARIA announcements
9
10
  - **Zero dependencies** — framework-agnostic core, tiny adapters for Vue, Svelte, Solid, React
10
11
  - **Accessible** — WAI-ARIA, 2D keyboard navigation, focus recovery, screen-reader DOM ordering
11
12
  - **10.6 KB gzipped** — composable features with perfect tree-shaking
12
13
  - **Constant memory** — ~0.1 MB overhead at any scale, from 10K to 1M+ items
14
+ - **Vertical & horizontal** — single axis-neutral code path, every feature works in both orientations
13
15
 
14
16
  ## Install
15
17
 
@@ -54,7 +56,7 @@ const list = vlist({ container: '#app', items, item: { height: 200, template: re
54
56
  |---------|------|-------------|
55
57
  | **Base** | 10.6 KB | Virtualization, ARIA, keyboard nav, gap, padding |
56
58
  | `withAsync()` | +4.6 KB | Lazy loading with velocity-aware fetching |
57
- | `withSelection()` | +2.7 KB | Single/multiple selection with 2D keyboard nav |
59
+ | `withSelection()` | +2.9 KB | Single/multiple selection with 2D keyboard nav |
58
60
  | `withScale()` | +3.7 KB | 1M+ items via scroll compression |
59
61
  | `withGroups()` | +2.7 KB | Sticky/inline headers |
60
62
  | `withAutoSize()` | +0.9 KB | Auto-measure items via ResizeObserver |
@@ -63,6 +65,7 @@ const list = vlist({ container: '#app', items, item: { height: 200, template: re
63
65
  | `withMasonry()` | +3.4 KB | Pinterest-style masonry with lane-aware keyboard nav |
64
66
  | `withTable()` | +5.5 KB | Data table with columns, resize, sort |
65
67
  | `withPage()` | +0.8 KB | Window-level scrolling |
68
+ | `withSortable()` | +2.9 KB | Drag-and-drop reordering with auto-scroll |
66
69
  | `withSnapshots()` | +0.8 KB | Scroll position save/restore |
67
70
 
68
71
  ## Framework Adapters
@@ -55,12 +55,12 @@ export interface ScrollbarFeatureConfig {
55
55
  */
56
56
  padding?: number;
57
57
  /**
58
- * Behavior when clicking on the scrollbar track (not the thumb) (default: 'jump').
59
- * - `'jump'` jumps directly to the clicked position (centers the thumb there).
60
- * - `'page'` — scrolls by one page (containerSize) toward the clicked position,
61
- * matching macOS native scrollbar behavior.
58
+ * Behavior when clicking on the scrollbar track (not the thumb) (default: 'scroll').
59
+ * - `'scroll'` scrolls toward the clicked position, matching macOS native scrollbar
60
+ * behavior. Hold to scroll continuously.
61
+ * - `'jump'` — jumps directly to the clicked position (centers the thumb there).
62
62
  */
63
- clickBehavior?: 'jump' | 'page';
63
+ clickBehavior?: 'jump' | 'scroll' | 'page';
64
64
  }
65
65
  /**
66
66
  * Create a scrollbar feature for the builder.
@@ -62,12 +62,12 @@ export interface ScrollbarConfig {
62
62
  */
63
63
  padding?: ScrollbarPadding;
64
64
  /**
65
- * Behavior when clicking on the scrollbar track (not the thumb) (default: 'page').
66
- * - `'page'` — scrolls by one page (containerSize) toward the clicked position,
67
- * matching macOS native scrollbar behavior. Hold to scroll continuously.
68
- * - `'jump'` — jumps directly to the clicked position (centers the thumb there).
65
+ * Behavior when clicking on the scrollbar track (not the thumb) (default: 'scroll').
66
+ * - `'scroll'` — scrolls toward the clicked position, matching macOS native scrollbar
67
+ * behavior. Hold to scroll continuously.
68
+ * - `'jump'` — jumps directly to the clicked position (centers the thumb there).
69
69
  */
70
- clickBehavior?: 'jump' | 'page';
70
+ clickBehavior?: 'jump' | 'scroll' | 'page';
71
71
  }
72
72
  /** Scrollbar instance */
73
73
  export interface Scrollbar {
@@ -69,6 +69,12 @@ export interface SortableConfig {
69
69
  * Prevents accidental drags on click.
70
70
  */
71
71
  dragThreshold?: number;
72
+ /**
73
+ * Container element for the drag ghost (default: document.body).
74
+ * Set this to keep the ghost inside a specific ancestor so it inherits
75
+ * scoped CSS (e.g. theme variables, list-specific item styles).
76
+ */
77
+ ghostContainer?: HTMLElement;
72
78
  }
73
79
  /**
74
80
  * Create a sortable feature for the builder.