@snack-uikit/table 0.31.1 → 0.32.0

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 (71) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +2 -0
  3. package/dist/cjs/components/Table/Table.d.ts +1 -1
  4. package/dist/cjs/components/Table/Table.js +101 -101
  5. package/dist/cjs/components/Table/styles.module.css +4 -3
  6. package/dist/cjs/components/types.d.ts +1 -0
  7. package/dist/cjs/helperComponents/Cells/BodyCell/BodyCell.d.ts +2 -1
  8. package/dist/cjs/helperComponents/Cells/BodyCell/BodyCell.js +4 -2
  9. package/dist/cjs/helperComponents/Cells/BodyCell/styles.module.css +8 -2
  10. package/dist/cjs/helperComponents/Cells/CopyCell/CopyCell.js +1 -1
  11. package/dist/cjs/helperComponents/Cells/HeaderCell/HeaderCell.d.ts +2 -1
  12. package/dist/cjs/helperComponents/Cells/HeaderCell/HeaderCell.js +4 -2
  13. package/dist/cjs/helperComponents/Cells/HeaderCell/styles.module.css +10 -1
  14. package/dist/cjs/helperComponents/Cells/StatusCell/styles.module.css +3 -3
  15. package/dist/cjs/helperComponents/Cells/TreeCell/TreeCell.d.ts +1 -1
  16. package/dist/cjs/helperComponents/Cells/TreeCell/TreeCell.js +28 -30
  17. package/dist/cjs/helperComponents/Cells/TreeCell/TreeLine/styles.module.css +2 -2
  18. package/dist/cjs/helperComponents/Cells/TreeCell/styles.module.css +16 -34
  19. package/dist/cjs/helperComponents/Rows/BodyRow.d.ts +3 -2
  20. package/dist/cjs/helperComponents/Rows/BodyRow.js +9 -4
  21. package/dist/cjs/helperComponents/Rows/HeaderRow.d.ts +2 -1
  22. package/dist/cjs/helperComponents/Rows/HeaderRow.js +11 -4
  23. package/dist/cjs/helperComponents/Rows/Row.d.ts +3 -3
  24. package/dist/cjs/helperComponents/Rows/Row.js +4 -2
  25. package/dist/cjs/helperComponents/Rows/styles.module.css +14 -6
  26. package/dist/cjs/helperComponents/TableEmptyState/styles.module.css +1 -1
  27. package/dist/esm/components/Table/Table.d.ts +1 -1
  28. package/dist/esm/components/Table/Table.js +15 -17
  29. package/dist/esm/components/Table/styles.module.css +4 -3
  30. package/dist/esm/components/types.d.ts +1 -0
  31. package/dist/esm/helperComponents/Cells/BodyCell/BodyCell.d.ts +2 -1
  32. package/dist/esm/helperComponents/Cells/BodyCell/BodyCell.js +2 -2
  33. package/dist/esm/helperComponents/Cells/BodyCell/styles.module.css +8 -2
  34. package/dist/esm/helperComponents/Cells/CopyCell/CopyCell.js +1 -1
  35. package/dist/esm/helperComponents/Cells/HeaderCell/HeaderCell.d.ts +2 -1
  36. package/dist/esm/helperComponents/Cells/HeaderCell/HeaderCell.js +2 -2
  37. package/dist/esm/helperComponents/Cells/HeaderCell/styles.module.css +10 -1
  38. package/dist/esm/helperComponents/Cells/StatusCell/styles.module.css +3 -3
  39. package/dist/esm/helperComponents/Cells/TreeCell/TreeCell.d.ts +1 -1
  40. package/dist/esm/helperComponents/Cells/TreeCell/TreeCell.js +26 -28
  41. package/dist/esm/helperComponents/Cells/TreeCell/TreeLine/TreeLine.js +2 -2
  42. package/dist/esm/helperComponents/Cells/TreeCell/TreeLine/styles.module.css +2 -2
  43. package/dist/esm/helperComponents/Cells/TreeCell/styles.module.css +16 -34
  44. package/dist/esm/helperComponents/Rows/BodyRow.d.ts +3 -2
  45. package/dist/esm/helperComponents/Rows/BodyRow.js +2 -2
  46. package/dist/esm/helperComponents/Rows/HeaderRow.d.ts +2 -1
  47. package/dist/esm/helperComponents/Rows/HeaderRow.js +2 -2
  48. package/dist/esm/helperComponents/Rows/Row.d.ts +3 -3
  49. package/dist/esm/helperComponents/Rows/Row.js +2 -2
  50. package/dist/esm/helperComponents/Rows/styles.module.css +14 -6
  51. package/dist/esm/helperComponents/TableEmptyState/styles.module.css +1 -1
  52. package/package.json +2 -2
  53. package/src/components/Table/Table.tsx +110 -117
  54. package/src/components/Table/styles.module.scss +4 -8
  55. package/src/components/types.ts +3 -0
  56. package/src/helperComponents/Cells/BodyCell/BodyCell.tsx +3 -1
  57. package/src/helperComponents/Cells/BodyCell/styles.module.scss +6 -1
  58. package/src/helperComponents/Cells/CopyCell/CopyCell.tsx +1 -1
  59. package/src/helperComponents/Cells/CopyCell/styles.module.scss +1 -1
  60. package/src/helperComponents/Cells/HeaderCell/HeaderCell.tsx +8 -2
  61. package/src/helperComponents/Cells/HeaderCell/styles.module.scss +9 -0
  62. package/src/helperComponents/Cells/StatusCell/styles.module.scss +9 -7
  63. package/src/helperComponents/Cells/TreeCell/TreeCell.tsx +51 -42
  64. package/src/helperComponents/Cells/TreeCell/TreeLine/TreeLine.tsx +2 -2
  65. package/src/helperComponents/Cells/TreeCell/TreeLine/styles.module.scss +8 -8
  66. package/src/helperComponents/Cells/TreeCell/styles.module.scss +36 -55
  67. package/src/helperComponents/Rows/BodyRow.tsx +7 -6
  68. package/src/helperComponents/Rows/HeaderRow.tsx +15 -6
  69. package/src/helperComponents/Rows/Row.tsx +10 -3
  70. package/src/helperComponents/Rows/styles.module.scss +30 -19
  71. package/src/helperComponents/TableEmptyState/styles.module.scss +1 -1
