@mezzanine-ui/react 1.0.0-beta.0 → 1.0.0-beta.2

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 (118) hide show
  1. package/Badge/Badge.js +2 -2
  2. package/Breadcrumb/BreadcrumbItem.d.ts +1 -1
  3. package/Description/Description.d.ts +40 -0
  4. package/Description/Description.js +33 -0
  5. package/Description/DescriptionContent.d.ts +41 -0
  6. package/Description/DescriptionContent.js +14 -0
  7. package/Description/DescriptionGroup.d.ts +13 -0
  8. package/Description/DescriptionGroup.js +12 -0
  9. package/Description/DescriptionTitle.d.ts +45 -0
  10. package/Description/DescriptionTitle.js +17 -0
  11. package/Description/index.d.ts +8 -0
  12. package/Description/index.js +4 -0
  13. package/Dropdown/Dropdown.d.ts +128 -15
  14. package/Dropdown/Dropdown.js +273 -32
  15. package/Dropdown/DropdownAction.d.ts +50 -0
  16. package/Dropdown/DropdownAction.js +26 -0
  17. package/Dropdown/DropdownItem.d.ts +60 -0
  18. package/Dropdown/DropdownItem.js +318 -0
  19. package/Dropdown/DropdownItemCard.d.ts +96 -0
  20. package/Dropdown/DropdownItemCard.js +115 -0
  21. package/Dropdown/DropdownStatus.d.ts +22 -0
  22. package/Dropdown/dropdownKeydownHandler.d.ts +15 -0
  23. package/Dropdown/highlightText.d.ts +9 -0
  24. package/Dropdown/highlightText.js +32 -0
  25. package/Dropdown/index.d.ts +1 -1
  26. package/Form/FormControlContext.d.ts +2 -2
  27. package/Form/FormField.d.ts +56 -4
  28. package/Form/FormField.js +8 -6
  29. package/Form/FormHintText.d.ts +24 -1
  30. package/Form/FormHintText.js +4 -4
  31. package/Form/FormLabel.d.ts +6 -3
  32. package/Form/FormLabel.js +5 -3
  33. package/Input/PasswordStrengthIndicator/PasswordStrengthIndicator.js +1 -1
  34. package/Navigation/Navigation.d.ts +17 -14
  35. package/Navigation/Navigation.js +73 -41
  36. package/Navigation/NavigationFooter.d.ts +10 -0
  37. package/Navigation/NavigationFooter.js +28 -0
  38. package/Navigation/NavigationHeader.d.ts +14 -0
  39. package/Navigation/NavigationHeader.js +15 -0
  40. package/Navigation/NavigationIconButton.d.ts +15 -0
  41. package/Navigation/NavigationIconButton.js +12 -0
  42. package/Navigation/NavigationOption.d.ts +35 -0
  43. package/Navigation/NavigationOption.js +54 -0
  44. package/Navigation/NavigationOptionCategory.d.ts +6 -0
  45. package/Navigation/NavigationOptionCategory.js +29 -0
  46. package/Navigation/NavigationUserMenu.d.ts +8 -0
  47. package/Navigation/NavigationUserMenu.js +18 -0
  48. package/Navigation/context.d.ts +15 -0
  49. package/Navigation/context.js +7 -0
  50. package/Navigation/index.d.ts +12 -6
  51. package/Navigation/index.js +6 -3
  52. package/Navigation/useCurrentPathname.d.ts +1 -0
  53. package/Navigation/useCurrentPathname.js +14 -0
  54. package/Slider/useSlider.js +1 -1
  55. package/Table/Table.d.ts +53 -15
  56. package/Table/Table.js +178 -82
  57. package/Table/TableContext.d.ts +18 -42
  58. package/Table/components/TableActionsCell.d.ts +26 -0
  59. package/Table/components/TableActionsCell.js +78 -0
  60. package/Table/components/TableBody.d.ts +2 -5
  61. package/Table/components/TableBody.js +16 -19
  62. package/Table/components/TableBulkActions.d.ts +15 -0
  63. package/Table/components/TableBulkActions.js +44 -0
  64. package/Table/components/TableCell.d.ts +2 -0
  65. package/Table/components/TableCell.js +42 -10
  66. package/Table/components/TableColGroup.js +10 -112
  67. package/Table/components/TableColumnTitleMenu.d.ts +6 -0
  68. package/Table/components/TableColumnTitleMenu.js +20 -0
  69. package/Table/components/TableDragHandleCell.d.ts +2 -0
  70. package/Table/components/TableDragHandleCell.js +8 -1
  71. package/Table/components/TableExpandCell.d.ts +2 -0
  72. package/Table/components/TableExpandCell.js +8 -1
  73. package/Table/components/TableExpandedRow.js +3 -2
  74. package/Table/components/TableHeader.d.ts +2 -4
  75. package/Table/components/TableHeader.js +11 -14
  76. package/Table/components/TableResizeHandle.js +3 -7
  77. package/Table/components/TableRow.js +54 -20
  78. package/Table/components/TableSelectionCell.d.ts +5 -0
  79. package/Table/components/TableSelectionCell.js +12 -1
  80. package/Table/components/index.d.ts +1 -0
  81. package/Table/components/index.js +1 -0
  82. package/Table/hooks/index.d.ts +1 -1
  83. package/Table/hooks/index.js +1 -1
  84. package/Table/hooks/useTableDataSource.d.ts +2 -2
  85. package/Table/hooks/useTableExpansion.js +0 -6
  86. package/Table/hooks/useTableFixedOffsets.d.ts +1 -1
  87. package/Table/hooks/useTableFixedOffsets.js +19 -21
  88. package/Table/hooks/useTableResizedColumns.d.ts +2 -0
  89. package/Table/hooks/useTableResizedColumns.js +22 -0
  90. package/Table/hooks/useTableScroll.d.ts +3 -1
  91. package/Table/hooks/useTableScroll.js +25 -19
  92. package/Table/hooks/useTableSelection.js +32 -8
  93. package/Table/hooks/useTableVirtualization.d.ts +1 -1
  94. package/Table/index.d.ts +4 -4
  95. package/Table/index.js +5 -3
  96. package/Table/utils/calculateColumnWidths.d.ts +28 -0
  97. package/Table/utils/calculateColumnWidths.js +80 -0
  98. package/Table/utils/index.d.ts +2 -0
  99. package/Table/utils/index.js +1 -0
  100. package/Table/utils/useTableRowSelection.d.ts +5 -5
  101. package/Table/utils/useTableRowSelection.js +1 -1
  102. package/hooks/useElementHeight.d.ts +8 -0
  103. package/hooks/useElementHeight.js +41 -0
  104. package/index.d.ts +8 -6
  105. package/index.js +9 -3
  106. package/package.json +5 -4
  107. package/utils/format-number-with-commas.d.ts +4 -0
  108. package/utils/format-number-with-commas.js +27 -0
  109. package/utils/parse-number-with-commas.d.ts +4 -0
  110. package/utils/parse-number-with-commas.js +22 -0
  111. package/Navigation/NavigationContext.d.ts +0 -5
  112. package/Navigation/NavigationContext.js +0 -8
  113. package/Navigation/NavigationItem.d.ts +0 -31
  114. package/Navigation/NavigationItem.js +0 -23
  115. package/Navigation/NavigationSubMenu.d.ts +0 -22
  116. package/Navigation/NavigationSubMenu.js +0 -50
  117. package/Table/hooks/useTableColumns.d.ts +0 -8
  118. package/Table/hooks/useTableColumns.js +0 -91
