vlist 1.9.1 → 2.0.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.
Files changed (108) hide show
  1. package/README.github.md +104 -97
  2. package/README.md +46 -33
  3. package/dist/constants.d.ts +11 -6
  4. package/dist/core/create.d.ts +10 -0
  5. package/dist/core/dom.d.ts +8 -0
  6. package/dist/core/hooks.d.ts +16 -0
  7. package/dist/core/index.d.ts +17 -0
  8. package/dist/core/pipeline.d.ts +51 -0
  9. package/dist/core/pool.d.ts +9 -0
  10. package/dist/core/scroll.d.ts +32 -0
  11. package/dist/core/sizes.d.ts +8 -0
  12. package/dist/core/state.d.ts +47 -0
  13. package/dist/core/types.d.ts +187 -0
  14. package/dist/{builder → core}/velocity.d.ts +1 -1
  15. package/dist/index.d.ts +28 -19
  16. package/dist/index.js +1 -1
  17. package/dist/internals.d.ts +11 -7
  18. package/dist/internals.js +1 -1
  19. package/dist/plugins/a11y/index.d.ts +2 -0
  20. package/dist/plugins/a11y/plugin.d.ts +13 -0
  21. package/dist/{features → plugins}/async/index.d.ts +1 -1
  22. package/dist/{features → plugins}/async/manager.d.ts +5 -1
  23. package/dist/plugins/async/plugin.d.ts +48 -0
  24. package/dist/plugins/autosize/index.d.ts +5 -0
  25. package/dist/plugins/autosize/plugin.d.ts +19 -0
  26. package/dist/plugins/grid/index.d.ts +7 -0
  27. package/dist/plugins/grid/plugin.d.ts +23 -0
  28. package/dist/{features → plugins}/groups/index.d.ts +1 -1
  29. package/dist/plugins/groups/plugin.d.ts +22 -0
  30. package/dist/plugins/masonry/index.d.ts +8 -0
  31. package/dist/plugins/masonry/plugin.d.ts +32 -0
  32. package/dist/plugins/page/index.d.ts +5 -0
  33. package/dist/plugins/page/plugin.d.ts +21 -0
  34. package/dist/plugins/scale/index.d.ts +5 -0
  35. package/dist/plugins/scale/plugin.d.ts +24 -0
  36. package/dist/plugins/scrollbar/index.d.ts +7 -0
  37. package/dist/plugins/scrollbar/plugin.d.ts +20 -0
  38. package/dist/plugins/selection/index.d.ts +6 -0
  39. package/dist/plugins/selection/plugin.d.ts +16 -0
  40. package/dist/{features → plugins}/selection/state.d.ts +8 -0
  41. package/dist/plugins/snapshots/index.d.ts +5 -0
  42. package/dist/plugins/snapshots/plugin.d.ts +17 -0
  43. package/dist/plugins/sortable/index.d.ts +6 -0
  44. package/dist/plugins/sortable/plugin.d.ts +34 -0
  45. package/dist/{features → plugins}/table/index.d.ts +1 -1
  46. package/dist/plugins/table/plugin.d.ts +20 -0
  47. package/dist/plugins/transition/index.d.ts +5 -0
  48. package/dist/plugins/transition/plugin.d.ts +22 -0
  49. package/dist/size.json +1 -1
  50. package/dist/utils/padding.d.ts +2 -4
  51. package/dist/vlist-grid.css +1 -1
  52. package/dist/vlist-masonry.css +1 -1
  53. package/dist/vlist-table.css +1 -1
  54. package/dist/vlist.css +1 -1
  55. package/package.json +9 -4
  56. package/dist/builder/a11y.d.ts +0 -16
  57. package/dist/builder/api.d.ts +0 -21
  58. package/dist/builder/context.d.ts +0 -36
  59. package/dist/builder/core.d.ts +0 -16
  60. package/dist/builder/data.d.ts +0 -71
  61. package/dist/builder/dom.d.ts +0 -15
  62. package/dist/builder/index.d.ts +0 -25
  63. package/dist/builder/materialize.d.ts +0 -166
  64. package/dist/builder/pool.d.ts +0 -10
  65. package/dist/builder/range.d.ts +0 -10
  66. package/dist/builder/scroll.d.ts +0 -24
  67. package/dist/builder/types.d.ts +0 -512
  68. package/dist/features/async/feature.d.ts +0 -72
  69. package/dist/features/autosize/feature.d.ts +0 -34
  70. package/dist/features/autosize/index.d.ts +0 -2
  71. package/dist/features/grid/feature.d.ts +0 -48
  72. package/dist/features/grid/index.d.ts +0 -9
  73. package/dist/features/groups/feature.d.ts +0 -75
  74. package/dist/features/masonry/feature.d.ts +0 -45
  75. package/dist/features/masonry/index.d.ts +0 -9
  76. package/dist/features/page/feature.d.ts +0 -109
  77. package/dist/features/page/index.d.ts +0 -9
  78. package/dist/features/scale/feature.d.ts +0 -42
  79. package/dist/features/scale/index.d.ts +0 -10
  80. package/dist/features/scrollbar/feature.d.ts +0 -81
  81. package/dist/features/scrollbar/index.d.ts +0 -8
  82. package/dist/features/selection/feature.d.ts +0 -91
  83. package/dist/features/selection/index.d.ts +0 -7
  84. package/dist/features/snapshots/feature.d.ts +0 -79
  85. package/dist/features/snapshots/index.d.ts +0 -9
  86. package/dist/features/sortable/feature.d.ts +0 -101
  87. package/dist/features/sortable/index.d.ts +0 -6
  88. package/dist/features/table/feature.d.ts +0 -67
  89. package/dist/features/transition/feature.d.ts +0 -30
  90. package/dist/features/transition/index.d.ts +0 -9
  91. /package/dist/{features → plugins}/async/placeholder.d.ts +0 -0
  92. /package/dist/{features → plugins}/async/sparse.d.ts +0 -0
  93. /package/dist/{features → plugins}/grid/layout.d.ts +0 -0
  94. /package/dist/{features → plugins}/grid/renderer.d.ts +0 -0
  95. /package/dist/{features → plugins}/grid/types.d.ts +0 -0
  96. /package/dist/{features → plugins}/groups/async-bridge.d.ts +0 -0
  97. /package/dist/{features → plugins}/groups/layout.d.ts +0 -0
  98. /package/dist/{features → plugins}/groups/sticky.d.ts +0 -0
  99. /package/dist/{features → plugins}/groups/types.d.ts +0 -0
  100. /package/dist/{features → plugins}/masonry/layout.d.ts +0 -0
  101. /package/dist/{features → plugins}/masonry/renderer.d.ts +0 -0
  102. /package/dist/{features → plugins}/masonry/types.d.ts +0 -0
  103. /package/dist/{features → plugins}/scrollbar/controller.d.ts +0 -0
  104. /package/dist/{features → plugins}/scrollbar/scrollbar.d.ts +0 -0
  105. /package/dist/{features → plugins}/table/header.d.ts +0 -0
  106. /package/dist/{features → plugins}/table/layout.d.ts +0 -0
  107. /package/dist/{features → plugins}/table/renderer.d.ts +0 -0
  108. /package/dist/{features → plugins}/table/types.d.ts +0 -0
