@dashforge/tw 0.8.1-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.
Files changed (180) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/COVERAGE.md +63 -0
  3. package/LICENSE +21 -0
  4. package/PERFORMANCE.md +59 -0
  5. package/REFINEMENT-NOTES.md +50 -0
  6. package/dist/index.esm.js +177 -67
  7. package/dist/src/components/DataGrid/DataGrid.d.ts.map +1 -1
  8. package/dist/src/components/DataGrid/filters/ColumnFilters.d.ts.map +1 -1
  9. package/dist/src/components/DataGrid/resize/useColumnResize.d.ts +7 -0
  10. package/dist/src/components/DataGrid/resize/useColumnResize.d.ts.map +1 -1
  11. package/dist/src/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts +6 -2
  12. package/dist/src/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts.map +1 -1
  13. package/dist/src/components/Dialog/Dialog.d.ts.map +1 -1
  14. package/dist/src/components/Table/Table.d.ts.map +1 -1
  15. package/dist/src/components/Table/cells/RenderChip.d.ts.map +1 -1
  16. package/dist/src/components/Table/table.types.d.ts +28 -3
  17. package/dist/src/components/Table/table.types.d.ts.map +1 -1
  18. package/dist/src/components/Typography/typography.variants.d.ts.map +1 -1
  19. package/eslint.config.mjs +16 -1
  20. package/package.json +9 -6
  21. package/src/components/Breadcrumbs/Breadcrumbs.perf.test.tsx +5 -2
  22. package/src/components/DataGrid/DataGrid.perf.test.tsx +114 -0
  23. package/src/components/DataGrid/DataGrid.test.tsx +240 -0
  24. package/src/components/DataGrid/DataGrid.tsx +104 -16
  25. package/src/components/DataGrid/filters/ColumnFilters.test.tsx +330 -0
  26. package/src/components/DataGrid/filters/ColumnFilters.tsx +26 -2
  27. package/src/components/DataGrid/reorder/useColumnReorder.test.ts +95 -3
  28. package/src/components/DataGrid/resize/useColumnResize.test.ts +144 -0
  29. package/src/components/DataGrid/resize/useColumnResize.ts +30 -1
  30. package/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx +42 -25
  31. package/src/components/Dialog/Dialog.tsx +9 -0
  32. package/src/components/Table/Table.perf.test.tsx +81 -0
  33. package/src/components/Table/Table.test.tsx +72 -1
  34. package/src/components/Table/Table.tsx +40 -4
  35. package/src/components/Table/cells/RenderChip.tsx +6 -9
  36. package/src/components/Table/cells/cells.test.tsx +247 -0
  37. package/src/components/Table/table.types.ts +28 -3
  38. package/src/components/Typography/Typography.test.tsx +15 -0
  39. package/src/components/Typography/typography.variants.ts +14 -1
  40. package/test-output/vitest/coverage/base.css +224 -0
  41. package/test-output/vitest/coverage/block-navigation.js +87 -0
  42. package/test-output/vitest/coverage/clover.xml +2418 -0
  43. package/test-output/vitest/coverage/coverage-final.json +89 -0
  44. package/test-output/vitest/coverage/favicon.png +0 -0
  45. package/test-output/vitest/coverage/index.html +746 -0
  46. package/test-output/vitest/coverage/prettify.css +1 -0
  47. package/test-output/vitest/coverage/prettify.js +2 -0
  48. package/test-output/vitest/coverage/sort-arrow-sprite.png +0 -0
  49. package/test-output/vitest/coverage/sorter.js +210 -0
  50. package/test-output/vitest/coverage/src/components/Accordion/Accordion.tsx.html +376 -0
  51. package/test-output/vitest/coverage/src/components/Accordion/accordion.variants.ts.html +181 -0
  52. package/test-output/vitest/coverage/src/components/Accordion/index.html +131 -0
  53. package/test-output/vitest/coverage/src/components/AppShell/AppShell.tsx.html +802 -0
  54. package/test-output/vitest/coverage/src/components/AppShell/appShell.variants.ts.html +247 -0
  55. package/test-output/vitest/coverage/src/components/AppShell/index.html +131 -0
  56. package/test-output/vitest/coverage/src/components/AspectRatio/AspectRatio.tsx.html +304 -0
  57. package/test-output/vitest/coverage/src/components/AspectRatio/index.html +116 -0
  58. package/test-output/vitest/coverage/src/components/Autocomplete/Autocomplete.tsx.html +3292 -0
  59. package/test-output/vitest/coverage/src/components/Autocomplete/autocomplete.variants.ts.html +508 -0
  60. package/test-output/vitest/coverage/src/components/Autocomplete/index.html +131 -0
  61. package/test-output/vitest/coverage/src/components/Box/Box.tsx.html +334 -0
  62. package/test-output/vitest/coverage/src/components/Box/box.variants.ts.html +775 -0
  63. package/test-output/vitest/coverage/src/components/Box/index.html +131 -0
  64. package/test-output/vitest/coverage/src/components/Breadcrumbs/Breadcrumbs.tsx.html +694 -0
  65. package/test-output/vitest/coverage/src/components/Breadcrumbs/breadcrumbs.variants.ts.html +247 -0
  66. package/test-output/vitest/coverage/src/components/Breadcrumbs/index.html +131 -0
  67. package/test-output/vitest/coverage/src/components/Button/Button.tsx.html +535 -0
  68. package/test-output/vitest/coverage/src/components/Button/button.variants.ts.html +562 -0
  69. package/test-output/vitest/coverage/src/components/Button/index.html +131 -0
  70. package/test-output/vitest/coverage/src/components/Checkbox/Checkbox.tsx.html +943 -0
  71. package/test-output/vitest/coverage/src/components/Checkbox/checkbox.variants.ts.html +289 -0
  72. package/test-output/vitest/coverage/src/components/Checkbox/index.html +131 -0
  73. package/test-output/vitest/coverage/src/components/ConfirmDialog/ConfirmDialog.tsx.html +841 -0
  74. package/test-output/vitest/coverage/src/components/ConfirmDialog/confirmDialog.variants.ts.html +313 -0
  75. package/test-output/vitest/coverage/src/components/ConfirmDialog/index.html +131 -0
  76. package/test-output/vitest/coverage/src/components/Container/Container.tsx.html +307 -0
  77. package/test-output/vitest/coverage/src/components/Container/container.variants.ts.html +328 -0
  78. package/test-output/vitest/coverage/src/components/Container/index.html +131 -0
  79. package/test-output/vitest/coverage/src/components/DataGrid/DataGrid.tsx.html +3937 -0
  80. package/test-output/vitest/coverage/src/components/DataGrid/dataGrid.variants.ts.html +541 -0
  81. package/test-output/vitest/coverage/src/components/DataGrid/filters/ColumnFilters.tsx.html +1453 -0
  82. package/test-output/vitest/coverage/src/components/DataGrid/filters/index.html +116 -0
  83. package/test-output/vitest/coverage/src/components/DataGrid/index.html +131 -0
  84. package/test-output/vitest/coverage/src/components/DataGrid/reorder/index.html +116 -0
  85. package/test-output/vitest/coverage/src/components/DataGrid/reorder/useColumnReorder.ts.html +517 -0
  86. package/test-output/vitest/coverage/src/components/DataGrid/resize/index.html +116 -0
  87. package/test-output/vitest/coverage/src/components/DataGrid/resize/useColumnResize.ts.html +490 -0
  88. package/test-output/vitest/coverage/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx.html +592 -0
  89. package/test-output/vitest/coverage/src/components/DataGrid/visibility/index.html +116 -0
  90. package/test-output/vitest/coverage/src/components/DateTimePicker/DateTimePicker.tsx.html +1042 -0
  91. package/test-output/vitest/coverage/src/components/DateTimePicker/dateTimePicker.variants.ts.html +337 -0
  92. package/test-output/vitest/coverage/src/components/DateTimePicker/index.html +131 -0
  93. package/test-output/vitest/coverage/src/components/Dialog/Dialog.tsx.html +391 -0
  94. package/test-output/vitest/coverage/src/components/Dialog/dialog.variants.ts.html +283 -0
  95. package/test-output/vitest/coverage/src/components/Dialog/index.html +131 -0
  96. package/test-output/vitest/coverage/src/components/Divider/Divider.tsx.html +505 -0
  97. package/test-output/vitest/coverage/src/components/Divider/divider.variants.ts.html +433 -0
  98. package/test-output/vitest/coverage/src/components/Divider/index.html +131 -0
  99. package/test-output/vitest/coverage/src/components/Grid/Grid.tsx.html +529 -0
  100. package/test-output/vitest/coverage/src/components/Grid/grid.variants.ts.html +484 -0
  101. package/test-output/vitest/coverage/src/components/Grid/index.html +131 -0
  102. package/test-output/vitest/coverage/src/components/LeftNav/LeftNav.tsx.html +1075 -0
  103. package/test-output/vitest/coverage/src/components/LeftNav/index.html +131 -0
  104. package/test-output/vitest/coverage/src/components/LeftNav/leftNav.variants.ts.html +406 -0
  105. package/test-output/vitest/coverage/src/components/NumberField/NumberField.tsx.html +1048 -0
  106. package/test-output/vitest/coverage/src/components/NumberField/index.html +131 -0
  107. package/test-output/vitest/coverage/src/components/NumberField/numberField.variants.ts.html +367 -0
  108. package/test-output/vitest/coverage/src/components/OTPField/OTPField.tsx.html +835 -0
  109. package/test-output/vitest/coverage/src/components/OTPField/index.html +131 -0
  110. package/test-output/vitest/coverage/src/components/OTPField/otpField.variants.ts.html +301 -0
  111. package/test-output/vitest/coverage/src/components/Pagination/Pagination.tsx.html +916 -0
  112. package/test-output/vitest/coverage/src/components/Pagination/index.html +146 -0
  113. package/test-output/vitest/coverage/src/components/Pagination/pagination.helpers.ts.html +391 -0
  114. package/test-output/vitest/coverage/src/components/Pagination/pagination.variants.ts.html +436 -0
  115. package/test-output/vitest/coverage/src/components/Popover/Popover.tsx.html +250 -0
  116. package/test-output/vitest/coverage/src/components/Popover/index.html +131 -0
  117. package/test-output/vitest/coverage/src/components/Popover/popover.variants.ts.html +157 -0
  118. package/test-output/vitest/coverage/src/components/RadioGroup/RadioGroup.tsx.html +934 -0
  119. package/test-output/vitest/coverage/src/components/RadioGroup/index.html +131 -0
  120. package/test-output/vitest/coverage/src/components/RadioGroup/radioGroup.variants.ts.html +346 -0
  121. package/test-output/vitest/coverage/src/components/Skeleton/Skeleton.tsx.html +232 -0
  122. package/test-output/vitest/coverage/src/components/Skeleton/index.html +131 -0
  123. package/test-output/vitest/coverage/src/components/Skeleton/skeleton.variants.ts.html +346 -0
  124. package/test-output/vitest/coverage/src/components/Snackbar/Snackbar.tsx.html +979 -0
  125. package/test-output/vitest/coverage/src/components/Snackbar/index.html +131 -0
  126. package/test-output/vitest/coverage/src/components/Snackbar/snackbar.variants.ts.html +307 -0
  127. package/test-output/vitest/coverage/src/components/Stack/Stack.tsx.html +430 -0
  128. package/test-output/vitest/coverage/src/components/Stack/index.html +131 -0
  129. package/test-output/vitest/coverage/src/components/Stack/stack.variants.ts.html +325 -0
  130. package/test-output/vitest/coverage/src/components/Switch/Switch.tsx.html +559 -0
  131. package/test-output/vitest/coverage/src/components/Switch/index.html +131 -0
  132. package/test-output/vitest/coverage/src/components/Switch/switch.variants.ts.html +295 -0
  133. package/test-output/vitest/coverage/src/components/Table/Table.tsx.html +2677 -0
  134. package/test-output/vitest/coverage/src/components/Table/cells/RenderButton.tsx.html +154 -0
  135. package/test-output/vitest/coverage/src/components/Table/cells/RenderChip.tsx.html +385 -0
  136. package/test-output/vitest/coverage/src/components/Table/cells/RenderText.tsx.html +196 -0
  137. package/test-output/vitest/coverage/src/components/Table/cells/RenderTwoLine.tsx.html +187 -0
  138. package/test-output/vitest/coverage/src/components/Table/cells/RowActionsMenu.tsx.html +526 -0
  139. package/test-output/vitest/coverage/src/components/Table/cells/index.html +191 -0
  140. package/test-output/vitest/coverage/src/components/Table/cells/index.ts.html +127 -0
  141. package/test-output/vitest/coverage/src/components/Table/index.html +131 -0
  142. package/test-output/vitest/coverage/src/components/Table/table.variants.ts.html +706 -0
  143. package/test-output/vitest/coverage/src/components/Tabs/Tabs.tsx.html +283 -0
  144. package/test-output/vitest/coverage/src/components/Tabs/index.html +131 -0
  145. package/test-output/vitest/coverage/src/components/Tabs/tabs.variants.ts.html +292 -0
  146. package/test-output/vitest/coverage/src/components/TextField/TextField.tsx.html +820 -0
  147. package/test-output/vitest/coverage/src/components/TextField/index.html +131 -0
  148. package/test-output/vitest/coverage/src/components/TextField/textField.variants.ts.html +400 -0
  149. package/test-output/vitest/coverage/src/components/Textarea/Textarea.tsx.html +655 -0
  150. package/test-output/vitest/coverage/src/components/Textarea/index.html +131 -0
  151. package/test-output/vitest/coverage/src/components/Textarea/textarea.variants.ts.html +340 -0
  152. package/test-output/vitest/coverage/src/components/Tooltip/Tooltip.tsx.html +295 -0
  153. package/test-output/vitest/coverage/src/components/Tooltip/index.html +131 -0
  154. package/test-output/vitest/coverage/src/components/Tooltip/tooltip.variants.ts.html +169 -0
  155. package/test-output/vitest/coverage/src/components/TopBar/TopBar.tsx.html +283 -0
  156. package/test-output/vitest/coverage/src/components/TopBar/index.html +131 -0
  157. package/test-output/vitest/coverage/src/components/TopBar/topBar.variants.ts.html +199 -0
  158. package/test-output/vitest/coverage/src/components/Typography/Typography.tsx.html +421 -0
  159. package/test-output/vitest/coverage/src/components/Typography/index.html +131 -0
  160. package/test-output/vitest/coverage/src/components/Typography/typography.variants.ts.html +436 -0
  161. package/test-output/vitest/coverage/src/components/VisuallyHidden/VisuallyHidden.tsx.html +262 -0
  162. package/test-output/vitest/coverage/src/components/VisuallyHidden/index.html +116 -0
  163. package/test-output/vitest/coverage/src/components/_shared/data/getNestedValue.ts.html +181 -0
  164. package/test-output/vitest/coverage/src/components/_shared/data/index.html +236 -0
  165. package/test-output/vitest/coverage/src/components/_shared/data/useColumnAutoDetect.ts.html +385 -0
  166. package/test-output/vitest/coverage/src/components/_shared/data/useControllableState.ts.html +229 -0
  167. package/test-output/vitest/coverage/src/components/_shared/data/useDebouncedValue.ts.html +157 -0
  168. package/test-output/vitest/coverage/src/components/_shared/data/useTableFilter.ts.html +439 -0
  169. package/test-output/vitest/coverage/src/components/_shared/data/useTableSearch.ts.html +283 -0
  170. package/test-output/vitest/coverage/src/components/_shared/data/useTableSelection.ts.html +385 -0
  171. package/test-output/vitest/coverage/src/components/_shared/data/useTableSort.ts.html +508 -0
  172. package/test-output/vitest/coverage/src/components/_shared/data/useVirtualizer.ts.html +682 -0
  173. package/test-output/vitest/coverage/src/components/_shared/index.html +116 -0
  174. package/test-output/vitest/coverage/src/components/_shared/resolveValidationState.ts.html +265 -0
  175. package/test-output/vitest/coverage/src/hooks/index.html +116 -0
  176. package/test-output/vitest/coverage/src/hooks/useAccessState.ts.html +328 -0
  177. package/test-output/vitest/coverage/src/index.html +116 -0
  178. package/test-output/vitest/coverage/src/index.ts.html +1153 -0
  179. package/test-output/vitest/coverage/src/utils/cn.ts.html +172 -0
  180. package/test-output/vitest/coverage/src/utils/index.html +116 -0
