vlist 3.2.0 → 3.3.0

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,7 +2,7 @@
2
2
 
3
3
  The virtual list library for every framework. Ultra efficient, batteries-included, and accessible with composable plugins.
4
4
 
5
- **v3.2.0** — `scroll.mode` on the one `vlist` entry: the default, `"auto"`, scrolls natively and hands a list past the browser's size limit to synthetic input, which draws its own scrollbar. Vue, Svelte, Solid and React entries in the package itself (`vlist/vue`, `vlist/svelte`, `vlist/solid`, `vlist/react`), feature-first and tree-shaken like the vanilla builder; the separate adapter packages are deprecated. See the [changelog](https://github.com/floor/vlist/blob/main/CHANGELOG.md).
5
+ **v3.3.0** — `scroll.mode` on the one `vlist` entry: the default, `"auto"`, scrolls natively and hands a list past the browser's size limit to synthetic input, which draws its own scrollbar. Vue, Svelte, Solid and React entries in the package itself (`vlist/vue`, `vlist/svelte`, `vlist/solid`, `vlist/react`), feature-first and tree-shaken like the vanilla builder; the separate adapter packages are deprecated. See the [changelog](https://github.com/floor/vlist/blob/main/CHANGELOG.md).
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/vlist.svg)](https://www.npmjs.com/package/vlist)
8
8
  [![bundle size](https://img.shields.io/bundlephobia/minzip/vlist)](https://bundlephobia.com/package/vlist)
@@ -11,7 +11,7 @@ The virtual list library for every framework. Ultra efficient, batteries-include
11
11
 
12
12
  - **Accessible** — `a11y()` or a selection mode adds WAI-ARIA, 2D keyboard navigation, focus recovery, screen-reader DOM ordering
13
13
  - **Zero dependencies** — framework-agnostic core, with Vue, Svelte, Solid and React entries in the same package
14
- - **10.3 KB gzipped** — composable plugins with perfect tree-shaking (Bundlephobia's badge measures the root entry with every plugin at once)
14
+ - **10.5 KB gzipped** — composable plugins with perfect tree-shaking (Bundlephobia's badge measures the root entry with every plugin at once)
15
15
  - **Constant memory** — ~0.1 MB overhead at any scale, from 10K to 1M+ items
16
16
  - **Tree, grid, masonry, carousel, table, groups, data, selection, search, sortable, transition** — all opt-in
17
17
  - **Axis-neutral** — vertical and horizontal scrolling through a single code path, all plugins work in both orientations
@@ -264,36 +264,36 @@ The touch-only `.vlist-item--touch-sort` class suppresses selection and callouts
264
264
 
265
265
  | Entry / export | Minified | Gzipped |
266
266
  |---|---:|---:|
267
- | **Base (`vlist`)** | 27.3 KB | 10.3 KB |
268
- | `vlist/synthetic` (deprecated) | 34.2 KB | 12.9 KB |
269
- | `vlist/native` (alias) | 27.3 KB | 10.3 KB |
270
- | `a11y()` | 32.4 KB | 12.2 KB |
271
- | `selection()` | 37.8 KB | 13.6 KB |
272
- | `data()` | 41.0 KB | 15.1 KB |
273
- | `scrollbar()` | 35.5 KB | 13.2 KB |
274
- | `sortable()` | 39.2 KB | 13.9 KB |
275
- | `groups()` | 43.5 KB | 15.7 KB |
276
- | `page()` | 29.9 KB | 11.2 KB |
277
- | `snapshots()` | 30.6 KB | 11.4 KB |
278
- | `transition()` | 34.1 KB | 12.3 KB |
279
- | `autosize()` | 31.7 KB | 11.9 KB |
280
- | `grid()` | 34.8 KB | 12.9 KB |
281
- | `table()` | 46.4 KB | 16.4 KB |
282
- | `masonry()` | 39.4 KB | 14.7 KB |
283
- | `tree()` | 43.1 KB | 15.6 KB |
284
- | `search()` | 36.9 KB | 13.6 KB |
285
- | `carousel()` | 43.3 KB | 15.8 KB |
286
- | `vlist/synthetic` + `carousel()` | 49.3 KB | 18.1 KB |
287
- | `vlist/synthetic` + `sortable()` | 46.1 KB | 16.5 KB |
288
- | `vlist/vue` `useVList` | 27.7 KB | 10.5 KB |
289
- | `vlist/svelte` `vlist` | 27.5 KB | 10.4 KB |
290
- | `vlist/solid` `createVList` | 27.6 KB | 10.4 KB |
291
- | `vlist/react` `useVList` | 27.8 KB | 10.5 KB |
292
- | `vlist/react` + `grid()` | 35.2 KB | 13.1 KB |
293
-
294
- Sizes are tree-shaken totals from `bun run size`, not additive plugin costs. Plugin rows include the native default factory plus that plugin; framework rows add the entry, with the framework itself external. The base is **10,539 bytes gzipped**, within the 10.3 KB budget (10,547 bytes). `bun run size` fails if a scenario fails to build, an unused plugin leaks into a bundle, or any published size exceeds its gzip budget. Synthetic input is **13,192 bytes** before plugins; with `scroll.mode`, a `vlist` list downloads the driver and its scrollbar as `synthetic-driver.js` (6.2 KB gzipped) only when it goes synthetic. The alias row measures the same source factory; the distributed alias re-exports it without duplicating the implementation.
295
-
296
- Bundlephobia's badge measures the package's root entry, which re-exports every plugin, minified and gzipped as one bundle. With a tree-shaking bundler, an app that imports named exports from `vlist` bundles the base (**10.3 KB gzipped**) and the features it uses; the table's rows are each a combined size, not amounts to add up.
267
+ | **Base (`vlist`)** | 27.9 KB | 10.5 KB |
268
+ | `vlist/synthetic` (deprecated) | 34.8 KB | 13.1 KB |
269
+ | `vlist/native` (alias) | 27.9 KB | 10.5 KB |
270
+ | `a11y()` | 32.9 KB | 12.4 KB |
271
+ | `selection()` | 38.4 KB | 13.8 KB |
272
+ | `data()` | 41.5 KB | 15.3 KB |
273
+ | `scrollbar()` | 36.1 KB | 13.4 KB |
274
+ | `sortable()` | 39.8 KB | 14.1 KB |
275
+ | `groups()` | 44.2 KB | 15.9 KB |
276
+ | `page()` | 30.4 KB | 11.4 KB |
277
+ | `snapshots()` | 31.2 KB | 11.6 KB |
278
+ | `transition()` | 34.6 KB | 12.5 KB |
279
+ | `autosize()` | 32.3 KB | 12.1 KB |
280
+ | `grid()` | 35.4 KB | 13.1 KB |
281
+ | `table()` | 47.0 KB | 16.6 KB |
282
+ | `masonry()` | 40.1 KB | 14.9 KB |
283
+ | `tree()` | 43.7 KB | 15.8 KB |
284
+ | `search()` | 37.5 KB | 13.8 KB |
285
+ | `carousel()` | 43.9 KB | 16.0 KB |
286
+ | `vlist/synthetic` + `carousel()` | 50.0 KB | 18.3 KB |
287
+ | `vlist/synthetic` + `sortable()` | 46.7 KB | 16.7 KB |
288
+ | `vlist/vue` `useVList` | 28.3 KB | 10.7 KB |
289
+ | `vlist/svelte` `vlist` | 28.1 KB | 10.6 KB |
290
+ | `vlist/solid` `createVList` | 28.2 KB | 10.6 KB |
291
+ | `vlist/react` `useVList` | 28.3 KB | 10.7 KB |
292
+ | `vlist/react` + `grid()` | 35.8 KB | 13.3 KB |
293
+
294
+ Sizes are tree-shaken totals from `bun run size`, not additive plugin costs. Plugin rows include the native default factory plus that plugin; framework rows add the entry, with the framework itself external. The base is **10,735 bytes gzipped**, within the 10.59 KB budget (10,844 bytes). `bun run size` fails if a scenario fails to build, an unused plugin leaks into a bundle, or any published size exceeds its gzip budget. Synthetic input is **13,402 bytes** before plugins; with `scroll.mode`, a `vlist` list downloads the driver and its scrollbar as `synthetic-driver.js` (6.2 KB gzipped) only when it goes synthetic. The alias row measures the same source factory; the distributed alias re-exports it without duplicating the implementation.
295
+
296
+ Bundlephobia's badge measures the package's root entry, which re-exports every plugin, minified and gzipped as one bundle. With a tree-shaking bundler, an app that imports named exports from `vlist` bundles the base (**10.5 KB gzipped**) and the features it uses; the table's rows are each a combined size, not amounts to add up.
297
297
 
298
298
  ## Examples
299
299
 
@@ -336,10 +336,17 @@ cell, which sorts the column when it is sortable: give the control `tabindex`, o
336
336
  Enter and Space emit `column:sort` on a sortable header and never `column:click`, so an action a
337
337
  keyboard user must reach should be a `button` supplied in the header label.
338
338
 
339
- A table's rows have a fixed height, so `autosize()` cannot be combined with `table()`;
339
+ Table rows use configured heights and are not automatically measured, so
340
+ `autosize()` cannot be combined with `table()`;
340
341
  the `vlist/config` route wires `autosize()` when only an estimate is given (`item.estimatedHeight`)
341
342
  and throws at creation. Give the table a fixed `rowHeight` and the config a fixed `item.height` instead.
342
343
 
344
+ `estimatedRowHeight` is deprecated in 3.3.0 and will be removed in 4.0 (#345).
345
+ It remains accepted but does not size or measure rows; non-production builds warn
346
+ once per `table()` call. Use a numeric `rowHeight` for fixed rows or a `rowHeight`
347
+ function for variable row sizes. For heights that change after creation, the
348
+ `remeasureItem(index)` API in 3.3.0 works with a `rowHeight` function (#347).
349
+
343
350
  ### Grid Layout
344
351
 
345
352
  ```typescript
@@ -532,6 +539,7 @@ const list = createVList(config, [plugin1(), plugin2()])
532
539
  | `list.removeItems(ids)` | Batch remove (simultaneous animations) |
533
540
  | `list.getItemAt(index)` | Get item at index |
534
541
  | `list.getIndexById(id)` | Get index by item ID |
542
+ | `list.remeasureItem(index)` | Ask the size source to re-read one item after its content changed; returns `false` when the size model cannot address it |
535
543
 
536
544
  ### Navigation
537
545
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  The virtual list library for every framework. Ultra efficient, batteries-included, and accessible with composable plugins.
4
4
 
5
- **v3.2.0** — `scroll.mode` on the one `vlist` entry: the default, `"auto"`, scrolls natively and hands a list past the browser's size limit to synthetic input, which draws its own scrollbar. Vue, Svelte, Solid and React entries in the package itself (`vlist/vue`, `vlist/svelte`, `vlist/solid`, `vlist/react`), feature-first and tree-shaken like the vanilla builder; the separate adapter packages are deprecated. See the [changelog](https://github.com/floor/vlist/blob/main/CHANGELOG.md).
5
+ **v3.3.0** — `scroll.mode` on the one `vlist` entry: the default, `"auto"`, scrolls natively and hands a list past the browser's size limit to synthetic input, which draws its own scrollbar. Vue, Svelte, Solid and React entries in the package itself (`vlist/vue`, `vlist/svelte`, `vlist/solid`, `vlist/react`), feature-first and tree-shaken like the vanilla builder; the separate adapter packages are deprecated. See the [changelog](https://github.com/floor/vlist/blob/main/CHANGELOG.md).
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/vlist.svg)](https://www.npmjs.com/package/vlist)
8
8
  [![bundle size](https://img.shields.io/bundlephobia/minzip/vlist)](https://bundlephobia.com/package/vlist)
@@ -11,7 +11,7 @@ The virtual list library for every framework. Ultra efficient, batteries-include
11
11
 
12
12
  - **Accessible** — `a11y()` or a selection mode adds WAI-ARIA, 2D keyboard navigation, focus recovery, screen-reader DOM ordering
13
13
  - **Zero dependencies** — framework-agnostic core, with Vue, Svelte, Solid and React entries in the same package
14
- - **10.3 KB gzipped** — composable plugins with perfect tree-shaking (Bundlephobia's badge measures the root entry with every plugin at once)
14
+ - **10.5 KB gzipped** — composable plugins with perfect tree-shaking (Bundlephobia's badge measures the root entry with every plugin at once)
15
15
  - **Constant memory** — ~0.1 MB overhead at any scale, from 10K to 1M+ items
16
16
  - **Axis-neutral** — vertical and horizontal scrolling through a single code path, all plugins work in both orientations
17
17
 
@@ -131,36 +131,43 @@ The touch-only `.vlist-item--touch-sort` class suppresses selection and callouts
131
131
 
132
132
  | Entry / export | Minified | Gzipped |
133
133
  |---|---:|---:|
134
- | **Base (`vlist`)** | 27.3 KB | 10.3 KB |
135
- | `vlist/synthetic` (deprecated) | 34.2 KB | 12.9 KB |
136
- | `vlist/native` (alias) | 27.3 KB | 10.3 KB |
137
- | `a11y()` | 32.4 KB | 12.2 KB |
138
- | `selection()` | 37.8 KB | 13.6 KB |
139
- | `data()` | 41.0 KB | 15.1 KB |
140
- | `scrollbar()` | 35.5 KB | 13.2 KB |
141
- | `sortable()` | 39.2 KB | 13.9 KB |
142
- | `groups()` | 43.5 KB | 15.7 KB |
143
- | `page()` | 29.9 KB | 11.2 KB |
144
- | `snapshots()` | 30.6 KB | 11.4 KB |
145
- | `transition()` | 34.1 KB | 12.3 KB |
146
- | `autosize()` | 31.7 KB | 11.9 KB |
147
- | `grid()` | 34.8 KB | 12.9 KB |
148
- | `table()` | 46.4 KB | 16.4 KB |
149
- | `masonry()` | 39.4 KB | 14.7 KB |
150
- | `tree()` | 43.1 KB | 15.6 KB |
151
- | `search()` | 36.9 KB | 13.6 KB |
152
- | `carousel()` | 43.3 KB | 15.8 KB |
153
- | `vlist/synthetic` + `carousel()` | 49.3 KB | 18.1 KB |
154
- | `vlist/synthetic` + `sortable()` | 46.1 KB | 16.5 KB |
155
- | `vlist/vue` `useVList` | 27.7 KB | 10.5 KB |
156
- | `vlist/svelte` `vlist` | 27.5 KB | 10.4 KB |
157
- | `vlist/solid` `createVList` | 27.6 KB | 10.4 KB |
158
- | `vlist/react` `useVList` | 27.8 KB | 10.5 KB |
159
- | `vlist/react` + `grid()` | 35.2 KB | 13.1 KB |
160
-
161
- Sizes are tree-shaken totals from `bun run size`, not additive plugin costs. Plugin rows include the native default factory plus that plugin; framework rows add the entry, with the framework itself external. The base is **10,539 bytes gzipped**, within the 10.3 KB budget (10,547 bytes). `bun run size` fails if a scenario fails to build, an unused plugin leaks into a bundle, or any published size exceeds its gzip budget. Synthetic input is **13,192 bytes** before plugins; with `scroll.mode`, a `vlist` list downloads the driver and its scrollbar as `synthetic-driver.js` (6.2 KB gzipped) only when it goes synthetic. The alias row measures the same source factory; the distributed alias re-exports it without duplicating the implementation.
162
-
163
- Bundlephobia's badge measures the package's root entry, which re-exports every plugin, minified and gzipped as one bundle. With a tree-shaking bundler, an app that imports named exports from `vlist` bundles the base (**10.3 KB gzipped**) and the features it uses; the table's rows are each a combined size, not amounts to add up.
134
+ | **Base (`vlist`)** | 27.9 KB | 10.5 KB |
135
+ | `vlist/synthetic` (deprecated) | 34.8 KB | 13.1 KB |
136
+ | `vlist/native` (alias) | 27.9 KB | 10.5 KB |
137
+ | `a11y()` | 32.9 KB | 12.4 KB |
138
+ | `selection()` | 38.4 KB | 13.8 KB |
139
+ | `data()` | 41.5 KB | 15.3 KB |
140
+ | `scrollbar()` | 36.1 KB | 13.4 KB |
141
+ | `sortable()` | 39.8 KB | 14.1 KB |
142
+ | `groups()` | 44.2 KB | 15.9 KB |
143
+ | `page()` | 30.4 KB | 11.4 KB |
144
+ | `snapshots()` | 31.2 KB | 11.6 KB |
145
+ | `transition()` | 34.6 KB | 12.5 KB |
146
+ | `autosize()` | 32.3 KB | 12.1 KB |
147
+ | `grid()` | 35.4 KB | 13.1 KB |
148
+ | `table()` | 47.0 KB | 16.6 KB |
149
+ | `masonry()` | 40.1 KB | 14.9 KB |
150
+ | `tree()` | 43.7 KB | 15.8 KB |
151
+ | `search()` | 37.5 KB | 13.8 KB |
152
+ | `carousel()` | 43.9 KB | 16.0 KB |
153
+ | `vlist/synthetic` + `carousel()` | 50.0 KB | 18.3 KB |
154
+ | `vlist/synthetic` + `sortable()` | 46.7 KB | 16.7 KB |
155
+ | `vlist/vue` `useVList` | 28.3 KB | 10.7 KB |
156
+ | `vlist/svelte` `vlist` | 28.1 KB | 10.6 KB |
157
+ | `vlist/solid` `createVList` | 28.2 KB | 10.6 KB |
158
+ | `vlist/react` `useVList` | 28.3 KB | 10.7 KB |
159
+ | `vlist/react` + `grid()` | 35.8 KB | 13.3 KB |
160
+
161
+ Sizes are tree-shaken totals from `bun run size`, not additive plugin costs. Plugin rows include the native default factory plus that plugin; framework rows add the entry, with the framework itself external. The base is **10,735 bytes gzipped**, within the 10.59 KB budget (10,844 bytes). `bun run size` fails if a scenario fails to build, an unused plugin leaks into a bundle, or any published size exceeds its gzip budget. Synthetic input is **13,402 bytes** before plugins; with `scroll.mode`, a `vlist` list downloads the driver and its scrollbar as `synthetic-driver.js` (6.2 KB gzipped) only when it goes synthetic. The alias row measures the same source factory; the distributed alias re-exports it without duplicating the implementation.
162
+
163
+ Bundlephobia's badge measures the package's root entry, which re-exports every plugin, minified and gzipped as one bundle. With a tree-shaking bundler, an app that imports named exports from `vlist` bundles the base (**10.5 KB gzipped**) and the features it uses; the table's rows are each a combined size, not amounts to add up.
164
+
165
+ `table()`'s `estimatedRowHeight` is deprecated in 3.3.0 and will be removed in 4.0
166
+ (#345). It remains accepted but does not size or measure rows; non-production
167
+ builds warn once per `table()` call. Use `rowHeight` for fixed rows or a `rowHeight`
168
+ function with the `remeasureItem(index)` API in 3.3.0 for heights that
169
+ change after creation (#347). Table rows are not automatically measured and
170
+ `table()` remains incompatible with `autosize()`.
164
171
 
165
172
  ## Frameworks
166
173
 
@@ -255,6 +255,19 @@ export interface VList<T extends VListItem = VListItem> {
255
255
  appendItems(items: T[]): void;
256
256
  prependItems(items: T[]): void;
257
257
  updateItem(id: string | number, updates: Partial<T>): void;
258
+ /**
259
+ * Ask whichever per-item size source owns the list to re-read item `index`,
260
+ * then make the list observe the result: content size, scroll anchor and any
261
+ * plugin state derived from offsets. The item data is not written, so a
262
+ * mounted row keeps its DOM — and a focused control inside it.
263
+ *
264
+ * @param index Data index, in `[0, total)`. Never throws for an index.
265
+ * @returns `true` when a size source was asked (the size may be unchanged),
266
+ * `false` when the index is not an integer or out of range, the layout's
267
+ * size model cannot address one data item (`grid()`, `masonry()`,
268
+ * `carousel()`), or the item spec is fixed.
269
+ */
270
+ remeasureItem(index: number): boolean;
258
271
  insertItem(item: T, index?: number): void;
259
272
  removeItem(id: string | number): void;
260
273
  removeItems(ids: ReadonlyArray<string | number>): number;