@dashforge/tw 0.8.0-beta → 0.9.0-beta
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 +188 -0
- package/COVERAGE.md +63 -0
- package/LICENSE +21 -0
- package/PERFORMANCE.md +59 -0
- package/REFINEMENT-NOTES.md +50 -0
- package/dist/index.esm.js +235 -160
- package/dist/src/components/DataGrid/DataGrid.d.ts.map +1 -1
- package/dist/src/components/DataGrid/filters/ColumnFilters.d.ts.map +1 -1
- package/dist/src/components/DataGrid/resize/useColumnResize.d.ts +7 -0
- package/dist/src/components/DataGrid/resize/useColumnResize.d.ts.map +1 -1
- package/dist/src/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts +44 -0
- package/dist/src/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts.map +1 -0
- package/dist/src/components/Dialog/Dialog.d.ts.map +1 -1
- package/dist/src/components/Table/Table.d.ts.map +1 -1
- package/dist/src/components/Table/cells/RenderChip.d.ts.map +1 -1
- package/dist/src/components/Table/table.types.d.ts +29 -6
- package/dist/src/components/Table/table.types.d.ts.map +1 -1
- package/dist/src/components/Typography/typography.variants.d.ts.map +1 -1
- package/eslint.config.mjs +16 -1
- package/package.json +11 -8
- package/src/components/Breadcrumbs/Breadcrumbs.perf.test.tsx +5 -2
- package/src/components/DataGrid/DataGrid.perf.test.tsx +114 -0
- package/src/components/DataGrid/DataGrid.test.tsx +253 -17
- package/src/components/DataGrid/DataGrid.tsx +107 -24
- package/src/components/DataGrid/filters/ColumnFilters.test.tsx +330 -0
- package/src/components/DataGrid/filters/ColumnFilters.tsx +26 -2
- package/src/components/DataGrid/reorder/useColumnReorder.test.ts +95 -3
- package/src/components/DataGrid/resize/useColumnResize.test.ts +144 -0
- package/src/components/DataGrid/resize/useColumnResize.ts +30 -1
- package/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx +186 -0
- package/src/components/Dialog/Dialog.tsx +9 -0
- package/src/components/Table/Table.perf.test.tsx +81 -0
- package/src/components/Table/Table.test.tsx +72 -1
- package/src/components/Table/Table.tsx +41 -8
- package/src/components/Table/cells/RenderChip.tsx +6 -9
- package/src/components/Table/cells/cells.test.tsx +247 -0
- package/src/components/Table/table.types.ts +29 -6
- package/src/components/Typography/Typography.test.tsx +15 -0
- package/src/components/Typography/typography.variants.ts +14 -1
- package/test-output/vitest/coverage/base.css +224 -0
- package/test-output/vitest/coverage/block-navigation.js +87 -0
- package/test-output/vitest/coverage/clover.xml +2418 -0
- package/test-output/vitest/coverage/coverage-final.json +89 -0
- package/test-output/vitest/coverage/favicon.png +0 -0
- package/test-output/vitest/coverage/index.html +746 -0
- package/test-output/vitest/coverage/prettify.css +1 -0
- package/test-output/vitest/coverage/prettify.js +2 -0
- package/test-output/vitest/coverage/sort-arrow-sprite.png +0 -0
- package/test-output/vitest/coverage/sorter.js +210 -0
- package/test-output/vitest/coverage/src/components/Accordion/Accordion.tsx.html +376 -0
- package/test-output/vitest/coverage/src/components/Accordion/accordion.variants.ts.html +181 -0
- package/test-output/vitest/coverage/src/components/Accordion/index.html +131 -0
- package/test-output/vitest/coverage/src/components/AppShell/AppShell.tsx.html +802 -0
- package/test-output/vitest/coverage/src/components/AppShell/appShell.variants.ts.html +247 -0
- package/test-output/vitest/coverage/src/components/AppShell/index.html +131 -0
- package/test-output/vitest/coverage/src/components/AspectRatio/AspectRatio.tsx.html +304 -0
- package/test-output/vitest/coverage/src/components/AspectRatio/index.html +116 -0
- package/test-output/vitest/coverage/src/components/Autocomplete/Autocomplete.tsx.html +3292 -0
- package/test-output/vitest/coverage/src/components/Autocomplete/autocomplete.variants.ts.html +508 -0
- package/test-output/vitest/coverage/src/components/Autocomplete/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Box/Box.tsx.html +334 -0
- package/test-output/vitest/coverage/src/components/Box/box.variants.ts.html +775 -0
- package/test-output/vitest/coverage/src/components/Box/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Breadcrumbs/Breadcrumbs.tsx.html +694 -0
- package/test-output/vitest/coverage/src/components/Breadcrumbs/breadcrumbs.variants.ts.html +247 -0
- package/test-output/vitest/coverage/src/components/Breadcrumbs/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Button/Button.tsx.html +535 -0
- package/test-output/vitest/coverage/src/components/Button/button.variants.ts.html +562 -0
- package/test-output/vitest/coverage/src/components/Button/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Checkbox/Checkbox.tsx.html +943 -0
- package/test-output/vitest/coverage/src/components/Checkbox/checkbox.variants.ts.html +289 -0
- package/test-output/vitest/coverage/src/components/Checkbox/index.html +131 -0
- package/test-output/vitest/coverage/src/components/ConfirmDialog/ConfirmDialog.tsx.html +841 -0
- package/test-output/vitest/coverage/src/components/ConfirmDialog/confirmDialog.variants.ts.html +313 -0
- package/test-output/vitest/coverage/src/components/ConfirmDialog/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Container/Container.tsx.html +307 -0
- package/test-output/vitest/coverage/src/components/Container/container.variants.ts.html +328 -0
- package/test-output/vitest/coverage/src/components/Container/index.html +131 -0
- package/test-output/vitest/coverage/src/components/DataGrid/DataGrid.tsx.html +3937 -0
- package/test-output/vitest/coverage/src/components/DataGrid/dataGrid.variants.ts.html +541 -0
- package/test-output/vitest/coverage/src/components/DataGrid/filters/ColumnFilters.tsx.html +1453 -0
- package/test-output/vitest/coverage/src/components/DataGrid/filters/index.html +116 -0
- package/test-output/vitest/coverage/src/components/DataGrid/index.html +131 -0
- package/test-output/vitest/coverage/src/components/DataGrid/reorder/index.html +116 -0
- package/test-output/vitest/coverage/src/components/DataGrid/reorder/useColumnReorder.ts.html +517 -0
- package/test-output/vitest/coverage/src/components/DataGrid/resize/index.html +116 -0
- package/test-output/vitest/coverage/src/components/DataGrid/resize/useColumnResize.ts.html +490 -0
- package/test-output/vitest/coverage/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx.html +592 -0
- package/test-output/vitest/coverage/src/components/DataGrid/visibility/index.html +116 -0
- package/test-output/vitest/coverage/src/components/DateTimePicker/DateTimePicker.tsx.html +1042 -0
- package/test-output/vitest/coverage/src/components/DateTimePicker/dateTimePicker.variants.ts.html +337 -0
- package/test-output/vitest/coverage/src/components/DateTimePicker/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Dialog/Dialog.tsx.html +391 -0
- package/test-output/vitest/coverage/src/components/Dialog/dialog.variants.ts.html +283 -0
- package/test-output/vitest/coverage/src/components/Dialog/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Divider/Divider.tsx.html +505 -0
- package/test-output/vitest/coverage/src/components/Divider/divider.variants.ts.html +433 -0
- package/test-output/vitest/coverage/src/components/Divider/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Grid/Grid.tsx.html +529 -0
- package/test-output/vitest/coverage/src/components/Grid/grid.variants.ts.html +484 -0
- package/test-output/vitest/coverage/src/components/Grid/index.html +131 -0
- package/test-output/vitest/coverage/src/components/LeftNav/LeftNav.tsx.html +1075 -0
- package/test-output/vitest/coverage/src/components/LeftNav/index.html +131 -0
- package/test-output/vitest/coverage/src/components/LeftNav/leftNav.variants.ts.html +406 -0
- package/test-output/vitest/coverage/src/components/NumberField/NumberField.tsx.html +1048 -0
- package/test-output/vitest/coverage/src/components/NumberField/index.html +131 -0
- package/test-output/vitest/coverage/src/components/NumberField/numberField.variants.ts.html +367 -0
- package/test-output/vitest/coverage/src/components/OTPField/OTPField.tsx.html +835 -0
- package/test-output/vitest/coverage/src/components/OTPField/index.html +131 -0
- package/test-output/vitest/coverage/src/components/OTPField/otpField.variants.ts.html +301 -0
- package/test-output/vitest/coverage/src/components/Pagination/Pagination.tsx.html +916 -0
- package/test-output/vitest/coverage/src/components/Pagination/index.html +146 -0
- package/test-output/vitest/coverage/src/components/Pagination/pagination.helpers.ts.html +391 -0
- package/test-output/vitest/coverage/src/components/Pagination/pagination.variants.ts.html +436 -0
- package/test-output/vitest/coverage/src/components/Popover/Popover.tsx.html +250 -0
- package/test-output/vitest/coverage/src/components/Popover/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Popover/popover.variants.ts.html +157 -0
- package/test-output/vitest/coverage/src/components/RadioGroup/RadioGroup.tsx.html +934 -0
- package/test-output/vitest/coverage/src/components/RadioGroup/index.html +131 -0
- package/test-output/vitest/coverage/src/components/RadioGroup/radioGroup.variants.ts.html +346 -0
- package/test-output/vitest/coverage/src/components/Skeleton/Skeleton.tsx.html +232 -0
- package/test-output/vitest/coverage/src/components/Skeleton/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Skeleton/skeleton.variants.ts.html +346 -0
- package/test-output/vitest/coverage/src/components/Snackbar/Snackbar.tsx.html +979 -0
- package/test-output/vitest/coverage/src/components/Snackbar/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Snackbar/snackbar.variants.ts.html +307 -0
- package/test-output/vitest/coverage/src/components/Stack/Stack.tsx.html +430 -0
- package/test-output/vitest/coverage/src/components/Stack/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Stack/stack.variants.ts.html +325 -0
- package/test-output/vitest/coverage/src/components/Switch/Switch.tsx.html +559 -0
- package/test-output/vitest/coverage/src/components/Switch/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Switch/switch.variants.ts.html +295 -0
- package/test-output/vitest/coverage/src/components/Table/Table.tsx.html +2677 -0
- package/test-output/vitest/coverage/src/components/Table/cells/RenderButton.tsx.html +154 -0
- package/test-output/vitest/coverage/src/components/Table/cells/RenderChip.tsx.html +385 -0
- package/test-output/vitest/coverage/src/components/Table/cells/RenderText.tsx.html +196 -0
- package/test-output/vitest/coverage/src/components/Table/cells/RenderTwoLine.tsx.html +187 -0
- package/test-output/vitest/coverage/src/components/Table/cells/RowActionsMenu.tsx.html +526 -0
- package/test-output/vitest/coverage/src/components/Table/cells/index.html +191 -0
- package/test-output/vitest/coverage/src/components/Table/cells/index.ts.html +127 -0
- package/test-output/vitest/coverage/src/components/Table/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Table/table.variants.ts.html +706 -0
- package/test-output/vitest/coverage/src/components/Tabs/Tabs.tsx.html +283 -0
- package/test-output/vitest/coverage/src/components/Tabs/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Tabs/tabs.variants.ts.html +292 -0
- package/test-output/vitest/coverage/src/components/TextField/TextField.tsx.html +820 -0
- package/test-output/vitest/coverage/src/components/TextField/index.html +131 -0
- package/test-output/vitest/coverage/src/components/TextField/textField.variants.ts.html +400 -0
- package/test-output/vitest/coverage/src/components/Textarea/Textarea.tsx.html +655 -0
- package/test-output/vitest/coverage/src/components/Textarea/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Textarea/textarea.variants.ts.html +340 -0
- package/test-output/vitest/coverage/src/components/Tooltip/Tooltip.tsx.html +295 -0
- package/test-output/vitest/coverage/src/components/Tooltip/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Tooltip/tooltip.variants.ts.html +169 -0
- package/test-output/vitest/coverage/src/components/TopBar/TopBar.tsx.html +283 -0
- package/test-output/vitest/coverage/src/components/TopBar/index.html +131 -0
- package/test-output/vitest/coverage/src/components/TopBar/topBar.variants.ts.html +199 -0
- package/test-output/vitest/coverage/src/components/Typography/Typography.tsx.html +421 -0
- package/test-output/vitest/coverage/src/components/Typography/index.html +131 -0
- package/test-output/vitest/coverage/src/components/Typography/typography.variants.ts.html +436 -0
- package/test-output/vitest/coverage/src/components/VisuallyHidden/VisuallyHidden.tsx.html +262 -0
- package/test-output/vitest/coverage/src/components/VisuallyHidden/index.html +116 -0
- package/test-output/vitest/coverage/src/components/_shared/data/getNestedValue.ts.html +181 -0
- package/test-output/vitest/coverage/src/components/_shared/data/index.html +236 -0
- package/test-output/vitest/coverage/src/components/_shared/data/useColumnAutoDetect.ts.html +385 -0
- package/test-output/vitest/coverage/src/components/_shared/data/useControllableState.ts.html +229 -0
- package/test-output/vitest/coverage/src/components/_shared/data/useDebouncedValue.ts.html +157 -0
- package/test-output/vitest/coverage/src/components/_shared/data/useTableFilter.ts.html +439 -0
- package/test-output/vitest/coverage/src/components/_shared/data/useTableSearch.ts.html +283 -0
- package/test-output/vitest/coverage/src/components/_shared/data/useTableSelection.ts.html +385 -0
- package/test-output/vitest/coverage/src/components/_shared/data/useTableSort.ts.html +508 -0
- package/test-output/vitest/coverage/src/components/_shared/data/useVirtualizer.ts.html +682 -0
- package/test-output/vitest/coverage/src/components/_shared/index.html +116 -0
- package/test-output/vitest/coverage/src/components/_shared/resolveValidationState.ts.html +265 -0
- package/test-output/vitest/coverage/src/hooks/index.html +116 -0
- package/test-output/vitest/coverage/src/hooks/useAccessState.ts.html +328 -0
- package/test-output/vitest/coverage/src/index.html +116 -0
- package/test-output/vitest/coverage/src/index.ts.html +1153 -0
- package/test-output/vitest/coverage/src/utils/cn.ts.html +172 -0
- package/test-output/vitest/coverage/src/utils/index.html +116 -0
- package/dist/src/components/DataGrid/visibility/ColumnVisibilityDialog.d.ts +0 -33
- package/dist/src/components/DataGrid/visibility/ColumnVisibilityDialog.d.ts.map +0 -1
- package/src/components/DataGrid/visibility/ColumnVisibilityDialog.tsx +0 -200
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,194 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
12
12
|
> duplicated intentionally — no shared "lowest common denominator" headless
|
|
13
13
|
> layer.
|
|
14
14
|
|
|
15
|
+
## [0.9.0-beta] — 2026-05-20
|
|
16
|
+
|
|
17
|
+
**Sprint 6 — core hardening.** A refinement pass over the theme
|
|
18
|
+
core, `<Table>` + `<DataGrid>`, the validation gates, and test
|
|
19
|
+
coverage. Released together with `@dashforge/tw-tokens 0.2.0-beta`
|
|
20
|
+
and `@dashforge/tw-theme 0.2.0-beta` — **upgrade all three together.**
|
|
21
|
+
|
|
22
|
+
**Minor bump** for the additive API surface (`TableLabels.noResults`,
|
|
23
|
+
theme-controlled shadows, the `tailwindcss` peer requirement).
|
|
24
|
+
Strictly additive — no breaking changes on existing component APIs.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **Theme-controlled shadows.** `<Box elevation>` and every
|
|
29
|
+
`shadow-*` utility now resolve to the new `@dashforge/tw-tokens`
|
|
30
|
+
shadow token axis (CSS-var refs via `dashforgePreset()`), so
|
|
31
|
+
elevation is runtime-patchable via
|
|
32
|
+
`patchTheme({ shadow: { md: '…' } })`. Zero `<Box>` code change —
|
|
33
|
+
the existing classes pick up the var refs through the preset.
|
|
34
|
+
- **`DataGrid` accessibility — `aria-rowcount` / `aria-rowindex`.**
|
|
35
|
+
The virtualized grid now announces the TRUE dataset position to
|
|
36
|
+
assistive tech (`aria-rowcount` on the table, `aria-rowindex` on
|
|
37
|
+
the header + every data row). Before, a screen reader reported the
|
|
38
|
+
position within the ~visible window, not the full dataset.
|
|
39
|
+
- **`DataGrid` keyboard column resize.** The column resize handle is
|
|
40
|
+
now keyboard-operable: `tabIndex=0`, `ArrowLeft`/`ArrowRight` nudge
|
|
41
|
+
the width 16px (64px with `Shift`), `aria-valuemin/max/now` on the
|
|
42
|
+
separator. WCAG 2.1 keyboard operability — the drag is no longer
|
|
43
|
+
the only path.
|
|
44
|
+
- **`TableLabels.noResults`** — `<Table>` + `<DataGrid>` now show a
|
|
45
|
+
distinct "No matching results" message when an active search /
|
|
46
|
+
filter empties the view, vs the existing `noData` for a genuinely
|
|
47
|
+
empty dataset. New i18n key.
|
|
48
|
+
- **`Enter`-to-apply** in every `DataGrid` column-filter Popover
|
|
49
|
+
input (was: must click "Apply").
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- **`DataGrid` column reorder** — the resize handle is now
|
|
54
|
+
`draggable={false}`, so grabbing it always resizes and never
|
|
55
|
+
starts a column-reorder drag. On coarse-pointer (touch) devices the
|
|
56
|
+
reorder `draggable` affordance is disabled — native HTML5
|
|
57
|
+
drag-and-drop does not fire touch events, so it was a dead
|
|
58
|
+
interaction. (A pointer-event reorder covering touch is tracked in
|
|
59
|
+
`REFINEMENT-NOTES.md`.)
|
|
60
|
+
- **`Table`** now emits a dev-only `console.warn` when `getRowId` is
|
|
61
|
+
omitted while sort / search / selection / expandable rows are
|
|
62
|
+
active — the positional-index fallback breaks row identity on
|
|
63
|
+
reorder. Prop JSDoc expanded. (`<DataGrid>` already requires
|
|
64
|
+
`getRowId`.)
|
|
65
|
+
- **`tailwind-merge`** bumped to `^3.0.0` (`tailwind-variants@3`
|
|
66
|
+
requires it). Full suite green on 3.6.0 — `cn()` + every TV recipe
|
|
67
|
+
unaffected.
|
|
68
|
+
- **`DataGrid` column-visibility menu** — the "Show all" / "Hide all"
|
|
69
|
+
text links are replaced by a single tri-state master checkbox at
|
|
70
|
+
the top of the column list (checked = all visible, indeterminate
|
|
71
|
+
= mixed, unchecked = all hidden), consistent with the row
|
|
72
|
+
select-all checkbox. Less chrome, no extra copy. The
|
|
73
|
+
`TableLabels` keys `columnsShowAll` + `columnsHideAll` are removed;
|
|
74
|
+
new key `columnsToggleAll` is the master checkbox `aria-label`.
|
|
75
|
+
The Popover title (`columnsTitle`) is unchanged and
|
|
76
|
+
consumer-customizable as before.
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
|
|
80
|
+
- **`<Typography>` dark-mode colour consistency.** The default
|
|
81
|
+
`color` changed from `inherit` to `neutral`. A bare
|
|
82
|
+
`<Typography>` now emits `text-neutral-900` (auto-inverting via
|
|
83
|
+
the `dashforgePreset()` CSS-var swap) instead of inheriting the
|
|
84
|
+
consuming app's arbitrary root colour — which is typically driven
|
|
85
|
+
off the OS `prefers-color-scheme`, diverging from the Dashforge
|
|
86
|
+
`data-dash-tw-theme` mode. Before the fix, default-colour and
|
|
87
|
+
explicitly-coloured text rendered as two different greys in dark
|
|
88
|
+
mode. Pass `color="inherit"` explicitly on a `<Typography>` placed
|
|
89
|
+
inside a coloured surface (`<Box variant="solid">`). Paired with
|
|
90
|
+
the `@dashforge/tw-theme 0.2.0-beta` base-layer surface anchor.
|
|
91
|
+
- **Console hygiene** — `<Dialog>` now passes
|
|
92
|
+
`aria-describedby={undefined}` on the content when no `description`
|
|
93
|
+
is supplied, silencing Radix's 8× *"Missing Description"* dev
|
|
94
|
+
warning. Correct a11y semantics for description-less dialogs.
|
|
95
|
+
- **Packaging** — `vitest` + `@vitejs/plugin-react` moved from
|
|
96
|
+
`dependencies` to `devDependencies`; consumers no longer pull the
|
|
97
|
+
test runner into `node_modules`.
|
|
98
|
+
|
|
99
|
+
### Dependencies
|
|
100
|
+
|
|
101
|
+
- New peer dependency: **`tailwindcss` `>=3.4.1`** — the
|
|
102
|
+
`dashforgePreset()` `darkMode: ['selector', …]` strategy requires
|
|
103
|
+
it, and the catalog's `dark:` brand-shift variants depend on that
|
|
104
|
+
config. Declared explicitly so a too-old Tailwind fails at install
|
|
105
|
+
rather than silently breaking dark mode.
|
|
106
|
+
|
|
107
|
+
### Tests + tooling
|
|
108
|
+
|
|
109
|
+
- Render-perf suite: `Table.perf.test.tsx` + `DataGrid.perf.test.tsx`
|
|
110
|
+
pin the non-virtualized (500 rows) and virtualized (10k / 100k
|
|
111
|
+
rows, O(window)) budgets in CI.
|
|
112
|
+
- +62 unit tests — the cell renderer library, `ColumnFilters`,
|
|
113
|
+
`useColumnResize`, `useColumnReorder` are now directly covered
|
|
114
|
+
(line coverage 85.78%). See `COVERAGE.md` for the report + the
|
|
115
|
+
tracked pre-Sprint-6 branch-coverage debt.
|
|
116
|
+
- Strict-flag assessment (`exactOptionalPropertyTypes` /
|
|
117
|
+
`noUncheckedIndexedAccess`) — see `PERFORMANCE.md`. Result: zero
|
|
118
|
+
real bugs; flag enablement deferred to `1.0.0-rc`.
|
|
119
|
+
|
|
120
|
+
### Migration
|
|
121
|
+
|
|
122
|
+
No code changes required:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
pnpm up @dashforge/tw@^0.9.0-beta \
|
|
126
|
+
@dashforge/tw-theme@^0.2.0-beta \
|
|
127
|
+
@dashforge/tw-tokens@^0.2.0-beta
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Ensure your project's `tailwindcss` is **`>=3.4.1`** (the new peer
|
|
131
|
+
requirement). If you customized `DataGrid` / `Table` labels via the
|
|
132
|
+
`labels` prop:
|
|
133
|
+
|
|
134
|
+
- the new optional `noResults` key defaults to
|
|
135
|
+
`"No matching results"` — translate it if you localize;
|
|
136
|
+
- the column-visibility keys `columnsShowAll` / `columnsHideAll`
|
|
137
|
+
are **removed** (the menu now uses a tri-state master checkbox) —
|
|
138
|
+
replace them with the single `columnsToggleAll` key
|
|
139
|
+
(default `"Toggle all columns"`, used as the checkbox `aria-label`).
|
|
140
|
+
|
|
141
|
+
## [0.8.1-beta] — 2026-05-19
|
|
142
|
+
|
|
143
|
+
**UX swap on `DataGrid` column visibility.** The "Columns" toolbar
|
|
144
|
+
button now opens a lightweight **`<Popover>` menu** anchored to the
|
|
145
|
+
button instead of a modal `<Dialog>`. Toggles **auto-commit on
|
|
146
|
+
click** — no draft state, no "Done" button, dismissed via
|
|
147
|
+
outside-click / Esc. Matches the AG-Grid / MUI DataGrid v6 / TanStack
|
|
148
|
+
pattern for the same affordance.
|
|
149
|
+
|
|
150
|
+
Rationale: the previous Dialog was too heavyweight for a settings
|
|
151
|
+
toggle. A modal interrupts the user's interaction with the grid
|
|
152
|
+
(the very thing they're configuring), traps focus, and requires an
|
|
153
|
+
explicit commit step. The Popover variant reads as a "settings
|
|
154
|
+
panel": the user can keep referring to the grid while picking
|
|
155
|
+
columns, and changes flow into the model immediately.
|
|
156
|
+
|
|
157
|
+
### Changed
|
|
158
|
+
|
|
159
|
+
- **`ColumnVisibilityTrigger`** (internal component used by
|
|
160
|
+
`<DataGrid enableColumnVisibility>`) — switched from `<Dialog>` to
|
|
161
|
+
`<Popover>`. Public DataGrid API surface unchanged: the
|
|
162
|
+
`enableColumnVisibility` flag, `hiddenColumns` /
|
|
163
|
+
`onHiddenColumnsChange` controllable state, and per-column
|
|
164
|
+
`hideable` / `defaultHidden` axes work identically.
|
|
165
|
+
|
|
166
|
+
- **`TableLabels`** — two now-unused keys removed:
|
|
167
|
+
- `columnsDescription` (the Dialog had a description line; the
|
|
168
|
+
Popover doesn't need one)
|
|
169
|
+
- `columnsDone` (no explicit commit step anymore — toggles
|
|
170
|
+
auto-commit)
|
|
171
|
+
The remaining four keys (`columnsButton`, `columnsTitle`,
|
|
172
|
+
`columnsShowAll`, `columnsHideAll`) are unchanged. Default for
|
|
173
|
+
`columnsTitle` adjusted from `"Manage columns"` to
|
|
174
|
+
`"Toggle columns"` (the action is now lighter).
|
|
175
|
+
|
|
176
|
+
### Migration
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
pnpm up @dashforge/tw@^0.8.1-beta
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
If you customized the column-visibility labels via the `labels`
|
|
183
|
+
prop, drop the two removed keys:
|
|
184
|
+
|
|
185
|
+
```diff
|
|
186
|
+
<DataGrid
|
|
187
|
+
rows={rows}
|
|
188
|
+
cols={cols}
|
|
189
|
+
labels={{
|
|
190
|
+
columnsButton: 'Colonne',
|
|
191
|
+
columnsTitle: 'Mostra colonne',
|
|
192
|
+
- columnsDescription: 'Mostra o nascondi colonne…',
|
|
193
|
+
columnsShowAll: 'Mostra tutte',
|
|
194
|
+
columnsHideAll: 'Nascondi tutte',
|
|
195
|
+
- columnsDone: 'Fatto',
|
|
196
|
+
}}
|
|
197
|
+
/>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
If you don't customize the labels (>99% of consumers), no action
|
|
201
|
+
required — the visual swap happens automatically.
|
|
202
|
+
|
|
15
203
|
## [0.8.0-beta] — 2026-05-19
|
|
16
204
|
|
|
17
205
|
**Sprint 4.2-bis — DataGrid v1-bis.** Ships the five power-user
|
package/COVERAGE.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# COVERAGE — `@dashforge/tw`
|
|
2
|
+
|
|
3
|
+
> Sprint 6 P4 deliverable (2026-05-20). Test-coverage audit + the
|
|
4
|
+
> gap-fill done this sprint, plus the tracked debt.
|
|
5
|
+
|
|
6
|
+
## Current coverage (`vitest --coverage`, v8 provider)
|
|
7
|
+
|
|
8
|
+
| Metric | Value | Target |
|
|
9
|
+
|--------|-------|--------|
|
|
10
|
+
| Statements | 83.53% | — |
|
|
11
|
+
| **Branches** | **75.87%** | 85% (not met — see Deferred) |
|
|
12
|
+
| Functions | 89.06% | — |
|
|
13
|
+
| **Lines** | **85.78%** | 85% ✅ |
|
|
14
|
+
|
|
15
|
+
Suite: **1105 tests** across 55 files.
|
|
16
|
+
|
|
17
|
+
## Filled in Sprint 6 P4 (+62 tests)
|
|
18
|
+
|
|
19
|
+
P4 targeted the Sprint 4.2 / 4.2-bis additions that shipped with
|
|
20
|
+
integration-only coverage. All are now directly unit-tested:
|
|
21
|
+
|
|
22
|
+
| Area | Before | After |
|
|
23
|
+
|------|--------|-------|
|
|
24
|
+
| Cell renderer library (`Table/cells/` — RenderText / RenderTwoLine / RenderChip / RenderButton / RowActionsMenu) | ~0% | high (30 tests) |
|
|
25
|
+
| `DataGrid/filters/ColumnFilters.tsx` | 22% branch | covered — every filter type + apply/clear/Enter (17 tests) |
|
|
26
|
+
| `DataGrid/resize/useColumnResize.ts` | 33% | **100%** (8 tests — `nudge` clamp paths + pointer-drag commit) |
|
|
27
|
+
| `DataGrid/reorder/useColumnReorder.ts` | 32% | 93% stmts / 98% lines (14 tests — `moveColumn` + drag handlers) |
|
|
28
|
+
|
|
29
|
+
## Deferred — pre-Sprint-6 branch-coverage debt
|
|
30
|
+
|
|
31
|
+
Line coverage met the 85% target. **Branch coverage (75.87%) did
|
|
32
|
+
not.** The shortfall is concentrated in form-input components that
|
|
33
|
+
predate Sprint 6 and shipped with partial branch coverage — their
|
|
34
|
+
validation-state / RBAC / controlled-vs-uncontrolled branches are
|
|
35
|
+
under-exercised:
|
|
36
|
+
|
|
37
|
+
| Component | Branch % |
|
|
38
|
+
|-----------|----------|
|
|
39
|
+
| `NumberField` | 50.56% |
|
|
40
|
+
| `AppShell` | 55.81% |
|
|
41
|
+
| `Textarea` | 56% |
|
|
42
|
+
| `Switch` | 62.5% |
|
|
43
|
+
| `TextField` | 63.63% |
|
|
44
|
+
| `RadioGroup` | 64.06% |
|
|
45
|
+
| `Checkbox` | 67.5% |
|
|
46
|
+
| `Autocomplete` | 68% |
|
|
47
|
+
| `OTPField` | 69.56% |
|
|
48
|
+
| `Dialog` | 75% |
|
|
49
|
+
| `DataGrid` | 76.15% |
|
|
50
|
+
|
|
51
|
+
Closing this to 85% overall is a focused **test-debt paydown
|
|
52
|
+
sprint** (~100+ branch-targeted tests across the 11 components) —
|
|
53
|
+
deliberately scoped OUT of Sprint 6, which is a Table/DataGrid +
|
|
54
|
+
theme-core refinement pass. Recommended slot: alongside the
|
|
55
|
+
`1.0.0-rc` hardening sprint.
|
|
56
|
+
|
|
57
|
+
## CI gate
|
|
58
|
+
|
|
59
|
+
The catalog-wide regression suite (`nx test @dashforge/tw`) is the
|
|
60
|
+
enforced gate. A hard per-file coverage threshold is **not** wired
|
|
61
|
+
into CI yet — doing so requires first closing the pre-Sprint-6 debt
|
|
62
|
+
above, otherwise the gate fails on day one. Wiring the threshold is
|
|
63
|
+
part of the same `1.0.0-rc` test-debt sprint.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dashforge
|
|
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.
|
package/PERFORMANCE.md
CHANGED
|
@@ -159,11 +159,70 @@ single Radix primitive's worth of code) without the policy
|
|
|
159
159
|
triggering, but small enough that a careless dep addition gets
|
|
160
160
|
flagged.
|
|
161
161
|
|
|
162
|
+
## Render perf test suite (Sprint 6 P3)
|
|
163
|
+
|
|
164
|
+
CI-enforced render budgets, co-located as `*.perf.test.tsx`. Bounds
|
|
165
|
+
are deliberately generous — they catch **order-of-magnitude**
|
|
166
|
+
regressions (an accidental O(n²) in the pipeline, or a virtualization
|
|
167
|
+
break that mounts the full dataset), not micro-jitter.
|
|
168
|
+
|
|
169
|
+
### `<Table>` — non-virtualized (`Table.perf.test.tsx`)
|
|
170
|
+
|
|
171
|
+
| Scenario | Budget | Asserts |
|
|
172
|
+
|---|---|---|
|
|
173
|
+
| Mount 500 rows (Table's row-count ceiling) | < 800 ms | render path stays linear |
|
|
174
|
+
| 500 rows in DOM | exactly 500 `<tbody tr>` | non-virtualized contract |
|
|
175
|
+
| Default sort over 500 rows | < 800 ms | sort pipeline is not O(n²) |
|
|
176
|
+
|
|
177
|
+
### `<DataGrid>` — virtualized (`DataGrid.perf.test.tsx`)
|
|
178
|
+
|
|
179
|
+
| Scenario | Budget | Asserts |
|
|
180
|
+
|---|---|---|
|
|
181
|
+
| Mount 10 000 rows | < 500 ms | render is O(window) |
|
|
182
|
+
| 10 000-row DOM node count | < 100 `<tbody tr>` | only the window is mounted |
|
|
183
|
+
| Mount 100 000 rows | < 800 ms | cost does NOT scale with the dataset |
|
|
184
|
+
|
|
185
|
+
The 100 000-row test is the load-bearing one: if a regression makes
|
|
186
|
+
`renderedRows` slice the full array, the DOM-node-count assertion
|
|
187
|
+
fails immediately (100k `<tr>` ≫ 100).
|
|
188
|
+
|
|
189
|
+
## Strict gate assessment (Sprint 6 P3)
|
|
190
|
+
|
|
191
|
+
A probe enabled `exactOptionalPropertyTypes` + `noUncheckedIndexedAccess`
|
|
192
|
+
+ `noUnusedParameters` on `@dashforge/tw`. Result: **42 errors, zero
|
|
193
|
+
real bugs.** Every hit was either pedantic (`exactOptionalPropertyTypes`
|
|
194
|
+
flagging `fn | undefined` passed to an optional prop) or invariant-safe
|
|
195
|
+
but unprovable (`noUncheckedIndexedAccess` flagging array accesses
|
|
196
|
+
already guarded by a `.length` check — AppShell focus trap, RadioGroup
|
|
197
|
+
option access, Autocomplete highlight index).
|
|
198
|
+
|
|
199
|
+
**Decision**: enabling those flags is a workspace-wide change (the
|
|
200
|
+
`@dashforge/source` path mapping pulls the bridge layer's source into
|
|
201
|
+
the same program) for near-zero bug-catching value. Deferred to the
|
|
202
|
+
`1.0.0-rc` hardening sprint. The codebase is already solid under the
|
|
203
|
+
current `strict: true` baseline + `noImplicitOverride` /
|
|
204
|
+
`noImplicitReturns` / `noUnusedLocals` / `noFallthroughCasesInSwitch`.
|
|
205
|
+
ESLint is on `typescript-eslint recommended` + `react-hooks
|
|
206
|
+
recommended` + Nx boundary/dependency checks; promotion to
|
|
207
|
+
`strict-type-checked` (type-aware `no-unsafe-*` / `no-floating-promises`)
|
|
208
|
+
is the same workspace-wide 1.0-rc item.
|
|
209
|
+
|
|
210
|
+
## Console hygiene (Sprint 6 P3)
|
|
211
|
+
|
|
212
|
+
The full test run is audited for stray `console.error` / `console.warn`.
|
|
213
|
+
Sprint 6 P3 fixed the one finding: Radix logged 8× *"Missing
|
|
214
|
+
`Description` or `aria-describedby` for DialogContent"* — `<Dialog>`
|
|
215
|
+
now passes `aria-describedby={undefined}` on the content when no
|
|
216
|
+
`description` is supplied (Radix's documented opt-out). Console is
|
|
217
|
+
clean apart from a single jsdom-only *"Not implemented: navigation"*
|
|
218
|
+
(an environment limitation, not a component defect).
|
|
219
|
+
|
|
162
220
|
## Reference
|
|
163
221
|
|
|
164
222
|
- **Build command**: `nx build @dashforge/tw`
|
|
165
223
|
- **Measurement script**: `gzip -c dist/index.esm.js | wc -c`
|
|
166
224
|
- **Render perf setup**: see Sprint 2 P1
|
|
167
225
|
(`/test-foundation` route in `dash` consumer)
|
|
226
|
+
- **Render perf suite**: `*.perf.test.tsx` (Sprint 6 P3 — Table + DataGrid)
|
|
168
227
|
- **CHANGELOG entries**: every release records the bundle delta
|
|
169
228
|
in the `Compatibility` section
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# REFINEMENT-NOTES — `@dashforge/tw` Table + DataGrid
|
|
2
|
+
|
|
3
|
+
> Sprint 6 P2 deliverable (2026-05-20). Blind technical review of
|
|
4
|
+
> `<Table>` + `<DataGrid>` — what was fixed, and what was explicitly
|
|
5
|
+
> deferred.
|
|
6
|
+
|
|
7
|
+
## Fixed in Sprint 6 P2
|
|
8
|
+
|
|
9
|
+
| ID | Area | Fix |
|
|
10
|
+
|----|------|-----|
|
|
11
|
+
| D1 | DataGrid a11y | `aria-rowcount` on the `<table>` (true dataset size, not the virtualized window) + `aria-rowindex` on the header row (1) and every data row (`absoluteIndex + 2`). A screen reader now announces the real position. |
|
|
12
|
+
| D3 | DataGrid a11y | Column resize is now keyboard-operable: the resize handle is `tabIndex=0`, `ArrowLeft`/`ArrowRight` nudge the width 16px (64px with Shift), `aria-valuemin/max/now` announce the bounds. New `nudge()` on `useColumnResize`. |
|
|
13
|
+
| D6 | DataGrid bug | The resize handle on a reorderable column could also start a column-reorder drag (the `<th>` is `draggable`). Handle now sets `draggable={false}` — grabbing it always resizes. |
|
|
14
|
+
| D2 | DataGrid touch | Column reorder rides native HTML5 drag-and-drop, whose events don't fire on touch. The grid now detects a coarse pointer (`matchMedia('(pointer: coarse)')`) and disables the `draggable` affordance there, so it isn't a dead interaction. (Full touch reorder — see Deferred below.) |
|
|
15
|
+
| D4 | DataGrid UX | `Enter` in any filter Popover input now applies the filter (was: must click "Apply"). |
|
|
16
|
+
| D7 | Table + DataGrid UX | Empty state distinguishes a genuinely empty dataset (`noData`) from one emptied by an active search / filter (`noResults`). New `TableLabels.noResults`. |
|
|
17
|
+
| D8 | Table | Verified non-issue — Table is auto-height by design; skeleton rows inherit cell density padding. Added a clarifying code comment. |
|
|
18
|
+
| M4 | Cell library | Cleaned up a self-contradictory comment in `RenderChip` (the `solid neutral` variant). |
|
|
19
|
+
| T1 | Table | `getRowId` stays optional (back-compat) but now emits a dev-only `console.warn` when omitted while sort / search / selection / expandable is active — the positional-index fallback breaks row identity on reorder. Expanded the prop JSDoc. |
|
|
20
|
+
|
|
21
|
+
## Deferred — tracked follow-ups
|
|
22
|
+
|
|
23
|
+
### T3 — Per-column filter UI on `<Table>`
|
|
24
|
+
`<DataGrid>` got the in-header filter Popover in 0.8.0-beta (`filterable: true`).
|
|
25
|
+
`<Table>` still only accepts a controlled `filterModel` with no UI to
|
|
26
|
+
produce it. Porting `ColumnFilterTrigger` + the filter pipeline to
|
|
27
|
+
Table is a feature, not a refinement — it belongs in a dedicated
|
|
28
|
+
feature sprint (or post-1.0). Until then, Table's `filterModel` is
|
|
29
|
+
consumer-driven only.
|
|
30
|
+
|
|
31
|
+
### C2 — Cell renderer library additions
|
|
32
|
+
The library ships `RenderText`, `RenderTwoLine`, `RenderChip`,
|
|
33
|
+
`RenderButton`, `RowActionsMenu`. Common table-cell patterns still
|
|
34
|
+
missing:
|
|
35
|
+
- `RenderDate` — locale-aware date formatting (`Intl.DateTimeFormat`,
|
|
36
|
+
zero-dep)
|
|
37
|
+
- `RenderAvatar` — avatar image / initials + label, the canonical
|
|
38
|
+
"user" cell
|
|
39
|
+
- `RenderLink` — a styled anchor honoring the theme
|
|
40
|
+
|
|
41
|
+
Purely additive — slated for a feature sprint, not refinement.
|
|
42
|
+
|
|
43
|
+
### D2-full — Pointer-events column reorder (touch support)
|
|
44
|
+
The D2 fix above is *graceful degradation* — reorder is cleanly
|
|
45
|
+
unavailable on touch rather than silently broken. A proper touch
|
|
46
|
+
implementation means replacing `useColumnReorder`'s HTML5
|
|
47
|
+
drag-and-drop with pointer events (à la `useColumnResize`): track
|
|
48
|
+
`pointerdown` → `pointermove` with hit-testing (`elementFromPoint`)
|
|
49
|
+
for the drop target → `pointerup` to commit. Meaningful rewrite —
|
|
50
|
+
deferred to a follow-up so P2 stays a refinement pass.
|