@dashforge/tw 0.4.0-beta → 0.6.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +391 -0
  2. package/dist/index.esm.js +2113 -2
  3. package/dist/src/components/Pagination/Pagination.d.ts +32 -0
  4. package/dist/src/components/Pagination/Pagination.d.ts.map +1 -0
  5. package/dist/src/components/Pagination/pagination.helpers.d.ts +23 -0
  6. package/dist/src/components/Pagination/pagination.helpers.d.ts.map +1 -0
  7. package/dist/src/components/Pagination/pagination.types.d.ts +120 -0
  8. package/dist/src/components/Pagination/pagination.types.d.ts.map +1 -0
  9. package/dist/src/components/Pagination/pagination.variants.d.ts +150 -0
  10. package/dist/src/components/Pagination/pagination.variants.d.ts.map +1 -0
  11. package/dist/src/components/Skeleton/Skeleton.d.ts +23 -0
  12. package/dist/src/components/Skeleton/Skeleton.d.ts.map +1 -0
  13. package/dist/src/components/Skeleton/skeleton.types.d.ts +56 -0
  14. package/dist/src/components/Skeleton/skeleton.types.d.ts.map +1 -0
  15. package/dist/src/components/Skeleton/skeleton.variants.d.ts +110 -0
  16. package/dist/src/components/Skeleton/skeleton.variants.d.ts.map +1 -0
  17. package/dist/src/components/Table/Table.d.ts +24 -0
  18. package/dist/src/components/Table/Table.d.ts.map +1 -0
  19. package/dist/src/components/Table/_internal/getNestedValue.d.ts +20 -0
  20. package/dist/src/components/Table/_internal/getNestedValue.d.ts.map +1 -0
  21. package/dist/src/components/Table/_internal/useColumnAutoDetect.d.ts +45 -0
  22. package/dist/src/components/Table/_internal/useColumnAutoDetect.d.ts.map +1 -0
  23. package/dist/src/components/Table/_internal/useControllableState.d.ts +23 -0
  24. package/dist/src/components/Table/_internal/useControllableState.d.ts.map +1 -0
  25. package/dist/src/components/Table/_internal/useDebouncedValue.d.ts +10 -0
  26. package/dist/src/components/Table/_internal/useDebouncedValue.d.ts.map +1 -0
  27. package/dist/src/components/Table/_internal/useTableFilter.d.ts +13 -0
  28. package/dist/src/components/Table/_internal/useTableFilter.d.ts.map +1 -0
  29. package/dist/src/components/Table/_internal/useTableSearch.d.ts +23 -0
  30. package/dist/src/components/Table/_internal/useTableSearch.d.ts.map +1 -0
  31. package/dist/src/components/Table/_internal/useTableSelection.d.ts +25 -0
  32. package/dist/src/components/Table/_internal/useTableSelection.d.ts.map +1 -0
  33. package/dist/src/components/Table/_internal/useTableSort.d.ts +20 -0
  34. package/dist/src/components/Table/_internal/useTableSort.d.ts.map +1 -0
  35. package/dist/src/components/Table/cells/RenderButton.d.ts +13 -0
  36. package/dist/src/components/Table/cells/RenderButton.d.ts.map +1 -0
  37. package/dist/src/components/Table/cells/RenderChip.d.ts +80 -0
  38. package/dist/src/components/Table/cells/RenderChip.d.ts.map +1 -0
  39. package/dist/src/components/Table/cells/RenderText.d.ts +21 -0
  40. package/dist/src/components/Table/cells/RenderText.d.ts.map +1 -0
  41. package/dist/src/components/Table/cells/RenderTwoLine.d.ts +20 -0
  42. package/dist/src/components/Table/cells/RenderTwoLine.d.ts.map +1 -0
  43. package/dist/src/components/Table/cells/RowActionsMenu.d.ts +36 -0
  44. package/dist/src/components/Table/cells/RowActionsMenu.d.ts.map +1 -0
  45. package/dist/src/components/Table/cells/index.d.ts +11 -0
  46. package/dist/src/components/Table/cells/index.d.ts.map +1 -0
  47. package/dist/src/components/Table/table.types.d.ts +304 -0
  48. package/dist/src/components/Table/table.types.d.ts.map +1 -0
  49. package/dist/src/components/Table/table.variants.d.ts +285 -0
  50. package/dist/src/components/Table/table.variants.d.ts.map +1 -0
  51. package/dist/src/index.d.ts +13 -1
  52. package/dist/src/index.d.ts.map +1 -1
  53. package/package.json +1 -1
  54. package/src/components/Pagination/Pagination.test.tsx +314 -0
  55. package/src/components/Pagination/Pagination.tsx +275 -0
  56. package/src/components/Pagination/pagination.helpers.ts +102 -0
  57. package/src/components/Pagination/pagination.types.ts +117 -0
  58. package/src/components/Pagination/pagination.variants.ts +111 -0
  59. package/src/components/Skeleton/Skeleton.test.tsx +127 -0
  60. package/src/components/Skeleton/Skeleton.tsx +49 -0
  61. package/src/components/Skeleton/skeleton.types.ts +59 -0
  62. package/src/components/Skeleton/skeleton.variants.ts +86 -0
  63. package/src/components/Table/Table.test.tsx +603 -0
  64. package/src/components/Table/Table.tsx +816 -0
  65. package/src/components/Table/_internal/getNestedValue.test.ts +50 -0
  66. package/src/components/Table/_internal/getNestedValue.ts +32 -0
  67. package/src/components/Table/_internal/themeIdentity.test.ts +84 -0
  68. package/src/components/Table/_internal/useColumnAutoDetect.test.ts +123 -0
  69. package/src/components/Table/_internal/useColumnAutoDetect.ts +100 -0
  70. package/src/components/Table/_internal/useControllableState.ts +48 -0
  71. package/src/components/Table/_internal/useDebouncedValue.ts +24 -0
  72. package/src/components/Table/_internal/useTableFilter.ts +37 -0
  73. package/src/components/Table/_internal/useTableSearch.test.ts +115 -0
  74. package/src/components/Table/_internal/useTableSearch.ts +66 -0
  75. package/src/components/Table/_internal/useTableSelection.test.ts +100 -0
  76. package/src/components/Table/_internal/useTableSelection.ts +100 -0
  77. package/src/components/Table/_internal/useTableSort.test.ts +150 -0
  78. package/src/components/Table/_internal/useTableSort.ts +141 -0
  79. package/src/components/Table/cells/RenderButton.tsx +23 -0
  80. package/src/components/Table/cells/RenderChip.tsx +103 -0
  81. package/src/components/Table/cells/RenderText.tsx +37 -0
  82. package/src/components/Table/cells/RenderTwoLine.tsx +34 -0
  83. package/src/components/Table/cells/RowActionsMenu.tsx +147 -0
  84. package/src/components/Table/cells/index.ts +14 -0
  85. package/src/components/Table/table.types.ts +337 -0
  86. package/src/components/Table/table.variants.ts +207 -0
  87. package/src/index.ts +60 -1