@@ -1,75 +0,0 @@
1
- /**
2
- * vlist/groups - Builder Feature
3
- * Adds grouped lists with sticky headers.
4
- *
5
- * Priority: 10 (runs first — transforms item list and height function before rendering)
6
- *
7
- * What it wires:
8
- * - Transforms item list — inserts header items at group boundaries
9
- * - Replaces height function — headers use headerHeight, data items use configured item.height
10
- * - Unified template — dispatches to headerTemplate for headers, user template for items
11
- * - Sticky header DOM — creates a positioned header element that updates as you scroll
12
- * - Index mapping — translates between data indices and layout indices
13
- * - CSS class — adds .vlist--grouped to the root element
14
- *
15
- * Restrictions:
16
- * - Items must be pre-sorted by group
17
- *
18
- * Can be combined with:
19
- * - withGrid for grouped 2D layouts
20
- * - withAsync for grouped lists with async pagination
21
- * - reverse: true (sticky header shows current section as you scroll up through history)
22
- * - orientation: 'horizontal' (sticky headers stick to left edge, push left when next header approaches)
23
- */
24
- import type { VListItem } from "../../types";
25
- import type { VListFeature } from "../../builder/types";
26
- /** Groups feature configuration */
27
- export interface GroupsFeatureConfig {
28
- /** Returns group key for item at index (required) */
29
- getGroupForIndex: (index: number, item?: any) => string;
30
- /** Group header configuration — mirrors the `item` config shape */
31
- header?: {
32
- /** Header size in pixels — vertical scrolling (default) */
33
- height?: number;
34
- /** Header size in pixels — horizontal scrolling */
35
- width?: number;
36
- /** Render function for headers (required) */
37
- template: (key: string, groupIndex: number) => HTMLElement | string;
38
- };
39
- /** @deprecated Use `header.height` instead. */
40
- headerHeight?: number;
41
- /** @deprecated Use `header.template` instead. */
42
- headerTemplate?: (key: string, groupIndex: number) => HTMLElement | string;
43
- /** Enable sticky headers — iOS Contacts style (default: true) */
44
- sticky?: boolean;
45
- }
46
- /**
47
- * Create a groups feature for the builder.
48
- *
49
- * Adds grouped lists with sticky section headers.
50
- *
51
- * ```ts
52
- * import { vlist, withGroups } from 'vlist'
53
- *
54
- * const contacts = vlist({
55
- * container: '#contacts',
56
- * item: { height: 56, template: renderContact },
57
- * items: sortedContacts,
58
- * })
59
- * .use(withGroups({
60
- * getGroupForIndex: (i) => sortedContacts[i].lastName[0],
61
- * header: {
62
- * height: 32,
63
- * template: (letter) => {
64
- * const el = document.createElement('div')
65
- * el.className = 'letter-header'
66
- * el.textContent = letter
67
- * return el
68
- * },
69
- * },
70
- * }))
71
- * .build()
72
- * ```
73
- */
74
- export declare const withGroups: <T extends VListItem = VListItem>(groupsRawConfig: GroupsFeatureConfig) => VListFeature<T>;
75
- //# sourceMappingURL=feature.d.ts.map
@@ -1,45 +0,0 @@
1
- /**
2
- * vlist/masonry - Builder Feature
3
- * Switches from list layout to masonry/Pinterest-style layout.
4
- *
5
- * Priority: 10 (runs first — replaces the renderer before anything else renders)
6
- *
7
- * What it does:
8
- * - Replaces renderer — swaps the list renderer with a masonry renderer
9
- * - Calculates item placements using shortest-lane algorithm
10
- * - Positions items using absolute coordinates (no row alignment)
11
- * - Renders only visible items based on scroll position
12
- * - CSS class — adds .vlist--masonry to the root element
13
- *
14
- * Key differences from grid:
15
- * - No row-based virtualization (items flow into shortest column/row)
16
- * - O(n) layout calculation (must track lane heights)
17
- * - Items positioned by cached x/y coordinates
18
- * - Variable heights create organic, packed layout
19
- *
20
- * Restrictions:
21
- * - Cannot be combined with reverse: true
22
- * - Item sizes must be deterministic (no dynamic content sizing)
23
- *
24
- * Can be combined with withSelection for selectable masonry layouts.
25
- *
26
- * Performance:
27
- * - Early exit when scroll position + container size unchanged (zero work per redundant frame)
28
- * - Cached empty Set for no-selection case (zero allocation per frame)
29
- * - Viewport state mutated in place (no object creation per frame)
30
- * - Cached getItem closure (no closure allocation per frame)
31
- *
32
- * - Items passed to renderer via data manager reference (no sparse array)
33
- * - All data mutation methods intercepted for layout recalculation
34
- */
35
- import type { VListItem } from "../../types";
36
- import type { VListFeature } from "../../builder/types";
37
- /** Masonry feature configuration */
38
- export interface MasonryFeatureConfig {
39
- /** Number of cross-axis divisions (columns in vertical, rows in horizontal) */
40
- columns: number;
41
- /** Gap between items in pixels (default: 0) */
42
- gap?: number;
43
- }
44
- export declare const withMasonry: <T extends VListItem = VListItem>(config: MasonryFeatureConfig) => VListFeature<T>;
45
- //# sourceMappingURL=feature.d.ts.map
@@ -1,9 +0,0 @@
1
- /**
2
- * vlist - Masonry Domain
3
- * Pinterest-style layout with shortest-lane placement
4
- */
5
- export { withMasonry, type MasonryFeatureConfig } from "./feature";
6
- export { createMasonryLayout } from "./layout";
7
- export { createMasonryRenderer, type MasonryRenderer, type GetItemFn } from "./renderer";
8
- export type { MasonryConfig, MasonryLayout, ItemPlacement, } from "./types";
9
- //# sourceMappingURL=index.d.ts.map
@@ -1,109 +0,0 @@
1
- /**
2
- * vlist/window - Window Scroll Mode Feature
3
- *
4
- * Enables the list to scroll with the page instead of in its own container.
5
- * Useful for infinite feeds, full-page lists, and chat UIs that integrate
6
- * with page scroll.
7
- *
8
- * Priority: 5 (runs early, before other features that depend on scroll)
9
- *
10
- * What it does:
11
- * - Uses window as scroll target instead of viewport element
12
- * - Calculates scroll position relative to document
13
- * - Uses window.innerWidth/innerHeight for container dimensions
14
- * - Listens to window resize events instead of ResizeObserver
15
- * - Adjusts DOM styles (overflow: visible, height: auto)
16
- * - Optionally accounts for fixed/sticky chrome via scrollPadding
17
- * - Uses behavior: "instant" on all scrollTo calls to override CSS
18
- * scroll-behavior: smooth that may be set on the page
19
- *
20
- * Bundle impact: ~0.3 KB gzipped when used
21
- */
22
- import type { VListItem } from "../../types";
23
- import type { VListFeature } from "../../builder/types";
24
- /**
25
- * Options for the window scroll mode feature.
26
- */
27
- export interface WithPageOptions {
28
- /**
29
- * Scroll padding — insets from the viewport edges where fixed/sticky
30
- * elements (headers, footers, toolbars) live.
31
- *
32
- * When keyboard focus moves an item behind a sticky bar, the list
33
- * auto-scrolls to keep it within the visible (unobstructed) area.
34
- * Also affects `scrollToIndex` alignment (start/center/end).
35
- *
36
- * Mirrors CSS `scroll-padding` semantics: defines the optimal viewing
37
- * region within the scrollport.
38
- *
39
- * Values can be numbers (pixels) or functions that return pixels
40
- * (useful when the sticky element's height is dynamic).
41
- *
42
- * @example
43
- * ```ts
44
- * withPage({
45
- * scrollPadding: { top: 60, bottom: 50 }
46
- * })
47
- * ```
48
- *
49
- * @example Dynamic values
50
- * ```ts
51
- * withPage({
52
- * scrollPadding: {
53
- * top: () => document.getElementById('sticky-header')!.offsetHeight,
54
- * bottom: 50
55
- * }
56
- * })
57
- * ```
58
- */
59
- scrollPadding?: {
60
- top?: number | (() => number);
61
- bottom?: number | (() => number);
62
- left?: number | (() => number);
63
- right?: number | (() => number);
64
- };
65
- }
66
- /**
67
- * Create a window scroll mode feature.
68
- *
69
- * Use this when you want your list to scroll with the page instead of
70
- * in a fixed-height container.
71
- *
72
- * @example
73
- * ```ts
74
- * import { vlist } from 'vlist/builder'
75
- * import { withWindow } from 'vlist/window'
76
- *
77
- * const feed = vlist({
78
- * container: '#infinite-feed',
79
- * item: { height: 200, template: renderPost },
80
- * items: posts
81
- * })
82
- * .use(withWindow())
83
- * .build()
84
- * ```
85
- *
86
- * @example With scroll padding for sticky chrome
87
- * ```ts
88
- * const feed = vlist({
89
- * container: '#infinite-feed',
90
- * item: { height: 200, template: renderPost },
91
- * items: posts
92
- * })
93
- * .use(withPage({ scrollPadding: { top: 60, bottom: 50 } }))
94
- * .build()
95
- * ```
96
- *
97
- * @example Horizontal window scrolling
98
- * ```ts
99
- * const timeline = vlist({
100
- * container: '#timeline',
101
- * item: { height: 100, template: renderEvent },
102
- * orientation: 'horizontal'
103
- * })
104
- * .use(withWindow())
105
- * .build()
106
- * ```
107
- */
108
- export declare const withPage: <T extends VListItem = VListItem>(options?: WithPageOptions) => VListFeature<T>;
109
- //# sourceMappingURL=feature.d.ts.map
@@ -1,9 +0,0 @@
1
- /**
2
- * vlist/window - Window Scroll Mode Feature
3
- *
4
- * Entry point for the window scroll feature.
5
- */
6
- export { withPage } from "./feature";
7
- export type { WithPageOptions } from "./feature";
8
- export type { VListFeature } from "../../builder/types";
9
- //# sourceMappingURL=index.d.ts.map
@@ -1,42 +0,0 @@
1
- /**
2
- * vlist/compression - Builder Feature
3
- * Enables support for lists with 1M+ items by compressing the scroll space
4
- * when the total height exceeds the browser's ~16.7M pixel limit.
5
- *
6
- * Priority: 20 (runs before scrollbar, after grid/groups)
7
- *
8
- * What it wires:
9
- * - Scroll mode switch — transitions from native to compressed scrolling when needed
10
- * - Scroll position mapping — maps compressed scroll positions to item indices
11
- * - Item positioning — positions items relative to viewport in compressed mode
12
- * - Custom scrollbar fallback — forces custom scrollbar in compressed mode
13
- * - Compression slack — extends scroll range so the linear index formula reaches every item
14
- * - Cached compression state — recalculates only when total item count changes
15
- * - Smooth scroll interpolation — lerp-based wheel handling for cross-browser consistency
16
- * - Touch scroll support — finger tracking + momentum for iOS Safari / mobile browsers
17
- *
18
- * No configuration needed — compression activates automatically when the total
19
- * height exceeds the browser limit, and deactivates when items are removed.
20
- */
21
- import type { VListItem } from "../../types";
22
- import type { VListFeature } from "../../builder/types";
23
- /** Configuration options for the scale feature */
24
- export interface ScaleConfig {
25
- /**
26
- * Force compressed scroll mode even when the total size is below the
27
- * browser's ~16.7M pixel limit.
28
- *
29
- * When `true`, the feature always activates compressed scrolling
30
- * (custom wheel/touch handling, lerp-based smooth scroll, custom
31
- * scrollbar fallback) regardless of the list size. This is useful for:
32
- *
33
- * - **Testing** — verify compression behaviour with a small item set
34
- * - **Consistent UX** — prefer the smooth scroll physics for all lists
35
- * - **Pre-emptive** — avoid the mode switch when items are added at runtime
36
- *
37
- * @default false
38
- */
39
- force?: boolean;
40
- }
41
- export declare const withScale: <T extends VListItem = VListItem>(config?: ScaleConfig) => VListFeature<T>;
42
- //# sourceMappingURL=feature.d.ts.map
@@ -1,10 +0,0 @@
1
- /**
2
- * vlist - Compression Sub-module
3
- * Re-exports compression utilities for tree-shakeable imports
4
- *
5
- * Usage: import { getCompressionInfo } from 'vlist/compression'
6
- * Usage: import { withScale } from 'vlist/compression'
7
- */
8
- export { MAX_VIRTUAL_SIZE, getCompressionState, needsCompression, getMaxItemsWithoutCompression, getCompressionInfo, calculateCompressedVisibleRange, calculateCompressedRenderRange, calculateCompressedItemPosition, calculateCompressedScrollToIndex, calculateIndexFromScrollPosition, type CompressionState, } from "../../rendering/scale";
9
- export { withScale, type ScaleConfig } from "./feature";
10
- //# sourceMappingURL=index.d.ts.map
@@ -1,81 +0,0 @@
1
- /**
2
- * vlist/scroll - Builder Feature
3
- * Wraps the custom scrollbar into a VListFeature for the composable builder.
4
- *
5
- * Priority: 30 (runs after renderer/data setup but before selection)
6
- *
7
- * What it wires:
8
- * - DOM elements — track, thumb, and optional hover zone appended to viewport
9
- * - CSS class — .vlist-viewport--custom-scrollbar hides native scrollbar
10
- * - Drag handlers — mousedown on thumb, mousemove/mouseup on document
11
- * - Track click — click on track to jump to position
12
- * - Hover handlers — mouseenter/leave on track, hover zone, and viewport
13
- * - Scroll sync — updates thumb position on every scroll frame
14
- * - Resize sync — updates thumb size when container or content height changes
15
- *
16
- * No public methods are added — the scrollbar is entirely automatic.
17
- */
18
- import type { VListItem } from "../../types";
19
- import type { VListFeature } from "../../builder/types";
20
- /** Scrollbar feature configuration */
21
- export interface ScrollbarFeatureConfig {
22
- /** Auto-hide scrollbar after idle (default: true) */
23
- autoHide?: boolean;
24
- /** Auto-hide delay in milliseconds (default: 1000) */
25
- autoHideDelay?: number;
26
- /** Minimum thumb size in pixels (default: 30) */
27
- minThumbSize?: number;
28
- /**
29
- * Show scrollbar when hovering near the scrollbar edge (default: true).
30
- * When true, an invisible hover zone is placed along the scrollbar edge.
31
- */
32
- showOnHover?: boolean;
33
- /**
34
- * Width of the invisible hover zone in pixels (default: 16).
35
- * Only used when `showOnHover` is true.
36
- */
37
- hoverZoneWidth?: number;
38
- /**
39
- * Show scrollbar when the mouse enters the list viewport (default: true).
40
- * When false, the scrollbar only appears on scroll or hover near edge.
41
- */
42
- showOnViewportEnter?: boolean;
43
- /**
44
- * Reserve layout space for the scrollbar (default: false).
45
- * When true, content shrinks to make room for the scrollbar track so it
46
- * never overlaps items. Equivalent to CSS `scrollbar-gutter: stable`.
47
- */
48
- gutter?: boolean;
49
- /**
50
- * Padding between the scrollbar track and the viewport edges in pixels (default: 1).
51
- * Insets the track from the right wall and from the top and bottom, so the scrollbar
52
- * floats rather than sitting flush against the edges. Also adjusts the thumb travel
53
- * range to keep position accurate.
54
- * Can also be set globally via the `--vlist-custom-scrollbar-padding` CSS variable.
55
- */
56
- padding?: number;
57
- /**
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
- */
63
- clickBehavior?: 'jump' | 'scroll' | 'page';
64
- }
65
- /**
66
- * Create a scrollbar feature for the builder.
67
- *
68
- * Replaces the native browser scrollbar with a custom, cross-browser
69
- * consistent scrollbar.
70
- *
71
- * ```ts
72
- * import { vlist } from 'vlist/builder'
73
- * import { withScrollbar } from 'vlist/scroll'
74
- *
75
- * const list = vlist({ ... })
76
- * .use(withScrollbar({ autoHide: true, autoHideDelay: 1000 }))
77
- * .build()
78
- * ```
79
- */
80
- export declare const withScrollbar: <T extends VListItem = VListItem>(config?: ScrollbarFeatureConfig) => VListFeature<T>;
81
- //# sourceMappingURL=feature.d.ts.map
@@ -1,8 +0,0 @@
1
- /**
2
- * vlist - Scroll Domain
3
- * Scroll controller and custom scrollbar
4
- */
5
- export { withScrollbar, type ScrollbarFeatureConfig } from "./feature";
6
- export { createScrollController, rafThrottle, isAtBottom, isAtTop, getScrollPercentage, isRangeVisible, type ScrollController, type ScrollControllerConfig, type ScrollEventData, type ScrollDirection, } from "./controller";
7
- export { createScrollbar, type Scrollbar, type ScrollbarConfig, type ScrollCallback, } from "./scrollbar";
8
- //# sourceMappingURL=index.d.ts.map
@@ -1,91 +0,0 @@
1
- /**
2
- * vlist/selection - Builder Feature
3
- * Wraps the selection domain into a VListFeature for the composable builder.
4
- *
5
- * Priority: 50 (runs after renderer and data are ready)
6
- *
7
- * Follows the WAI-ARIA APG "Recommended" multi-select listbox model:
8
- *
9
- * What it wires:
10
- * - Click handler on items container — toggles selection on item click
11
- * - Shift+click in multiple mode selects a contiguous range from last-selected item
12
- * - Keyboard handler on root — ArrowUp/Down/PageUp/PageDown/Home/End for focus, Space/Enter for toggle
13
- * - In single mode with followFocus: true, selection follows focus on arrow keys
14
- * - In multiple mode, arrow keys move focus only; Space/Enter toggles selection
15
- * - Shift+Arrow toggles the destination item (additive, one at a time)
16
- * - Shift+Space selects a contiguous range from last-selected item to focused item
17
- * - Ctrl+Shift+Home/End selects from focused item to first/last item
18
- * - Ctrl+A / Cmd+A selects all (or deselects all if all are selected)
19
- * - ARIA attributes — aria-selected on items, aria-activedescendant on root
20
- * - Live region — announces selection changes to screen readers
21
- * - Render integration — registers internal getters (_getSelectedIds,
22
- * _getFocusedIndex) so renderers read real selection state directly,
23
- * eliminating the previous querySelectorAll-based DOM bypass.
24
- *
25
- * Added methods: select, deselect, toggleSelect, selectAll, clearSelection,
26
- * getSelected, getSelectedItems, selectNext, selectPrevious
27
- *
28
- * Internal methods (for renderer integration, not public API):
29
- * _getSelectedIds — returns the live Set<string|number> of selected IDs
30
- * _getFocusedIndex — returns the current focused index
31
- *
32
- * Added events: item:click, selection:change
33
- */
34
- import type { VListItem, SelectionMode } from "../../types";
35
- import type { VListFeature } from "../../builder/types";
36
- /** Selection feature configuration */
37
- export interface SelectionFeatureConfig {
38
- /** Selection mode (default: 'single') */
39
- mode?: SelectionMode;
40
- /** Initially selected item IDs */
41
- initial?: Array<string | number>;
42
- /**
43
- * When true, arrow keys select the focused item in single mode
44
- * (WAI-ARIA "selection follows focus" pattern). Default: false.
45
- * Ignored in multiple mode (focus and selection are always independent).
46
- */
47
- followFocus?: boolean;
48
- /**
49
- * Which item Shift+Arrow toggles in multiple mode.
50
- * - `'origin'` (default) — toggles the item you're moving FROM (macOS-style).
51
- * - `'destination'` — toggles the item you're moving TO
52
- * (WAI-ARIA APG recommended model).
53
- *
54
- * Only affects Shift+Arrow keys; has no effect on Shift+Space,
55
- * Shift+Click, or Ctrl+Shift+Home/End.
56
- */
57
- shiftArrowToggle?: "origin" | "destination";
58
- /**
59
- * Show focus ring on mouse click (default: false).
60
- * By default, clicking an item selects it but does not show the focus
61
- * ring — matching the web platform's :focus-visible convention.
62
- * Set to true for file-manager or spreadsheet-style UIs where the
63
- * focus indicator doubles as a "current item" marker.
64
- */
65
- focusOnClick?: boolean;
66
- /**
67
- * How right-click affects selection (default: 'select').
68
- * - `'select'` — if the item is not selected, clear selection and select it;
69
- * if already selected, keep current selection (file explorer behavior).
70
- * - `'keep'` — never change selection on right-click.
71
- * - `false` — don't register a contextmenu handler at all.
72
- */
73
- contextMenu?: "select" | "keep" | false;
74
- }
75
- /**
76
- * Create a selection feature for the builder.
77
- *
78
- * ```ts
79
- * import { vlist } from 'vlist/builder'
80
- * import { withSelection } from 'vlist/selection'
81
- *
82
- * const list = vlist({ ... })
83
- * .use(withSelection({ mode: 'multiple', initial: ['id-1'] }))
84
- * .build()
85
- *
86
- * list.select('id-2')
87
- * list.getSelected() // ['id-1', 'id-2']
88
- * ```
89
- */
90
- export declare const withSelection: <T extends VListItem = VListItem>(config?: SelectionFeatureConfig) => VListFeature<T>;
91
- //# sourceMappingURL=feature.d.ts.map
@@ -1,7 +0,0 @@
1
- /**
2
- * vlist - Selection Domain
3
- * Selection state management
4
- */
5
- export { withSelection, type SelectionFeatureConfig } from "./feature";
6
- export { createSelectionState, selectItems, deselectItems, toggleSelection, selectAll, clearSelection, setFocusedIndex, moveFocusUp, moveFocusDown, moveFocusToFirst, moveFocusToLast, moveFocusByPage, selectFocused, selectRange, getSelectedIds, getSelectedItems, getSelectionCount, isSelected, isSelectionEmpty, claimPlaceholderSelection, type SelectionState, } from "./state";
7
- //# sourceMappingURL=index.d.ts.map
@@ -1,79 +0,0 @@
1
- /**
2
- * vlist/snapshots - Builder Feature
3
- * Adds scroll save/restore for SPA navigation and tab switching.
4
- *
5
- * Priority: 50 (runs last — needs all other features initialized)
6
- *
7
- * What it wires:
8
- * - getScrollSnapshot() — captures current scroll position (item index + sub-pixel offset)
9
- * - restoreScroll() — restores scroll position from snapshot
10
- * - autoSave — automatically saves snapshots to sessionStorage on scroll idle
11
- * and selection change, and auto-restores on next build()
12
- *
13
- * Snapshots capture the first visible item index and the pixel offset within
14
- * that item — not raw scrollTop. This means:
15
- * - Snapshots survive list recreation (navigate away and back)
16
- * - Snapshots work correctly with compression (1M+ items)
17
- * - Snapshots include selection state if selection is installed
18
- *
19
- * Added methods: getScrollSnapshot, restoreScroll
20
- *
21
- * Helper:
22
- * - getAutoSaveSnapshot(key) — read a saved snapshot from sessionStorage
23
- * so that withAsync can derive `autoLoad` and `total` from it.
24
- */
25
- import type { VListItem, ScrollSnapshot } from "../../types";
26
- import type { VListFeature } from "../../builder/types";
27
- /** Configuration for the snapshots feature. */
28
- export interface SnapshotConfig {
29
- /**
30
- * Snapshot to restore automatically after `build()` completes.
31
- *
32
- * When provided, `restoreScroll(restore)` is scheduled via
33
- * `queueMicrotask` — it runs right after `.build()` returns but
34
- * before the browser paints, so the user never sees position 0.
35
- *
36
- * ```ts
37
- * const saved = sessionStorage.getItem('scroll');
38
- * const snapshot = saved ? JSON.parse(saved) : undefined;
39
- *
40
- * const list = vlist({ ... })
41
- * .use(withAsync({
42
- * adapter,
43
- * autoLoad: !snapshot, // skip autoLoad when restoring
44
- * total: snapshot?.total, // from snapshot — no hardcoded constant needed
45
- * }))
46
- * .use(withSnapshots({ restore: snapshot })) // auto-restores after build()
47
- * .build();
48
- * ```
49
- */
50
- restore?: ScrollSnapshot;
51
- /**
52
- * Automatically save and restore snapshots via sessionStorage.
53
- *
54
- * Pass a string key to enable — snapshots are saved to
55
- * `sessionStorage` under that key whenever scroll becomes idle
56
- * or selection changes. On the next `build()`, the snapshot is
57
- * automatically restored if a matching key exists.
58
- *
59
- * This replaces the manual save/restore pattern — no event
60
- * listeners, debounce timers, or sessionStorage calls needed.
61
- *
62
- * ```ts
63
- * // That's it — save and restore are fully automatic:
64
- * const list = vlist({ ... })
65
- * .use(withAsync({ adapter }))
66
- * .use(withSnapshots({ autoSave: 'my-list-scroll' }))
67
- * .build();
68
- * ```
69
- *
70
- * When `autoSave` is set, the `restore` option is ignored —
71
- * the saved snapshot is read from sessionStorage automatically.
72
- * The `autoLoad` and `total` options on `withAsync` are also
73
- * configured automatically (autoLoad is skipped when restoring,
74
- * and total is read from the snapshot).
75
- */
76
- autoSave?: string;
77
- }
78
- export declare const withSnapshots: <T extends VListItem = VListItem>(config?: SnapshotConfig) => VListFeature<T>;
79
- //# sourceMappingURL=feature.d.ts.map
@@ -1,9 +0,0 @@
1
- /**
2
- * vlist/snapshots - Scroll Save/Restore
3
- * Feature for SPA navigation and tab switching
4
- *
5
- * Usage: import { withSnapshots } from 'vlist/snapshots'
6
- */
7
- export { withSnapshots } from "./feature";
8
- export type { SnapshotConfig } from "./feature";
9
- //# sourceMappingURL=index.d.ts.map