@@ -2,7 +2,7 @@
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import { memo, useRef, useCallback } from 'react';
4
4
  import { tableClasses } from '@mezzanine-ui/core/table';
5
- import { useTableContext } from '../TableContext.js';
5
+ import { useTableContext, useTableDataContext } from '../TableContext.js';
6
6
 
7
7
  /**
8
8
  * TableResizeHandle provides column resizing functionality.
@@ -10,7 +10,8 @@ import { useTableContext } from '../TableContext.js';
10
10
  * maintaining the total width of both columns.
11
11
  */
12
12
  const TableResizeHandle = memo(function TableResizeHandle({ column, columnIndex, }) {
13
- const { columnState, columns, draggable, expansion, scrollContainerRef, selection, } = useTableContext();
13
+ const { columnState, draggable, expansion, scrollContainerRef, selection } = useTableContext();
14
+ const { columns } = useTableDataContext();
14
15
  const { setResizedColumnWidth } = columnState || {};
15
16
  const startWidthRef = useRef(0);
16
17
  const nextStartWidthRef = useRef(0);
@@ -61,17 +62,14 @@ const TableResizeHandle = memo(function TableResizeHandle({ column, columnIndex,
61
62
  startXRef.current = event.clientX;
62
63
  startWidthRef.current = currentWidth;
63
64
  nextStartWidthRef.current = nextWidth;
64
- // Get min/max constraints (undefined means no constraint)
65
65
  const minWidth = column.minWidth;
66
66
  const maxWidth = column.maxWidth;
67
67
  const nextMinWidth = nextColumn.minWidth;
68
68
  const nextMaxWidth = nextColumn.maxWidth;
69
69
  const handleMouseMove = (moveEvent) => {
70
70
  const diff = moveEvent.clientX - startXRef.current;
71
- // Calculate desired new widths
72
71
  const newWidth = startWidthRef.current + diff;
73
72
  const newNextWidth = nextStartWidthRef.current - diff;
74
- // Check if either column would hit its constraint
75
73
  let isConstrained = false;
76
74
  // Check current column constraints
77
75
  if (minWidth !== undefined && newWidth < minWidth) {
@@ -87,11 +85,9 @@ const TableResizeHandle = memo(function TableResizeHandle({ column, columnIndex,
87
85
  if (nextMaxWidth !== undefined && newNextWidth > nextMaxWidth) {
88
86
  isConstrained = true;
89
87
  }
90
- // If either column is constrained, stop both from changing
91
88
  if (isConstrained) {
92
89
  return;
93
90
  }
94
- // Final validation: ensure we don't go below 0
95
91
  if (newWidth < 0 || newNextWidth < 0) {
96
92
  return;
97
93
  }
@@ -1,8 +1,10 @@
1
1
  'use client';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { memo, forwardRef, useMemo, useCallback } from 'react';
4
- import { getRowKey, tableClasses, DRAG_HANDLE_KEY, EXPANSION_KEY, SELECTION_KEY } from '@mezzanine-ui/core/table';
5
- import { useTableContext, useTableSuperContext } from '../TableContext.js';
4
+ import { getRowKey, tableClasses, DRAG_HANDLE_KEY, DRAG_HANDLE_COLUMN_WIDTH, EXPANSION_KEY, EXPANSION_COLUMN_WIDTH, SELECTION_KEY, SELECTION_COLUMN_WIDTH, TABLE_ACTIONS_KEY } from '@mezzanine-ui/core/table';
5
+ import { calculateColumnWidths } from '../utils/calculateColumnWidths.js';
6
+ import { useTableContext, useTableDataContext, useTableSuperContext } from '../TableContext.js';
7
+ import { TableActionsCell } from './TableActionsCell.js';
6
8
  import { TableCell } from './TableCell.js';
7
9
  import { TableDragHandleCell } from './TableDragHandleCell.js';
8
10
  import { TableExpandCell } from './TableExpandCell.js';
@@ -20,13 +22,18 @@ const parseFixed = (fixed) => {
20
22
  const TableRowInner = forwardRef(function TableRow(props, ref) {
21
23
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
22
24
  const { className, draggableProvided, record, rowIndex, style } = props;
23
- const { columns, draggable, expansion, fixedOffsets, rowHeight, highlight, selection, transitionState, } = useTableContext();
25
+ const { actions, draggable, expansion, fixedOffsets, highlight, rowHeight, selection, separatorAtRowIndexes, transitionState, zebraStriping, } = useTableContext();
26
+ const { columns } = useTableDataContext();
27
+ const isDragging = useMemo(() => {
28
+ var _a;
29
+ return ((_a = draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.draggableProps.style) === null || _a === void 0 ? void 0 : _a.position) === 'fixed';
30
+ }, [draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.draggableProps.style]);
24
31
  const resolvedStyle = useMemo(() => ({
25
32
  ...style,
26
33
  ...draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.draggableProps.style,
27
34
  height: rowHeight,
28
35
  }), [style, rowHeight, draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.draggableProps.style]);
29
- const { containerWidth, scrollLeft } = useTableSuperContext();
36
+ const { containerWidth, getResizedColumnWidth, scrollLeft } = useTableSuperContext();
30
37
  const rowKey = useMemo(() => getRowKey(record), [record]);
31
38
  const isSelected = (_e = (_d = (_c = (_b = (_a = selection === null || selection === void 0 ? void 0 : selection.config) === null || _a === void 0 ? void 0 : _a.getCheckboxProps) === null || _b === void 0 ? void 0 : _b.call(_a, record)) === null || _c === void 0 ? void 0 : _c.selected) !== null && _d !== void 0 ? _d : selection === null || selection === void 0 ? void 0 : selection.isRowSelected(rowKey)) !== null && _e !== void 0 ? _e : false;
32
39
  const isIndeterminate = (_j = (_h = (_g = (_f = selection === null || selection === void 0 ? void 0 : selection.config) === null || _f === void 0 ? void 0 : _f.getCheckboxProps) === null || _g === void 0 ? void 0 : _g.call(_f, record)) === null || _h === void 0 ? void 0 : _h.indeterminate) !== null && _j !== void 0 ? _j : false;
@@ -35,6 +42,33 @@ const TableRowInner = forwardRef(function TableRow(props, ref) {
35
42
  const isAdding = (_l = transitionState === null || transitionState === void 0 ? void 0 : transitionState.addingKeys.has(rowKey)) !== null && _l !== void 0 ? _l : false;
36
43
  const isDeleting = (_m = transitionState === null || transitionState === void 0 ? void 0 : transitionState.deletingKeys.has(rowKey)) !== null && _m !== void 0 ? _m : false;
37
44
  const isFadingOut = (_o = transitionState === null || transitionState === void 0 ? void 0 : transitionState.fadingOutKeys.has(rowKey)) !== null && _o !== void 0 ? _o : false;
45
+ // Calculate column widths when dragging (since position: fixed breaks colgroup)
46
+ const draggingColumnWidths = useMemo(() => {
47
+ if (!isDragging || !containerWidth)
48
+ return null;
49
+ // Calculate action columns total width
50
+ let actionColumnsWidth = 0;
51
+ if (draggable === null || draggable === void 0 ? void 0 : draggable.enabled)
52
+ actionColumnsWidth += DRAG_HANDLE_COLUMN_WIDTH;
53
+ if (selection)
54
+ actionColumnsWidth += SELECTION_COLUMN_WIDTH;
55
+ if (expansion)
56
+ actionColumnsWidth += EXPANSION_COLUMN_WIDTH;
57
+ return calculateColumnWidths({
58
+ actionColumnsWidth,
59
+ columns,
60
+ containerWidth,
61
+ getResizedColumnWidth,
62
+ });
63
+ }, [
64
+ isDragging,
65
+ containerWidth,
66
+ columns,
67
+ draggable === null || draggable === void 0 ? void 0 : draggable.enabled,
68
+ expansion,
69
+ getResizedColumnWidth,
70
+ selection,
71
+ ]);
38
72
  // Check if this row should be highlighted based on highlight mode
39
73
  const isRowHighlighted = useMemo(() => {
40
74
  if (!highlight)
@@ -50,14 +84,6 @@ const TableRowInner = forwardRef(function TableRow(props, ref) {
50
84
  return true;
51
85
  return false;
52
86
  }, [highlight, rowIndex]);
53
- const handleRowClick = useCallback(() => {
54
- // Future: support row click to expand or select
55
- }, []);
56
- const handleKeyDown = useCallback((event) => {
57
- if (event.key === 'Enter' || event.key === ' ') {
58
- handleRowClick();
59
- }
60
- }, [handleRowClick]);
61
87
  const handleMouseLeave = useCallback(() => {
62
88
  highlight === null || highlight === void 0 ? void 0 : highlight.setHoveredCell(null, null);
63
89
  }, [highlight]);
@@ -69,7 +95,7 @@ const TableRowInner = forwardRef(function TableRow(props, ref) {
69
95
  const isFixed = !!draggable.fixed;
70
96
  const showShadow = isFixed &&
71
97
  (fixedOffsets === null || fixedOffsets === void 0 ? void 0 : fixedOffsets.shouldShowShadow(DRAG_HANDLE_KEY, scrollLeft !== null && scrollLeft !== void 0 ? scrollLeft : 0, containerWidth !== null && containerWidth !== void 0 ? containerWidth : 0));
72
- return (jsx(TableDragHandleCell, { dragHandleProps: draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.dragHandleProps, fixed: isFixed, fixedOffset: (_a = offsetInfo === null || offsetInfo === void 0 ? void 0 : offsetInfo.offset) !== null && _a !== void 0 ? _a : 0, showShadow: showShadow !== null && showShadow !== void 0 ? showShadow : false }));
98
+ return (jsx(TableDragHandleCell, { dragHandleProps: draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.dragHandleProps, fixed: isFixed, fixedOffset: (_a = offsetInfo === null || offsetInfo === void 0 ? void 0 : offsetInfo.offset) !== null && _a !== void 0 ? _a : 0, showShadow: showShadow !== null && showShadow !== void 0 ? showShadow : false, width: isDragging ? DRAG_HANDLE_COLUMN_WIDTH : undefined }));
73
99
  };
74
100
  const renderSelectionCell = () => {
75
101
  var _a, _b;
@@ -80,7 +106,7 @@ const TableRowInner = forwardRef(function TableRow(props, ref) {
80
106
  const isFixed = !!((_a = selection.config) === null || _a === void 0 ? void 0 : _a.fixed);
81
107
  const showShadow = isFixed &&
82
108
  (fixedOffsets === null || fixedOffsets === void 0 ? void 0 : fixedOffsets.shouldShowShadow(SELECTION_KEY, scrollLeft !== null && scrollLeft !== void 0 ? scrollLeft : 0, containerWidth !== null && containerWidth !== void 0 ? containerWidth : 0));
83
- return (jsx(TableSelectionCell, { disabled: isDisabled, fixed: isFixed, fixedOffset: (_b = offsetInfo === null || offsetInfo === void 0 ? void 0 : offsetInfo.offset) !== null && _b !== void 0 ? _b : 0, indeterminate: isIndeterminate, onChange: () => selection.toggleRow(rowKey, record), selected: isSelected, showShadow: showShadow !== null && showShadow !== void 0 ? showShadow : false }));
109
+ return (jsx(TableSelectionCell, { disabled: isDisabled, fixed: isFixed, fixedOffset: (_b = offsetInfo === null || offsetInfo === void 0 ? void 0 : offsetInfo.offset) !== null && _b !== void 0 ? _b : 0, indeterminate: isIndeterminate, mode: selection.mode, onChange: () => selection.toggleRow(rowKey, record), selected: isSelected, showShadow: showShadow !== null && showShadow !== void 0 ? showShadow : false, width: isDragging ? SELECTION_COLUMN_WIDTH : undefined }));
84
110
  };
85
111
  const renderExpandCell = () => {
86
112
  var _a;
@@ -94,7 +120,7 @@ const TableRowInner = forwardRef(function TableRow(props, ref) {
94
120
  const isFixed = !!config.fixed;
95
121
  const showShadow = isFixed &&
96
122
  (fixedOffsets === null || fixedOffsets === void 0 ? void 0 : fixedOffsets.shouldShowShadow(EXPANSION_KEY, scrollLeft !== null && scrollLeft !== void 0 ? scrollLeft : 0, containerWidth !== null && containerWidth !== void 0 ? containerWidth : 0));
97
- return (jsx(TableExpandCell, { canExpand: canExpand, expanded: isExpanded, fixed: isFixed, fixedOffset: (_a = offsetInfo === null || offsetInfo === void 0 ? void 0 : offsetInfo.offset) !== null && _a !== void 0 ? _a : 0, onClick: () => expansion.toggleExpand(rowKey, record), showShadow: showShadow !== null && showShadow !== void 0 ? showShadow : false }));
123
+ return (jsx(TableExpandCell, { canExpand: canExpand, expanded: isExpanded, fixed: isFixed, fixedOffset: (_a = offsetInfo === null || offsetInfo === void 0 ? void 0 : offsetInfo.offset) !== null && _a !== void 0 ? _a : 0, onClick: () => expansion.toggleExpand(rowKey, record), showShadow: showShadow !== null && showShadow !== void 0 ? showShadow : false, width: isDragging ? EXPANSION_COLUMN_WIDTH : undefined }));
98
124
  };
99
125
  const renderCells = () => {
100
126
  return columns.map((column, columnIndex) => {
@@ -105,21 +131,29 @@ const TableRowInner = forwardRef(function TableRow(props, ref) {
105
131
  // Show shadow based on scroll position and sticky state
106
132
  const showShadow = !!fixedPos &&
107
133
  (fixedOffsets === null || fixedOffsets === void 0 ? void 0 : fixedOffsets.shouldShowShadow(column.key, scrollLeft !== null && scrollLeft !== void 0 ? scrollLeft : 0, containerWidth !== null && containerWidth !== void 0 ? containerWidth : 0));
108
- return (jsx(TableCell, { column: column, columnIndex: columnIndex, fixed: fixedPos !== null && fixedPos !== void 0 ? fixedPos : undefined, fixedOffset: offset, record: record, rowIndex: rowIndex, showShadow: showShadow !== null && showShadow !== void 0 ? showShadow : false }, column.key));
134
+ // Render actions cell for TABLE_ACTIONS_KEY column
135
+ if (column.key === TABLE_ACTIONS_KEY && actions) {
136
+ return (jsx(TableActionsCell, { actions: actions, className: column.className, columnIndex: columnIndex, fixed: fixedPos !== null && fixedPos !== void 0 ? fixedPos : undefined, fixedOffset: offset, record: record, rowIndex: rowIndex, showShadow: showShadow !== null && showShadow !== void 0 ? showShadow : false, width: draggingColumnWidths === null || draggingColumnWidths === void 0 ? void 0 : draggingColumnWidths.get(column.key) }, column.key));
137
+ }
138
+ return (jsx(TableCell, { column: column, columnIndex: columnIndex, fixed: fixedPos !== null && fixedPos !== void 0 ? fixedPos : undefined, fixedOffset: offset, record: record, rowIndex: rowIndex, showShadow: showShadow !== null && showShadow !== void 0 ? showShadow : false, width: draggingColumnWidths === null || draggingColumnWidths === void 0 ? void 0 : draggingColumnWidths.get(column.key) }, column.key));
109
139
  });
110
140
  };
111
141
  // Combine refs if draggable is provided
112
142
  const rowRef = draggableProvided
113
143
  ? composeRefs([ref, draggableProvided.innerRef])
114
144
  : ref;
115
- return (jsxs("tr", { "aria-rowindex": rowIndex + 1, "aria-selected": isSelected, className: cx(tableClasses.row, {
145
+ const isZebraRow = zebraStriping && rowIndex % 2 === 1;
146
+ const isSeparatorRow = separatorAtRowIndexes === null || separatorAtRowIndexes === void 0 ? void 0 : separatorAtRowIndexes.includes(rowIndex);
147
+ return (jsxs("tr", { "aria-rowindex": rowIndex + 1, "aria-selected": isSelected, className: cx(tableClasses.bodyRow, {
116
148
  [tableClasses.bodyRowAdding]: isAdding,
117
149
  [tableClasses.bodyRowDeleting]: isDeleting,
150
+ [tableClasses.bodyRowDragging]: isDragging,
118
151
  [tableClasses.bodyRowFadingOut]: isFadingOut,
119
152
  [tableClasses.bodyRowHighlight]: isRowHighlighted,
120
- [tableClasses.rowExpanded]: isExpanded,
121
- [tableClasses.rowSelected]: isSelected,
122
- }, className), "data-index": rowIndex, "data-row-key": rowKey, onClick: handleRowClick, onKeyDown: handleKeyDown, onMouseLeave: handleMouseLeave, ref: rowRef, tabIndex: 0, ...draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.draggableProps, style: resolvedStyle, children: [renderDragHandleCell(), renderExpandCell(), renderSelectionCell(), renderCells()] }));
153
+ [tableClasses.bodyRowSelected]: isSelected,
154
+ [tableClasses.bodyRowSeparator]: isSeparatorRow,
155
+ [tableClasses.bodyRowZebra]: isZebraRow,
156
+ }, className), "data-index": rowIndex, "data-row-key": rowKey, onMouseLeave: handleMouseLeave, ref: rowRef, tabIndex: 0, ...draggableProvided === null || draggableProvided === void 0 ? void 0 : draggableProvided.draggableProps, style: resolvedStyle, children: [renderDragHandleCell(), renderExpandCell(), renderSelectionCell(), renderCells()] }));
123
157
  });
124
158
  const TableRow = memo(TableRowInner);
125
159
 
@@ -1,3 +1,4 @@
1
+ import { type TableSelectionMode } from '@mezzanine-ui/core/table';
1
2
  export interface TableSelectionCellProps {
2
3
  className?: string;
3
4
  disabled?: boolean;
@@ -6,8 +7,12 @@ export interface TableSelectionCellProps {
6
7
  hidden?: boolean;
7
8
  indeterminate?: boolean;
8
9
  isHeader?: boolean;
10
+ /** Selection mode */
11
+ mode?: TableSelectionMode;
9
12
  onChange: () => void;
10
13
  selected: boolean;
11
14
  showShadow?: boolean;
15
+ /** Explicit width for dragging state */
16
+ width?: number;
12
17
  }
13
18
  export declare const TableSelectionCell: import("react").NamedExoticComponent<TableSelectionCellProps & import("react").RefAttributes<HTMLTableCellElement>>;
@@ -5,13 +5,21 @@ import { tableClasses } from '@mezzanine-ui/core/table';
5
5
  import Checkbox from '../../Checkbox/Checkbox.js';
6
6
  import { useTableContext } from '../TableContext.js';
7
7
  import Skeleton from '../../Skeleton/Skeleton.js';
8
+ import Radio from '../../Radio/Radio.js';
8
9
  import cx from 'clsx';
9
10
 
10
11
  const TableSelectionCellInner = forwardRef(function TableSelectionCell(props, ref) {
11
12
  const { loading } = useTableContext();
12
- const { className, disabled = false, fixed = false, fixedOffset = 0, hidden = false, indeterminate = false, isHeader = false, onChange, selected, showShadow = false, } = props;
13
+ const { className, disabled = false, fixed = false, fixedOffset = 0, hidden = false, indeterminate = false, isHeader = false, mode = 'checkbox', onChange, selected, showShadow = false, width, } = props;
13
14
  const CellComponent = isHeader ? 'th' : 'td';
14
15
  const cellStyle = {};
16
+ // Apply explicit width for dragging state
17
+ if (width !== undefined) {
18
+ cellStyle.width = width;
19
+ cellStyle.minWidth = width;
20
+ cellStyle.maxWidth = width;
21
+ cellStyle.flexShrink = 0;
22
+ }
15
23
  if (fixed) {
16
24
  cellStyle['--fixed-start-offset'] =
17
25
  `${fixedOffset}px`;
@@ -22,6 +30,9 @@ const TableSelectionCellInner = forwardRef(function TableSelectionCell(props, re
22
30
  if (loading) {
23
31
  return jsx(Skeleton, { width: "100%", variant: "body-highlight" });
24
32
  }
33
+ if (mode === 'radio') {
34
+ return (jsx(Radio, { checked: selected, disabled: disabled, onChange: onChange }));
35
+ }
25
36
  return (jsx(Checkbox, { checked: selected, disabled: disabled, indeterminate: indeterminate, onChange: onChange }));
26
37
  };
27
38
  return (jsx(CellComponent, { className: cx(isHeader ? tableClasses.headerCell : tableClasses.cell, tableClasses.selectionCell, {
@@ -1,3 +1,4 @@
1
+ export { TableActionsCell, type TableActionsCellProps, } from './TableActionsCell';
1
2
  export { TableBody, type TableBodyProps } from './TableBody';
2
3
  export { TableCell, type TableCellProps } from './TableCell';
3
4
  export { TableColGroup, type TableColGroupProps } from './TableColGroup';
@@ -1,3 +1,4 @@
1
+ export { TableActionsCell } from './TableActionsCell.js';
1
2
  export { TableBody } from './TableBody.js';
2
3
  export { TableCell } from './TableCell.js';
3
4
  export { TableColGroup } from './TableColGroup.js';
@@ -1,6 +1,6 @@
1
1
  export { useTableSorting, type UseTableSortingOptions, } from './useTableSorting';
2
2
  export { useTableSelection, type UseTableSelectionOptions, } from './useTableSelection';
3
- export { useTableColumns, type UseTableColumnsOptions, } from './useTableColumns';
3
+ export { useTableResizedColumns } from './useTableResizedColumns';
4
4
  export { useTableExpansion, type UseTableExpansionOptions, } from './useTableExpansion';
5
5
  export { useTableFixedOffsets, type FixedOffsetInfo, type UseTableFixedOffsetsOptions, type UseTableFixedOffsetsReturn, } from './useTableFixedOffsets';
6
6
  export { useTableScroll, type UseTableScrollReturn } from './useTableScroll';
@@ -1,6 +1,6 @@
1
1
  export { useTableSorting } from './useTableSorting.js';
2
2
  export { useTableSelection } from './useTableSelection.js';
3
- export { useTableColumns } from './useTableColumns.js';
3
+ export { useTableResizedColumns } from './useTableResizedColumns.js';
4
4
  export { useTableExpansion } from './useTableExpansion.js';
5
5
  export { useTableFixedOffsets } from './useTableFixedOffsets.js';
6
6
  export { useTableScroll } from './useTableScroll.js';
@@ -25,13 +25,13 @@ export interface UpdateDataSourceOptions {
25
25
  * If provided, these items will show the adding animation.
26
26
  * If not provided, new items will appear without animation.
27
27
  */
28
- addedKeys?: (string | number)[];
28
+ addedKeys?: string[];
29
29
  /**
30
30
  * Keys of items being removed that should be animated.
31
31
  * These items should NOT be in the new data array.
32
32
  * The hook will temporarily keep them for animation, then remove after animation completes.
33
33
  */
34
- removedKeys?: (string | number)[];
34
+ removedKeys?: string[];
35
35
  }
36
36
  export interface UseTableDataSourceReturn<T extends TableDataSource> {
37
37
  /** Current data source to pass to Table component */
@@ -25,12 +25,6 @@ function useTableExpansion({ expandable, hasDragHandle, }) {
25
25
  }, [expandedRowKeys, isControlled, onExpand, onExpandedRowsChange]);
26
26
  const expansionLeftPadding = useMemo(() => {
27
27
  let padding = 0;
28
- // Number(
29
- // getCSSVariableValue('--mzn-spacing-padding-horizontal-comfort').replace(
30
- // 'rem',
31
- // '',
32
- // ),
33
- // ) * 16;
34
28
  if (hasDragHandle)
35
29
  padding += DRAG_HANDLE_COLUMN_WIDTH;
36
30
  if (expandable)
@@ -26,4 +26,4 @@ export interface UseTableFixedOffsetsOptions {
26
26
  /** Get computed width for a column (from columnState) */
27
27
  getResizedColumnWidth?: (key: string) => number | undefined;
28
28
  }
29
- export declare function useTableFixedOffsets(options: UseTableFixedOffsetsOptions): UseTableFixedOffsetsReturn;
29
+ export declare function useTableFixedOffsets(props: UseTableFixedOffsetsOptions): UseTableFixedOffsetsReturn;
@@ -10,15 +10,15 @@ const parseFixed = (fixed) => {
10
10
  return 'end';
11
11
  return null;
12
12
  };
13
- function useTableFixedOffsets(options) {
14
- const { expansionLeftPadding = 0 } = useTableSuperContext();
15
- const { actionConfig, columns, getResizedColumnWidth } = options;
13
+ function useTableFixedOffsets(props) {
14
+ const { expansionLeftPadding = 0, hasDragHandleFixed: parentHasDragHandleFixed, } = useTableSuperContext();
15
+ const { actionConfig, columns, getResizedColumnWidth } = props;
16
16
  // Store measured widths
17
17
  const [measuredWidths, setMeasuredWidths] = useState(new Map());
18
- const { hasDragHandle, hasExpansion, hasSelection } = actionConfig;
18
+ const { hasDragHandle, hasExpansion, hasSelection, dragHandleFixed, expansionFixed, selectionFixed, } = actionConfig;
19
19
  useEffect(() => {
20
20
  const innerMap = new Map();
21
- if (hasDragHandle) {
21
+ if (hasDragHandle || parentHasDragHandleFixed) {
22
22
  innerMap.set(DRAG_HANDLE_KEY, DRAG_HANDLE_COLUMN_WIDTH);
23
23
  }
24
24
  if (hasExpansion) {
@@ -28,7 +28,7 @@ function useTableFixedOffsets(options) {
28
28
  innerMap.set(SELECTION_KEY, SELECTION_COLUMN_WIDTH);
29
29
  }
30
30
  setMeasuredWidths(innerMap);
31
- }, [hasDragHandle, hasExpansion, hasSelection]);
31
+ }, [hasDragHandle, hasExpansion, hasSelection, parentHasDragHandleFixed]);
32
32
  // Get width for a column (prioritize measured, then computed, then defined, then fallback)
33
33
  const getWidth = useCallback((key, fallback = 0) => {
34
34
  // Get static widths first
@@ -52,17 +52,15 @@ function useTableFixedOffsets(options) {
52
52
  const { fixedEndKeys, fixedStartKeys } = useMemo(() => {
53
53
  const startKeys = [];
54
54
  const endKeys = [];
55
- // Action columns first (in order: drag handle, expansion, selection)
56
- if (actionConfig.hasDragHandle && actionConfig.dragHandleFixed) {
55
+ if ((hasDragHandle && dragHandleFixed) || parentHasDragHandleFixed) {
57
56
  startKeys.push(DRAG_HANDLE_KEY);
58
57
  }
59
- if (actionConfig.hasExpansion && actionConfig.expansionFixed) {
58
+ if (hasExpansion && expansionFixed) {
60
59
  startKeys.push(EXPANSION_KEY);
61
60
  }
62
- if (actionConfig.hasSelection && actionConfig.selectionFixed) {
61
+ if (hasSelection && selectionFixed) {
63
62
  startKeys.push(SELECTION_KEY);
64
63
  }
65
- // Then data columns
66
64
  columns.forEach((column) => {
67
65
  const side = parseFixed(column.fixed);
68
66
  if (side === 'start') {
@@ -73,12 +71,20 @@ function useTableFixedOffsets(options) {
73
71
  }
74
72
  });
75
73
  return { fixedEndKeys: endKeys, fixedStartKeys: startKeys };
76
- }, [actionConfig, columns]);
74
+ }, [
75
+ hasDragHandle,
76
+ dragHandleFixed,
77
+ hasExpansion,
78
+ expansionFixed,
79
+ hasSelection,
80
+ selectionFixed,
81
+ columns,
82
+ parentHasDragHandleFixed,
83
+ ]);
77
84
  // Calculate all fixed offsets
78
85
  const fixedOffsets = useMemo(() => {
79
86
  const startOffsets = new Map();
80
87
  const endOffsets = new Map();
81
- // Calculate start offsets
82
88
  let currentStartOffset = 0;
83
89
  fixedStartKeys.forEach((key) => {
84
90
  startOffsets.set(key, {
@@ -87,7 +93,6 @@ function useTableFixedOffsets(options) {
87
93
  });
88
94
  currentStartOffset += getWidth(key);
89
95
  });
90
- // Calculate end offsets (from right to left)
91
96
  let currentEndOffset = 0;
92
97
  for (let i = fixedEndKeys.length - 1; i >= 0; i--) {
93
98
  const key = fixedEndKeys[i];
@@ -99,10 +104,8 @@ function useTableFixedOffsets(options) {
99
104
  }
100
105
  return { endOffsets, startOffsets };
101
106
  }, [fixedEndKeys, fixedStartKeys, getWidth]);
102
- // Build ordered list of all columns (for position calculation)
103
107
  const allColumnKeys = useMemo(() => {
104
108
  const keys = [];
105
- // Action columns first
106
109
  if (hasDragHandle) {
107
110
  keys.push(DRAG_HANDLE_KEY);
108
111
  }
@@ -112,13 +115,11 @@ function useTableFixedOffsets(options) {
112
115
  if (hasSelection) {
113
116
  keys.push(SELECTION_KEY);
114
117
  }
115
- // Then data columns
116
118
  columns.forEach((column) => {
117
119
  keys.push(column.key);
118
120
  });
119
121
  return keys;
120
122
  }, [hasDragHandle, hasSelection, hasExpansion, columns]);
121
- // Calculate original positions (left edge) for all columns
122
123
  const originalPositions = useMemo(() => {
123
124
  const positions = new Map();
124
125
  let currentPosition = 0;
@@ -128,9 +129,6 @@ function useTableFixedOffsets(options) {
128
129
  });
129
130
  return positions;
130
131
  }, [allColumnKeys, getWidth]);
131
- /**
132
- * Determine if a column should show shadow.
133
- */
134
132
  const shouldShowShadow = useCallback((key, scrollLeft, containerWidth) => {
135
133
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
136
134
  const offsetInfo = (_a = fixedOffsets.startOffsets.get(key)) !== null && _a !== void 0 ? _a : fixedOffsets.endOffsets.get(key);
@@ -0,0 +1,2 @@
1
+ import type { TableResizedColumnState } from '../TableContext';
2
+ export declare function useTableResizedColumns(): TableResizedColumnState;
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+ import { useState, useCallback } from 'react';
3
+
4
+ function useTableResizedColumns() {
5
+ const [resizedColumnWidths, setResizedColumnWidths] = useState(new Map());
6
+ const getResizedColumnWidth = useCallback((key) => {
7
+ return resizedColumnWidths.get(key);
8
+ }, [resizedColumnWidths]);
9
+ const setResizedColumnWidth = useCallback((key, width) => {
10
+ setResizedColumnWidths((prev) => {
11
+ const next = new Map(prev);
12
+ next.set(key, width);
13
+ return next;
14
+ });
15
+ }, []);
16
+ return {
17
+ getResizedColumnWidth,
18
+ setResizedColumnWidth,
19
+ };
20
+ }
21
+
22
+ export { useTableResizedColumns };
@@ -4,7 +4,9 @@ export interface UseTableScrollReturn {
4
4
  handleScroll: (event: React.UIEvent<HTMLDivElement>) => void;
5
5
  isScrollingHorizontally: boolean;
6
6
  scrollLeft: number;
7
- /** Set refs for measuring container width */
7
+ /** Ref object for internal use */
8
+ containerRef: React.RefObject<HTMLDivElement | null>;
9
+ /** Callback ref setter that should be used for the scroll container */
8
10
  setContainerRef: (element: HTMLDivElement | null) => void;
9
11
  }
10
12
  export declare function useTableScroll({ enabled, }: {
@@ -6,45 +6,51 @@ function useTableScroll({ enabled, }) {
6
6
  const [scrollLeft, setScrollLeft] = useState(0);
7
7
  const [containerWidth, setContainerWidth] = useState(0);
8
8
  const containerRef = useRef(null);
9
- const setContainerRef = useCallback((element) => {
10
- containerRef.current = element;
11
- }, []);
9
+ const resizeObserverRef = useRef(null);
12
10
  const measureDimensions = useCallback(() => {
13
11
  if (containerRef.current) {
14
12
  const newContainerWidth = containerRef.current.clientWidth;
15
13
  setContainerWidth((prev) => prev !== newContainerWidth ? newContainerWidth : prev);
16
14
  }
17
15
  }, []);
16
+ // Callback ref that sets up ResizeObserver when element is attached
17
+ const setContainerRef = useCallback((element) => {
18
+ // Clean up previous observer
19
+ if (resizeObserverRef.current) {
20
+ resizeObserverRef.current.disconnect();
21
+ resizeObserverRef.current = null;
22
+ }
23
+ containerRef.current = element;
24
+ if (element && enabled) {
25
+ // Measure immediately
26
+ measureDimensions();
27
+ // Set up ResizeObserver
28
+ resizeObserverRef.current = new ResizeObserver(() => {
29
+ measureDimensions();
30
+ });
31
+ resizeObserverRef.current.observe(element);
32
+ }
33
+ }, [enabled, measureDimensions]);
18
34
  const handleScroll = useCallback((event) => {
19
35
  const target = event.currentTarget;
20
36
  const newScrollLeft = target.scrollLeft;
21
37
  setScrollLeft(newScrollLeft);
22
38
  setIsScrollingHorizontally(newScrollLeft > 0);
23
39
  }, []);
24
- // Set up ResizeObserver to track dimension changes
40
+ // Cleanup on unmount
25
41
  useEffect(() => {
26
- const { current: container } = containerRef;
27
- if (!container || !enabled)
28
- return;
29
- const resizeObserver = new ResizeObserver(() => {
30
- measureDimensions();
31
- });
32
- resizeObserver.observe(container);
33
42
  return () => {
34
- resizeObserver.disconnect();
43
+ if (resizeObserverRef.current) {
44
+ resizeObserverRef.current.disconnect();
45
+ }
35
46
  };
36
- }, [measureDimensions, enabled]);
37
- // Initial measurement after mount
38
- useEffect(() => {
39
- if (enabled) {
40
- measureDimensions();
41
- }
42
- }, [measureDimensions, enabled]);
47
+ }, []);
43
48
  return useMemo(() => ({
44
49
  containerWidth,
45
50
  handleScroll,
46
51
  isScrollingHorizontally,
47
52
  scrollLeft,
53
+ containerRef,
48
54
  setContainerRef,
49
55
  }), [
50
56
  containerWidth,
@@ -3,28 +3,44 @@ import { useMemo, useCallback } from 'react';
3
3
  import { getRowKey } from '@mezzanine-ui/core/table';
4
4
 
5
5
  function useTableSelection({ dataSource, rowSelection, }) {
6
- const { selectedRowKeys = [], isCheckboxDisabled, onChange, onSelectAll, preserveSelectedRowKeys = false, } = rowSelection || {};
6
+ var _a;
7
+ // Extract common props
8
+ const { onChange, mode = 'checkbox' } = rowSelection || {};
9
+ const selections = mode === 'radio'
10
+ ? rowSelection.selectedRowKey
11
+ : rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.selectedRowKeys;
12
+ const isSelectionDisabled = rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.isSelectionDisabled;
13
+ const onSelectAll = mode === 'radio' ? undefined : rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.onSelectAll;
14
+ const preserveSelectedRowKeys = mode === 'radio' ? false : ((_a = rowSelection === null || rowSelection === void 0 ? void 0 : rowSelection.preserveSelectedRowKeys) !== null && _a !== void 0 ? _a : false);
15
+ const selectedRowKeys = useMemo(() => {
16
+ var _a;
17
+ if (mode === 'radio') {
18
+ const key = selections;
19
+ return key !== undefined ? [key] : [];
20
+ }
21
+ return (_a = selections) !== null && _a !== void 0 ? _a : [];
22
+ }, [mode, selections]);
7
23
  const selectableKeys = useMemo(() => {
8
24
  if (!rowSelection)
9
25
  return [];
10
26
  return dataSource
11
27
  .filter((record) => {
12
- if (!isCheckboxDisabled)
28
+ if (!isSelectionDisabled)
13
29
  return true;
14
- const disabled = isCheckboxDisabled(record);
30
+ const disabled = isSelectionDisabled(record);
15
31
  return !disabled;
16
32
  })
17
33
  .map((record) => getRowKey(record));
18
- }, [dataSource, isCheckboxDisabled, rowSelection]);
34
+ }, [dataSource, isSelectionDisabled, rowSelection]);
19
35
  const isRowSelected = useCallback((key) => {
20
36
  return selectedRowKeys.includes(key);
21
37
  }, [selectedRowKeys]);
22
38
  const isRowDisabled = useCallback((record) => {
23
- if (!isCheckboxDisabled)
39
+ if (!isSelectionDisabled)
24
40
  return false;
25
- const disabled = isCheckboxDisabled(record);
41
+ const disabled = isSelectionDisabled(record);
26
42
  return disabled;
27
- }, [isCheckboxDisabled]);
43
+ }, [isSelectionDisabled]);
28
44
  const isAllSelected = useMemo(() => {
29
45
  if (!selectableKeys.length)
30
46
  return false;
@@ -37,13 +53,20 @@ function useTableSelection({ dataSource, rowSelection, }) {
37
53
  return selectedCount > 0 && selectedCount < selectableKeys.length;
38
54
  }, [selectableKeys, selectedRowKeys]);
39
55
  const toggleRow = useCallback((key) => {
56
+ // Radio mode: only one selection allowed
57
+ if (mode === 'radio') {
58
+ const selectedRow = dataSource.find((r) => getRowKey(r) === key) || null;
59
+ onChange === null || onChange === void 0 ? void 0 : onChange(key, selectedRow);
60
+ return;
61
+ }
62
+ // Checkbox mode: toggle selection
40
63
  const newKeys = selectedRowKeys.includes(key)
41
64
  ? selectedRowKeys.filter((k) => k !== key)
42
65
  : [...selectedRowKeys, key];
43
66
  const selectedRow = dataSource.find((r) => getRowKey(r) === key) || null;
44
67
  const selectedRows = dataSource.filter((r) => newKeys.includes(getRowKey(r)));
45
68
  onChange === null || onChange === void 0 ? void 0 : onChange(newKeys, selectedRow, selectedRows);
46
- }, [selectedRowKeys, dataSource, onChange]);
69
+ }, [mode, selectedRowKeys, dataSource, onChange]);
47
70
  const toggleAll = useCallback(() => {
48
71
  let newKeys;
49
72
  let type;
@@ -85,6 +108,7 @@ function useTableSelection({ dataSource, rowSelection, }) {
85
108
  isIndeterminate,
86
109
  isRowDisabled,
87
110
  isRowSelected,
111
+ mode,
88
112
  selectedRowKeys,
89
113
  toggleAll,
90
114
  toggleRow,
@@ -3,7 +3,7 @@ import { type TableDataSource } from '@mezzanine-ui/core/table';
3
3
  export interface UseTableVirtualizationOptions<T extends TableDataSource> {
4
4
  dataSource: T[];
5
5
  enabled?: boolean;
6
- isRowExpanded?: (key: string | number) => boolean;
6
+ isRowExpanded?: (key: string) => boolean;
7
7
  overscan?: number;
8
8
  scrollContainerRef: React.RefObject<HTMLDivElement | null>;
9
9
  }