@mezzanine-ui/react 1.0.0-beta.1 → 1.0.0-beta.3

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 (172) hide show
  1. package/Anchor/Anchor.d.ts +51 -18
  2. package/Anchor/Anchor.js +15 -15
  3. package/Anchor/AnchorGroup.d.ts +34 -0
  4. package/Anchor/AnchorGroup.js +37 -0
  5. package/Anchor/AnchorItem.d.ts +30 -0
  6. package/Anchor/AnchorItem.js +65 -0
  7. package/Anchor/index.d.ts +2 -0
  8. package/Anchor/index.js +1 -0
  9. package/Anchor/utils.d.ts +13 -0
  10. package/Anchor/utils.js +95 -0
  11. package/AutoComplete/AutoComplete.d.ts +194 -0
  12. package/AutoComplete/AutoComplete.js +419 -0
  13. package/AutoComplete/index.d.ts +2 -0
  14. package/AutoComplete/index.js +1 -0
  15. package/AutoComplete/useAutoCompleteCreation.d.ts +33 -0
  16. package/AutoComplete/useAutoCompleteCreation.js +201 -0
  17. package/AutoComplete/useAutoCompleteKeyboard.d.ts +31 -0
  18. package/AutoComplete/useAutoCompleteKeyboard.js +149 -0
  19. package/AutoComplete/useAutoCompleteSearch.d.ts +16 -0
  20. package/AutoComplete/useAutoCompleteSearch.js +69 -0
  21. package/AutoComplete/useCreationTracker.d.ts +17 -0
  22. package/AutoComplete/useCreationTracker.js +47 -0
  23. package/Badge/Badge.js +2 -2
  24. package/Breadcrumb/BreadcrumbItem.d.ts +1 -1
  25. package/Button/Button.js +13 -11
  26. package/Button/index.d.ts +1 -1
  27. package/Button/typings.d.ts +27 -4
  28. package/Description/Description.d.ts +30 -0
  29. package/Description/Description.js +13 -0
  30. package/Description/DescriptionContent.d.ts +41 -0
  31. package/Description/DescriptionContent.js +14 -0
  32. package/Description/DescriptionGroup.d.ts +13 -0
  33. package/Description/DescriptionGroup.js +12 -0
  34. package/Description/DescriptionTitle.d.ts +45 -0
  35. package/Description/DescriptionTitle.js +17 -0
  36. package/Description/index.d.ts +8 -0
  37. package/Description/index.js +4 -0
  38. package/Dropdown/Dropdown.d.ts +43 -3
  39. package/Dropdown/Dropdown.js +154 -35
  40. package/Dropdown/DropdownAction.d.ts +1 -1
  41. package/Dropdown/DropdownAction.js +1 -4
  42. package/Dropdown/DropdownItem.d.ts +21 -4
  43. package/Dropdown/DropdownItem.js +23 -10
  44. package/Dropdown/DropdownItemCard.d.ts +5 -5
  45. package/Dropdown/DropdownItemCard.js +11 -10
  46. package/Dropdown/DropdownStatus.d.ts +2 -2
  47. package/Dropdown/DropdownStatus.js +29 -0
  48. package/Dropdown/dropdownKeydownHandler.d.ts +2 -1
  49. package/Dropdown/dropdownKeydownHandler.js +73 -0
  50. package/Dropdown/highlightText.js +5 -1
  51. package/Dropdown/shortcutTextHandler.d.ts +24 -0
  52. package/Dropdown/shortcutTextHandler.js +171 -0
  53. package/Form/FormControlContext.d.ts +2 -2
  54. package/Form/FormField.d.ts +56 -4
  55. package/Form/FormField.js +10 -6
  56. package/Form/FormHintText.d.ts +24 -1
  57. package/Form/FormHintText.js +4 -4
  58. package/Form/FormLabel.d.ts +6 -3
  59. package/Form/FormLabel.js +5 -3
  60. package/Input/Input.d.ts +29 -3
  61. package/Input/Input.js +22 -6
  62. package/Input/PasswordStrengthIndicator/PasswordStrengthIndicator.js +1 -1
  63. package/Modal/Modal.d.ts +103 -11
  64. package/Modal/Modal.js +14 -9
  65. package/Modal/ModalBodyForVerification.d.ts +59 -0
  66. package/Modal/ModalBodyForVerification.js +99 -0
  67. package/Modal/ModalControl.d.ts +2 -2
  68. package/Modal/ModalControl.js +1 -1
  69. package/Modal/ModalFooter.d.ts +119 -1
  70. package/Modal/ModalFooter.js +15 -3
  71. package/Modal/ModalHeader.d.ts +26 -7
  72. package/Modal/ModalHeader.js +33 -7
  73. package/Modal/index.d.ts +4 -5
  74. package/Modal/index.js +1 -2
  75. package/Modal/useModalContainer.d.ts +12 -3
  76. package/Modal/useModalContainer.js +28 -6
  77. package/Navigation/CollapsedMenu.d.ts +6 -0
  78. package/Navigation/CollapsedMenu.js +16 -0
  79. package/Navigation/Navigation.d.ts +17 -3
  80. package/Navigation/Navigation.js +48 -33
  81. package/Navigation/NavigationFooter.js +4 -2
  82. package/Navigation/NavigationHeader.d.ts +11 -1
  83. package/Navigation/NavigationHeader.js +6 -3
  84. package/Navigation/NavigationOption.d.ts +3 -2
  85. package/Navigation/NavigationOption.js +45 -26
  86. package/Navigation/NavigationOptionCategory.js +20 -2
  87. package/Navigation/context.d.ts +2 -0
  88. package/Navigation/useVisibleItems.d.ts +5 -0
  89. package/Navigation/useVisibleItems.js +54 -0
  90. package/NotificationCenter/NotificationCenter.d.ts +124 -0
  91. package/NotificationCenter/NotificationCenter.js +259 -0
  92. package/NotificationCenter/NotificationCenterDrawer.d.ts +89 -0
  93. package/NotificationCenter/index.d.ts +3 -0
  94. package/NotificationCenter/index.js +1 -0
  95. package/PageFooter/PageFooter.d.ts +19 -9
  96. package/PageFooter/PageFooter.js +10 -10
  97. package/PageHeader/PageHeader.js +4 -12
  98. package/PageToolbar/PageToolbar.d.ts +2 -6
  99. package/PageToolbar/utils.js +4 -12
  100. package/Select/index.d.ts +0 -2
  101. package/Select/index.js +0 -1
  102. package/Slider/useSlider.js +1 -1
  103. package/Table/Table.d.ts +53 -15
  104. package/Table/Table.js +178 -82
  105. package/Table/TableContext.d.ts +18 -42
  106. package/Table/components/TableActionsCell.d.ts +26 -0
  107. package/Table/components/TableActionsCell.js +78 -0
  108. package/Table/components/TableBody.d.ts +2 -5
  109. package/Table/components/TableBody.js +16 -19
  110. package/Table/components/TableBulkActions.d.ts +15 -0
  111. package/Table/components/TableBulkActions.js +26 -0
  112. package/Table/components/TableCell.d.ts +2 -0
  113. package/Table/components/TableCell.js +42 -10
  114. package/Table/components/TableColGroup.js +10 -112
  115. package/Table/components/TableColumnTitleMenu.d.ts +6 -0
  116. package/Table/components/TableColumnTitleMenu.js +20 -0
  117. package/Table/components/TableDragHandleCell.d.ts +2 -0
  118. package/Table/components/TableDragHandleCell.js +8 -1
  119. package/Table/components/TableExpandCell.d.ts +2 -0
  120. package/Table/components/TableExpandCell.js +8 -1
  121. package/Table/components/TableExpandedRow.js +3 -2
  122. package/Table/components/TableHeader.d.ts +2 -4
  123. package/Table/components/TableHeader.js +11 -14
  124. package/Table/components/TableResizeHandle.js +3 -7
  125. package/Table/components/TableRow.js +54 -20
  126. package/Table/components/TableSelectionCell.d.ts +5 -0
  127. package/Table/components/TableSelectionCell.js +12 -1
  128. package/Table/components/index.d.ts +1 -0
  129. package/Table/components/index.js +1 -0
  130. package/Table/hooks/index.d.ts +1 -1
  131. package/Table/hooks/index.js +1 -1
  132. package/Table/hooks/useTableDataSource.d.ts +2 -2
  133. package/Table/hooks/useTableExpansion.js +0 -6
  134. package/Table/hooks/useTableFixedOffsets.d.ts +1 -1
  135. package/Table/hooks/useTableFixedOffsets.js +24 -26
  136. package/Table/hooks/useTableResizedColumns.d.ts +2 -0
  137. package/Table/hooks/useTableResizedColumns.js +22 -0
  138. package/Table/hooks/useTableScroll.d.ts +3 -1
  139. package/Table/hooks/useTableScroll.js +25 -19
  140. package/Table/hooks/useTableSelection.js +32 -8
  141. package/Table/hooks/useTableVirtualization.d.ts +1 -1
  142. package/Table/index.d.ts +4 -4
  143. package/Table/index.js +5 -3
  144. package/Table/utils/calculateColumnWidths.d.ts +28 -0
  145. package/Table/utils/calculateColumnWidths.js +80 -0
  146. package/Table/utils/index.d.ts +2 -0
  147. package/Table/utils/index.js +1 -0
  148. package/Table/utils/useTableRowSelection.d.ts +5 -5
  149. package/Table/utils/useTableRowSelection.js +14 -6
  150. package/Tag/TagGroup.d.ts +3 -0
  151. package/Tag/index.d.ts +2 -0
  152. package/Tag/index.js +1 -0
  153. package/Upload/UploadPictureCard.js +1 -1
  154. package/index.d.ts +36 -20
  155. package/index.js +26 -7
  156. package/package.json +4 -4
  157. package/utils/format-number-with-commas.d.ts +4 -0
  158. package/utils/format-number-with-commas.js +27 -0
  159. package/utils/parse-number-with-commas.d.ts +4 -0
  160. package/utils/parse-number-with-commas.js +22 -0
  161. package/Modal/ModalActions.d.ts +0 -9
  162. package/Modal/ModalActions.js +0 -20
  163. package/Modal/ModalBody.d.ts +0 -7
  164. package/Modal/ModalBody.js +0 -14
  165. package/Notification/Notification.d.ts +0 -54
  166. package/Notification/Notification.js +0 -76
  167. package/Notification/index.d.ts +0 -3
  168. package/Notification/index.js +0 -1
  169. package/Select/AutoComplete.d.ts +0 -107
  170. package/Select/AutoComplete.js +0 -114
  171. package/Table/hooks/useTableColumns.d.ts +0 -8
  172. package/Table/hooks/useTableColumns.js +0 -91