@@ -24,16 +24,18 @@ export function getTreeColumnDef({ showToggle = false, icon = _jsx(FileSVG, { si
24
24
  skipOnExport: false,
25
25
  },
26
26
  enableSorting: false,
27
- header: header,
28
- cell: function Cell({ row, cell }) {
27
+ header,
28
+ cell: function TreeCell({ row, cell }) {
29
+ var _a;
29
30
  const isExpanded = row.getIsExpanded();
30
31
  const isExpandable = row.getCanExpand();
31
32
  const isMultiSelect = row.getCanMultiSelect();
32
33
  const parent = row.getParentRow();
33
34
  const isRowsSelectionEnabled = row.getCanSelect();
34
- const isAlSubRowsSelected = row.getIsAllSubRowsSelected();
35
+ const isAllSubRowsSelected = row.getIsAllSubRowsSelected();
35
36
  const isSomeSubRowSelected = row.getIsSomeSelected();
36
37
  const isRowSelected = row.getIsSelected();
38
+ const isLastChildRow = ((_a = parent === null || parent === void 0 ? void 0 : parent.subRows.at(-1)) === null || _a === void 0 ? void 0 : _a.id) === row.id;
37
39
  const depth = row.depth;
38
40
  const { ref } = useCellResize(TREE_CELL_ID, cell);
39
41
  const linesVisibilityByIndex = useMemo(() => {
@@ -50,42 +52,38 @@ export function getTreeColumnDef({ showToggle = false, icon = _jsx(FileSVG, { si
50
52
  return (child === null || child === void 0 ? void 0 : child.id) !== ((_a = parent.subRows.at(-1)) === null || _a === void 0 ? void 0 : _a.id) || (row === null || row === void 0 ? void 0 : row.id) === (child === null || child === void 0 ? void 0 : child.id);
51
53
  });
52
54
  }, [row, depth]);
53
- const lines = new Array(depth)
54
- .fill('')
55
- .map((_, index) => (_jsx(TreeLine, { visible: linesVisibilityByIndex.at(index), className: index !== 0 ? styles.line : styles.firstLine }, index)));
55
+ const lines = useMemo(() => Array.from({ length: depth }, (_, index) => (_jsx(TreeLine, { visible: linesVisibilityByIndex.at(index), className: index !== 0 ? styles.line : styles.firstLine, halfHeight: index === depth - 1 && isLastChildRow }, index))), [depth, linesVisibilityByIndex, isLastChildRow]);
56
56
  useEffect(() => {
57
- if (!isMultiSelect || !isExpandable) {
57
+ if (!isMultiSelect || !isExpandable || !isRowsSelectionEnabled) {
58
58
  return;
59
59
  }
60
- if (isAlSubRowsSelected && !isRowSelected) {
60
+ if (isAllSubRowsSelected && !isRowSelected) {
61
61
  row.toggleSelected(true, { selectChildren: false });
62
62
  return;
63
63
  }
64
- if (!isAlSubRowsSelected && isRowSelected && !isSomeSubRowSelected) {
64
+ if (isRowSelected && !isAllSubRowsSelected && isSomeSubRowSelected) {
65
65
  row.toggleSelected(false, { selectChildren: false });
66
66
  return;
67
67
  }
68
- }, [isAlSubRowsSelected, isSomeSubRowSelected, row, isRowSelected, isMultiSelect, isExpandable]);
69
- const recursiveToggleSubRows = useCallback((row, value, opts) => {
70
- row.toggleSelected(value, opts);
71
- if (row.subRows.length > 0) {
72
- row.subRows.forEach(subRow => {
73
- recursiveToggleSubRows(subRow, value, opts);
74
- });
75
- }
76
- }, []);
77
- const toggleClickHandler = useCallback((event) => {
68
+ }, [
69
+ isAllSubRowsSelected,
70
+ isSomeSubRowSelected,
71
+ row,
72
+ isRowSelected,
73
+ isMultiSelect,
74
+ isExpandable,
75
+ isRowsSelectionEnabled,
76
+ ]);
77
+ const toggleClickHandler = useCallback(event => {
78
78
  event.stopPropagation();
79
- if (isMultiSelect && isSomeSubRowSelected && !isRowSelected) {
80
- recursiveToggleSubRows(row, false, { selectChildren: true });
81
- return;
82
- }
83
- if (!isMultiSelect) {
84
- row.toggleSelected(!isRowSelected, { selectChildren: false });
79
+ if (isMultiSelect) {
80
+ const shouldToggleOn = !isAllSubRowsSelected && !isRowSelected;
81
+ const selectChildren = isAllSubRowsSelected || isSomeSubRowSelected || shouldToggleOn;
82
+ row.toggleSelected(shouldToggleOn, { selectChildren });
85
83
  return;
86
84
  }
87
- row.toggleSelected();
88
- }, [isRowSelected, row, isSomeSubRowSelected, isMultiSelect, recursiveToggleSubRows]);
85
+ row.toggleSelected(!isRowSelected, { selectChildren: false });
86
+ }, [isMultiSelect, row, isAllSubRowsSelected, isSomeSubRowSelected, isRowSelected]);
89
87
  const chevronClickHandler = useCallback(event => {
90
88
  event.stopPropagation();
91
89
  row.toggleExpanded();
@@ -95,7 +93,7 @@ export function getTreeColumnDef({ showToggle = false, icon = _jsx(FileSVG, { si
95
93
  // @ts-ignore
96
94
  cell.row.original[accessorKey]
97
95
  : cell.getValue();
98
- return (_jsx("div", { role: 'presentation', "data-test-id": TEST_IDS.tree.node, className: styles.treeCellContainer, onClick: toggleClickHandler, children: _jsxs("div", { className: styles.treeCell, ref: ref, children: [lines, Boolean(parent) && _jsx(TreeLine, { horizontal: true, visible: true }), isExpandable && (_jsx(ButtonFunction, { size: 'xs', "data-test-id": TEST_IDS.tree.chevron, icon: _jsx(ChevronRightSVG, {}), onClick: chevronClickHandler, className: styles.cellExpandButton, "data-expanded": isExpanded || undefined })), _jsxs("div", { className: styles.treeNodeContent, children: [showToggle && (_jsx("div", { tabIndex: -1, className: styles.treeCheckboxWrap, children: isMultiSelect ? (_jsx(Checkbox, { size: 's', disabled: !isRowsSelectionEnabled, checked: isRowSelected, "data-test-id": TEST_IDS.tree.checkbox, indeterminate: isSomeSubRowSelected && !isAlSubRowsSelected })) : (_jsx(Radio, { size: 's', disabled: !isRowsSelectionEnabled, "data-test-id": TEST_IDS.tree.radio, checked: isRowSelected })) })), _jsxs("div", { role: 'presentation', onClick: chevronClickHandler, className: styles.cellUserToggleIcon, children: [isExpandable && isExpanded && expandedIcon, isExpandable && !isExpanded && collapsedIcon] }), _jsxs("div", { role: 'presentation', className: styles.userContent, children: [!isExpandable && icon, _jsx(TruncateString, { text: value })] })] })] }) }));
96
+ return (_jsx("div", { role: 'presentation', "data-test-id": TEST_IDS.tree.node, className: styles.treeCellContainer, onClick: toggleClickHandler, children: _jsxs("div", { className: styles.treeCell, ref: ref, children: [lines, Boolean(parent) && _jsx(TreeLine, { horizontal: true, visible: true }), isExpandable && (_jsx(ButtonFunction, { size: 'xs', "data-test-id": TEST_IDS.tree.chevron, icon: _jsx(ChevronRightSVG, {}), onClick: chevronClickHandler, className: styles.cellExpandButton, "data-expanded": isExpanded || undefined })), _jsxs("div", { className: styles.treeNodeContent, "data-disabled": !isRowsSelectionEnabled || undefined, "data-selected": isRowSelected || undefined, "data-multiselect": isMultiSelect || undefined, children: [showToggle && (_jsx("div", { tabIndex: -1, className: styles.treeCheckboxWrap, children: isMultiSelect ? (_jsx(Checkbox, { size: 's', disabled: !isRowsSelectionEnabled, checked: isRowSelected, "data-test-id": TEST_IDS.tree.checkbox, indeterminate: isSomeSubRowSelected && !isAllSubRowsSelected })) : (_jsx(Radio, { size: 's', disabled: !isRowsSelectionEnabled, "data-test-id": TEST_IDS.tree.radio, checked: isRowSelected })) })), _jsxs("div", { role: 'presentation', onClick: chevronClickHandler, className: styles.cellUserToggleIcon, children: [isExpandable && isExpanded && expandedIcon, isExpandable && !isExpanded && collapsedIcon] }), _jsxs("div", { role: 'presentation', className: styles.userContent, children: [!isExpandable && icon, _jsx(TruncateString, { text: value })] })] })] }) }));
99
97
  },
100
98
  };
101
99
  }
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import classNames from 'classnames';
2
+ import cn from 'classnames';
3
3
  import styles from './styles.module.css';
4
4
  export function TreeLine({ halfHeight, horizontal, visible, className }) {
5
- return (_jsx("div", { className: classNames(styles.treeLine, className), "data-horizontal": horizontal || undefined, "data-half-height": halfHeight || undefined, "data-visible": visible || undefined }));
5
+ return (_jsx("div", { className: cn(styles.treeLine, className), "data-horizontal": horizontal || undefined, "data-half-height": halfHeight || undefined, "data-visible": visible || undefined }));
6
6
  }
@@ -1,6 +1,6 @@
1
1
  .treeLine{
2
2
  width:1px;
3
- height:var(--size-markdown-table-cell-height, 40px);
3
+ height:100%;
4
4
  opacity:0;
5
5
  }
6
6
  .treeLine[data-visible]{
@@ -9,7 +9,7 @@
9
9
  }
10
10
  .treeLine[data-half-height]{
11
11
  align-self:start;
12
- height:calc(var(--size-markdown-table-cell-height, 40px) / 2);
12
+ height:50%;
13
13
  }
14
14
  .treeLine[data-horizontal]{
15
15
  width:calc(var(--size-markdown-table-cell-height, 40px) / 2);
@@ -1,21 +1,29 @@
1
+ .treeCellContainer{
2
+ position:relative;
3
+ overflow:hidden;
4
+ height:100%;
5
+ font-family:var(--sans-body-m-font-family, SB Sans Interface);
6
+ font-weight:var(--sans-body-m-font-weight, Regular);
7
+ line-height:var(--sans-body-m-line-height, 20px);
8
+ font-size:var(--sans-body-m-font-size, 14px);
9
+ letter-spacing:var(--sans-body-m-letter-spacing, 0.1px);
10
+ paragraph-spacing:var(--sans-body-m-paragraph-spacing, 7.7px);
11
+ }
12
+
1
13
  .treeCell{
2
14
  display:flex;
3
15
  align-items:center;
4
16
  justify-content:start;
5
17
  width:-moz-fit-content;
6
18
  width:fit-content;
7
- height:var(--size-markdown-table-cell-height, 40px);
19
+ height:100%;
8
20
  }
9
21
 
10
22
  .cellUserToggleIcon{
11
- cursor:pointer;
12
23
  display:flex;
13
24
  align-items:center;
14
25
  box-sizing:border-box;
15
26
  }
16
- .cellUserToggleIcon svg{
17
- color:var(--sys-neutral-text-support, #6d707f);
18
- }
19
27
 
20
28
  .treeNodeContent{
21
29
  gap:var(--space-tree-item-content-layout-gap, 4px);
@@ -29,7 +37,8 @@
29
37
  display:flex;
30
38
  align-items:center;
31
39
  box-sizing:border-box;
32
- height:var(--size-markdown-table-cell-height, 40px);
40
+ height:100%;
41
+ color:var(--sys-neutral-text-support, #6d707f);
33
42
  }
34
43
  .treeNodeContent:focus-visible{
35
44
  outline-width:var(--border-state-focus-s-border-width, 2px);
@@ -41,42 +50,15 @@
41
50
  .treeNodeContent[data-multiselect]{
42
51
  cursor:default;
43
52
  }
44
- .treeNodeContent[aria-disabled=true]{
53
+ .treeNodeContent[data-disabled]{
45
54
  cursor:not-allowed;
46
- }
47
- .treeNodeContent[aria-disabled=true]::before{
48
- display:none;
49
- }
50
- .treeNodeContent[aria-disabled=true] .treeNodeTitle, .treeNodeContent[aria-disabled=true] .treeNodeIcon{
51
55
  color:var(--sys-neutral-text-disabled, #aaaebd);
52
56
  }
53
- .treeNodeContent[aria-selected=true]:not([data-multiselect]){
54
- opacity:var(--opacity-a008, 0.08);
55
- background-color:var(--sys-primary-accent-default, #794ed3);
56
- }
57
- .treeNodeContent[aria-selected=true]:not([data-multiselect]):hover{
58
- opacity:var(--opacity-a016, 0.16);
59
- }
60
57
 
61
58
  .userContent{
62
- cursor:pointer;
63
59
  display:flex;
64
60
  align-items:center;
65
61
  }
66
- .userContent svg{
67
- color:var(--sys-neutral-text-support, #6d707f);
68
- }
69
-
70
- .treeCellContainer{
71
- position:relative;
72
- overflow:hidden;
73
- font-family:var(--sans-body-m-font-family, SB Sans Interface);
74
- font-weight:var(--sans-body-m-font-weight, Regular);
75
- line-height:var(--sans-body-m-line-height, 20px);
76
- font-size:var(--sans-body-m-font-size, 14px);
77
- letter-spacing:var(--sans-body-m-letter-spacing, 0.1px);
78
- paragraph-spacing:var(--sans-body-m-paragraph-spacing, 7.7px);
79
- }
80
62
 
81
63
  .line{
82
64
  margin-left:calc(var(--dimension-4m, 32px) + var(--dimension-025m, 2px));
@@ -1,5 +1,6 @@
1
1
  import { Row as TableRow } from '@tanstack/react-table';
2
2
  import { MouseEvent } from 'react';
3
+ import { RowProps } from './Row';
3
4
  export type RowInfo<TData> = {
4
5
  id: string;
5
6
  data: TData;
@@ -7,8 +8,8 @@ export type RowInfo<TData> = {
7
8
  toggleSelected(value?: boolean): void;
8
9
  };
9
10
  export type RowClickHandler<TData> = (e: MouseEvent<HTMLDivElement>, row: RowInfo<TData>) => void;
10
- export type BodyRowProps<TData> = {
11
+ export type BodyRowProps<TData> = Pick<RowProps, 'rowAutoHeight'> & {
11
12
  row: TableRow<TData>;
12
13
  onRowClick?: RowClickHandler<TData>;
13
14
  };
14
- export declare function BodyRow<TData>({ row, onRowClick }: BodyRowProps<TData>): import("react/jsx-runtime").JSX.Element;
15
+ export declare function BodyRow<TData>({ row, onRowClick, rowAutoHeight }: BodyRowProps<TData>): import("react/jsx-runtime").JSX.Element;
@@ -7,7 +7,7 @@ import { useRowCells } from '../hooks';
7
7
  import { PinnedCells } from './PinnedCells';
8
8
  import { Row } from './Row';
9
9
  import styles from './styles.module.css';
10
- export function BodyRow({ row, onRowClick }) {
10
+ export function BodyRow({ row, onRowClick, rowAutoHeight }) {
11
11
  const { pinnedLeft, pinnedRight, unpinned } = useRowCells(row);
12
12
  const [dropListOpened, setDropListOpen] = useState(false);
13
13
  const disabled = !row.getCanSelect();
@@ -23,5 +23,5 @@ export function BodyRow({ row, onRowClick }) {
23
23
  };
24
24
  return (_jsx(RowContext.Provider, { value: { dropListOpened, setDropListOpen }, children: _jsxs(Row, { onClick: handleRowClick, "data-clickable": Boolean(onRowClick) || undefined, "data-disabled": disabled || undefined, "data-selected": row.getIsSelected() ||
25
25
  (row.getIsSomeSelected() && !row.getCanMultiSelect() && !row.getIsExpanded()) ||
26
- undefined, "data-actions-opened": dropListOpened || undefined, "data-test-id": TEST_IDS.bodyRow, "data-row-id": row.id, className: styles.bodyRow, children: [pinnedLeft && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Left, children: pinnedLeft.map(cell => (_jsx(BodyCell, { cell: cell }, cell.id))) })), unpinned.map(cell => (_jsx(BodyCell, { cell: cell }, cell.id))), pinnedRight && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Right, children: pinnedRight.map(cell => (_jsx(BodyCell, { cell: cell }, cell.id))) }))] }) }));
26
+ undefined, "data-actions-opened": dropListOpened || undefined, "data-test-id": TEST_IDS.bodyRow, "data-row-id": row.id, className: styles.bodyRow, rowAutoHeight: rowAutoHeight, children: [pinnedLeft && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Left, children: pinnedLeft.map(cell => (_jsx(BodyCell, { cell: cell, rowAutoHeight: rowAutoHeight }, cell.id))) })), unpinned.map(cell => (_jsx(BodyCell, { cell: cell, rowAutoHeight: rowAutoHeight }, cell.id))), pinnedRight && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Right, children: pinnedRight.map(cell => (_jsx(BodyCell, { cell: cell, rowAutoHeight: rowAutoHeight }, cell.id))) }))] }) }));
27
27
  }
@@ -1 +1,2 @@
1
- export declare function HeaderRow(): import("react/jsx-runtime").JSX.Element;
1
+ import { RowProps } from './Row';
2
+ export declare function HeaderRow({ rowAutoHeight }: Pick<RowProps, 'rowAutoHeight'>): import("react/jsx-runtime").JSX.Element;
@@ -5,7 +5,7 @@ import { useHeaderGroups } from '../hooks';
5
5
  import { PinnedCells } from './PinnedCells';
6
6
  import { Row } from './Row';
7
7
  import styles from './styles.module.css';
8
- export function HeaderRow() {
8
+ export function HeaderRow({ rowAutoHeight }) {
9
9
  const { leftPinned, unpinned, rightPinned } = useHeaderGroups();
10
- return (_jsxs(Row, { className: styles.tableHeader, "data-test-id": TEST_IDS.headerRow, children: [leftPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Left, children: leftPinned.map(headerGroup => headerGroup.headers.map(header => header.isPlaceholder ? null : _jsx(HeaderCell, { header: header }, header.id))) })), unpinned.map(headerGroup => headerGroup.headers.map(header => _jsx(HeaderCell, { header: header }, header.id))), rightPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Right, children: rightPinned.map(headerGroup => headerGroup.headers.map(header => header.isPlaceholder ? null : (_jsx(HeaderCell, { header: header, pinPosition: COLUMN_PIN_POSITION.Right }, header.id)))) }))] }));
10
+ return (_jsxs(Row, { className: styles.tableHeader, "data-test-id": TEST_IDS.headerRow, rowAutoHeight: rowAutoHeight, children: [leftPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Left, children: leftPinned.map(headerGroup => headerGroup.headers.map(header => header.isPlaceholder ? null : (_jsx(HeaderCell, { header: header, rowAutoHeight: rowAutoHeight }, header.id)))) })), unpinned.map(headerGroup => headerGroup.headers.map(header => _jsx(HeaderCell, { header: header, rowAutoHeight: rowAutoHeight }, header.id))), rightPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Right, children: rightPinned.map(headerGroup => headerGroup.headers.map(header => header.isPlaceholder ? null : (_jsx(HeaderCell, { header: header, pinPosition: COLUMN_PIN_POSITION.Right, rowAutoHeight: rowAutoHeight }, header.id)))) }))] }));
11
11
  }