@@ -0,0 +1,207 @@
1
+ import { tv, type VariantProps } from 'tailwind-variants';
2
+
3
+ /**
4
+ * `<Table>` variant recipe.
5
+ *
6
+ * Slots:
7
+ * - `root` — outer wrapper
8
+ * - `toolbar` — search + filter chips row above table
9
+ * - `search` — search input
10
+ * - `scroll` — `<div class="overflow-auto">` wrapping the table
11
+ * - `table` — `<table>` element
12
+ * - `thead` — `<thead>` (sticky positioning here)
13
+ * - `tbody` — `<tbody>`
14
+ * - `headerRow` — `<tr>` inside `<thead>`
15
+ * - `headerCell` — `<th>` cell
16
+ * - `headerCellButton` — `<button>` inside sortable `<th>`
17
+ * - `row` — `<tr>` inside `<tbody>` (data row)
18
+ * - `cell` — `<td>` data cell
19
+ * - `selectionCell` — first `<td>` when selection mode active
20
+ * - `expandToggleCell` — second `<td>` when expandable active
21
+ * - `expandedRow` — full-width `<tr>` rendered after an expanded row
22
+ * - `rowActionsCell` — last `<td>` when `rowActions` provided
23
+ * - `emptyState` — placeholder when rows is empty
24
+ * - `loadingOverlay` — skeleton overlay when loading
25
+ * - `bulkActionFooter` — sticky footer with bulk actions
26
+ *
27
+ * Variant axes:
28
+ * - `variant` — visual row-division style:
29
+ * - `plain` — minimal separators
30
+ * - `lines` — Stripe-style thin horizontal dividers (default)
31
+ * - `striped` — alternating row backgrounds (zebra)
32
+ * - `bordered` — full cell borders
33
+ * - `card` — each row rendered as a separate surface card
34
+ * - `size` — `sm` / `md` (default) / `lg`
35
+ * - `density` — `compact` (40px row) / `comfortable` (default 48px) / `spacious` (56px)
36
+ *
37
+ * Smart-default alignment (per column) is applied by the Table
38
+ * component code, NOT here — it depends on the runtime-detected
39
+ * value type, which the recipe doesn't see.
40
+ *
41
+ * **Dashforge identity rule** (memory: `feedback_dashforge_preset_is_identity`):
42
+ * This recipe uses NO `dark:` variants on the neutral palette. The
43
+ * `dashforgePreset()` CSS-variable swap auto-inverts neutral tokens
44
+ * (`bg-neutral-50` is light surface in light mode, dark surface in
45
+ * dark mode — same class, different physical color). Adding a
46
+ * `dark:` variant on neutral palette = DOUBLE inversion = breaks
47
+ * dark mode. The selected-row state uses the canonical LeftNav
48
+ * `itemActive` pattern (`bg-primary-100 text-primary-900 font-medium`),
49
+ * which works in both modes because the primary palette has no
50
+ * inversion (both `bg` and `text` resolve to the same physical
51
+ * colors regardless of mode → guaranteed contrast).
52
+ */
53
+ export const tableVariants = tv({
54
+ slots: {
55
+ root: 'w-full',
56
+ toolbar: 'flex flex-wrap items-center gap-3 mb-3',
57
+ search: [
58
+ 'inline-flex items-center gap-2',
59
+ 'w-full max-w-sm rounded-md',
60
+ 'border border-neutral-300',
61
+ // bg-neutral-50 auto-inverts via CSS var swap (light in light mode,
62
+ // dark in dark mode). Same semantic as TextField wrapper.
63
+ 'bg-neutral-50',
64
+ 'focus-within:ring-2 focus-within:ring-primary-500',
65
+ 'transition-colors motion-reduce:transition-none',
66
+ ],
67
+ scroll: 'relative w-full overflow-auto rounded-md',
68
+ table: 'w-full caption-bottom text-left',
69
+ // thead matches the page surface (auto-inverts). When sticky the
70
+ // header sits opaque against the scroll content beneath it.
71
+ thead: 'bg-neutral-50',
72
+ tbody: '',
73
+ headerRow: '',
74
+ headerCell: [
75
+ // Less prominent than the body — secondary-text intent
76
+ // (auto-inverts: dark grey in light mode, light grey in dark).
77
+ 'text-neutral-700',
78
+ 'font-semibold whitespace-nowrap select-none',
79
+ 'border-b border-neutral-200',
80
+ ],
81
+ headerCellButton: [
82
+ 'group inline-flex items-center gap-1 select-none',
83
+ // hover increases prominence (auto-inverts).
84
+ 'hover:text-neutral-900',
85
+ 'focus:outline-none focus-visible:underline',
86
+ 'transition-colors motion-reduce:transition-none',
87
+ ],
88
+ row: [
89
+ 'group/row transition-colors motion-reduce:transition-none',
90
+ // bg-neutral-100 = "elevated above surface" in both modes via
91
+ // auto-inversion. Slightly visible against the table bg.
92
+ 'hover:bg-neutral-100',
93
+ // Canonical LeftNav `itemActive` pattern — primary palette
94
+ // doesn't invert, so dark-navy text on light-blue bg in BOTH
95
+ // modes. Guaranteed contrast.
96
+ 'data-[selected=true]:bg-primary-100',
97
+ 'data-[selected=true]:text-primary-900',
98
+ 'data-[selected=true]:font-medium',
99
+ ],
100
+ cell: [
101
+ // Auto-inverts — dark text in light mode, light text in dark mode.
102
+ 'text-neutral-900',
103
+ 'border-b border-neutral-200',
104
+ 'align-middle',
105
+ ],
106
+ selectionCell: 'w-10 text-center',
107
+ expandToggleCell: 'w-10 text-center',
108
+ // Expanded panel uses one tier of elevation above the page surface.
109
+ expandedRow: 'bg-neutral-100',
110
+ rowActionsCell: [
111
+ 'w-12 text-right',
112
+ // Row actions hidden until row is hovered or focus-within
113
+ // (Pencil & Paper UX pattern: reveal-on-hover reduces visual density).
114
+ 'opacity-0 group-hover/row:opacity-100 group-focus-within/row:opacity-100',
115
+ 'transition-opacity motion-reduce:transition-none',
116
+ ],
117
+ emptyState: [
118
+ 'py-12 text-center text-neutral-500',
119
+ ],
120
+ loadingOverlay: [
121
+ 'pointer-events-none',
122
+ ],
123
+ bulkActionFooter: [
124
+ 'sticky bottom-0 z-20',
125
+ 'flex flex-wrap items-center justify-between gap-3',
126
+ 'px-3 py-2 mt-0',
127
+ 'border-t border-neutral-200',
128
+ // Surface-elevated bg + shadow ladder.
129
+ 'bg-neutral-50 shadow-md',
130
+ ],
131
+ },
132
+ variants: {
133
+ variant: {
134
+ plain: {},
135
+ lines: {
136
+ // Default — Stripe-style 1px horizontal dividers (already
137
+ // applied via `border-b` on row + cell). No extra style here.
138
+ },
139
+ striped: {
140
+ // bg-neutral-100/60 = subtle elevation tier (auto-inverts).
141
+ row: 'odd:bg-neutral-100/60',
142
+ },
143
+ bordered: {
144
+ table: 'border border-neutral-200',
145
+ cell: 'border-r last:border-r-0 border-neutral-200',
146
+ headerCell: 'border-r last:border-r-0 border-neutral-200',
147
+ },
148
+ card: {
149
+ scroll: 'overflow-visible',
150
+ table: 'border-separate border-spacing-y-2',
151
+ row: [
152
+ 'rounded-lg shadow-sm',
153
+ // Each row becomes an elevated card above the surface.
154
+ 'bg-neutral-50',
155
+ ],
156
+ cell: 'border-b-0 first:rounded-l-lg last:rounded-r-lg',
157
+ headerCell: 'border-b-0',
158
+ },
159
+ },
160
+ size: {
161
+ sm: {
162
+ headerCell: 'text-xs',
163
+ cell: 'text-xs',
164
+ search: 'text-xs',
165
+ },
166
+ md: {
167
+ headerCell: 'text-sm',
168
+ cell: 'text-sm',
169
+ search: 'text-sm',
170
+ },
171
+ lg: {
172
+ headerCell: 'text-base',
173
+ cell: 'text-base',
174
+ search: 'text-base',
175
+ },
176
+ },
177
+ density: {
178
+ // Pencil & Paper UX research: 40px / 48px / 56px row height.
179
+ compact: {
180
+ headerCell: 'px-2 py-1',
181
+ cell: 'px-2 py-1',
182
+ },
183
+ comfortable: {
184
+ headerCell: 'px-3 py-2',
185
+ cell: 'px-3 py-2',
186
+ },
187
+ spacious: {
188
+ headerCell: 'px-4 py-3',
189
+ cell: 'px-4 py-3',
190
+ },
191
+ },
192
+ stickyHeader: {
193
+ true: {
194
+ thead: 'sticky top-0 z-10',
195
+ },
196
+ false: {},
197
+ },
198
+ },
199
+ defaultVariants: {
200
+ variant: 'lines',
201
+ size: 'md',
202
+ density: 'comfortable',
203
+ stickyHeader: true,
204
+ },
205
+ });
206
+
207
+ export type TableVariants = VariantProps<typeof tableVariants>;
package/src/index.ts CHANGED
@@ -262,6 +262,65 @@ export type {
262
262
  } from './components/Accordion/accordion.types.js';
