@snack-uikit/table 0.30.0 → 0.30.1-preview-9a03a1c9.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.
- package/README.md +2 -0
- package/dist/cjs/components/Table/Table.d.ts +1 -1
- package/dist/cjs/components/Table/Table.js +116 -89
- package/dist/cjs/components/Table/hooks/index.d.ts +1 -0
- package/dist/cjs/components/Table/hooks/index.js +2 -1
- package/dist/cjs/components/Table/hooks/useColumnOrderByDrag.d.ts +9 -0
- package/dist/cjs/components/Table/hooks/useColumnOrderByDrag.js +76 -0
- package/dist/cjs/components/types.d.ts +2 -0
- package/dist/cjs/constants.d.ts +1 -0
- package/dist/cjs/constants.js +3 -2
- package/dist/cjs/helperComponents/Cells/BodyCell/BodyCell.d.ts +2 -1
- package/dist/cjs/helperComponents/Cells/BodyCell/BodyCell.js +13 -3
- package/dist/cjs/helperComponents/Cells/HeaderCell/DragHandle.d.ts +6 -0
- package/dist/cjs/helperComponents/Cells/HeaderCell/DragHandle.js +27 -0
- package/dist/cjs/helperComponents/Cells/HeaderCell/HeaderCell.d.ts +2 -1
- package/dist/cjs/helperComponents/Cells/HeaderCell/HeaderCell.js +22 -2
- package/dist/cjs/helperComponents/Cells/HeaderCell/styles.module.css +11 -0
- package/dist/cjs/helperComponents/Rows/BodyRow.d.ts +4 -1
- package/dist/cjs/helperComponents/Rows/BodyRow.js +30 -12
- package/dist/cjs/helperComponents/Rows/HeaderRow.d.ts +7 -1
- package/dist/cjs/helperComponents/Rows/HeaderRow.js +33 -13
- package/dist/cjs/helperComponents/hooks.d.ts +22 -13
- package/dist/cjs/helperComponents/hooks.js +63 -15
- package/dist/cjs/types.d.ts +5 -0
- package/dist/esm/components/Table/Table.d.ts +1 -1
- package/dist/esm/components/Table/Table.js +17 -12
- package/dist/esm/components/Table/hooks/index.d.ts +1 -0
- package/dist/esm/components/Table/hooks/index.js +1 -0
- package/dist/esm/components/Table/hooks/useColumnOrderByDrag.d.ts +9 -0
- package/dist/esm/components/Table/hooks/useColumnOrderByDrag.js +66 -0
- package/dist/esm/components/types.d.ts +2 -0
- package/dist/esm/constants.d.ts +1 -0
- package/dist/esm/constants.js +1 -0
- package/dist/esm/helperComponents/Cells/BodyCell/BodyCell.d.ts +2 -1
- package/dist/esm/helperComponents/Cells/BodyCell/BodyCell.js +7 -3
- package/dist/esm/helperComponents/Cells/HeaderCell/DragHandle.d.ts +6 -0
- package/dist/esm/helperComponents/Cells/HeaderCell/DragHandle.js +6 -0
- package/dist/esm/helperComponents/Cells/HeaderCell/HeaderCell.d.ts +2 -1
- package/dist/esm/helperComponents/Cells/HeaderCell/HeaderCell.js +13 -4
- package/dist/esm/helperComponents/Cells/HeaderCell/styles.module.css +11 -0
- package/dist/esm/helperComponents/Rows/BodyRow.d.ts +4 -1
- package/dist/esm/helperComponents/Rows/BodyRow.js +4 -3
- package/dist/esm/helperComponents/Rows/HeaderRow.d.ts +7 -1
- package/dist/esm/helperComponents/Rows/HeaderRow.js +4 -3
- package/dist/esm/helperComponents/hooks.d.ts +22 -13
- package/dist/esm/helperComponents/hooks.js +58 -15
- package/dist/esm/types.d.ts +5 -0
- package/package.json +6 -2
- package/src/components/Table/Table.tsx +133 -102
- package/src/components/Table/hooks/index.ts +1 -0
- package/src/components/Table/hooks/useColumnOrderByDrag.ts +100 -0
- package/src/components/types.ts +3 -0
- package/src/constants.tsx +2 -0
- package/src/helperComponents/Cells/BodyCell/BodyCell.tsx +9 -2
- package/src/helperComponents/Cells/HeaderCell/DragHandle.tsx +18 -0
- package/src/helperComponents/Cells/HeaderCell/HeaderCell.tsx +19 -4
- package/src/helperComponents/Cells/HeaderCell/styles.module.scss +11 -0
- package/src/helperComponents/Rows/BodyRow.tsx +36 -9
- package/src/helperComponents/Rows/HeaderRow.tsx +51 -18
- package/src/helperComponents/hooks.ts +78 -15
- package/src/types.ts +6 -0
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useSortable } from '@dnd-kit/sortable';
|
|
2
3
|
import { flexRender } from '@tanstack/react-table';
|
|
3
4
|
import cn from 'classnames';
|
|
4
5
|
import { useRef } from 'react';
|
|
5
6
|
import { TruncateString } from '@snack-uikit/truncate-string';
|
|
6
|
-
import { TEST_IDS } from '../../../constants';
|
|
7
|
+
import { TEST_IDS, UNDRAGGABLE_COLUMNS } from '../../../constants';
|
|
7
8
|
import { useCellSizes } from '../../hooks';
|
|
8
9
|
import { Cell } from '../Cell';
|
|
10
|
+
import { DragHandle } from './DragHandle';
|
|
9
11
|
import { getSortingIcon } from './helpers';
|
|
10
12
|
import { ResizeHandle } from './ResizeHandle';
|
|
11
13
|
import styles from './styles.module.css';
|
|
12
|
-
export function HeaderCell({ header, pinPosition, className }) {
|
|
14
|
+
export function HeaderCell({ header, pinPosition, isDraggable, className }) {
|
|
13
15
|
const cellRef = useRef(null);
|
|
14
16
|
const isSortable = header.column.getCanSort();
|
|
15
17
|
const isResizable = header.column.getCanResize();
|
|
@@ -19,12 +21,19 @@ export function HeaderCell({ header, pinPosition, className }) {
|
|
|
19
21
|
const columnSizingInfo = header.getContext().table.getState().columnSizingInfo;
|
|
20
22
|
const isSomeColumnResizing = columnSizingInfo.isResizingColumn;
|
|
21
23
|
const columnDef = header.column.columnDef;
|
|
22
|
-
const style = useCellSizes(header);
|
|
24
|
+
const style = useCellSizes(header, { isDraggable });
|
|
25
|
+
const { attributes, listeners, setNodeRef } = useSortable({
|
|
26
|
+
id: header.column.id,
|
|
27
|
+
});
|
|
23
28
|
const sortingHandler = (e) => {
|
|
24
29
|
var _a;
|
|
25
30
|
if (isSomeColumnResizing)
|
|
26
31
|
return;
|
|
27
32
|
return (_a = header.column.getToggleSortingHandler()) === null || _a === void 0 ? void 0 : _a(e);
|
|
28
33
|
};
|
|
29
|
-
|
|
34
|
+
const isAvailableForDrag = !UNDRAGGABLE_COLUMNS.includes(header.column.id);
|
|
35
|
+
return (_jsxs(Cell, { style: style, onClick: sortingHandler, "data-sortable": isSortable || undefined, "data-draggable": isDraggable || undefined, "data-no-padding": columnDef.noHeaderCellPadding || undefined, "data-no-offset": columnDef.noHeaderCellBorderOffset || undefined, "data-test-id": TEST_IDS.headerCell, "data-align": columnDef.headerAlign || undefined, "data-header-id": header.id, "data-resizing": isResizing || undefined, "data-pin-position": pinPosition || undefined, role: 'columnheader', className: cn(styles.tableHeaderCell, className, columnDef.headerClassName), ref: element => {
|
|
36
|
+
setNodeRef(element);
|
|
37
|
+
return cellRef;
|
|
38
|
+
}, children: [_jsxs("div", { className: styles.tableHeaderCellMain, children: [columnDef.header && (_jsx("div", { className: styles.tableHeaderCellName, children: _jsx(TruncateString, { text: flexRender(columnDef.header, header.getContext()) }) })), Boolean(sortIcon) && (_jsx("div", { className: styles.tableHeaderIcon, "data-sort-direction": sortDirection, "data-test-id": TEST_IDS.headerSortIndicator, children: sortIcon }))] }), isAvailableForDrag && Boolean(isDraggable) && _jsx(DragHandle, { attributes: attributes, listeners: listeners }), Boolean(isResizable) && _jsx(ResizeHandle, { header: header, cellRef: cellRef })] }));
|
|
30
39
|
}
|
|
@@ -129,4 +129,15 @@
|
|
|
129
129
|
.tableHeaderIcon svg{
|
|
130
130
|
width:var(--size-icon-container-xs, 16px) !important;
|
|
131
131
|
height:var(--size-icon-container-xs, 16px) !important;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.dragHandle{
|
|
135
|
+
cursor:pointer;
|
|
136
|
+
display:flex;
|
|
137
|
+
flex-direction:row;
|
|
138
|
+
gap:2px;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.dragIcon{
|
|
142
|
+
color:var(--sys-neutral-text-light, #8b8e9b);
|
|
132
143
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Row as TableRow } from '@tanstack/react-table';
|
|
2
2
|
import { MouseEvent } from 'react';
|
|
3
|
+
import { GroupedColumnOrderState } from '../../types';
|
|
3
4
|
export type RowInfo<TData> = {
|
|
4
5
|
id: string;
|
|
5
6
|
data: TData;
|
|
@@ -10,5 +11,7 @@ export type RowClickHandler<TData> = (e: MouseEvent<HTMLDivElement>, row: RowInf
|
|
|
10
11
|
export type BodyRowProps<TData> = {
|
|
11
12
|
row: TableRow<TData>;
|
|
12
13
|
onRowClick?: RowClickHandler<TData>;
|
|
14
|
+
groupedColumnOrderState: GroupedColumnOrderState;
|
|
15
|
+
enableColumnsOrderSortByDrag?: boolean;
|
|
13
16
|
};
|
|
14
|
-
export declare function BodyRow<TData>({ row, onRowClick }: BodyRowProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export declare function BodyRow<TData>({ row, onRowClick, groupedColumnOrderState, enableColumnsOrderSortByDrag, }: BodyRowProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { horizontalListSortingStrategy, SortableContext } from '@dnd-kit/sortable';
|
|
2
3
|
import { useState } from 'react';
|
|
3
4
|
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../constants';
|
|
4
5
|
import { BodyCell } from '../Cells';
|
|
@@ -7,8 +8,8 @@ import { useRowCells } from '../hooks';
|
|
|
7
8
|
import { PinnedCells } from './PinnedCells';
|
|
8
9
|
import { Row } from './Row';
|
|
9
10
|
import styles from './styles.module.css';
|
|
10
|
-
export function BodyRow({ row, onRowClick }) {
|
|
11
|
-
const {
|
|
11
|
+
export function BodyRow({ row, onRowClick, groupedColumnOrderState, enableColumnsOrderSortByDrag, }) {
|
|
12
|
+
const { leftPinned, rightPinned, unpinned } = useRowCells(row, groupedColumnOrderState);
|
|
12
13
|
const [dropListOpened, setDropListOpen] = useState(false);
|
|
13
14
|
const disabled = !row.getCanSelect();
|
|
14
15
|
const handleRowClick = (e) => {
|
|
@@ -23,5 +24,5 @@ export function BodyRow({ row, onRowClick }) {
|
|
|
23
24
|
};
|
|
24
25
|
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
26
|
(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: [
|
|
27
|
+
undefined, "data-actions-opened": dropListOpened || undefined, "data-test-id": TEST_IDS.bodyRow, "data-row-id": row.id, className: styles.bodyRow, children: [leftPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Left, children: leftPinned.map(cell => (_jsx(SortableContext, { items: groupedColumnOrderState.leftPinned, strategy: horizontalListSortingStrategy, children: _jsx(BodyCell, { cell: cell, isDraggable: enableColumnsOrderSortByDrag }, cell.id) }, cell.id))) })), unpinned.map(cell => (_jsx(SortableContext, { items: groupedColumnOrderState.unpinned, strategy: horizontalListSortingStrategy, children: _jsx(BodyCell, { cell: cell, isDraggable: enableColumnsOrderSortByDrag }, cell.id) }, cell.id))), rightPinned && (_jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Right, children: rightPinned.map(cell => (_jsx(SortableContext, { items: groupedColumnOrderState.rightPinned, strategy: horizontalListSortingStrategy, children: _jsx(BodyCell, { cell: cell, isDraggable: enableColumnsOrderSortByDrag }, cell.id) }, cell.id))) }))] }) }));
|
|
27
28
|
}
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { GroupedColumnOrderState } from '../../types';
|
|
2
|
+
type Props = {
|
|
3
|
+
groupedColumnOrderState: GroupedColumnOrderState;
|
|
4
|
+
enableColumnsOrderSortByDrag?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare function HeaderRow({ groupedColumnOrderState, enableColumnsOrderSortByDrag }: Props): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { horizontalListSortingStrategy, SortableContext } from '@dnd-kit/sortable';
|
|
2
3
|
import { COLUMN_PIN_POSITION, TEST_IDS } from '../../constants';
|
|
3
4
|
import { HeaderCell } from '../Cells';
|
|
4
5
|
import { useHeaderGroups } from '../hooks';
|
|
5
6
|
import { PinnedCells } from './PinnedCells';
|
|
6
7
|
import { Row } from './Row';
|
|
7
8
|
import styles from './styles.module.css';
|
|
8
|
-
export function HeaderRow() {
|
|
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)))) }))] }));
|
|
9
|
+
export function HeaderRow({ groupedColumnOrderState, enableColumnsOrderSortByDrag }) {
|
|
10
|
+
const { leftPinned, unpinned, rightPinned } = useHeaderGroups(groupedColumnOrderState);
|
|
11
|
+
return (_jsxs(Row, { className: styles.tableHeader, "data-test-id": TEST_IDS.headerRow, children: [leftPinned && (_jsx(SortableContext, { items: groupedColumnOrderState.leftPinned, strategy: horizontalListSortingStrategy, children: _jsx(PinnedCells, { position: COLUMN_PIN_POSITION.Left, children: leftPinned.map(headerGroup => headerGroup.headers.map(header => header.isPlaceholder ? null : (_jsx(HeaderCell, { header: header, isDraggable: enableColumnsOrderSortByDrag && groupedColumnOrderState.leftPinned.length > 1 }, header.id)))) }) })), _jsx(SortableContext, { items: groupedColumnOrderState.unpinned, strategy: horizontalListSortingStrategy, children: unpinned.map(headerGroup => headerGroup.headers.map(header => (_jsx(HeaderCell, { header: header, isDraggable: enableColumnsOrderSortByDrag && groupedColumnOrderState.unpinned.length > 1 }, header.id)))) }), rightPinned && (_jsx(SortableContext, { items: groupedColumnOrderState.rightPinned, strategy: horizontalListSortingStrategy, children: _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, isDraggable: enableColumnsOrderSortByDrag && groupedColumnOrderState.rightPinned.length > 1 }, header.id)))) }) }))] }));
|
|
11
12
|
}
|
|
@@ -1,25 +1,34 @@
|
|
|
1
1
|
import { Cell, Header, HeaderGroup, Row } from '@tanstack/react-table';
|
|
2
|
-
|
|
2
|
+
import { CSSProperties } from 'react';
|
|
3
|
+
import { GroupedColumnOrderState } from '../types';
|
|
4
|
+
export declare function useHeaderGroups(groupedColumnOrderState: GroupedColumnOrderState): {
|
|
3
5
|
unpinned: HeaderGroup<any>[];
|
|
4
6
|
leftPinned?: undefined;
|
|
5
7
|
rightPinned?: undefined;
|
|
6
8
|
} | {
|
|
7
|
-
leftPinned:
|
|
8
|
-
|
|
9
|
+
leftPinned: {
|
|
10
|
+
headers: Header<unknown, unknown>[];
|
|
11
|
+
depth: number;
|
|
12
|
+
id: string;
|
|
13
|
+
}[] | undefined;
|
|
14
|
+
rightPinned: {
|
|
15
|
+
headers: Header<unknown, unknown>[];
|
|
16
|
+
depth: number;
|
|
17
|
+
id: string;
|
|
18
|
+
}[] | undefined;
|
|
9
19
|
unpinned: HeaderGroup<any>[];
|
|
10
20
|
};
|
|
11
|
-
export declare function useRowCells<TData>(row: Row<TData
|
|
21
|
+
export declare function useRowCells<TData>(row: Row<TData>, groupedColumnOrderState: GroupedColumnOrderState): {
|
|
12
22
|
unpinned: Cell<TData, unknown>[];
|
|
13
|
-
|
|
14
|
-
|
|
23
|
+
leftPinned?: undefined;
|
|
24
|
+
rightPinned?: undefined;
|
|
15
25
|
} | {
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
leftPinned: Cell<TData, unknown>[] | undefined;
|
|
27
|
+
rightPinned: Cell<TData, unknown>[] | undefined;
|
|
18
28
|
unpinned: Cell<TData, unknown>[];
|
|
19
29
|
};
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
width: string;
|
|
23
|
-
maxWidth: number | undefined;
|
|
24
|
-
flexShrink: string;
|
|
30
|
+
type CellSizesOptions = {
|
|
31
|
+
isDraggable?: boolean;
|
|
25
32
|
};
|
|
33
|
+
export declare function useCellSizes<TData>(element: Cell<TData, unknown> | Header<TData, unknown>, options?: CellSizesOptions): CSSProperties;
|
|
34
|
+
export {};
|
|
@@ -1,12 +1,23 @@
|
|
|
1
|
+
import { useSortable } from '@dnd-kit/sortable';
|
|
2
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
1
3
|
import { useMemo } from 'react';
|
|
2
4
|
import { useTableContext } from './contexts';
|
|
3
5
|
function hasHeaders(groups) {
|
|
4
6
|
return groups.some(group => group.headers.length);
|
|
5
7
|
}
|
|
6
|
-
|
|
8
|
+
const sortHeaderGroup = (groups, groupOrder) => groups.map(group => (Object.assign(Object.assign({}, group), { headers: group.headers.sort((a, b) => {
|
|
9
|
+
const indexA = groupOrder.findIndex(columnId => columnId === a.id);
|
|
10
|
+
const indexB = groupOrder.findIndex(columnId => columnId === b.id);
|
|
11
|
+
if (indexA > -1 && indexB > -1) {
|
|
12
|
+
return indexA - indexB;
|
|
13
|
+
}
|
|
14
|
+
return 0;
|
|
15
|
+
}) })));
|
|
16
|
+
export function useHeaderGroups(groupedColumnOrderState) {
|
|
7
17
|
const { table } = useTableContext();
|
|
8
18
|
const columnDefs = table._getColumnDefs();
|
|
9
19
|
const pinEnabled = table.getIsSomeColumnsPinned();
|
|
20
|
+
const { columnOrder } = table.getState();
|
|
10
21
|
return useMemo(() => {
|
|
11
22
|
if (!pinEnabled) {
|
|
12
23
|
return {
|
|
@@ -16,18 +27,29 @@ export function useHeaderGroups() {
|
|
|
16
27
|
const left = table.getLeftHeaderGroups();
|
|
17
28
|
const right = table.getRightHeaderGroups();
|
|
18
29
|
return {
|
|
19
|
-
leftPinned: hasHeaders(left) ? left : undefined,
|
|
20
|
-
rightPinned: hasHeaders(right) ? right : undefined,
|
|
30
|
+
leftPinned: hasHeaders(left) ? sortHeaderGroup(left, groupedColumnOrderState.leftPinned) : undefined,
|
|
31
|
+
rightPinned: hasHeaders(right) ? sortHeaderGroup(right, groupedColumnOrderState.rightPinned) : undefined,
|
|
21
32
|
unpinned: table.getCenterHeaderGroups(),
|
|
22
33
|
};
|
|
23
34
|
// need to rebuild if columnDefinitions has changed
|
|
24
35
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
25
|
-
}, [table, pinEnabled, columnDefs]);
|
|
36
|
+
}, [table, pinEnabled, columnDefs, columnOrder, groupedColumnOrderState]);
|
|
37
|
+
}
|
|
38
|
+
function sortPinnedColumnsByOrderState(groupOrder) {
|
|
39
|
+
return (a, b) => {
|
|
40
|
+
const indexA = groupOrder.findIndex(columnId => columnId === a.column.id);
|
|
41
|
+
const indexB = groupOrder.findIndex(columnId => columnId === b.column.id);
|
|
42
|
+
if (indexA > -1 && indexB > -1) {
|
|
43
|
+
return indexA - indexB;
|
|
44
|
+
}
|
|
45
|
+
return 0;
|
|
46
|
+
};
|
|
26
47
|
}
|
|
27
|
-
export function useRowCells(row) {
|
|
48
|
+
export function useRowCells(row, groupedColumnOrderState) {
|
|
28
49
|
const { table } = useTableContext();
|
|
29
50
|
const pinEnabled = table.getIsSomeColumnsPinned();
|
|
30
51
|
const columnDefs = table._getColumnDefs();
|
|
52
|
+
const { columnOrder } = table.getState();
|
|
31
53
|
return useMemo(() => {
|
|
32
54
|
if (!pinEnabled) {
|
|
33
55
|
return {
|
|
@@ -37,24 +59,45 @@ export function useRowCells(row) {
|
|
|
37
59
|
const left = row.getLeftVisibleCells();
|
|
38
60
|
const right = row.getRightVisibleCells();
|
|
39
61
|
return {
|
|
40
|
-
|
|
41
|
-
|
|
62
|
+
leftPinned: left.length
|
|
63
|
+
? left.slice().sort(sortPinnedColumnsByOrderState(groupedColumnOrderState.leftPinned))
|
|
64
|
+
: undefined,
|
|
65
|
+
rightPinned: right.length
|
|
66
|
+
? right.slice().sort(sortPinnedColumnsByOrderState(groupedColumnOrderState.rightPinned))
|
|
67
|
+
: undefined,
|
|
42
68
|
unpinned: row.getCenterVisibleCells(),
|
|
43
69
|
};
|
|
44
70
|
// need to rebuild if columnDefinitions has changed
|
|
45
71
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
46
|
-
}, [row, pinEnabled, columnDefs]);
|
|
72
|
+
}, [row, pinEnabled, columnDefs, columnOrder, groupedColumnOrderState]);
|
|
47
73
|
}
|
|
48
|
-
export function useCellSizes(element) {
|
|
74
|
+
export function useCellSizes(element, options) {
|
|
49
75
|
const column = element.column;
|
|
76
|
+
const { isDragging, transform } = useSortable({
|
|
77
|
+
id: column.id,
|
|
78
|
+
});
|
|
50
79
|
const minWidth = column.columnDef.minSize;
|
|
51
80
|
const maxWidth = column.columnDef.maxSize;
|
|
52
81
|
const width = `var(--table-column-${column.id}-size)`;
|
|
53
82
|
const flexShrink = `var(--table-column-${column.id}-flex)`;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
83
|
+
const isHeaderCell = 'headerGroup' in element;
|
|
84
|
+
return useMemo(() => {
|
|
85
|
+
const styles = {
|
|
86
|
+
minWidth,
|
|
87
|
+
width,
|
|
88
|
+
maxWidth,
|
|
89
|
+
flexShrink,
|
|
90
|
+
};
|
|
91
|
+
if (options === null || options === void 0 ? void 0 : options.isDraggable) {
|
|
92
|
+
styles.opacity = isDragging ? 0.8 : 1;
|
|
93
|
+
styles.position = 'relative';
|
|
94
|
+
styles.transform = CSS.Translate.toString(transform);
|
|
95
|
+
styles.transition = 'width transform 0.2s ease-in-out';
|
|
96
|
+
styles.zIndex = isDragging ? 1 : 0;
|
|
97
|
+
if (isHeaderCell) {
|
|
98
|
+
styles.whiteSpace = 'nowrap';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return styles;
|
|
102
|
+
}, [options === null || options === void 0 ? void 0 : options.isDraggable, flexShrink, isDragging, isHeaderCell, maxWidth, minWidth, transform, width]);
|
|
60
103
|
}
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -40,5 +40,10 @@ type PinnedColumnDefinition<TData> = BaseColumnDefinition<TData> & {
|
|
|
40
40
|
size: number;
|
|
41
41
|
};
|
|
42
42
|
export type ColumnDefinition<TData> = NormalColumnDefinition<TData> | PinnedColumnDefinition<TData>;
|
|
43
|
+
export type GroupedColumnOrderState = {
|
|
44
|
+
leftPinned: string[];
|
|
45
|
+
rightPinned: string[];
|
|
46
|
+
unpinned: string[];
|
|
47
|
+
};
|
|
43
48
|
export type { RowActionsColumnDefProps, StatusColumnDefinitionProps, RowInfo, RowClickHandler, ActionsGenerator, CopyCellProps, MapStatusToAppearanceFnType, } from './helperComponents';
|
|
44
49
|
export type { ColumnPinPosition, PaginationState, SortingState, RowSelectionState, RowSelectionOptions, EmptyStateProps, ToolbarProps, HeaderContext, CellContext, };
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "Table",
|
|
7
|
-
"version": "0.30.0",
|
|
7
|
+
"version": "0.30.1-preview-9a03a1c9.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
"license": "Apache-2.0",
|
|
37
37
|
"scripts": {},
|
|
38
38
|
"dependencies": {
|
|
39
|
+
"@dnd-kit/core": "6.3.1",
|
|
40
|
+
"@dnd-kit/modifiers": "9.0.0",
|
|
41
|
+
"@dnd-kit/sortable": "10.0.0",
|
|
42
|
+
"@dnd-kit/utilities": "3.2.2",
|
|
39
43
|
"@snack-uikit/button": "0.19.7",
|
|
40
44
|
"@snack-uikit/chips": "0.25.3",
|
|
41
45
|
"@snack-uikit/icon-predefined": "0.7.3",
|
|
@@ -61,5 +65,5 @@
|
|
|
61
65
|
"peerDependencies": {
|
|
62
66
|
"@snack-uikit/locale": "*"
|
|
63
67
|
},
|
|
64
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "a7e76287bbbbb376afb7bc895cfa1e125751608f"
|
|
65
69
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { closestCenter, DndContext } from '@dnd-kit/core';
|
|
2
|
+
import { restrictToHorizontalAxis } from '@dnd-kit/modifiers';
|
|
1
3
|
import {
|
|
2
4
|
CellContext,
|
|
3
5
|
ColumnPinningState,
|
|
@@ -43,7 +45,7 @@ import { getTreeColumnDef } from '../../helperComponents/Cells/TreeCell';
|
|
|
43
45
|
import { ColumnDefinition } from '../../types';
|
|
44
46
|
import { fuzzyFilter } from '../../utils';
|
|
45
47
|
import { TableProps } from '../types';
|
|
46
|
-
import { useLoadingTable, useStateControl } from './hooks';
|
|
48
|
+
import { useColumnOrderByDrag, useLoadingTable, useStateControl } from './hooks';
|
|
47
49
|
import { usePageReset } from './hooks/usePageReset';
|
|
48
50
|
import styles from './styles.module.scss';
|
|
49
51
|
import {
|
|
@@ -97,6 +99,7 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
|
|
|
97
99
|
savedState,
|
|
98
100
|
expanding,
|
|
99
101
|
bulkActions: bulkActionsProp,
|
|
102
|
+
enableColumnsOrderSortByDrag,
|
|
100
103
|
...rest
|
|
101
104
|
}: TableProps<TData, TFilters>) {
|
|
102
105
|
const { state: globalFilter, onStateChange: onGlobalFilterChange } = useStateControl<string>(search, '');
|
|
@@ -130,6 +133,9 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
|
|
|
130
133
|
return cols;
|
|
131
134
|
}, [columnDefinitions, enableSelection, enableSelectPinned, expanding]);
|
|
132
135
|
|
|
136
|
+
const { columnOrder, setColumnOrder, groupedColumnOrderState, sensors, handleDragEnd } =
|
|
137
|
+
useColumnOrderByDrag(tableColumns);
|
|
138
|
+
|
|
133
139
|
const columnPinning = useMemo(() => {
|
|
134
140
|
const pinningState: Required<ColumnPinningState> = { left: [], right: [] };
|
|
135
141
|
for (const col of tableColumns) {
|
|
@@ -160,6 +166,7 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
|
|
|
160
166
|
columns: tableColumns,
|
|
161
167
|
state: {
|
|
162
168
|
columnPinning,
|
|
169
|
+
columnOrder,
|
|
163
170
|
globalFilter,
|
|
164
171
|
rowSelection,
|
|
165
172
|
sorting,
|
|
@@ -173,6 +180,7 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
|
|
|
173
180
|
minSize: 40,
|
|
174
181
|
cell: (cell: CellContext<TData, unknown>) => <TruncateString text={String(cell.getValue())} maxLines={1} />,
|
|
175
182
|
},
|
|
183
|
+
onColumnOrderChange: setColumnOrder,
|
|
176
184
|
|
|
177
185
|
manualSorting,
|
|
178
186
|
manualPagination,
|
|
@@ -362,110 +370,133 @@ export function Table<TData extends object, TFilters extends FiltersState = Reco
|
|
|
362
370
|
const showToolbar = !suppressToolbar;
|
|
363
371
|
|
|
364
372
|
return (
|
|
365
|
-
<
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
373
|
+
<DndContext
|
|
374
|
+
collisionDetection={closestCenter}
|
|
375
|
+
modifiers={[restrictToHorizontalAxis]}
|
|
376
|
+
onDragEnd={handleDragEnd}
|
|
377
|
+
sensors={sensors}
|
|
378
|
+
>
|
|
379
|
+
<CellAutoResizeContext.Provider value={{ updateCellMap }}>
|
|
380
|
+
<div
|
|
381
|
+
style={{
|
|
382
|
+
'--page-size': cssPageSize,
|
|
383
|
+
}}
|
|
384
|
+
className={cn(styles.wrapper, className)}
|
|
385
|
+
{...extractSupportProps(rest)}
|
|
386
|
+
>
|
|
387
|
+
{showToolbar && (
|
|
388
|
+
<div className={styles.header}>
|
|
389
|
+
<Toolbar
|
|
390
|
+
search={
|
|
391
|
+
suppressSearch
|
|
392
|
+
? undefined
|
|
393
|
+
: {
|
|
394
|
+
value: globalFilter,
|
|
395
|
+
onChange: onGlobalFilterChange,
|
|
396
|
+
loading: search?.loading,
|
|
397
|
+
placeholder: search?.placeholder || t('searchPlaceholder'),
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
className={styles.toolbar}
|
|
401
|
+
onRefresh={onRefresh ? handleOnRefresh : undefined}
|
|
402
|
+
bulkActions={bulkActions}
|
|
403
|
+
selectionMode={rowSelectionProp?.multiRow ? 'multiple' : 'single'}
|
|
404
|
+
checked={table.getIsAllPageRowsSelected()}
|
|
405
|
+
indeterminate={table.getIsSomePageRowsSelected()}
|
|
406
|
+
onCheck={enableSelection ? handleOnToolbarCheck : undefined}
|
|
407
|
+
outline={outline}
|
|
408
|
+
after={
|
|
409
|
+
toolbarAfter || exportSettings ? (
|
|
410
|
+
<>
|
|
411
|
+
{toolbarAfter}
|
|
412
|
+
{exportSettings && (
|
|
413
|
+
<ExportButton
|
|
414
|
+
settings={exportSettings}
|
|
415
|
+
columnDefinitions={columnDefinitions}
|
|
416
|
+
data={data}
|
|
417
|
+
topRows={filteredTopRows}
|
|
418
|
+
centerRows={centerRows}
|
|
419
|
+
/>
|
|
420
|
+
)}
|
|
421
|
+
</>
|
|
422
|
+
) : undefined
|
|
423
|
+
}
|
|
424
|
+
moreActions={moreActions}
|
|
425
|
+
filterRow={columnFilters}
|
|
426
|
+
data-test-id={TEST_IDS.toolbar}
|
|
427
|
+
/>
|
|
428
|
+
</div>
|
|
429
|
+
)}
|
|
430
|
+
|
|
431
|
+
<div className={styles.scrollWrapper} data-outline={outline || undefined}>
|
|
432
|
+
<Scroll size='s' className={styles.table} ref={scrollContainerRef}>
|
|
433
|
+
<div className={styles.tableContent} style={columnSizes.vars}>
|
|
434
|
+
<TableContext.Provider value={{ table }}>
|
|
435
|
+
{loading ? (
|
|
436
|
+
<SkeletonContextProvider loading>
|
|
437
|
+
<HeaderRow groupedColumnOrderState={groupedColumnOrderState} />
|
|
438
|
+
{loadingTableRows.map(row => (
|
|
439
|
+
<BodyRow key={row.id} row={row} groupedColumnOrderState={groupedColumnOrderState} />
|
|
440
|
+
))}
|
|
441
|
+
</SkeletonContextProvider>
|
|
442
|
+
) : (
|
|
443
|
+
<>
|
|
444
|
+
{centerRows.length || filteredTopRows.length ? (
|
|
445
|
+
<HeaderRow
|
|
446
|
+
groupedColumnOrderState={groupedColumnOrderState}
|
|
447
|
+
enableColumnsOrderSortByDrag={enableColumnsOrderSortByDrag}
|
|
448
|
+
/>
|
|
449
|
+
) : null}
|
|
450
|
+
|
|
451
|
+
{filteredTopRows.length ? (
|
|
452
|
+
<div className={styles.topRowWrapper}>
|
|
453
|
+
{filteredTopRows.map(row => (
|
|
454
|
+
<BodyRow
|
|
455
|
+
key={row.id}
|
|
456
|
+
row={row}
|
|
457
|
+
onRowClick={onRowClick}
|
|
458
|
+
groupedColumnOrderState={groupedColumnOrderState}
|
|
459
|
+
/>
|
|
460
|
+
))}
|
|
461
|
+
</div>
|
|
462
|
+
) : null}
|
|
463
|
+
|
|
464
|
+
{centerRows.map(row => (
|
|
465
|
+
<BodyRow
|
|
466
|
+
key={row.id}
|
|
467
|
+
row={row}
|
|
468
|
+
onRowClick={onRowClick}
|
|
469
|
+
groupedColumnOrderState={groupedColumnOrderState}
|
|
470
|
+
enableColumnsOrderSortByDrag={enableColumnsOrderSortByDrag}
|
|
471
|
+
/>
|
|
472
|
+
))}
|
|
473
|
+
|
|
474
|
+
<TableEmptyState
|
|
475
|
+
emptyStates={emptyStates}
|
|
476
|
+
dataError={dataError}
|
|
477
|
+
dataFiltered={dataFiltered || Boolean(table.getState().globalFilter)}
|
|
478
|
+
tableRowsLength={tableRows.length + filteredTopRows.length}
|
|
405
479
|
/>
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
data-test-id={TEST_IDS.toolbar}
|
|
413
|
-
/>
|
|
480
|
+
</>
|
|
481
|
+
)}
|
|
482
|
+
</TableContext.Provider>
|
|
483
|
+
</div>
|
|
484
|
+
<div className={styles.scrollStub} ref={scrollRef as RefObject<HTMLDivElement>} />
|
|
485
|
+
</Scroll>
|
|
414
486
|
</div>
|
|
415
|
-
)}
|
|
416
|
-
|
|
417
|
-
<div className={styles.scrollWrapper} data-outline={outline || undefined}>
|
|
418
|
-
<Scroll size='s' className={styles.table} ref={scrollContainerRef}>
|
|
419
|
-
<div className={styles.tableContent} style={columnSizes.vars}>
|
|
420
|
-
<TableContext.Provider value={{ table }}>
|
|
421
|
-
{loading ? (
|
|
422
|
-
<SkeletonContextProvider loading>
|
|
423
|
-
<HeaderRow />
|
|
424
|
-
{loadingTableRows.map(row => (
|
|
425
|
-
<BodyRow key={row.id} row={row} />
|
|
426
|
-
))}
|
|
427
|
-
</SkeletonContextProvider>
|
|
428
|
-
) : (
|
|
429
|
-
<>
|
|
430
|
-
{centerRows.length || filteredTopRows.length ? <HeaderRow /> : null}
|
|
431
|
-
|
|
432
|
-
{filteredTopRows.length ? (
|
|
433
|
-
<div className={styles.topRowWrapper}>
|
|
434
|
-
{filteredTopRows.map(row => (
|
|
435
|
-
<BodyRow key={row.id} row={row} onRowClick={onRowClick} />
|
|
436
|
-
))}
|
|
437
|
-
</div>
|
|
438
|
-
) : null}
|
|
439
|
-
|
|
440
|
-
{centerRows.map(row => (
|
|
441
|
-
<BodyRow key={row.id} row={row} onRowClick={onRowClick} />
|
|
442
|
-
))}
|
|
443
|
-
|
|
444
|
-
<TableEmptyState
|
|
445
|
-
emptyStates={emptyStates}
|
|
446
|
-
dataError={dataError}
|
|
447
|
-
dataFiltered={dataFiltered || Boolean(table.getState().globalFilter)}
|
|
448
|
-
tableRowsLength={tableRows.length + filteredTopRows.length}
|
|
449
|
-
/>
|
|
450
|
-
</>
|
|
451
|
-
)}
|
|
452
|
-
</TableContext.Provider>
|
|
453
|
-
</div>
|
|
454
|
-
<div className={styles.scrollStub} ref={scrollRef as RefObject<HTMLDivElement>} />
|
|
455
|
-
</Scroll>
|
|
456
|
-
</div>
|
|
457
487
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
488
|
+
{!suppressPagination && (
|
|
489
|
+
<TablePagination
|
|
490
|
+
table={table}
|
|
491
|
+
options={paginationProp?.options}
|
|
492
|
+
optionsLabel={paginationProp?.optionsLabel}
|
|
493
|
+
pageCount={pageCount}
|
|
494
|
+
optionsRender={paginationProp?.optionsRender}
|
|
495
|
+
/>
|
|
496
|
+
)}
|
|
497
|
+
</div>
|
|
498
|
+
</CellAutoResizeContext.Provider>
|
|
499
|
+
</DndContext>
|
|
469
500
|
);
|
|
470
501
|
}
|
|
471
502
|
|