@@ -1,7 +1,8 @@
1
- import type { HighlightMode, TableSize, TableColumn, TableDataSource, TableExpandable, TableRowSelection, TableScroll } from '@mezzanine-ui/core/table';
1
+ import type { HighlightMode, TableSize, TableActionsBase, TableColumn, TableDataSource, TableExpandable, TableRowSelection, TableScroll, TableSelectionMode } from '@mezzanine-ui/core/table';
2
2
  import type { EmptyProps } from '../Empty';
3
3
  import type { PaginationProps } from '../Pagination';
4
4
  import type { UseTableFixedOffsetsReturn } from './hooks/useTableFixedOffsets';
5
+ import type { TableTransitionState } from './hooks/useTableDataSource';
5
6
  /** Sorting context state */
6
7
  export interface TableSortingState {
7
8
  onSort: (key: string) => void;
@@ -12,88 +13,63 @@ export interface TableSelectionState<T extends TableDataSource = TableDataSource
12
13
  isAllSelected: boolean;
13
14
  isIndeterminate: boolean;
14
15
  isRowDisabled: (record: T) => boolean;
15
- isRowSelected: (key: string | number) => boolean;
16
- selectedRowKeys: (string | number)[];
16
+ isRowSelected: (key: string) => boolean;
17
+ mode: TableSelectionMode;
18
+ selectedRowKeys: string[];
17
19
  toggleAll: () => void;
18
- toggleRow: (key: string | number, record: T) => void;
20
+ toggleRow: (key: string, record: T) => void;
19
21
  }
