vlist 0.1.3 → 1.5.4

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 (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +558 -0
  3. package/dist/builder/a11y.d.ts +16 -0
  4. package/dist/builder/api.d.ts +21 -0
  5. package/dist/builder/context.d.ts +36 -0
  6. package/dist/builder/core.d.ts +16 -0
  7. package/dist/builder/data.d.ts +69 -0
  8. package/dist/builder/dom.d.ts +15 -0
  9. package/dist/builder/index.d.ts +25 -0
  10. package/dist/builder/materialize.d.ts +165 -0
  11. package/dist/builder/pool.d.ts +10 -0
  12. package/dist/builder/range.d.ts +10 -0
  13. package/dist/builder/scroll.d.ts +24 -0
  14. package/dist/builder/types.d.ts +464 -0
  15. package/dist/builder/velocity.d.ts +23 -0
  16. package/dist/constants.d.ts +58 -0
  17. package/dist/events/emitter.d.ts +18 -0
  18. package/dist/events/index.d.ts +6 -0
  19. package/dist/features/async/feature.d.ts +72 -0
  20. package/dist/features/async/index.d.ts +9 -0
  21. package/dist/features/async/manager.d.ts +103 -0
  22. package/dist/features/async/placeholder.d.ts +54 -0
  23. package/dist/features/async/sparse.d.ts +91 -0
  24. package/dist/features/autosize/feature.d.ts +34 -0
  25. package/dist/features/autosize/index.d.ts +2 -0
  26. package/dist/features/grid/feature.d.ts +48 -0
  27. package/dist/features/grid/index.d.ts +9 -0
  28. package/dist/features/grid/layout.d.ts +29 -0
  29. package/dist/features/grid/renderer.d.ts +71 -0
  30. package/dist/features/grid/types.d.ts +71 -0
  31. package/dist/features/groups/feature.d.ts +74 -0
  32. package/dist/features/groups/index.d.ts +10 -0
  33. package/dist/features/groups/layout.d.ts +47 -0
  34. package/dist/features/groups/sticky.d.ts +21 -0
  35. package/dist/features/groups/types.d.ts +86 -0
  36. package/dist/features/masonry/feature.d.ts +45 -0
  37. package/dist/features/masonry/index.d.ts +9 -0
  38. package/dist/features/masonry/layout.d.ts +29 -0
  39. package/dist/features/masonry/renderer.d.ts +55 -0
  40. package/dist/features/masonry/types.d.ts +68 -0
  41. package/dist/features/page/feature.d.ts +53 -0
  42. package/dist/features/page/index.d.ts +8 -0
  43. package/dist/features/scale/feature.d.ts +42 -0
  44. package/dist/features/scale/index.d.ts +10 -0
  45. package/dist/features/scrollbar/controller.d.ts +121 -0
  46. package/dist/features/scrollbar/feature.d.ts +60 -0
  47. package/dist/features/scrollbar/index.d.ts +8 -0
  48. package/dist/features/scrollbar/scrollbar.d.ts +73 -0
  49. package/dist/features/selection/feature.d.ts +75 -0
  50. package/dist/features/selection/index.d.ts +7 -0
  51. package/dist/features/selection/state.d.ts +115 -0
  52. package/dist/features/snapshots/feature.d.ts +79 -0
  53. package/dist/features/snapshots/index.d.ts +9 -0
  54. package/dist/features/table/feature.d.ts +67 -0
  55. package/dist/features/table/header.d.ts +49 -0
  56. package/dist/features/table/index.d.ts +10 -0
  57. package/dist/features/table/layout.d.ts +26 -0
  58. package/dist/features/table/renderer.d.ts +72 -0
  59. package/dist/features/table/types.d.ts +239 -0
  60. package/dist/index.d.ts +28 -0
  61. package/dist/index.js +1 -0
  62. package/dist/internals.d.ts +21 -0
  63. package/dist/internals.js +1 -0
  64. package/dist/rendering/index.d.ts +12 -0
  65. package/dist/rendering/measured.d.ts +52 -0
  66. package/dist/rendering/renderer.d.ts +111 -0
  67. package/dist/rendering/scale.d.ts +121 -0
  68. package/dist/rendering/scroll.d.ts +23 -0
  69. package/dist/rendering/sizes.d.ts +63 -0
  70. package/dist/rendering/sort.d.ts +33 -0
  71. package/dist/rendering/viewport.d.ts +139 -0
  72. package/dist/size.json +1 -0
  73. package/dist/types.d.ts +487 -0
  74. package/dist/utils/padding.d.ts +38 -0
  75. package/dist/utils/stats.d.ts +49 -0
  76. package/dist/vlist-extras.css +1 -0
  77. package/dist/vlist-grid.css +1 -0
  78. package/dist/vlist-masonry.css +1 -0
  79. package/dist/vlist-table.css +1 -0
  80. package/dist/vlist.css +1 -0
  81. package/package.json +66 -14
  82. package/README.MD +0 -80
  83. package/index.d.ts +0 -3
  84. package/index.js +0 -196
  85. package/virtual-scroll.component.d.ts +0 -34
  86. package/vlist.d.ts +0 -4
  87. package/vlist.metadata.json +0 -1
  88. package/vlist.umd.js +0 -197
@@ -0,0 +1,73 @@
1
+ /**
2
+ * vlist - Custom Scrollbar
3
+ * Provides visual scroll indication for compressed mode where native scrollbar is hidden
4
+ *
5
+ * Features:
6
+ * - Visual track and thumb
7
+ * - Thumb size proportional to visible content
8
+ * - Click on track to jump to position
9
+ * - Drag thumb to scroll
10
+ * - Auto-hide after idle (optional)
11
+ * - Show on hover with configurable hover zone (optional)
12
+ * - CSS variables for customization
13
+ * - Horizontal mode support (direction-aware axis)
14
+ */
15
+ /** Scrollbar configuration */
16
+ export interface ScrollbarConfig {
17
+ /** Enable scrollbar (default: true when compressed) */
18
+ enabled?: boolean;
19
+ /** Auto-hide scrollbar after idle (default: true) */
20
+ autoHide?: boolean;
21
+ /** Auto-hide delay in milliseconds (default: 1000) */
22
+ autoHideDelay?: number;
23
+ /** Minimum thumb size in pixels (default: 30) */
24
+ minThumbSize?: number;
25
+ /**
26
+ * Show scrollbar when hovering near the scrollbar edge (default: true).
27
+ * When true, an invisible hover zone is placed along the scrollbar edge.
28
+ * Moving the mouse into this zone reveals the scrollbar; it stays visible
29
+ * as long as the cursor remains over the zone or the track.
30
+ */
31
+ showOnHover?: boolean;
32
+ /**
33
+ * Width of the invisible hover zone in pixels (default: 16).
34
+ * Only used when `showOnHover` is true.
35
+ * A wider zone makes the scrollbar easier to discover;
36
+ * a narrower zone avoids interference with content near the edge.
37
+ */
38
+ hoverZoneWidth?: number;
39
+ /**
40
+ * Show scrollbar when the mouse enters the list viewport (default: true).
41
+ * When false, the scrollbar only appears on scroll or when hovering
42
+ * near the scrollbar edge (if `showOnHover` is true).
43
+ */
44
+ showOnViewportEnter?: boolean;
45
+ }
46
+ /** Scrollbar instance */
47
+ export interface Scrollbar {
48
+ /** Show the scrollbar */
49
+ show: () => void;
50
+ /** Hide the scrollbar */
51
+ hide: () => void;
52
+ /** Update scrollbar dimensions based on content/container size */
53
+ updateBounds: (totalHeight: number, containerHeight: number) => void;
54
+ /** Update thumb position based on scroll position */
55
+ updatePosition: (scrollTop: number) => void;
56
+ /** Check if scrollbar is visible */
57
+ isVisible: () => boolean;
58
+ /** Destroy and cleanup */
59
+ destroy: () => void;
60
+ }
61
+ /** Callback for scroll position changes */
62
+ export type ScrollCallback = (position: number) => void;
63
+ /**
64
+ * Create a scrollbar instance
65
+ *
66
+ * @param viewport - The viewport element to attach scrollbar to
67
+ * @param onScroll - Callback when scrollbar interaction causes scroll
68
+ * @param config - Scrollbar configuration
69
+ * @param classPrefix - CSS class prefix (default: 'vlist')
70
+ * @param horizontal - Whether the scrollbar is horizontal (default: false)
71
+ */
72
+ export declare const createScrollbar: (viewport: HTMLElement, onScroll: ScrollCallback, config?: ScrollbarConfig, classPrefix?: string, horizontal?: boolean) => Scrollbar;
73
+ //# sourceMappingURL=scrollbar.d.ts.map
@@ -0,0 +1,75 @@
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
+ /**
60
+ * Create a selection feature for the builder.
61
+ *
62
+ * ```ts
63
+ * import { vlist } from 'vlist/builder'
64
+ * import { withSelection } from 'vlist/selection'
65
+ *
66
+ * const list = vlist({ ... })
67
+ * .use(withSelection({ mode: 'multiple', initial: ['id-1'] }))
68
+ * .build()
69
+ *
70
+ * list.select('id-2')
71
+ * list.getSelected() // ['id-1', 'id-2']
72
+ * ```
73
+ */
74
+ export declare const withSelection: <T extends VListItem = VListItem>(config?: SelectionFeatureConfig) => VListFeature<T>;
75
+ //# sourceMappingURL=feature.d.ts.map
@@ -0,0 +1,7 @@
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
@@ -0,0 +1,115 @@
1
+ /**
2
+ * vlist - Selection State Management
3
+ * Pure functions for managing selection state
4
+ */
5
+ import type { VListItem, SelectionMode, SelectionState } from "../../types";
6
+ export type { SelectionState } from "../../types";
7
+ /**
8
+ * Transfer selection from a placeholder ID to a real item ID.
9
+ *
10
+ * When select-all or shift-click ranges include unloaded async items, the
11
+ * selection Set contains index-based placeholder IDs (`__placeholder_{index}`).
12
+ * When those items load, this function swaps the placeholder entry for the
13
+ * real item ID so the item renders as selected.
14
+ *
15
+ * @returns `true` if a transfer occurred (the item was selected via its placeholder).
16
+ */
17
+ export declare const claimPlaceholderSelection: (selectedIds: Set<string | number>, index: number, itemId: string | number) => boolean;
18
+ /**
19
+ * Create initial selection state
20
+ * Pure function - no side effects
21
+ */
22
+ export declare const createSelectionState: (initial?: Array<string | number>) => SelectionState;
23
+ /**
24
+ * Select items by ID
25
+ * Pure function - returns new state
26
+ */
27
+ export declare const selectItems: (state: SelectionState, ids: Array<string | number>, mode: SelectionMode) => SelectionState;
28
+ /**
29
+ * Deselect items by ID
30
+ * Pure function - returns new state
31
+ */
32
+ export declare const deselectItems: (state: SelectionState, ids: Array<string | number>) => SelectionState;
33
+ /**
34
+ * Toggle item selection
35
+ * Pure function - returns new state
36
+ */
37
+ export declare const toggleSelection: (state: SelectionState, id: string | number, mode: SelectionMode) => SelectionState;
38
+ /**
39
+ * Select all items
40
+ * Pure function - returns new state
41
+ */
42
+ export declare const selectAll: <T extends VListItem>(state: SelectionState, items: T[], mode: SelectionMode) => SelectionState;
43
+ /**
44
+ * Clear all selection
45
+ * Pure function - returns new state
46
+ */
47
+ export declare const clearSelection: (state: SelectionState) => SelectionState;
48
+ /**
49
+ * Set focused index
50
+ * Mutates state in-place to avoid allocation on hot path
51
+ */
52
+ export declare const setFocusedIndex: (state: SelectionState, index: number) => SelectionState;
53
+ /**
54
+ * Move focus up
55
+ * Mutates state in-place to avoid allocation on hot path
56
+ * @param delta - Number of items to move by (default 1). Useful for grid layouts where row navigation moves by `columns`.
57
+ */
58
+ export declare const moveFocusUp: (state: SelectionState, totalItems: number, wrap?: boolean, delta?: number) => SelectionState;
59
+ /**
60
+ * Move focus down
61
+ * Mutates state in-place to avoid allocation on hot path
62
+ * @param delta - Number of items to move by (default 1). Useful for grid layouts where row navigation moves by `columns`.
63
+ */
64
+ export declare const moveFocusDown: (state: SelectionState, totalItems: number, wrap?: boolean, delta?: number) => SelectionState;
65
+ /**
66
+ * Move focus to first item
67
+ * Mutates state in-place to avoid allocation on hot path
68
+ */
69
+ export declare const moveFocusToFirst: (state: SelectionState, totalItems: number) => SelectionState;
70
+ /**
71
+ * Move focus to last item
72
+ * Mutates state in-place to avoid allocation on hot path
73
+ */
74
+ export declare const moveFocusToLast: (state: SelectionState, totalItems: number) => SelectionState;
75
+ /**
76
+ * Move focus by page (for Page Up/Down)
77
+ * Mutates state in-place to avoid allocation on hot path
78
+ */
79
+ export declare const moveFocusByPage: (state: SelectionState, totalItems: number, pageSize: number, direction: "up" | "down") => SelectionState;
80
+ /**
81
+ * Check if an item is selected
82
+ * Pure function - no side effects
83
+ */
84
+ export declare const isSelected: (state: SelectionState, id: string | number) => boolean;
85
+ /**
86
+ * Get selected IDs as array
87
+ * Pure function - no side effects
88
+ */
89
+ export declare const getSelectedIds: (state: SelectionState) => Array<string | number>;
90
+ /**
91
+ * Get selected items using ID lookup (O(k) where k = selected count)
92
+ * Pure function - no side effects
93
+ */
94
+ export declare const getSelectedItems: <T extends VListItem>(state: SelectionState, getItemById: (id: string | number) => T | undefined) => T[];
95
+ /**
96
+ * Get selection count
97
+ * Pure function - no side effects
98
+ */
99
+ export declare const getSelectionCount: (state: SelectionState) => number;
100
+ /**
101
+ * Check if selection is empty
102
+ * Pure function - no side effects
103
+ */
104
+ export declare const isSelectionEmpty: (state: SelectionState) => boolean;
105
+ /**
106
+ * Handle keyboard selection (Space/Enter on focused item)
107
+ * Pure function - returns new state
108
+ */
109
+ export declare const selectFocused: <T extends VListItem>(state: SelectionState, items: T[], mode: SelectionMode) => SelectionState;
110
+ /**
111
+ * Handle shift+click range selection
112
+ * Pure function - returns new state
113
+ */
114
+ export declare const selectRange: <T extends VListItem>(state: SelectionState, items: T[], fromIndex: number, toIndex: number, mode: SelectionMode) => SelectionState;
115
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1,79 @@
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
@@ -0,0 +1,9 @@
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
@@ -0,0 +1,67 @@
1
+ /**
2
+ * vlist/table - Builder Feature
3
+ * Switches from list layout to a data table with columns, resizable headers,
4
+ * sticky header row, and cell-based rendering.
5
+ *
6
+ * Priority: 10 (runs first — replaces the renderer before anything else renders)
7
+ *
8
+ * What it wires:
9
+ * - Replaces render functions — swaps the core render loop with table-aware rendering
10
+ * - Sticky header — creates a fixed header row above the viewport
11
+ * - Column layout — manages column widths, offsets, and resize logic
12
+ * - Resize interaction — drag handles on header column borders
13
+ * - Sort events — click on sortable header emits column:sort
14
+ * - Horizontal scroll sync — header scrolls in sync with the viewport
15
+ * - CSS class — adds .vlist--table to the root element
16
+ * - Variable row heights — supports fixed and function-based heights
17
+ *
18
+ * Critical design: This feature uses ctx.setRenderFns() to completely replace
19
+ * the core's render loop, NOT ctx.replaceRenderer() which is a no-op in the
20
+ * materialize context. This follows the same pattern as withGrid.
21
+ *
22
+ * Restrictions:
23
+ * - Cannot be combined with withGrid or withMasonry (conflicting layout modes)
24
+ * - Cannot be combined with orientation: 'horizontal' (tables are always vertical)
25
+ *
26
+ * Can be combined with:
27
+ * - withSelection (row selection works as-is)
28
+ * - withScrollbar (custom scrollbar)
29
+ * - withAsync (async data loading)
30
+ * - withSnapshots (scroll position save/restore)
31
+ * - withScale (large dataset compression)
32
+ */
33
+ import type { VListItem } from "../../types";
34
+ import type { VListFeature } from "../../builder/types";
35
+ import type { TableConfig } from "./types";
36
+ /** Table feature configuration — re-exported as TableFeatureConfig */
37
+ export type TableFeatureConfig<T extends VListItem = VListItem> = TableConfig<T>;
38
+ /**
39
+ * Create a table feature for the builder.
40
+ *
41
+ * Switches from list layout to a data table with column headers, resizable
42
+ * columns, and cell-based row rendering.
43
+ *
44
+ * ```ts
45
+ * import { vlist } from 'vlist/builder'
46
+ * import { withTable } from 'vlist/table'
47
+ *
48
+ * const table = vlist({
49
+ * container: '#my-table',
50
+ * item: { height: 40, template: () => '' },
51
+ * items: users,
52
+ * })
53
+ * .use(withTable({
54
+ * columns: [
55
+ * { key: 'name', label: 'Name', width: 200 },
56
+ * { key: 'email', label: 'Email', width: 300 },
57
+ * { key: 'role', label: 'Role', width: 120 },
58
+ * ],
59
+ * rowHeight: 40,
60
+ * headerHeight: 44,
61
+ * resizable: true,
62
+ * }))
63
+ * .build()
64
+ * ```
65
+ */
66
+ export declare const withTable: <T extends VListItem = VListItem>(config: TableFeatureConfig<T>) => VListFeature<T>;
67
+ //# sourceMappingURL=feature.d.ts.map
@@ -0,0 +1,49 @@
1
+ /**
2
+ * vlist/table - Header
3
+ * Manages the sticky header row that sits above the scrolling viewport.
4
+ *
5
+ * The header is a positioned DOM element inserted into the vlist root
6
+ * container (above the viewport, like the sticky group header). It contains
7
+ * one cell per column, each showing the column label. Resize handles are
8
+ * rendered at the right edge of each resizable column's header cell.
9
+ *
10
+ * Layout:
11
+ * .vlist (root, position: relative)
12
+ * ├── .vlist-table-header (position: absolute, top: 0, z-index: 5)
13
+ * │ ├── .vlist-table-header-cell [col 0]
14
+ * │ │ ├── .vlist-table-header-content (label)
15
+ * │ │ ├── .vlist-table-header-sort (sort indicator)
16
+ * │ │ └── .vlist-table-header-resize (drag handle)
17
+ * │ ├── .vlist-table-header-cell [col 1]
18
+ * │ │ └── ...
19
+ * │ └── ...
20
+ * └── .vlist-viewport (scrollable, top offset by headerHeight)
21
+ *
22
+ * Resize interaction:
23
+ * mousedown on handle → pointermove updates column width → pointerup commits
24
+ * During drag, a class is added to the root for cursor override.
25
+ *
26
+ * Sort interaction:
27
+ * click on a sortable header cell emits column:sort via the provided callback.
28
+ * The header renders a visual indicator (▲/▼) for the active sort column.
29
+ *
30
+ * Horizontal scroll sync:
31
+ * The header's scrollLeft is kept in sync with the viewport's scrollLeft
32
+ * via the `syncScroll` method, called from the feature's afterScroll hook.
33
+ */
34
+ import type { VListItem } from "../../types";
35
+ import type { TableHeader, ColumnSortEvent, ColumnClickEvent } from "./types";
36
+ /**
37
+ * Create a TableHeader instance.
38
+ *
39
+ * @param root - The vlist root element (.vlist)
40
+ * @param viewport - The vlist viewport element (for scroll sync)
41
+ * @param headerHeight - Height of the header row in pixels
42
+ * @param classPrefix - CSS class prefix (default: 'vlist')
43
+ * @param onResize - Callback when a column is resized (receives column index and new width)
44
+ * @param onSort - Callback when a sortable header is clicked
45
+ * @param onClick - Callback when any header cell is clicked
46
+ * @returns TableHeader instance
47
+ */
48
+ export declare const createTableHeader: <T extends VListItem = VListItem>(root: HTMLElement, viewport: HTMLElement, headerHeight: number, classPrefix: string, onResize: (columnIndex: number, newWidth: number) => void, onSort?: (event: ColumnSortEvent) => void, onClick?: (event: ColumnClickEvent) => void) => TableHeader<T>;
49
+ //# sourceMappingURL=header.d.ts.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * vlist - Table Domain
3
+ * Data table layout with columns, resizable headers, and cell rendering
4
+ */
5
+ export { withTable, type TableFeatureConfig } from "./feature";
6
+ export { createTableLayout } from "./layout";
7
+ export { createTableHeader } from "./header";
8
+ export { createTableRenderer, type TableRendererInstance } from "./renderer";
9
+ export type { TableConfig, TableColumn, TableLayout, TableHeader, TableRenderer, ResolvedColumn, ColumnResizeEvent, ColumnSortEvent, ColumnClickEvent, } from "./types";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * vlist/table - Layout
3
+ * Manages column widths, offsets, and resize operations.
4
+ *
5
+ * Column width resolution strategy:
6
+ * 1. Columns with explicit `width` get their requested width (clamped to min/max)
7
+ * 2. Remaining container space is distributed equally among columns without `width`
8
+ * 3. If all columns have explicit widths and total < container, no stretching occurs
9
+ * 4. If total column width > container, the table scrolls horizontally
10
+ *
11
+ * All offset calculations are O(n) where n = number of columns (typically small).
12
+ * Resize operations recalculate offsets for columns after the resized one.
13
+ */
14
+ import type { VListItem } from "../../types";
15
+ import type { TableColumn, TableLayout } from "./types";
16
+ /**
17
+ * Create a TableLayout instance.
18
+ *
19
+ * @param columnDefs - Column definitions from config
20
+ * @param globalMinWidth - Default min column width (from TableConfig.minColumnWidth)
21
+ * @param globalMaxWidth - Default max column width (from TableConfig.maxColumnWidth)
22
+ * @param globalResizable - Default resizable flag (from TableConfig.resizable)
23
+ * @returns TableLayout with column resolution and resize capabilities
24
+ */
25
+ export declare const createTableLayout: <T extends VListItem = VListItem>(columnDefs: TableColumn<T>[], globalMinWidth?: number, globalMaxWidth?: number, globalResizable?: boolean) => TableLayout<T>;
26
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1,72 @@
1
+ /**
2
+ * vlist/table - Renderer
3
+ * Renders virtualized rows with cell-based layout within the virtual scroll container.
4
+ *
5
+ * Each row is an absolutely positioned element (like the list renderer),
6
+ * containing child elements for each cell. Cells are sized and positioned
7
+ * according to the resolved column layout from TableLayout.
8
+ *
9
+ * Key design decisions:
10
+ * - Rows are the unit of virtualization (same as list mode — 1:1 with items)
11
+ * - Each row contains N cell elements (one per column)
12
+ * - Row positioning is translateY-based (from the size cache)
13
+ * - Cell positioning uses absolute left + width from the column layout
14
+ * - Element pooling avoids createElement cost (row-level pooling)
15
+ * - Change tracking skips template re-evaluation when data + state unchanged
16
+ * - Release grace period prevents boundary thrashing (hover blink, transition replay)
17
+ * - DocumentFragment batched insertion for new elements
18
+ *
19
+ * Performance:
20
+ * - O(1) Set-based visibility diffing (not O(n) .some())
21
+ * - Template re-evaluation skipped when item id + selection/focus state unchanged
22
+ * - Position update skipped when coordinates unchanged (position tracking)
23
+ * - Cell widths are only updated when column layout changes (not every scroll frame)
24
+ * - Released elements removed from DOM immediately, pooled for reuse
25
+ *
26
+ * DOM structure per row:
27
+ * .vlist-item.vlist-table-row (position: absolute, translateY)
28
+ * ├── .vlist-table-cell [col 0] (position: absolute, left, width)
29
+ * ├── .vlist-table-cell [col 1]
30
+ * └── ...
31
+ */
32
+ import type { VListItem, Range } from "../../types";
33
+ import type { SizeCache } from "../../rendering/sizes";
34
+ import type { CompressionContext } from "../../rendering/renderer";
35
+ import type { TableLayout, TableColumn } from "./types";
36
+ /** Table renderer instance */
37
+ export interface TableRendererInstance<T extends VListItem = VListItem> {
38
+ /** Render rows for a range, with cell-based layout */
39
+ render: (items: T[], range: Range, selectedIds: Set<string | number>, focusedIndex: number, compressionCtx?: CompressionContext) => void;
40
+ /** Update item positions (for compressed scrolling) */
41
+ updatePositions: (compressionCtx: CompressionContext) => void;
42
+ /** Update a single row (e.g., after selection change) */
43
+ updateItem: (index: number, item: T, isSelected: boolean, isFocused: boolean) => void;
44
+ /** Update only CSS classes on a rendered row */
45
+ updateItemClasses: (index: number, isSelected: boolean, isFocused: boolean) => void;
46
+ /** Get rendered row element by item index */
47
+ getElement: (index: number) => HTMLElement | undefined;
48
+ /** Update cell positions and widths after column resize */
49
+ updateColumnLayout: (layout: TableLayout<T>) => void;
50
+ /** Set the group header check function (called by withGroups integration) */
51
+ setGroupHeaderFn: (fn: ((item: T) => boolean) | null, template: ((key: string, groupIndex: number) => HTMLElement | string) | null) => void;
52
+ /** Clear all rendered rows */
53
+ clear: () => void;
54
+ /** Destroy renderer and cleanup */
55
+ destroy: () => void;
56
+ }
57
+ /**
58
+ * Create a TableRenderer instance.
59
+ *
60
+ * @param container - The .vlist-items container element
61
+ * @param sizeCache - Size cache for row offset lookups
62
+ * @param layout - Table layout for column widths/offsets
63
+ * @param columns - Column definitions (for cell templates)
64
+ * @param classPrefix - CSS class prefix
65
+ * @param ariaIdPrefix - Prefix for ARIA IDs
66
+ * @param columnBorders - Whether to show vertical borders between cells
67
+ * @param rowBorders - Whether to show horizontal borders between rows
68
+ * @param getTotalItems - Function to get total item count (for ARIA)
69
+ * @returns TableRendererInstance
70
+ */
71
+ export declare const createTableRenderer: <T extends VListItem = VListItem>(container: HTMLElement, getSizeCache: () => SizeCache, layout: TableLayout<T>, _columns: TableColumn<T>[], classPrefix: string, ariaIdPrefix: string, getTotalItems: () => number, striped?: boolean | "data" | "even" | "odd", stripeIndexFn?: () => (index: number) => number) => TableRendererInstance<T>;
72
+ //# sourceMappingURL=renderer.d.ts.map