@zakkster/lite-table 1.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,93 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@zakkster/lite-table` are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] — 2026-06 (M1 stable)
9
+
10
+ First public release. The headless core + DOM mount, virtualized rows on a
11
+ pooled-slot CSS Grid, full keyboard + ARIA, single-key + chained sort, single +
12
+ range + all-mode selection, draggable column resize / reorder, pinned columns
13
+ with sticky offsets, flex columns.
14
+
15
+ ### Public API
16
+
17
+ - **`createTable(config)`** — headless reactive state (renderer-agnostic, SSR-safe).
18
+ Returns a `TableCore` with reactive `visibleRows`, `visibleColumns`,
19
+ `colTemplate`, `colPlacement`, `leftOffsets`, `rightOffsets`, `sortChain`,
20
+ `focusedCell`, `selection`, `selectedCount`, plus imperative
21
+ `setSort`/`addSort`/`toggleSort`/`clearSort`,
22
+ `selectRow`/`selectRowRange`/`selectAll`/`clearSelection`/`isSelected`/
23
+ `selectedIds`/`selectedRows`/`forEachSelected`,
24
+ `setColumnWidth`/`setColumnHidden`/`setColumnPin`/`setColumnFlex`/
25
+ `setColumnOrder`/`moveColumn`,
26
+ `moveFocus`,
27
+ `cellId`, and `dispose`.
28
+ - **`mountTable(host, table, options?)`** — CSS Grid renderer with pooled slot
29
+ virtualization. Returns a `TableMount` with `root`, `viewport`, `axis`,
30
+ `scrollToIndex(index, "start"|"center"|"end")`, `poolSize()`, and `dispose()`.
31
+
32
+ ### Architecture invariants
33
+
34
+ - **No `<table>`.** CSS Grid layout; `role=grid` / `row` / `columnheader` /
35
+ `gridcell`. The root container is the only focusable element; logical focus
36
+ is the `focusedCell` signal, and `aria-activedescendant` tracks it.
37
+ - **Position-keyed slot pool.** DOM topology never changes during scroll,
38
+ sort, filter, hide, reorder, or pin. Sub-row scroll = 0 DOM writes
39
+ (Object.is cutoff on the truncated start index). Pool size is bounded by
40
+ viewport, not dataset.
41
+ - **Identity follows the row, not the slot.** Every cell's id is reactively
42
+ bound to `lt_<rowId>__<columnKey>`. Focus, selection, edit state, and
43
+ `aria-activedescendant` are all keyed on row identity — they survive scroll,
44
+ sort, filter, recycling, and even row-removal-then-re-add.
45
+ - **Reactive columns.** Each column has its own `width` / `hidden` / `pin` /
46
+ `flex` signals. `visibleColumns` is a computed derived from a
47
+ `columnOrder` signal. Reorder mutates the order array; resize mutates one
48
+ width signal; hide flips one boolean; pin moves between buckets.
49
+ - **Single grid for pinning.** Pinned columns live in the same CSS Grid as
50
+ the body, with `position: sticky` plus a reactive `left` or `right` offset
51
+ equal to the cumulative width of their bucket up to that column.
52
+ - **Pinning suspends flex.** When a column is pinned, its `flex` is ignored —
53
+ pinned columns must render at exactly `width()px` so sticky offsets line
54
+ up. Unpin re-engages flex.
55
+ - **Predicate-based selection.** `selection.mode === "all"` is a blacklist;
56
+ Ctrl+A is O(1) (flip the mode, empty the set). Materialization to a list
57
+ of IDs happens on demand via `selectedIds()` / `selectedRows()` /
58
+ `forEachSelected()`.
59
+
60
+ ### Performance
61
+
62
+ Empirical (Node 22 + happy-dom + signal-graph stats):
63
+
64
+ - **Scroll sub-row**: 0 DOM allocations, 0 updates.
65
+ - **Scroll boundary**: 0 allocations; ~484 in-place updates per boundary crossed.
66
+ - **Scroll 1000 rows**: 0 allocations, ~504 in-place updates total.
67
+ - **10,000 boundary scrolls**: signal-node delta 0, link delta 0, pool delta 0.
68
+ - **Mount cost is constant** versus dataset size: pool ~24 slots whether
69
+ 1K or 1M rows.
70
+
71
+ ### Tests
72
+
73
+ 110 tests across 9 files (node:test, `--expose-gc`):
74
+
75
+ - `alloc.test.js` — write counts, signal-graph stability, pool invariants.
76
+ - `columns.test.js` — width/hide/pin/flex/reorder, `colPlacement` and
77
+ `colTemplate` consistency, the pinning-suspends-flex invariant.
78
+ - `core.test.js` — `createTable` shape + validation.
79
+ - `dom.test.js` — mount structure, ARIA wiring, reactive cell text, pool sizing.
80
+ - `keyboard.test.js` — every direction of `moveFocus` + Space/Esc/Ctrl+A.
81
+ - `recycle.test.js` — slot identity stability, cell IDs follow rows, focus
82
+ survives scroll-out + filter-out.
83
+ - `selection.test.js` — every mode + anchor + DOM aria-selected + Ctrl/Shift
84
+ click + all-mode + materialization paths.
85
+ - `sort.test.js` — chain semantics, stable multi-key sort, DOM click-sort.
86
+ - `extras.test.js` — `scrollToIndex` align modes, pointer-driven resize +
87
+ reorder, `injectStyles:false`, mount-disposes-table lifecycle, null / 0 /
88
+ string-id cells, `addSort(null)`, `moveFocus` from null, 50-col stress,
89
+ steady-state graph stability under 1000+ sort/select/resize loops.
90
+
91
+ ### License
92
+
93
+ MIT (c) Zahary Shinikchiev
package/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zahary Shinikchiev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.