package/dist/index.esm.js CHANGED
@@ -5285,6 +5285,15 @@ const SnackbarContext = /*#__PURE__*/ createContext(null);
5285
5285
  * has set its own color (e.g. `<Box variant="solid" color="primary">`
5286
5286
  * paints white text).
5287
5287
  */ color: {
5288
+ // `inherit` is the explicit escape hatch — use it on a
5289
+ // `<Typography>` inside a coloured surface (e.g.
5290
+ // `<Box variant="solid" color="primary">` paints white text)
5291
+ // so the text picks up the surface colour. It is NO LONGER the
5292
+ // default: a bare `<Typography>` would otherwise inherit the
5293
+ // consuming app's arbitrary root colour (often OS-`prefers-
5294
+ // color-scheme` driven), which diverges from the Dashforge
5295
+ // `data-dash-tw-theme` mode and breaks colour consistency in
5296
+ // dark mode. The default is now `neutral` — see `defaultVariants`.
5288
5297
  inherit: 'text-inherit',
5289
5298
  primary: 'text-primary-700 dark:text-primary-400',
5290
5299
  secondary: 'text-secondary-700 dark:text-secondary-400',
@@ -5337,7 +5346,11 @@ const SnackbarContext = /*#__PURE__*/ createContext(null);
5337
5346
  },