@@ -1,9 +1,9 @@
1
1
  import { MouseEvent, ReactNode } from 'react';
2
2
  import { DataAttributes } from '../types';
3
- type RowProps = {
3
+ export type RowProps = {
4
4
  children: ReactNode;
5
5
  onClick?(e: MouseEvent<HTMLDivElement>): void;
6
6
  className?: string;
7
+ rowAutoHeight?: boolean;
7
8
  } & DataAttributes;
8
- export declare function Row({ onClick, children, className, ...attributes }: RowProps): import("react/jsx-runtime").JSX.Element;
9
- export {};
9
+ export declare function Row({ onClick, children, className, rowAutoHeight, ...attributes }: RowProps): import("react/jsx-runtime").JSX.Element;
@@ -13,8 +13,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
13
13
  import cn from 'classnames';
14
14
  import styles from './styles.module.css';
15
15
  export function Row(_a) {
16
- var { onClick, children, className } = _a, attributes = __rest(_a, ["onClick", "children", "className"]);
16
+ var { onClick, children, className, rowAutoHeight } = _a, attributes = __rest(_a, ["onClick", "children", "className", "rowAutoHeight"]);
17
17
  return (
18
18
  // eslint-disable-next-line jsx-a11y/interactive-supports-focus
19
- _jsx("div", Object.assign({ onClick: onClick, className: cn(styles.tableRow, className), role: 'row' }, attributes, { children: children })));
19
+ _jsx("div", Object.assign({ onClick: onClick, className: cn(styles.tableRow, className), "data-auto-height": rowAutoHeight || undefined, role: 'row' }, attributes, { children: children })));
20
20
  }