263
263
  export { accordionVariants } from './components/Accordion/accordion.variants.js';
264
264
 
265
+ // F12 utilities: loading placeholder + pagination control.
266
+
267
+ export { Skeleton } from './components/Skeleton/Skeleton.js';
268
+ export type {
269
+ SkeletonProps,
270
+ SkeletonSlotProps,
271
+ } from './components/Skeleton/skeleton.types.js';
272
+ export { skeletonVariants } from './components/Skeleton/skeleton.variants.js';
273
+
274
+ export { Pagination } from './components/Pagination/Pagination.js';
275
+ export type {
276
+ PaginationProps,
277
+ PaginationSlotProps,
278
+ PaginationLabels,
279
+ } from './components/Pagination/pagination.types.js';
280
+ export { paginationVariants } from './components/Pagination/pagination.variants.js';
281
+
282
+ // F13 tier-5: market-grounded Table (Stripe-style visuals, Pencil&Paper
283
+ // UX research, W3C WAI a11y). DataGrid (with virtualization) ships in
284
+ // Sprint 4.2.
285
+
286
+ export { Table } from './components/Table/Table.js';
287
+ export type {
288
+ TableProps,
289
+ TableColumn,
290
+ TableColumnInferredType,
291
+ TableCellContext,
292
+ TableSortDirection,
293
+ TableSortItem,
294
+ TableSortModel,
295
+ TableFilterItem,
296
+ TableFilterModel,
297
+ TableRowSelectionMode,
298
+ TableExpandableConfig,
299
+ TableLabels,
300
+ TableSlotProps,
301
+ NestedKeyOf,
302
+ } from './components/Table/table.types.js';
303
+ export { tableVariants } from './components/Table/table.variants.js';
304
+ // Cell renderer library
305
+ export {
306
+ RenderText,
307
+ RenderTwoLine,
308
+ RenderChip,
309
+ RenderButton,
310
+ RowActionsMenu,
311
+ } from './components/Table/cells/index.js';
312
+ export type {
313
+ RenderTextProps,
314
+ RenderTwoLineProps,
315
+ RenderChipProps,
316
+ RenderButtonProps,
317
+ RowActionsMenuProps,
318
+ TableRowAction,
319
+ } from './components/Table/cells/index.js';
320
+ // Helpers (exported for power users building custom Table-like
321
+ // components on top of the same primitives).
322
+ export { getNestedValue } from './components/Table/_internal/getNestedValue.js';
323
+
265
324
  // ───── Hooks ─────
266
325
  export { useAccessState } from './hooks/useAccessState.js';
267
326
 
@@ -276,4 +335,4 @@ export type { VariantProps } from 'tailwind-variants';
276
335
  /**
277
336
  * Package version (synced with `package.json` at publish time).
278
337
  */
279
- export const VERSION = '0.4.0-beta';
338
+ export const VERSION = '0.6.0-beta';