5338
5347
  defaultVariants: {
5339
5348
  variant: 'body1',
5340
- color: 'inherit',
5349
+ // `neutral` (not `inherit`): a bare `<Typography>` emits
5350
+ // `text-neutral-900`, which auto-inverts via the dashforgePreset()
5351
+ // CSS-var swap and follows the Dashforge mode. Pass
5352
+ // `color="inherit"` explicitly inside a coloured surface.
5353
+ color: 'neutral',
5341
5354
  align: 'left'
5342
5355
  }
5343
5356
  });
@@ -6915,8 +6928,11 @@ VisuallyHidden.displayName = 'VisuallyHidden';
6915
6928
  jsx(RadixDialog.Overlay, {
6916
6929
  className: cn(v.overlay(), slotProps == null ? void 0 : (_slotProps_overlay = slotProps.overlay) == null ? void 0 : _slotProps_overlay.className)
6917
6930
  }),
6918
- jsxs(RadixDialog.Content, {
6919
- className: cn(v.content(), sx, slotProps == null ? void 0 : (_slotProps_content = slotProps.content) == null ? void 0 : _slotProps_content.className),
6931
+ jsxs(RadixDialog.Content, _extends({
6932
+ className: cn(v.content(), sx, slotProps == null ? void 0 : (_slotProps_content = slotProps.content) == null ? void 0 : _slotProps_content.className)
6933
+ }, description == null ? {
6934
+ 'aria-describedby': undefined
6935
+ } : {}, {
6920
6936
  onPointerDownOutside: (event)=>{
6921
6937
  if (disableBackdropClose) event.preventDefault();
6922
6938
  },
@@ -6955,7 +6971,7 @@ VisuallyHidden.displayName = 'VisuallyHidden';
6955
6971
  })
6956
6972
  })
6957
6973
  ]
6958
- })
6974
+ }))
6959
6975
  ]
6960
6976
  })
6961
6977
  });