@@ -1,14 +1,19 @@
1
1
  .tableRow{
2
2
  --snack-ui-table-row-background:var(--sys-neutral-background1-level, #fdfdfd);
3
- height:var(--size-table-line-height, 40px);
4
3
  border-top:var(--border-width-table, 1px);
5
4
  border-bottom:var(--border-width-table, 1px);
5
+ min-height:var(--size-table-line-height, 40px);
6
6
  position:relative;
7
7
  display:flex;
8
8
  box-sizing:border-box;
9
- border-color:transparent;
10
9
  background-color:var(--snack-ui-table-row-background);
10
+ border-color:transparent;
11
11
  border-style:solid none;
12
+ height:var(--size-table-line-height, 40px);
13
+ }
14
+ .tableRow[data-auto-height]{
15
+ height:auto;
16
+ min-height:var(--size-table-line-height, 40px);
12
17
  }
13
18
 
14
19
  .rowPinnedCells{
@@ -49,16 +54,13 @@
49
54
  .bodyRow ~ .bodyRow:before{
50
55
  content:"";
51
56
  position:absolute;
57
+ z-index:2;
52
58
  top:calc(-1 * var(--border-width-table, 1px));
53
59
  left:0;
54
- z-index:2;
55
60
  width:100%;
56
61
  height:var(--border-width-table-line, 0.5px);
57
62
  background-color:var(--sys-neutral-decor-disabled, #e6e8ef);
58
63
  }
59
- .bodyRow:hover::before, .bodyRow:hover + .bodyRow::before{
60
- height:0;
61
- }
62
64
  .bodyRow[data-disabled]{
63
65
  cursor:not-allowed;
64
66
  background-color:var(--sys-neutral-background, #eeeff3);
@@ -84,6 +86,9 @@
84
86
  .bodyRow[data-clickable]{
85
87
  cursor:pointer;
86
88
  }
89
+ .bodyRow:not([data-disabled]):hover::before{
90
+ height:0;
91
+ }
87
92
  .bodyRow:not([data-disabled]):not([data-selected]):hover, .bodyRow:not([data-disabled]):not([data-selected])[data-actions-opened]{
88
93
  background-color:color-mix(in srgb, var(--sys-neutral-accent-default, #787b8a), var(--snack-ui-table-row-background) calc((1 - var(--opacity-a008, 0.08)) * 100%));
89
94
  border-color:var(--sys-neutral-decor-hovered, #cfd2dc);
@@ -92,6 +97,9 @@
92
97
  background-color:color-mix(in srgb, var(--sys-neutral-accent-default, #787b8a), var(--snack-ui-table-row-background) calc((1 - var(--opacity-a008, 0.08)) * 100%));
93
98
  border-color:inherit;
94
99
  }
100
+ .bodyRow:not([data-disabled]):hover + .bodyRow::before{
101
+ height:0;
102
+ }
95
103
 
96
104
  .tableHeader{
97
105
  position:sticky;
@@ -4,6 +4,6 @@
4
4
  align-items:center;
5
5
  justify-content:center;
6
6
  box-sizing:border-box;
7
- height:calc(var(--page-size, 10) * var(--size-table-line-height, 40px) + var(--size-table-line-height, 40px));
7
+ height:var(--size-table-information-min-height, 304px);
8
8
  padding:var(--dimension-3m, 24px);
9
9
  }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Table",
7
- "version": "0.31.1",
7
+ "version": "0.32.0",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -61,5 +61,5 @@
61
61
  "peerDependencies": {
62
62
  "@snack-uikit/locale": "*"
63
63
  },
64
- "gitHead": "b7485df8da9869f0fe2b2e22974a06d9a04e0835"
64
+ "gitHead": "3c671e7c832a7d1c30dc4e1eed74c8b8160bd90c"
65
65
  }
@@ -98,6 +98,7 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
98
98
  savedState,
99
99
  expanding,
100
100
  bulkActions: bulkActionsProp,
101
+ rowAutoHeight,
101
102
  ...rest
102
103
  }: TableProps<TData, TFilters>) {
103
104
  const { state: globalFilter, onStateChange: onGlobalFilterChange } = useStateControl<string>(search, '');
@@ -174,7 +175,13 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
174
175
  enableSorting: false,
175
176
  enableResizing: false,
176
177
  minSize: 40,
177
- cell: (cell: CellContext<TData, unknown>) => <TruncateString text={String(cell.getValue())} maxLines={1} />,
178
+ cell: (cell: CellContext<TData, unknown>) => {
179
+ if (rowAutoHeight) {
180
+ return cell.getValue();
181
+ }
182
+
183
+ return <TruncateString text={String(cell.getValue())} maxLines={1} />;
184
+ },
178
185
  },
179
186
 
180
187
  manualSorting,
@@ -336,7 +343,6 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
336
343
  const tableFilteredRowsIds = tableFilteredRows.map(row => row.id);
337
344
  const topRows = table.getTopRows();
338
345
  const loadingTableRows = loadingTable.getRowModel().rows;
339
- const tablePagination = table.getState().pagination;
340
346
 
341
347
  const filteredTopRows = table.getState().globalFilter
342
348
  ? topRows.filter(tr => tableFilteredRowsIds.includes(tr.id))
@@ -346,12 +352,6 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
346
352
  const { t } = useLocale('Table');
347
353
  const emptyStates = useEmptyState({ noDataState, noResultsState, errorDataState });
348
354
 
349
- const cssPageSize = useMemo(() => {
350
- const tempPageSize = (!suppressPagination ? tablePagination?.pageSize : pageSize) + filteredTopRows.length;
351
-
352
- return !tableRows.length ? Math.min(Math.max(tempPageSize, 5), DEFAULT_PAGE_SIZE) : tempPageSize;
353
- }, [filteredTopRows.length, pageSize, suppressPagination, tablePagination?.pageSize, tableRows.length]);
354
-
355
355
  usePageReset({
356
356
  manualPagination,
357
357
  maximumAvailablePage: pageCount || tableFilteredRows.length / pagination.pageSize,
@@ -365,118 +365,111 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
365
365
  const showToolbar = !suppressToolbar;
366
366
 
367
367
  return (
368
- <CellAutoResizeContext.Provider value={{ updateCellMap }}>
369
- <div
370
- style={{
371
- '--page-size': cssPageSize,
372
- }}
373
- className={cn(styles.wrapper, className)}
374
- {...extractSupportProps(rest)}
375
- >
376
- {showToolbar && (
377
- <div className={styles.header}>
378
- <Toolbar
379
- search={
380
- suppressSearch
381
- ? undefined
382
- : {
383
- value: globalFilter,
384
- onChange: onGlobalFilterChange,
385
- loading: search?.loading,
386
- placeholder: search?.placeholder || t('searchPlaceholder'),
387
- }
388
- }
389
- className={styles.toolbar}
390
- onRefresh={onRefresh ? handleOnRefresh : undefined}
391
- bulkActions={bulkActions}
392
- selectionMode={rowSelectionProp?.multiRow ? 'multiple' : 'single'}
393
- checked={table.getIsAllPageRowsSelected()}
394
- indeterminate={table.getIsSomePageRowsSelected()}
395
- onCheck={enableSelection ? handleOnToolbarCheck : undefined}
396
- outline={outline}
397
- after={
398
- toolbarAfter || exportSettings ? (
399
- <>
400
- {toolbarAfter}
401
- {exportSettings && (
402
- <ExportButton
403
- settings={exportSettings}
404
- columnDefinitions={columnDefinitions}
405
- data={data}
406
- topRows={filteredTopRows}
407
- centerRows={centerRows}
408
- />
409
- )}
410
- </>
411
- ) : undefined
412
- }
413
- moreActions={moreActions}
414
- filterRow={columnFilters}
415
- data-test-id={TEST_IDS.toolbar}
416
- />
417
- </div>
418
- )}
419
-
420
- <div className={styles.scrollWrapper} data-outline={outline || undefined}>
421
- <Scroll size='s' className={styles.table} ref={scrollContainerRef}>
422
- <div className={styles.tableContent} style={columnSizes.vars}>
423
- <TableContext.Provider value={{ table }}>
424
- {(!infiniteLoading || !data.length) && loading ? (
425
- <SkeletonContextProvider loading>
426
- <HeaderRow />
427
- {loadingTableRows.map(row => (
428
- <BodyRow key={row.id} row={row} />
429
- ))}
430
- </SkeletonContextProvider>
431
- ) : (
432
- <>
433
- {centerRows.length || filteredTopRows.length ? <HeaderRow /> : null}
434
-
435
- {filteredTopRows.length ? (
436
- <div className={styles.topRowWrapper}>
437
- {filteredTopRows.map(row => (
438
- <BodyRow key={row.id} row={row} onRowClick={onRowClick} />
439
- ))}
440
- </div>
441
- ) : null}
442
-
443
- {centerRows.map(row => (
444
- <BodyRow key={row.id} row={row} onRowClick={onRowClick} />
445
- ))}
446
-
447
- {data.length > 0 && infiniteLoading && loading && (
448
- <SkeletonContextProvider loading>
449
- {loadingTableRows.slice(0, 3).map(row => (
450
- <BodyRow key={row.id} row={row} />
451
- ))}
452
- </SkeletonContextProvider>
453
- )}
454
-
455
- <TableEmptyState
456
- emptyStates={emptyStates}
457
- dataError={dataError}
458
- dataFiltered={dataFiltered || Boolean(table.getState().globalFilter)}
459
- tableRowsLength={tableRows.length + filteredTopRows.length}
368
+ <div className={cn(styles.wrapper, className)} {...extractSupportProps(rest)}>
369
+ {showToolbar && (
370
+ <div className={styles.header}>
371
+ <Toolbar
372
+ search={
373
+ suppressSearch
374
+ ? undefined
375
+ : {
376
+ value: globalFilter,
377
+ onChange: onGlobalFilterChange,
378
+ loading: search?.loading,
379
+ placeholder: search?.placeholder || t('searchPlaceholder'),
380
+ }
381
+ }
382
+ className={styles.toolbar}
383
+ onRefresh={onRefresh ? handleOnRefresh : undefined}
384
+ bulkActions={bulkActions}
385
+ selectionMode={rowSelectionProp?.multiRow ? 'multiple' : 'single'}
386
+ checked={table.getIsAllPageRowsSelected()}
387
+ indeterminate={table.getIsSomePageRowsSelected()}
388
+ onCheck={enableSelection ? handleOnToolbarCheck : undefined}
389
+ outline={outline}
390
+ after={
391
+ toolbarAfter || exportSettings ? (
392
+ <>
393
+ {toolbarAfter}
394
+ {exportSettings && (
395
+ <ExportButton
396
+ settings={exportSettings}
397
+ columnDefinitions={columnDefinitions}
398
+ data={data}
399
+ topRows={filteredTopRows}
400
+ centerRows={centerRows}
460
401
  />
461
- </>
462
- )}
463
- </TableContext.Provider>
464
- </div>
465
- <div className={styles.scrollStub} ref={scrollRef as RefObject<HTMLDivElement>} />
466
- </Scroll>
402
+ )}
403
+ </>
404
+ ) : undefined
405
+ }
406
+ moreActions={moreActions}
407
+ filterRow={columnFilters}
408
+ data-test-id={TEST_IDS.toolbar}
409
+ />
410
+ </div>
411
+ )}
412
+
413
+ <Scroll size='s' className={styles.table} ref={scrollContainerRef} data-outline={outline || undefined}>
414
+ <div className={styles.tableContent} style={columnSizes.vars}>
415
+ <CellAutoResizeContext.Provider value={{ updateCellMap }}>
416
+ <TableContext.Provider value={{ table }}>
417
+ {(!infiniteLoading || !data.length) && loading ? (
418
+ <SkeletonContextProvider loading>
419
+ <HeaderRow rowAutoHeight={rowAutoHeight} />
420
+ {loadingTableRows.map(row => (
421
+ <BodyRow key={row.id} row={row} rowAutoHeight={rowAutoHeight} />
422
+ ))}
423
+ </SkeletonContextProvider>
424
+ ) : (
425
+ <>
426
+ {centerRows.length || filteredTopRows.length ? <HeaderRow /> : null}
427
+
428
+ {filteredTopRows.length ? (
429
+ <div className={styles.topRowWrapper}>
430
+ {filteredTopRows.map(row => (
431
+ <BodyRow key={row.id} row={row} onRowClick={onRowClick} rowAutoHeight={rowAutoHeight} />
432
+ ))}
433
+ </div>
434
+ ) : null}
435
+
436
+ {centerRows.map(row => (
437
+ <BodyRow key={row.id} row={row} onRowClick={onRowClick} rowAutoHeight={rowAutoHeight} />
438
+ ))}
439
+
440
+ {data.length > 0 && infiniteLoading && loading && !dataError && (
441
+ <SkeletonContextProvider loading>
442
+ {loadingTableRows.slice(0, 3).map(row => (
443
+ <BodyRow key={row.id} row={row} />
444
+ ))}
445
+ </SkeletonContextProvider>
446
+ )}
447
+
448
+ <TableEmptyState
449
+ emptyStates={emptyStates}
450
+ dataError={dataError}
451
+ dataFiltered={dataFiltered || Boolean(table.getState().globalFilter)}
452
+ tableRowsLength={tableRows.length + filteredTopRows.length}
453
+ />
454
+ </>
455
+ )}
456
+ </TableContext.Provider>
457
+ </CellAutoResizeContext.Provider>
467
458
  </div>
468
459
 
469
- {!infiniteLoading && !suppressPagination && (
470
- <TablePagination
471
- table={table}
472
- options={paginationProp?.options}
473
- optionsLabel={paginationProp?.optionsLabel}
474
- pageCount={pageCount}
475
- optionsRender={paginationProp?.optionsRender}
476
- />
477
- )}
478
- </div>
479
- </CellAutoResizeContext.Provider>
460
+ <div className={styles.scrollStub} ref={scrollRef as RefObject<HTMLDivElement>} />
461
+ </Scroll>
462
+
463
+ {!infiniteLoading && !suppressPagination && (
464
+ <TablePagination
465
+ table={table}
466
+ options={paginationProp?.options}
467
+ optionsLabel={paginationProp?.optionsLabel}
468
+ pageCount={pageCount}
469
+ optionsRender={paginationProp?.optionsRender}
470
+ />
471
+ )}
472
+ </div>
480
473
  );
481
474
  }
482
475