20
22
  /** Expansion context state */
21
23
  export interface TableExpansionState<T extends TableDataSource = TableDataSource> {
22
24
  config: TableExpandable<T>;
23
25
  expansionLeftPadding: number;
24
- expandedRowKeys: (string | number)[];
25
- isRowExpanded: (key: string | number) => boolean;
26
- toggleExpand: (key: string | number, record: T) => void;
26
+ expandedRowKeys: string[];
27
+ isRowExpanded: (key: string) => boolean;
28
+ toggleExpand: (key: string, record: T) => void;
27
29
  }
28
30
  /** Column state with computed widths */
29
- export interface TableColumnState {
30
- resizedColumnWidths: Map<string, number>;
31
- columns: TableColumn[];
32
- fixedEndColumns: TableColumn[];
33
- fixedStartColumns: TableColumn[];
31
+ export interface TableResizedColumnState {
34
32
  getResizedColumnWidth: (key: string) => number | undefined;
35
- scrollableColumns: TableColumn[];
36
33
  setResizedColumnWidth: (key: string, width: number) => void;
37
- totalFixedEndWidth: number;
38
- totalFixedStartWidth: number;
39
34
  }
40
35
  /** Draggable state */
41
36
  export interface TableDraggableState {
42
- draggingId: string | null;
43
37
  enabled: boolean;
44
38
  fixed?: boolean | 'start';
45
39
  }
46
40
  /** Highlight state for hover effects */
47
41
  export interface TableHighlightState {
48
- /** Current column index being hovered */
49
42
  columnIndex: number | null;
50
- /** Highlight mode */
51
43
  mode: HighlightMode;
52
- /** Current row index being hovered */
53
44
  rowIndex: number | null;
54
- /** Set hovered cell */
55
45
  setHoveredCell: (rowIndex: number | null, columnIndex: number | null) => void;
56
46
  }
57
- /** Transition state for row add/remove animations */
58
- export interface TableTransitionState {
59
- /** Keys of rows currently in adding state (highlighted) */
60
- addingKeys: Set<string>;
61
- /** Keys of rows currently in deleting state (red highlight) */
62
- deletingKeys: Set<string>;
63
- /** Keys of rows currently fading out */
64
- fadingOutKeys: Set<string>;
65
- }
66
47
  /** Main table context */
67
48
  export interface TableContextValue<T extends TableDataSource = TableDataSource> {
68
- columnState?: TableColumnState;
69
- columns: TableColumn<T>[];
70
- /** Container width for scroll calculations */
49
+ actions?: TableActionsBase<T>;
50
+ columnState?: TableResizedColumnState;
71
51
  dataSource: T[];
72
52
  draggable?: TableDraggableState;
73
- emptyProps?: EmptyProps;
53
+ emptyProps?: EmptyProps & {
54
+ height?: number | string;
55
+ };
74
56
  expansion?: TableExpansionState<T>;
75
- /** Fixed column offset calculations */
76
57
  fixedOffsets?: UseTableFixedOffsetsReturn;
77
- /** Whether columns are resizable by user interaction */
78
58
  resizable?: boolean;
79
- /** Row height */
80
59
  rowHeight: number;
81
- /** Highlight state for hover effects */
82
60
  highlight?: TableHighlightState;
83
61
  isScrollingHorizontally?: boolean;
84
62
  loading?: boolean;
85
63
  pagination?: PaginationProps;
86
64
  size?: TableSize;
87
65
  scroll?: TableScroll;
88
- /** Ref to the scroll container div for virtualization */
89
66
  scrollContainerRef?: React.RefObject<HTMLDivElement | null>;
90
67
  selection?: TableSelectionState<T>;
68
+ separatorAtRowIndexes?: number[];
91
69
  sorting?: TableSortingState;
92
- /** Transition state for row add/remove animations */
93
70
  transitionState?: TableTransitionState;
94
- /** Whether virtual scrolling is enabled */
95
71
  virtualScrollEnabled?: boolean;
96
- /** Whether the table is inside an expanded content area */
72
+ zebraStriping?: boolean;
97
73
  isInsideExpandedContentArea?: boolean;
98
74
  }
99
75
  export declare const TableContext: import("react").Context<TableContextValue<TableDataSource> | null>;
@@ -107,10 +83,10 @@ export declare const TableDataContext: import("react").Context<TableDataContextV
107
83
  export declare function useTableDataContext<T extends TableDataSource = TableDataSource>(): TableDataContextValue<T>;
108
84
  export interface TableSuperContextValue {
109
85
  containerWidth?: number;
110
- /** Get resized column width from root table (for child table column sync) */
111
86
  getResizedColumnWidth?: (key: string) => number | undefined;
112
87
  scrollLeft?: number;
113
88
  expansionLeftPadding?: number;
89
+ hasDragHandleFixed?: boolean;
114
90
  }
115
91
  export declare const TableSuperContext: import("react").Context<TableSuperContextValue | null>;
116
92
  export declare function useTableSuperContext(): TableSuperContextValue;
@@ -0,0 +1,26 @@
1
+ import { type TableActionsBase, type TableDataSource } from '@mezzanine-ui/core/table';
2
+ export interface TableActionsCellProps<T extends TableDataSource = TableDataSource> {
3
+ /** Actions configuration */
4
+ actions: TableActionsBase<T>;
5
+ /** Custom class name */
6
+ className?: string;
7
+ /** Column index for highlight calculation */
8
+ columnIndex: number;
9
+ /** Fixed position */
10
+ fixed?: 'end' | 'start';
11
+ /** Fixed offset */
12
+ fixedOffset?: number;
13
+ /** Row record */
14
+ record: T;
15
+ /** Row index */
16
+ rowIndex: number;
17
+ /** Whether to show shadow */
18
+ showShadow?: boolean;
19
+ /** Cell style */
20
+ style?: React.CSSProperties;
21
+ /** Explicit width for dragging state */
22
+ width?: number;
23
+ }
24
+ declare const TableActionsCellInner: import("react").ForwardRefExoticComponent<TableActionsCellProps<TableDataSource> & import("react").RefAttributes<HTMLTableCellElement>>;
25
+ export declare const TableActionsCell: typeof TableActionsCellInner;
26
+ export {};
@@ -0,0 +1,78 @@
1
+ 'use client';
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { memo, forwardRef, useMemo } from 'react';
4
+ import { getCellAlignClass, tableClasses } from '@mezzanine-ui/core/table';
5
+ import { useTableContext } from '../TableContext.js';
6
+ import Button from '../../Button/Button.js';
7
+ import ButtonGroup from '../../Button/ButtonGroup.js';
8
+ import cx from 'clsx';
9
+
10
+ const TableActionsCellInner = forwardRef(function TableActionsCell(props, ref) {
11
+ var _a;
12
+ const { actions, className, columnIndex, fixed, fixedOffset = 0, record, rowIndex, showShadow = false, style, width, } = props;
13
+ const { highlight, loading } = useTableContext();
14
+ const actionItems = useMemo(() => actions.render(record, rowIndex), [actions, record, rowIndex]);
15
+ const cellStyle = useMemo(() => {
16
+ const baseStyle = { ...style };
17
+ if (width !== undefined) {
18
+ baseStyle.width = width;
19
+ baseStyle.minWidth = width;
20
+ baseStyle.maxWidth = width;
21
+ baseStyle.flexShrink = 0;
22
+ }
23
+ if (fixed === 'start') {
24
+ baseStyle['--fixed-start-offset'] =
25
+ `${fixedOffset}px`;
26
+ }
27
+ else if (fixed === 'end') {
28
+ baseStyle['--fixed-end-offset'] =
29
+ `${fixedOffset}px`;
30
+ }
31
+ return baseStyle;
32
+ }, [style, fixed, fixedOffset, width]);
33
+ const alignClass = getCellAlignClass((_a = actions.align) !== null && _a !== void 0 ? _a : 'end');
34
+ const isCellHighlighted = useMemo(() => {
35
+ if (!highlight)
36
+ return false;
37
+ const { columnIndex: hoveredColumn, mode, rowIndex: hoveredRow, } = highlight;
38
+ if (hoveredRow === null || hoveredColumn === null)
39
+ return false;
40
+ switch (mode) {
41
+ case 'cell':
42
+ return hoveredRow === rowIndex && hoveredColumn === columnIndex;
43
+ case 'column':
44
+ return hoveredColumn === columnIndex;
45
+ case 'cross':
46
+ return hoveredColumn === columnIndex;
47
+ case 'row':
48
+ default:
49
+ return false;
50
+ }
51
+ }, [highlight, rowIndex, columnIndex]);
52
+ const handleMouseEnter = () => {
53
+ highlight === null || highlight === void 0 ? void 0 : highlight.setHoveredCell(rowIndex, columnIndex);
54
+ };
55
+ if (loading) {
56
+ return (jsx("td", { className: cx(tableClasses.cell, {
57
+ [tableClasses.cellFixed]: !!fixed,
58
+ [tableClasses.cellFixedEnd]: fixed === 'end',
59
+ [tableClasses.cellFixedShadow]: showShadow,
60
+ [tableClasses.cellFixedStart]: fixed === 'start',
61
+ [tableClasses.cellHighlight]: isCellHighlighted,
62
+ }, className), onMouseEnter: handleMouseEnter, ref: ref, style: cellStyle }));
63
+ }
64
+ return (jsx("td", { className: cx(tableClasses.cell, {
65
+ [tableClasses.cellFixed]: !!fixed,
66
+ [tableClasses.cellFixedEnd]: fixed === 'end',
67
+ [tableClasses.cellFixedShadow]: showShadow,
68
+ [tableClasses.cellFixedStart]: fixed === 'start',
69
+ [tableClasses.cellHighlight]: isCellHighlighted,
70
+ }, className), onMouseEnter: handleMouseEnter, ref: ref, style: cellStyle, children: jsx("div", { className: cx(tableClasses.cellContent, alignClass), children: jsx(ButtonGroup, { size: "sub", variant: actions.variant, children: actionItems.map((item) => {
71
+ var _a, _b, _c;
72
+ const isDisabled = (_b = (_a = item.disabled) === null || _a === void 0 ? void 0 : _a.call(item, record)) !== null && _b !== void 0 ? _b : false;
73
+ return (jsx(Button, { disabled: isDisabled, icon: item.icon, onClick: () => item.onClick(record, rowIndex), type: "button", variant: item.variant, children: item.name }, `${item.name || 'name'}-${((_c = item.icon) === null || _c === void 0 ? void 0 : _c.name) || 'icon'}-${rowIndex}`));
74
+ }) }) }) }));
75
+ });
76
+ const TableActionsCell = memo(TableActionsCellInner);
77
+
78
+ export { TableActionsCell };
@@ -1,5 +1,2 @@
1
- export interface TableBodyProps {
2
- className?: string;
3
- droppableRef?: React.Ref<HTMLTableSectionElement>;
4
- }
5
- export declare const TableBody: import("react").NamedExoticComponent<TableBodyProps & import("react").RefAttributes<HTMLTableSectionElement>>;
1
+ export type TableBodyProps = unknown;
2
+ export declare const TableBody: import("react").NamedExoticComponent<import("react").RefAttributes<HTMLTableSectionElement>>;
@@ -3,28 +3,28 @@ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
3
  import { memo, forwardRef, useMemo, Fragment as Fragment$1 } from 'react';
4
4
  import { tableClasses, getRowKey } from '@mezzanine-ui/core/table';
5
5
  import { Draggable } from '@hello-pangea/dnd';
6
- import { useTableContext } from '../TableContext.js';
6
+ import { useTableContext, useTableDataContext } from '../TableContext.js';
7
7
  import { TableRow } from './TableRow.js';
8
8
  import { TableExpandedRow } from './TableExpandedRow.js';
9
9
  import { useTableVirtualization } from '../hooks/useTableVirtualization.js';
10
- import { composeRefs } from '../../utils/composeRefs.js';
11
10
  import { MOTION_EASING, MOTION_DURATION } from '@mezzanine-ui/system/motion';
12
11
  import Empty from '../../Empty/Empty.js';
13
12
  import Fade from '../../Transition/Fade.js';
14
13
  import cx from 'clsx';
15
14
 
16
- const TableBodyInner = forwardRef(function TableBody(props, ref) {
17
- const { className, droppableRef } = props;
18
- const { columns, dataSource, draggable, emptyProps, expansion, loading, scrollContainerRef, selection, size, virtualScrollEnabled, } = useTableContext();
19
- // Use virtualization with the scroll container ref from parent
15
+ const TableBodyInner = forwardRef(function TableBody(_, ref) {
16
+ const { dataSource, draggable, emptyProps, expansion, loading, scrollContainerRef, selection, size, virtualScrollEnabled, } = useTableContext();
17
+ const { columns } = useTableDataContext();
18
+ /** Feature: Empty State */
19
+ const isEmpty = useMemo(() => !dataSource.length, [dataSource.length]);
20
+ /** Feature: Virtualized Scroll */
20
21
  const virtualization = useTableVirtualization({
21
22
  dataSource,
22
- enabled: virtualScrollEnabled !== null && virtualScrollEnabled !== void 0 ? virtualScrollEnabled : false,
23
+ enabled: virtualScrollEnabled,
23
24
  isRowExpanded: expansion === null || expansion === void 0 ? void 0 : expansion.isRowExpanded,
24
25
  scrollContainerRef: scrollContainerRef,
25
26
  });
26
- const isEmpty = dataSource.length === 0;
27
- // Calculate total column span for empty row
27
+ /** Calculate total columns */
28
28
  const totalColSpan = useMemo(() => {
29
29
  let colSpan = columns.length;
30
30
  if (draggable === null || draggable === void 0 ? void 0 : draggable.enabled)
@@ -35,7 +35,7 @@ const TableBodyInner = forwardRef(function TableBody(props, ref) {
35
35
  colSpan += 1;
36
36
  return colSpan;
37
37
  }, [columns.length, draggable === null || draggable === void 0 ? void 0 : draggable.enabled, expansion, selection]);
38
- // Helper to render expanded content with optional animation
38
+ /** Feature: Expanded Row render */
39
39
  const renderExpandedContent = (record, isExpanded) => {
40
40
  if (!expansion)
41
41
  return null;
@@ -47,18 +47,17 @@ const TableBodyInner = forwardRef(function TableBody(props, ref) {
47
47
  exit: MOTION_EASING.exit,
48
48
  }, in: isExpanded, children: jsx(TableExpandedRow, { record: record }) }));
49
49
  };
50
- // Helper to render row and its expanded content
50
+ /** Main Render */
51
51
  const renderRowContent = (record, index, options) => {
52
52
  var _a;
53
53
  const rowKey = getRowKey(record);
54
54
  const isExpanded = (_a = expansion === null || expansion === void 0 ? void 0 : expansion.isRowExpanded(rowKey)) !== null && _a !== void 0 ? _a : false;
55
- return (jsxs(Fragment, { children: [jsx(TableRow, { className: options === null || options === void 0 ? void 0 : options.className, "data-index": virtualization ? index : undefined, draggableProvided: options === null || options === void 0 ? void 0 : options.draggableProvided, record: record, ref: options === null || options === void 0 ? void 0 : options.measureRef, rowIndex: index }), renderExpandedContent(record, isExpanded)] }));
55
+ return (jsxs(Fragment, { children: [jsx(TableRow, { className: (options === null || options === void 0 ? void 0 : options.isDragging) ? tableClasses.bodyRowDragging : undefined, "data-index": virtualization ? index : undefined, draggableProvided: options === null || options === void 0 ? void 0 : options.draggableProvided, record: record, ref: options === null || options === void 0 ? void 0 : options.measureRef, rowIndex: index }), renderExpandedContent(record, isExpanded)] }));
56
56
  };
57
57
  const renderRows = () => {
58
- // Empty state
59
58
  if (isEmpty && !loading) {
60
- const { size: emptySize = size, ...restEmptyProp } = emptyProps || {};
61
- return (jsx("tr", { className: tableClasses.emptyRow, children: jsx("td", { className: tableClasses.empty, colSpan: totalColSpan, children: jsx(Empty, { size: emptySize, ...restEmptyProp }) }) }));
59
+ const { size: emptySize = size, height, ...restEmptyProp } = emptyProps || {};
60
+ return (jsx("tr", { className: tableClasses.emptyRow, children: jsx("td", { className: tableClasses.empty, colSpan: totalColSpan, style: height ? { height } : undefined, children: jsx(Empty, { size: emptySize, ...restEmptyProp }) }) }));
62
61
  }
63
62
  // Determine items to render (virtualized or all)
64
63
  const itemsToRender = virtualization
@@ -78,9 +77,7 @@ const TableBodyInner = forwardRef(function TableBody(props, ref) {
78
77
  // Draggable mode
79
78
  if ((draggable === null || draggable === void 0 ? void 0 : draggable.enabled) && !virtualization) {
80
79
  return (jsx(Draggable, { draggableId: String(rowKey), index: item.index, isDragDisabled: !draggable.enabled, children: (provided, snapshot) => (jsx(Fragment, { children: renderRowContent(item.record, item.index, {
81
- className: snapshot.isDragging
82
- ? tableClasses.bodyRowDragging
83
- : undefined,
80
+ isDragging: snapshot.isDragging,
84
81
  draggableProvided: provided,
85
82
  }) })) }, rowKey));
86
83
  }
@@ -95,7 +92,7 @@ const TableBodyInner = forwardRef(function TableBody(props, ref) {
95
92
  }
96
93
  return rowElements;
97
94
  };
98
- return (jsx("tbody", { className: cx(tableClasses.body, className), ref: droppableRef ? composeRefs([ref, droppableRef]) : ref, children: renderRows() }));
95
+ return (jsx("tbody", { className: cx(tableClasses.body), ref: ref, children: renderRows() }));
99
96
  });
100
97
  const TableBody = memo(TableBodyInner);
101
98
 
@@ -0,0 +1,15 @@
1
+ import { TableRowSelectionCheckbox, type TableBulkActions as TableBulkActionsConfig } from '@mezzanine-ui/core/table';
2
+ export interface TableBulkActionsProps {
3
+ /** Bulk actions configuration */
4
+ bulkActions: TableBulkActionsConfig;
5
+ /** Custom class name */
6
+ className?: string;
7
+ /** Whether to use fixed positioning */
8
+ isFixed?: boolean;
9
+ /** Callback to clear all selections */
10
+ onClearSelection: VoidFunction;
11
+ /** Array of selected row keys */
12
+ selectedRowKeys: TableRowSelectionCheckbox['selectedRowKeys'];
13
+ }
14
+ declare function TableBulkActions(props: TableBulkActionsProps): import("react/jsx-runtime").JSX.Element | null;
15
+ export default TableBulkActions;
@@ -0,0 +1,26 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { getRowKey, tableClasses } from '@mezzanine-ui/core/table';
3
+ import { CloseIcon } from '@mezzanine-ui/icons';
4
+ import Button from '../../Button/Button.js';
5
+ import { useTableDataContext } from '../TableContext.js';
6
+ import Dropdown from '../../Dropdown/Dropdown.js';
7
+ import cx from 'clsx';
8
+
9
+ function TableBulkActions(props) {
10
+ var _a;
11
+ const { bulkActions, className, isFixed, onClearSelection, selectedRowKeys } = props;
12
+ const { dataSource } = useTableDataContext();
13
+ const { destructiveAction, mainActions, overflowAction, renderSelectionSummary, } = bulkActions;
14
+ if (!selectedRowKeys.length) {
15
+ return null;
16
+ }
17
+ const selectedRows = dataSource.filter((data) => selectedRowKeys.includes(getRowKey(data)));
18
+ const label = renderSelectionSummary
19
+ ? renderSelectionSummary(selectedRowKeys.length, selectedRowKeys, selectedRows)
20
+ : `${selectedRowKeys.length} item${selectedRowKeys.length > 1 ? 's' : ''} selected`;
21
+ return (jsxs("div", { className: cx(tableClasses.bulkActions, className, {
22
+ [tableClasses.bulkActionsFixed]: isFixed,
23
+ }), children: [jsx("div", { className: tableClasses.bulkActionsSelectionSummary, children: jsx(Button, { iconType: "trailing", icon: CloseIcon, onClick: onClearSelection, size: "sub", type: "button", variant: "inverse", children: label }) }), jsxs("div", { className: tableClasses.bulkActionsActionArea, children: [mainActions.map((action, index) => (jsx(Button, { iconType: "leading", icon: action.icon, onClick: () => action.onClick(selectedRowKeys, selectedRows), size: "sub", type: "button", variant: "inverse-ghost", children: action.label }, `main-action-${index}`))), destructiveAction && (jsxs(Fragment, { children: [jsx("div", { className: tableClasses.bulkActionsSeparator }), jsx(Button, { iconType: "leading", icon: destructiveAction.icon, onClick: () => destructiveAction.onClick(selectedRowKeys, selectedRows), size: "sub", type: "button", variant: "destructive-ghost", children: destructiveAction.label })] })), overflowAction && (jsxs(Fragment, { children: [jsx("div", { className: tableClasses.bulkActionsSeparator }), jsx(Dropdown, { maxHeight: overflowAction.maxHeight, onSelect: (option) => overflowAction.onSelect(option, selectedRowKeys, selectedRows), options: overflowAction.options, placement: (_a = overflowAction.placement) !== null && _a !== void 0 ? _a : 'top', children: jsx(Button, { size: "sub", type: "button", variant: "inverse-ghost", iconType: "leading", icon: overflowAction.icon, children: overflowAction.label }) })] }))] })] }));
24
+ }
25
+
26
+ export { TableBulkActions as default };
@@ -11,6 +11,8 @@ export interface TableCellProps<T extends TableDataSource = TableDataSource> {
11
11
  /** Whether to show shadow on this cell (only for edge fixed columns) */
12
12
  showShadow?: boolean;
13
13
  style?: React.CSSProperties;
14
+ /** Explicit width for dragging state (when position: fixed breaks colgroup) */
15
+ width?: number;
14
16
  }
15
17
  declare const TableCellInner: import("react").ForwardRefExoticComponent<TableCellProps<TableDataSource> & import("react").RefAttributes<HTMLTableCellElement>>;
16
18
  export declare const TableCell: typeof TableCellInner;
@@ -1,14 +1,16 @@
1
1
  'use client';
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { memo, forwardRef, useMemo, useCallback } from 'react';
3
+ import { memo, forwardRef, useMemo, useCallback, useRef } from 'react';
4
4
  import { getCellAlignClass, tableClasses } from '@mezzanine-ui/core/table';
5
5
  import { useTableContext } from '../TableContext.js';
6
6
  import Skeleton from '../../Skeleton/Skeleton.js';
7
+ import Tooltip from '../../Tooltip/Tooltip.js';
7
8
  import cx from 'clsx';
8
9
 
9
10
  const TableCellInner = forwardRef(function TableCell(props, ref) {
11
+ var _a;
10
12
  const { loading } = useTableContext();
11
- const { className, colSpan = 1, column, columnIndex, fixed, fixedOffset = 0, record, rowIndex, showShadow = false, style, } = props;
13
+ const { className, colSpan = 1, column, columnIndex, fixed, fixedOffset = 0, record, rowIndex, showShadow = false, style, width, } = props;
12
14
  const { highlight } = useTableContext();
13
15
  const cellValue = useMemo(() => {
14
16
  var _a;
@@ -19,12 +21,15 @@ const TableCellInner = forwardRef(function TableCell(props, ref) {
19
21
  return record[dataIndex];
20
22
  }, [column, record, rowIndex]);
21
23
  // Width is managed by colgroup, set fixed position offset via CSS variable
24
+ // When width is provided (dragging state), apply it directly
22
25
  const cellStyle = useMemo(() => {
23
26
  const baseStyle = { ...style };
24
- if (column.ellipsis) {
25
- baseStyle.overflow = 'hidden';
26
- baseStyle.textOverflow = 'ellipsis';
27
- baseStyle.whiteSpace = 'nowrap';
27
+ // Apply explicit width for dragging state
28
+ if (width !== undefined) {
29
+ baseStyle.width = width;
30
+ baseStyle.minWidth = width;
31
+ baseStyle.maxWidth = width;
32
+ baseStyle.flexShrink = 0;
28
33
  }
29
34
  // Set CSS variable for fixed column positioning
30
35
  if (fixed === 'start') {
@@ -36,7 +41,7 @@ const TableCellInner = forwardRef(function TableCell(props, ref) {
36
41
  `${fixedOffset}px`;
37
42
  }
38
43
  return baseStyle;
39
- }, [style, column.ellipsis, fixed, fixedOffset]);
44
+ }, [style, fixed, fixedOffset, width]);
40
45
  const alignClass = getCellAlignClass(column.align);
41
46
  // Check if this cell should be highlighted based on highlight mode
42
47
  const isCellHighlighted = useMemo(() => {
@@ -60,14 +65,41 @@ const TableCellInner = forwardRef(function TableCell(props, ref) {
60
65
  const handleMouseEnter = useCallback(() => {
61
66
  highlight === null || highlight === void 0 ? void 0 : highlight.setHoveredCell(rowIndex, columnIndex);
62
67
  }, [highlight, rowIndex, columnIndex]);
63
- return (jsx("td", { className: cx(tableClasses.cell, alignClass, {
64
- [tableClasses.cellEllipsis]: column.ellipsis,
68
+ /** Feature: Ellipsis */
69
+ const ellipsisRef = useRef(null);
70
+ // default to true if undefined
71
+ const isColumnEllipsis = (_a = column.ellipsis) !== null && _a !== void 0 ? _a : true;
72
+ const renderChild = () => {
73
+ if (loading) {
74
+ return jsx(Skeleton, { width: "100%", variant: "body-highlight" });
75
+ }
76
+ if (isColumnEllipsis) {
77
+ return (jsx(Tooltip, { anchor: ellipsisRef, title: cellValue, options: {
78
+ placement: 'top-start',
79
+ }, children: ({ onMouseEnter, onMouseLeave }) => (
80
+ /** @Note "display: grid" for feature ellipsis to work properly */
81
+ jsx("div", { style: { display: 'grid', width: '100%' }, children: jsx("div", { ref: ellipsisRef, className: cx(tableClasses.cellContent, alignClass, {
82
+ [tableClasses.cellEllipsis]: isColumnEllipsis,
83
+ }), onMouseEnter: (e) => {
84
+ if (ellipsisRef.current) {
85
+ const { current: el } = ellipsisRef;
86
+ const isOverflow = el.scrollWidth > el.offsetWidth;
87
+ if (isOverflow)
88
+ onMouseEnter(e);
89
+ }
90
+ }, onMouseLeave: onMouseLeave, children: cellValue }) })) }));
91
+ }
92
+ return (
93
+ /** @Note "display: grid" for feature ellipsis to work properly */
94
+ jsx("div", { style: { display: 'grid', width: '100%' }, children: jsx("div", { className: cx(tableClasses.cellContent, alignClass), children: cellValue }) }));
95
+ };
96
+ return (jsx("td", { className: cx(tableClasses.cell, {
65
97
  [tableClasses.cellFixed]: !!fixed,
66
98
  [tableClasses.cellFixedEnd]: fixed === 'end',
67
99
  [tableClasses.cellFixedShadow]: showShadow,
68
100
  [tableClasses.cellFixedStart]: fixed === 'start',
69
101
  [tableClasses.cellHighlight]: isCellHighlighted,
70
- }, column.className, className), colSpan: colSpan > 1 ? colSpan : undefined, onMouseEnter: handleMouseEnter, ref: ref, style: cellStyle, children: loading ? (jsx(Skeleton, { width: "100%", variant: "body-highlight" })) : (jsx("span", { className: tableClasses.cellContent, children: cellValue })) }));
102
+ }, className), colSpan: colSpan > 1 ? colSpan : undefined, onMouseEnter: handleMouseEnter, ref: ref, style: cellStyle, children: renderChild() }));
71
103
  });
72
104
  const TableCell = memo(TableCellInner);
73
105
 
@@ -2,117 +2,13 @@
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import { memo, useMemo } from 'react';
4
4
  import { DRAG_HANDLE_COLUMN_WIDTH, SELECTION_COLUMN_WIDTH, EXPANSION_COLUMN_WIDTH, tableClasses, DRAG_HANDLE_KEY, EXPANSION_KEY, SELECTION_KEY } from '@mezzanine-ui/core/table';
5
- import { useTableContext, useTableSuperContext } from '../TableContext.js';
5
+ import { useTableContext, useTableDataContext, useTableSuperContext } from '../TableContext.js';
6
+ import { calculateColumnWidths, shouldCalculateWidths } from '../utils/calculateColumnWidths.js';
6
7
 
7
- /**
8
- * Check if width calculation should be applied.
9
- * Only calculate explicit widths for root tables (not nested).
10
- * Nested tables should let columns use natural CSS behavior.
11
- */
12
- function shouldCalculateWidths(isNestedTable, containerWidth) {
13
- // Don't calculate widths for nested tables - they inherit parent's context
14
- // and should use natural CSS column sizing
15
- if (isNestedTable) {
16
- return false;
17
- }
18
- // Don't calculate if container width is not available
19
- if (!containerWidth || containerWidth <= 0) {
20
- return false;
21
- }
22
- return true;
23
- }
24
- /**
25
- * Calculate the resolved width for each column.
26
- * - Columns with explicit width use that value
27
- * - Columns without width share the remaining space equally (simulating flex: 1)
28
- * - All widths are clamped to minWidth/maxWidth if specified
29
- */
30
- function calculateColumnWidths(columns, containerWidth, actionColumnsWidth, getResizedColumnWidth) {
31
- const widthMap = new Map();
32
- // If container width is not available yet, return empty map
33
- if (containerWidth <= 0) {
34
- return widthMap;
35
- }
36
- // Available width for data columns
37
- const availableWidth = containerWidth - actionColumnsWidth;
38
- if (availableWidth <= 0) {
39
- return widthMap;
40
- }
41
- // First pass: identify columns with explicit width and calculate total fixed width
42
- let totalFixedWidth = 0;
43
- const flexColumns = [];
44
- columns.forEach((column) => {
45
- const resizedWidth = getResizedColumnWidth === null || getResizedColumnWidth === void 0 ? void 0 : getResizedColumnWidth(column.key);
46
- if (resizedWidth !== undefined) {
47
- // Column has been resized, use that width
48
- widthMap.set(column.key, resizedWidth);
49
- totalFixedWidth += resizedWidth;
50
- }
51
- else if (column.width !== undefined) {
52
- // Column has explicit width
53
- const width = clampWidth(column.width, column.minWidth, column.maxWidth);
54
- widthMap.set(column.key, width);
55
- totalFixedWidth += width;
56
- }
57
- else {
58
- // Column needs flex width calculation
59
- flexColumns.push(column);
60
- }
61
- });
62
- // Second pass: distribute remaining width to flex columns
63
- if (flexColumns.length > 0) {
64
- const remainingWidth = availableWidth - totalFixedWidth;
65
- // Calculate flex widths while respecting min/max constraints
66
- // This may require multiple iterations if constraints cause redistribution
67
- let iterationCount = 0;
68
- const maxIterations = flexColumns.length + 1;
69
- let unallocatedWidth = remainingWidth;
70
- const pendingColumns = [...flexColumns];
71
- while (pendingColumns.length > 0 && iterationCount < maxIterations) {
72
- iterationCount += 1;
73
- const flexWidth = unallocatedWidth / pendingColumns.length;
74
- const stillPending = [];
75
- pendingColumns.forEach((column) => {
76
- const clampedWidth = clampWidth(flexWidth, column.minWidth, column.maxWidth);
77
- if (clampedWidth !== flexWidth) {
78
- // Width was clamped, allocate this column and redistribute
79
- widthMap.set(column.key, clampedWidth);
80
- unallocatedWidth -= clampedWidth;
81
- }
82
- else {
83
- stillPending.push(column);
84
- }
85
- });
86
- // If no columns were allocated in this iteration, allocate all remaining
87
- if (stillPending.length === pendingColumns.length) {
88
- stillPending.forEach((column) => {
89
- const finalWidth = Math.max(0, unallocatedWidth / stillPending.length);
90
- widthMap.set(column.key, finalWidth);
91
- });
92
- break;
93
- }
94
- pendingColumns.length = 0;
95
- pendingColumns.push(...stillPending);
96
- }
97
- }
98
- return widthMap;
99
- }
100
- /**
101
- * Clamp a width value between min and max bounds
102
- */
103
- function clampWidth(width, minWidth, maxWidth) {
104
- let result = width;
105
- if (minWidth !== undefined && result < minWidth) {
106
- result = minWidth;
107
- }
108
- if (maxWidth !== undefined && result > maxWidth) {
109
- result = maxWidth;
110
- }
111
- return result;
112
- }
113
8
  const TableColGroupInner = memo(function TableColGroup(props) {
114
9
  const { className } = props;
115
- const { columnState, columns, draggable, expansion, isInsideExpandedContentArea, selection, } = useTableContext();
10
+ const { columnState, draggable, expansion, isInsideExpandedContentArea, selection, } = useTableContext();
11
+ const { columns } = useTableDataContext();
116
12
  const { containerWidth, getResizedColumnWidth: getParentResizedColumnWidth } = useTableSuperContext();
117
13
  // For nested tables, use parent's resized widths; for root tables, use own
118
14
  const getResizedColumnWidth = isInsideExpandedContentArea
@@ -136,7 +32,12 @@ const TableColGroupInner = memo(function TableColGroup(props) {
136
32
  if (!enableWidthCalculation) {
137
33
  return new Map();
138
34
  }
139
- return calculateColumnWidths(columns, containerWidth !== null && containerWidth !== void 0 ? containerWidth : 0, actionColumnsWidth, getResizedColumnWidth);
35
+ return calculateColumnWidths({
36
+ actionColumnsWidth,
37
+ columns,
38
+ containerWidth: containerWidth !== null && containerWidth !== void 0 ? containerWidth : 0,
39
+ getResizedColumnWidth,
40
+ });
140
41
  }, [
141
42
  enableWidthCalculation,
142
43
  columns,
@@ -146,7 +47,6 @@ const TableColGroupInner = memo(function TableColGroup(props) {
146
47
  ]);
147
48
  const renderCols = () => {
148
49
  const cols = [];
149
- // Drag handle column (must be first)
150
50
  if (draggable === null || draggable === void 0 ? void 0 : draggable.enabled) {
151
51
  cols.push(jsx("col", { className: tableClasses.dragHandleCell, style: {
152
52
  maxWidth: DRAG_HANDLE_COLUMN_WIDTH,
@@ -154,7 +54,6 @@ const TableColGroupInner = memo(function TableColGroup(props) {
154
54
  width: DRAG_HANDLE_COLUMN_WIDTH,
155
55
  } }, DRAG_HANDLE_KEY));
156
56
  }
157
- // Expand column
158
57
  if (expansion) {
159
58
  cols.push(jsx("col", { className: tableClasses.expandCell, style: {
160
59
  maxWidth: EXPANSION_COLUMN_WIDTH,
@@ -162,7 +61,6 @@ const TableColGroupInner = memo(function TableColGroup(props) {
162
61
  width: EXPANSION_COLUMN_WIDTH,
163
62
  } }, EXPANSION_KEY));
164
63
  }
165
- // Selection column
166
64
  if (selection) {
167
65
  cols.push(jsx("col", { className: tableClasses.selectionColumn, style: {
168
66
  maxWidth: SELECTION_COLUMN_WIDTH,
@@ -0,0 +1,6 @@
1
+ import { TableColumn } from '@mezzanine-ui/core/table';
2
+ interface TableColumnTitleMenuProps {
3
+ column: TableColumn;
4
+ }
5
+ declare function TableColumnTitleMenu(props: TableColumnTitleMenuProps): import("react/jsx-runtime").JSX.Element | null;
6
+ export default TableColumnTitleMenu;