@@ -8650,6 +8666,7 @@ function inferType(value) {
8650
8666
  const DEFAULT_LABELS$1 = {
8651
8667
  searchPlaceholder: 'Search...',
8652
8668
  noData: 'No data',
8669
+ noResults: 'No matching results',
8653
8670
  loading: 'Loading…',
8654
8671
  ariaSortNone: 'Not sorted. Click to sort ascending.',
8655
8672
  ariaSortAscending: 'Sorted ascending. Click to sort descending.',
@@ -8676,8 +8693,7 @@ const DEFAULT_LABELS$1 = {
8676
8693
  densitySpacious: 'Spacious',
8677
8694
  columnsButton: 'Columns',
8678
8695
  columnsTitle: 'Toggle columns',
8679
- columnsShowAll: 'Show all',
8680
- columnsHideAll: 'Hide all'
8696
+ columnsToggleAll: 'Toggle all columns'
8681
8697
  };
8682
8698
  const DEFAULT_GET_ROW_ID = (_row, index)=>String(index);
8683
8699
  /**
@@ -8706,6 +8722,26 @@ const DEFAULT_GET_ROW_ID = (_row, index)=>String(index);
8706
8722
  sortModel: sortModelProp, onSortChange, defaultSortModel, enableSearch = false, searchQuery: searchQueryProp, onSearchQueryChange, searchPlaceholder, searchDebounceMs = 200, filterModel: filterModelProp, onFilterChange, rowSelection = 'none', selectedRowIds: selectedRowIdsProp, onSelectionChange, bulkActions, expandable, rowActions, loading = false, loadingRowCount = 5, emptyState, stickyHeader = true, caption, showCaption = false, access: tableAccess, labels: labelsProp, variant, size, density, sx, slotProps } = props;
8707
8723
  const labels = _extends({}, DEFAULT_LABELS$1, labelsProp);
8708
8724
  const tableAccessState = useAccessState(tableAccess);
8725
+ // Dev-only guard: `getRowId` is optional (positional-index fallback)
8726
+ // but that fallback breaks row identity once rows reorder (sort) or
8727
+ // change presence (search / filter) — selection + expansion state
8728
+ // then jump to the wrong rows. Warn when it's omitted AND a feature
8729
+ // that relies on stable identity is active. Stripped in production.
8730
+ const getRowIdProvided = props.getRowId !== undefined;
8731
+ useEffect(()=>{
8732
+ if (process.env.NODE_ENV === 'production') return;
8733
+ if (getRowIdProvided) return;
8734
+ const identityMatters = rowSelection !== 'none' || expandable != null || enableSearch || cols.some((c)=>Boolean(c.sortable));
8735
+ if (identityMatters) {
8736
+ console.warn('[Dashforge Table] `getRowId` is not set — falling back to the ' + 'positional row index. With sort / search / selection / ' + 'expandable rows active, the index-based key breaks row ' + 'identity when rows reorder. Pass a stable resolver, e.g. ' + '`getRowId={(row) => row.id}`.');
8737
+ }
8738
+ }, [
8739
+ getRowIdProvided,
8740
+ rowSelection,
8741
+ expandable,
8742
+ enableSearch,
8743
+ cols
8744
+ ]);
8709
8745
  // ───── Controllable state machinery ─────
8710
8746
  const [sortModel, setSortModel] = useControllableState({
8711
8747
  controlledValue: sortModelProp,
@@ -8861,7 +8897,9 @@ const DEFAULT_GET_ROW_ID = (_row, index)=>String(index);
8861
8897
  }) : sortedRows.length === 0 ? renderEmptyState$1({
8862
8898
  totalColumnCount,
8863
8899
  emptyState,
8864
- fallback: labels.noData,
8900
+ // Distinguish a genuinely empty dataset from one
8901
+ // emptied by an active search / filter.
8902
+ fallback: rows.length > 0 && (debouncedSearchQuery.trim().length > 0 || filterModel.length > 0) ? labels.noResults : labels.noData,
8865
8903
  cellClass: cn(v.cell(), v.emptyState(), slotProps == null ? void 0 : (_slotProps_emptyState = slotProps.emptyState) == null ? void 0 : _slotProps_emptyState.className)
8866
8904
  }) : sortedRows.map((row, idx)=>{
8867
8905
  var _slotProps_row, _slotProps_cell, _slotProps_cell1, _slotProps_selectionCell, _slotProps_cell2, _slotProps_expandToggleCell, _slotProps_cell3, _slotProps_rowActionsCell, _slotProps_expandedRow;
@@ -9083,6 +9121,10 @@ function handleSortClick$1(col, event, current, setSortModel) {
9083
9121
  }
9084
9122
  function renderLoadingRows$1(args) {
9085
9123
  const { count, visibleCols, showSelectionColumn, showExpandColumn, showRowActionsColumn, rowClass, cellClass } = args;
9124
+ // No explicit row height here (unlike DataGrid's loading rows, which
9125
+ // pin `rowHeight` for the virtualization math): Table is auto-height
9126
+ // by design. Skeleton rows inherit the same density padding via
9127
+ // `cellClass`, so they line up with real rows without a fixed height.
9086
9128
  return Array.from({
9087
9129
  length: count
9088
9130
  }).map((_, i)=>jsxs("tr", {
@@ -9324,15 +9366,12 @@ function SearchIcon$1(props) {
9324
9366
  color: 'secondary',
9325
9367
  class: 'bg-secondary-100 dark:bg-secondary-950 text-secondary-700 dark:text-secondary-300'
9326
9368
  },
9327
- // solid = full bg + light text
9328
- // solid neutral: bg + text both anchored to neutral palette
9329
- // (auto-inverts). `text-white` would not invert and would break
9330
- // contrast in light mode against a `bg-neutral-700` dark bg, so
9331
- // we stick to `text-neutral-50` (light text in light mode, dark
9332
- // in dark — wait, that's wrong too). Actually `text-neutral-50`
9333
- // auto-inverts: light text in light mode (against dark bg) is
9334
- // what we want; in dark mode `bg-neutral-700` becomes light AND
9335
- // `text-neutral-50` becomes dark — contrast preserved.
9369
+ // solid = full bg + contrasting text.
9370
+ // solid neutral: both `bg-neutral-700` and `text-neutral-50` sit
9371
+ // on the neutral palette, so they auto-invert together via the
9372
+ // CSS-var swap — bg/text contrast is preserved in BOTH modes.
9373
+ // (`text-white` is deliberately NOT used here: white does not
9374
+ // auto-invert, which would flip the contrast in dark mode.)
9336
9375
  {
9337
9376
  variant: 'solid',
9338
9377
  color: 'neutral',
@@ -9863,6 +9902,17 @@ function setFilter(model, field, next) {
9863
9902
  next
9864
9903
  ];
9865
9904
  }
9905
+ /**
9906
+ * Shared `onKeyDown` for filter inputs — pressing Enter commits the
9907
+ * filter (equivalent to clicking Apply). Without this the user has to
9908
+ * leave the keyboard and click the button, which reads as broken for
9909
+ * a single-field text filter.
9910
+ */ function onEnterApply(e, apply) {
9911
+ if (e.key === 'Enter') {
9912
+ e.preventDefault();
9913
+ apply();
9914
+ }
9915
+ }
9866
9916
  const DEFAULT_FILTER_LABELS = {
9867
9917
  filterColumn: 'Filter',
9868
9918
  filterApply: 'Apply',
@@ -9948,6 +9998,11 @@ function FilterPanel(props) {
9948
9998
  function TextFilter(props) {
9949
9999
  const { field, current, onCommit, labels } = props;
9950
10000
  const [value, setValue] = useState(typeof (current == null ? void 0 : current.value) === 'string' ? current.value : '');
10001
+ const apply = ()=>onCommit(value.trim() ? {
10002
+ field,
10003
+ op: 'contains',
10004
+ value
10005
+ } : null);
9951
10006
  return jsxs("div", {
9952
10007
  className: "flex flex-col gap-2 min-w-[200px]",
9953
10008
  children: [
@@ -9955,16 +10010,13 @@ function TextFilter(props) {
9955
10010
  type: "text",
9956
10011
  value: value,
9957
10012
  onChange: (e)=>setValue(e.target.value),
10013
+ onKeyDown: (e)=>onEnterApply(e, apply),
9958
10014
  placeholder: "\u2026",
9959
10015
  autoFocus: true,
9960
10016
  className: "rounded-md border border-neutral-300 bg-neutral-50 px-2 py-1.5 text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500"
9961
10017
  }),
9962
10018
  jsx(FilterActions, {
9963
- onApply: ()=>onCommit(value.trim() ? {
9964
- field,
9965
- op: 'contains',
9966
- value
9967
- } : null),
10019
+ onApply: apply,
9968
10020
  onClear: ()=>{
9969
10021
  setValue('');
9970
10022
  onCommit(null);
@@ -10018,6 +10070,7 @@ function NumberRangeFilter(props) {
10018
10070
  type: "number",
10019
10071
  value: min,
10020
10072
  onChange: (e)=>setMin(e.target.value),
10073
+ onKeyDown: (e)=>onEnterApply(e, apply),
10021
10074
  autoFocus: true,
10022
10075
  className: "rounded-md border border-neutral-300 bg-neutral-50 px-2 py-1.5 text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500"
10023
10076
  })
@@ -10033,6 +10086,7 @@ function NumberRangeFilter(props) {
10033
10086
  type: "number",
10034
10087
  value: max,
10035
10088
  onChange: (e)=>setMax(e.target.value),
10089
+ onKeyDown: (e)=>onEnterApply(e, apply),
10036
10090
  className: "rounded-md border border-neutral-300 bg-neutral-50 px-2 py-1.5 text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500"
10037
10091
  })
10038
10092
  ]
@@ -10141,6 +10195,7 @@ function DateRangeFilter(props) {
10141
10195
  type: "date",
10142
10196
  value: from,
10143
10197
  onChange: (e)=>setFrom(e.target.value),
10198
+ onKeyDown: (e)=>onEnterApply(e, apply),
10144
10199
  autoFocus: true,
10145
10200
  className: "rounded-md border border-neutral-300 bg-neutral-50 px-2 py-1.5 text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500"
10146
10201
  })
@@ -10156,6 +10211,7 @@ function DateRangeFilter(props) {
10156
10211
  type: "date",
10157
10212
  value: to,
10158
10213
  onChange: (e)=>setTo(e.target.value),
10214
+ onKeyDown: (e)=>onEnterApply(e, apply),
10159
10215
  className: "rounded-md border border-neutral-300 bg-neutral-50 px-2 py-1.5 text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500"
10160
10216
  })
10161
10217
  ]
@@ -10215,8 +10271,7 @@ function FilterIcon() {
10215
10271
  const DEFAULT_VISIBILITY_LABELS = {
10216
10272
  columnsButton: 'Columns',
10217
10273
  columnsTitle: 'Toggle columns',
10218
- columnsShowAll: 'Show all',
10219
- columnsHideAll: 'Hide all'
10274
+ columnsToggleAll: 'Toggle all columns'
10220
10275
  };
10221
10276
  function ColumnVisibilityTrigger(props) {
10222
10277
  const { cols, hiddenColumns, onChange, disabled, labels: labelsProp } = props;
@@ -10232,44 +10287,40 @@ function ColumnVisibilityTrigger(props) {
10232
10287
  field
10233
10288
  ]);
10234
10289
  };
10235
- const showAll = ()=>onChange([]);
10236
- const hideAll = ()=>onChange(hideableCols.map((c)=>c.field));
10290
+ // Tri-state master: checked = every hideable column visible,
10291
+ // unchecked = every one hidden, indeterminate = mixed.
10292
+ const allVisible = hideableCols.every((c)=>!hiddenColumns.includes(c.field));
10293
+ const allHidden = hideableCols.length > 0 && hideableCols.every((c)=>hiddenColumns.includes(c.field));
10294
+ const someHidden = !allVisible && !allHidden;
10295
+ // Standard select-all semantics: when everything is visible the
10296
+ // master hides all; otherwise it shows all.
10297
+ const toggleAll = ()=>{
10298
+ onChange(allVisible ? hideableCols.map((c)=>c.field) : []);
10299
+ };
10237
10300
  return jsx(Popover, {
10238
10301
  open: open,
10239
10302
  onOpenChange: setOpen,
10240
10303
  side: "bottom",
10241
10304
  align: "end",
10242
10305
  content: jsxs("div", {
10243
- className: "flex flex-col gap-2 min-w-[220px]",
10306
+ className: "flex flex-col gap-1 min-w-[220px]",
10244
10307
  children: [
10245
10308
  jsxs("div", {
10246
- className: "flex items-center justify-between pb-2 border-b border-neutral-200",
10309
+ className: "flex items-center gap-2 px-1 pb-2 mb-1 border-b border-neutral-200",
10247
10310
  children: [
10311
+ jsx("input", {
10312
+ type: "checkbox",
10313
+ "aria-label": labels.columnsToggleAll,
10314
+ checked: allVisible,
10315
+ ref: (el)=>{
10316
+ if (el) el.indeterminate = someHidden;
10317
+ },
10318
+ onChange: toggleAll,
10319
+ className: "cursor-pointer"
10320
+ }),
10248
10321
  jsx("span", {
10249
10322
  className: "text-xs font-semibold text-neutral-700 uppercase tracking-wide",
10250
10323
  children: labels.columnsTitle
10251
- }),
10252
- jsxs("div", {
10253
- className: "flex items-center gap-2",
10254
- children: [
10255
- jsx("button", {
10256
- type: "button",
10257
- onClick: showAll,
10258
- className: "text-xs text-neutral-600 hover:text-neutral-900 underline-offset-2 hover:underline focus:outline-none focus-visible:underline",
10259
- children: labels.columnsShowAll
10260
- }),
10261
- jsx("span", {
10262
- className: "text-neutral-300",
10263
- "aria-hidden": "true",
10264
- children: "\u00B7"
10265
- }),
10266
- jsx("button", {
10267
- type: "button",
10268
- onClick: hideAll,
10269
- className: "text-xs text-neutral-600 hover:text-neutral-900 underline-offset-2 hover:underline focus:outline-none focus-visible:underline",
10270
- children: labels.columnsHideAll
10271
- })
10272
- ]
10273
10324
  })
10274
10325
  ]
10275
10326
  }),
@@ -10398,8 +10449,21 @@ function useColumnResize(args) {
10398
10449
  minWidth,
10399
10450
  maxWidth
10400
10451
  ]);
10452
+ const nudge = useCallback((field, currentWidth, delta, clampMin, clampMax)=>{
10453
+ const effectiveMin = Math.max(minWidth, clampMin);
10454
+ const effectiveMax = Math.min(maxWidth, clampMax);
10455
+ const next = clamp(currentWidth + delta, effectiveMin, effectiveMax);
10456
+ onChange(_extends({}, widthsRef.current, {
10457
+ [field]: next
10458
+ }));
10459
+ }, [
10460
+ onChange,
10461
+ minWidth,
10462
+ maxWidth
10463
+ ]);
10401
10464
  return {
10402
- startResize
10465
+ startResize,
10466
+ nudge
10403
10467
  };
10404
10468
  }
10405
10469
  function clamp(n, min, max) {
@@ -10494,6 +10558,7 @@ function arraysEqual(a, b) {
10494
10558
  const DEFAULT_LABELS = {
10495
10559
  searchPlaceholder: 'Search...',
10496
10560
  noData: 'No data',
10561
+ noResults: 'No matching results',
10497
10562
  loading: 'Loading…',
10498
10563
  ariaSortNone: 'Not sorted. Click to sort ascending.',
10499
10564
  ariaSortAscending: 'Sorted ascending. Click to sort descending.',
@@ -10520,8 +10585,7 @@ const DEFAULT_LABELS = {
10520
10585
  densitySpacious: 'Spacious',
10521
10586
  columnsButton: 'Columns',
10522
10587
  columnsTitle: 'Toggle columns',
10523
- columnsShowAll: 'Show all',
10524
- columnsHideAll: 'Hide all'
10588
+ columnsToggleAll: 'Toggle all columns'
10525
10589
  };
10526
10590
  /**
10527
10591
  * Dashforge TW `<DataGrid>` — virtualized data table.
@@ -10609,7 +10673,7 @@ const DEFAULT_LABELS = {
10609
10673
  defaultValue: defaultColumnWidths,
10610
10674
  onChange: onColumnWidthsChange
10611
10675
  });
10612
- const { startResize } = useColumnResize({
10676
+ const { startResize, nudge: nudgeColumnWidth } = useColumnResize({
10613
10677
  widths: columnWidths,
10614
10678
  onChange: setColumnWidths
10615
10679
  });
@@ -10626,6 +10690,22 @@ const DEFAULT_LABELS = {
10626
10690
  order: columnOrder,
10627
10691
  onChange: setColumnOrder
10628
10692
  });
10693
+ // Column reorder rides on native HTML5 drag-and-drop, whose
10694
+ // `dragstart` / `drop` events DO NOT fire for touch input. On a
10695
+ // coarse-pointer device the drag would be a dead affordance — so
10696
+ // we detect the primary pointer and gate reorder off there. Mouse
10697
+ // / trackpad / pen (fine pointer) keep the feature. A pointer-event
10698
+ // based reorder that also covers touch is tracked as a follow-up
10699
+ // in REFINEMENT-NOTES.md.
10700
+ const [coarsePointer, setCoarsePointer] = useState(false);
10701
+ useEffect(()=>{
10702
+ if (typeof window === 'undefined' || !window.matchMedia) return;
10703
+ const mq = window.matchMedia('(pointer: coarse)');
10704
+ setCoarsePointer(mq.matches);
10705
+ const onChange = (e)=>setCoarsePointer(e.matches);
10706
+ mq.addEventListener('change', onChange);
10707
+ return ()=>mq.removeEventListener('change', onChange);
10708
+ }, []);
10629
10709
  // Apply the active order to the columns list. Cols not in the
10630
10710
  // order array (e.g. newly-added columns at runtime) are appended
10631
10711
  // in their original position from `cols`.
@@ -10780,8 +10860,7 @@ const DEFAULT_LABELS = {
10780
10860
  labels: {
10781
10861
  columnsButton: labels.columnsButton,
10782
10862
  columnsTitle: labels.columnsTitle,
10783
- columnsShowAll: labels.columnsShowAll,
10784
- columnsHideAll: labels.columnsHideAll
10863
+ columnsToggleAll: labels.columnsToggleAll
10785
10864
  }
10786
10865
  })
10787
10866
  ]
@@ -10795,6 +10874,7 @@ const DEFAULT_LABELS = {
10795
10874
  } : undefined,
10796
10875
  children: jsxs("table", {
10797
10876
  className: cn(v.table(), slotProps == null ? void 0 : (_slotProps_table = slotProps.table) == null ? void 0 : _slotProps_table.className),
10877
+ "aria-rowcount": effectiveTotalCount > 0 ? effectiveTotalCount + 1 : -1,
10798
10878
  children: [
10799
10879
  caption != null && jsx("caption", {
10800
10880
  className: cn(!showCaption && 'sr-only', 'py-2 text-sm text-neutral-500'),
@@ -10803,6 +10883,7 @@ const DEFAULT_LABELS = {
10803
10883
  jsx("thead", {
10804
10884
  className: cn(stickyHeader ? v.thead() : 'bg-neutral-50', slotProps == null ? void 0 : (_slotProps_thead = slotProps.thead) == null ? void 0 : _slotProps_thead.className),
10805
10885
  children: jsxs("tr", {
10886
+ "aria-rowindex": 1,
10806
10887
  className: cn(v.headerRow(), slotProps == null ? void 0 : (_slotProps_headerRow = slotProps.headerRow) == null ? void 0 : _slotProps_headerRow.className),
10807
10888
  children: [
10808
10889
  showSelectionColumn && jsx("th", {
@@ -10832,7 +10913,8 @@ const DEFAULT_LABELS = {
10832
10913
  effectiveWidth: resolveColumnWidth(col, columnWidths),
10833
10914
  resizable: enableColumnResize && col.resizable !== false,
10834
10915
  startResize: startResize,
10835
- reorderable: enableColumnReorder && col.reorderable !== false,
10916
+ nudgeColumnWidth: nudgeColumnWidth,
10917
+ reorderable: enableColumnReorder && col.reorderable !== false && !coarsePointer,
10836
10918
  reorderHandlers: reorderHandlers,
10837
10919
  labels: labels,
10838
10920
  className: cn(v.headerCell(), col.sticky === 'left' && v.stickyLeftHeaderCell(), col.sticky === 'right' && v.stickyRightHeaderCell(), slotProps == null ? void 0 : (_slotProps_headerCell = slotProps.headerCell) == null ? void 0 : _slotProps_headerCell.className),
@@ -10861,7 +10943,11 @@ const DEFAULT_LABELS = {
10861
10943
  }) : sortedRows.length === 0 ? renderEmptyState({
10862
10944
  totalColumnCount,
10863
10945
  emptyState,
10864
- fallback: labels.noData,
10946
+ // Distinguish a genuinely empty dataset from one
10947
+ // emptied by an active search / filter (works for
10948
+ // server-side mode too — a query that returns 0
10949
+ // rows still reads as "no matching results").
10950
+ fallback: rows.length > 0 && (debouncedSearchQuery.trim().length > 0 || filterModel.length > 0) ? labels.noResults : labels.noData,
10865
10951
  cellClass: cn(v.cell(), v.emptyState(), slotProps == null ? void 0 : (_slotProps_emptyState = slotProps.emptyState) == null ? void 0 : _slotProps_emptyState.className)
10866
10952
  }) : renderVirtualizedBody({
10867
10953
  vWindow,
@@ -10929,7 +11015,8 @@ const DEFAULT_LABELS = {
10929
11015
  }
10930
11016
  // ───── Header cell ─────
10931
11017
  function HeaderCell(props) {
10932
- const { col, sortModel, onSortClick, inferredType, filterModel, onFilterChange, effectiveWidth, resizable, startResize, reorderable, reorderHandlers, labels, className, buttonClassName, disabled } = props;
11018
+ var _col_minWidth, _col_maxWidth;
11019
+ const { col, sortModel, onSortClick, inferredType, filterModel, onFilterChange, effectiveWidth, resizable, startResize, nudgeColumnWidth, reorderable, reorderHandlers, labels, className, buttonClassName, disabled } = props;
10933
11020
  const align = resolveAlign(col, inferredType);
10934
11021
  const alignClass = align === 'right' ? 'text-right' : align === 'center' ? 'text-center' : 'text-left';
10935
11022
  const sortEntry = sortModel.find((s)=>s.field === col.field);
@@ -10956,20 +11043,42 @@ function HeaderCell(props) {
10956
11043
  onDrop: reorderHandlers.drop(col.field),
10957
11044
  onDragEnd: reorderHandlers.dragEnd
10958
11045
  } : {};
11046
+ // Resize bounds — shared by the pointer-drag and keyboard paths.
11047
+ const resizeMin = (_col_minWidth = col.minWidth) != null ? _col_minWidth : 40;
11048
+ const resizeMax = (_col_maxWidth = col.maxWidth) != null ? _col_maxWidth : 1200;
11049
+ // Keyboard nudge step: 16px, or 64px with Shift held (coarse).
11050
+ const measureWidth = (handle)=>{
11051
+ var _ref;
11052
+ var _handle_parentElement;
11053
+ return (_ref = effectiveWidth != null ? effectiveWidth : (_handle_parentElement = handle.parentElement) == null ? void 0 : _handle_parentElement.getBoundingClientRect().width) != null ? _ref : 120;
11054
+ };
10959
11055
  const resizeHandle = resizable ? jsx("span", {
10960
11056
  role: "separator",
10961
11057
  "aria-orientation": "vertical",
10962
11058
  "aria-label": `Resize ${typeof col.header === 'string' ? col.header : col.field}`,
11059
+ "aria-valuemin": resizeMin,
11060
+ "aria-valuemax": resizeMax,
11061
+ "aria-valuenow": effectiveWidth != null ? effectiveWidth : undefined,
11062
+ // Keyboard-operable: focusable + ArrowLeft/Right resize. WCAG 2.1
11063
+ // keyboard operability — the drag is no longer the only path.
11064
+ tabIndex: disabled ? -1 : 0,
11065
+ // D6 guard: the parent `<th>` is `draggable` when reorderable;
11066
+ // marking the handle non-draggable means grabbing the handle
11067
+ // starts a RESIZE, never a column-reorder drag.
11068
+ draggable: false,
10963
11069
  onPointerDown: (e)=>{
10964
- var _ref, _col_minWidth, _col_maxWidth;
10965
- const handle = e.currentTarget;
10966
- const th = handle.parentElement;
10967
- const startWidth = (_ref = effectiveWidth != null ? effectiveWidth : th == null ? void 0 : th.getBoundingClientRect().width) != null ? _ref : 120;
10968
- const min = (_col_minWidth = col.minWidth) != null ? _col_minWidth : 40;
10969
- const max = (_col_maxWidth = col.maxWidth) != null ? _col_maxWidth : 1200;
10970
- startResize(col.field, startWidth, min, max)(e);
10971
- },
10972
- className: cn('absolute top-0 bottom-0 right-0 w-1.5', 'cursor-col-resize select-none touch-none', 'hover:bg-primary-300 active:bg-primary-400', 'transition-colors motion-reduce:transition-none')
11070
+ const startWidth = measureWidth(e.currentTarget);
11071
+ startResize(col.field, startWidth, resizeMin, resizeMax)(e);
11072
+ },
11073
+ onKeyDown: (e)=>{
11074
+ if (disabled) return;
11075
+ if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;
11076
+ e.preventDefault();
11077
+ const step = (e.shiftKey ? 64 : 16) * (e.key === 'ArrowLeft' ? -1 : 1);
11078
+ const current = measureWidth(e.currentTarget);
11079
+ nudgeColumnWidth(col.field, current, step, resizeMin, resizeMax);
11080
+ },
11081
+ className: cn('absolute top-0 bottom-0 right-0 w-1.5', 'cursor-col-resize select-none touch-none', 'hover:bg-primary-300 active:bg-primary-400', 'focus:outline-none focus-visible:bg-primary-400', 'transition-colors motion-reduce:transition-none')
10973
11082
  }) : null;
10974
11083
  const filterType = col.filterable ? resolveFilterType(col, inferredType) : null;
10975
11084
  const filterTrigger = col.filterable && filterType ? jsx(ColumnFilterTrigger, {
@@ -11096,6 +11205,7 @@ function renderVirtualizedBody(args) {
11096
11205
  const rowId = getRowId(row, absoluteIdx);
11097
11206
  const isSelected = selection.isSelected(rowId);
11098
11207
  return jsxs("tr", {
11208
+ "aria-rowindex": absoluteIdx + 2,
11099
11209
  "data-selected": isSelected ? 'true' : 'false',
11100
11210
  "aria-selected": rowSelection !== 'none' ? isSelected : undefined,
11101
11211
  className: classes.row,
@@ -1 +1 @@
1
- {"version":3,"file":"DataGrid.d.ts","sourceRoot":"","sources":["../../../../src/components/DataGrid/DataGrid.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA0CzD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,kDAkhBjE"}
1
+ {"version":3,"file":"DataGrid.d.ts","sourceRoot":"","sources":["../../../../src/components/DataGrid/DataGrid.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA0CzD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,kDA6jBjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnFilters.d.ts","sourceRoot":"","sources":["../../../../../src/components/DataGrid/filters/ColumnFilters.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,gBAAgB,EAChB,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAqCpC,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAiBD,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,eAAe,CAAC;IAC5B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,cAAc,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,2CAkDlE"}
1
+ {"version":3,"file":"ColumnFilters.d.ts","sourceRoot":"","sources":["../../../../../src/components/DataGrid/filters/ColumnFilters.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,gBAAgB,EAChB,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAqDpC,MAAM,WAAW,kBAAkB;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAiBD,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,eAAe,CAAC;IAC5B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,cAAc,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,2CAkDlE"}
@@ -27,6 +27,13 @@ export interface UseColumnResizeArgs {
27
27
  }
28
28
  export interface ColumnResizeHandlers {
29
29
  startResize: (field: string, startWidth: number, clampMin: number, clampMax: number) => (e: RPointerEvent<HTMLElement>) => void;
30
+ /**
31
+ * Commit a single clamped width delta — the keyboard-resize path.
32
+ * Wired to ArrowLeft/ArrowRight on the focused resize handle so the
33
+ * feature is reachable without a pointer (WCAG 2.1 — keyboard
34
+ * operability). Same clamping as the drag path.
35
+ */
36
+ nudge: (field: string, currentWidth: number, delta: number, clampMin: number, clampMax: number) => void;
30
37
  }
31
38
  export declare function useColumnResize(args: UseColumnResizeArgs): ColumnResizeHandlers;
32
39
  //# sourceMappingURL=useColumnResize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useColumnResize.d.ts","sourceRoot":"","sources":["../../../../../src/components/DataGrid/resize/useColumnResize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,YAAY,IAAI,aAAa,EAAE,MAAM,OAAO,CAAC;AAEhF;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,8BAA8B;IAC9B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IACjD,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,CACX,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,KACb,CAAC,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;CAC9C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,oBAAoB,CA4D/E"}
1
+ {"version":3,"file":"useColumnResize.d.ts","sourceRoot":"","sources":["../../../../../src/components/DataGrid/resize/useColumnResize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,YAAY,IAAI,aAAa,EAAE,MAAM,OAAO,CAAC;AAEhF;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,8BAA8B;IAC9B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IACjD,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,CACX,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,KACb,CAAC,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAC7C;;;;;OAKG;IACH,KAAK,EAAE,CACL,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,KACb,IAAI,CAAC;CACX;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,oBAAoB,CA4E/E"}
@@ -26,8 +26,12 @@ import type { TableColumn } from '../../Table/table.types.js';
26
26
  export interface ColumnVisibilityLabels {
27
27
  columnsButton?: string;
28
28
  columnsTitle?: string;
29
- columnsShowAll?: string;
30
- columnsHideAll?: string;
29
+ /**
30
+ * Accessible label for the tri-state master checkbox that
31
+ * shows/hides every hideable column at once. Not shown as visible
32
+ * text — surfaced to assistive tech via `aria-label`.
33
+ */
34
+ columnsToggleAll?: string;
31
35
  }
32
36
  export interface ColumnVisibilityTriggerProps<T extends object> {
33
37
  cols: TableColumn<T>[];
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnVisibilityMenu.d.ts","sourceRoot":"","sources":["../../../../../src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AASD,MAAM,WAAW,4BAA4B,CAAC,CAAC,SAAS,MAAM;IAC5D,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,EACtD,KAAK,EAAE,4BAA4B,CAAC,CAAC,CAAC,2CA6FvC"}
1
+ {"version":3,"file":"ColumnVisibilityMenu.d.ts","sourceRoot":"","sources":["../../../../../src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAQD,MAAM,WAAW,4BAA4B,CAAC,CAAC,SAAS,MAAM;IAC5D,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,EACtD,KAAK,EAAE,4BAA4B,CAAC,CAAC,CAAC,2CA2GvC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/Dialog/Dialog.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,2CAyExC"}
1
+ {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/Dialog/Dialog.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,2CAkFxC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/Table.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,UAAU,EAKX,MAAM,kBAAkB,CAAC;AAqC1B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,kDAgW3D"}
1
+ {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../../src/components/Table/Table.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,UAAU,EAKX,MAAM,kBAAkB,CAAC;AAqC1B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,kDAgY3D"}
@@ -1 +1 @@
1
- {"version":3,"file":"RenderChip.d.ts","sourceRoot":"","sources":["../../../../../src/components/Table/cells/RenderChip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG1D;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDAsEhB,CAAC;AAEH,KAAK,YAAY,GAAG,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAOhD"}
1
+ {"version":3,"file":"RenderChip.d.ts","sourceRoot":"","sources":["../../../../../src/components/Table/cells/RenderChip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG1D;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDAmEhB,CAAC;AAEH,KAAK,YAAY,GAAG,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAOhD"}
@@ -215,7 +215,14 @@ export type TableRowSelectionMode = 'none' | 'single' | 'multiple';
215
215
  */
216
216
  export interface TableLabels {
217
217
  searchPlaceholder?: string;
218
+ /** Shown when the dataset itself is empty (0 input rows). */
218
219
  noData?: string;
220
+ /**
221
+ * Shown when the dataset has rows but an active search / filter
222
+ * excluded them all. Distinct from `noData` so the user can tell
223
+ * "nothing here" from "nothing matches your query".
224
+ */
225
+ noResults?: string;
219
226
  loading?: string;
220
227
  ariaSortNone?: string;
221
228
  ariaSortAscending?: string;
@@ -248,8 +255,8 @@ export interface TableLabels {
248
255
  /** Column visibility menu (Popover-based, auto-commit). */
249
256
  columnsButton?: string;
250
257
  columnsTitle?: string;
251
- columnsShowAll?: string;
252
- columnsHideAll?: string;
258
+ /** Aria-label for the tri-state show/hide-all master checkbox. */
259
+ columnsToggleAll?: string;
253
260
  }
254
261
  export interface TableSlotProps {
255
262
  root?: {
@@ -335,7 +342,25 @@ export interface TableExpandableConfig<T> {
335
342
  export interface TableProps<T extends object> extends Pick<TableVariants, 'variant' | 'size' | 'density'> {
336
343
  rows: T[];
337
344
  cols: TableColumn<T>[];
338
- /** Stable row id resolver. Default: positional index. */
345
+ /**
346
+ * Stable row-id resolver — the React key + the identity used by
347
+ * selection and row-expansion state.
348
+ *
349
+ * **Strongly recommended whenever sort / search / selection /
350
+ * expandable rows are used.** The default falls back to the
351
+ * positional index (`String(index)`); once rows reorder (sort) or
352
+ * change presence (search / filter), index `2` points at a
353
+ * *different* row, so selection and expansion state silently jump
354
+ * to the wrong rows. Pass a value derived from the data itself:
355
+ *
356
+ * ```tsx
357
+ * <Table getRowId={(row) => row.id} … />
358
+ * ```
359
+ *
360
+ * Dashforge emits a `console.warn` in development when `getRowId`
361
+ * is omitted and one of those features is active. (`<DataGrid>`
362
+ * makes this prop required for the same reason.)
363
+ */
339
364
  getRowId?: (row: T, index: number) => string;
340
365
  sortModel?: TableSortModel;
341
366
  onSortChange?: (model: TableSortModel) => void;