@dxos/react-ui-table 0.8.1-staging.391c573 → 0.8.1-staging.9eaf14f
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/dist/lib/browser/{chunk-3FR6NHPD.mjs → chunk-YWNRUF4J.mjs} +8 -6
- package/dist/lib/browser/chunk-YWNRUF4J.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +625 -225
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types/index.mjs +1 -1
- package/dist/lib/node/{chunk-NB3SFHGA.cjs → chunk-TGG6OZ54.cjs} +10 -8
- package/dist/lib/node/chunk-TGG6OZ54.cjs.map +7 -0
- package/dist/lib/node/index.cjs +618 -220
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types/index.cjs +3 -3
- package/dist/lib/node/types/index.cjs.map +1 -1
- package/dist/lib/node-esm/{chunk-RLVVOZW5.mjs → chunk-KKLP54L3.mjs} +8 -6
- package/dist/lib/node-esm/chunk-KKLP54L3.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +625 -225
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/types/index.mjs +1 -1
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts +24 -0
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -0
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +10 -0
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -0
- package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +1 -0
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +4 -3
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/index.d.ts +1 -0
- package/dist/types/src/components/Table/index.d.ts.map +1 -1
- package/dist/types/src/components/Table/relations.stories.d.ts +9 -0
- package/dist/types/src/components/Table/relations.stories.d.ts.map +1 -0
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +7 -7
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/useTableModel.d.ts +8 -9
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/model/index.d.ts +1 -0
- package/dist/types/src/model/index.d.ts.map +1 -1
- package/dist/types/src/model/selection-model.d.ts +6 -3
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +42 -16
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +4 -4
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/model/table-sorting.d.ts +2 -2
- package/dist/types/src/model/table-sorting.d.ts.map +1 -1
- package/dist/types/src/types/table.d.ts +7 -32
- package/dist/types/src/types/table.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts +31 -0
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/table-controls.d.ts +2 -2
- package/dist/types/src/util/table-controls.d.ts.map +1 -1
- package/dist/types/src/util/table.d.ts +5 -3
- package/dist/types/src/util/table.d.ts.map +1 -1
- package/package.json +37 -36
- package/src/components/Table/ColumnActionsMenu.tsx +6 -4
- package/src/components/Table/ColumnSettings.tsx +5 -6
- package/src/components/Table/CreateRefPanel.tsx +3 -3
- package/src/components/Table/DynamicTable.stories.tsx +155 -0
- package/src/components/Table/DynamicTable.tsx +104 -0
- package/src/components/Table/RefPanel.tsx +3 -3
- package/src/components/Table/RowActionsMenu.tsx +18 -3
- package/src/components/Table/Table.stories.tsx +170 -115
- package/src/components/Table/Table.tsx +71 -26
- package/src/components/Table/index.ts +1 -0
- package/src/components/Table/relations.stories.tsx +113 -0
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +15 -5
- package/src/components/TableCellEditor/TableCellEditor.tsx +102 -4
- package/src/components/testing.ts +0 -1
- package/src/hooks/useTableModel.ts +35 -14
- package/src/model/index.ts +1 -0
- package/src/model/selection-model.ts +12 -2
- package/src/model/table-model.test.ts +2 -2
- package/src/model/table-model.ts +117 -32
- package/src/model/table-presentation.test.ts +2 -2
- package/src/model/table-presentation.ts +94 -22
- package/src/model/table-sorting.ts +3 -2
- package/src/playwright/smoke.spec.ts +2 -3
- package/src/types/table.ts +9 -10
- package/src/util/dynamic-table.ts +103 -0
- package/src/util/index.ts +1 -0
- package/src/util/table-controls.ts +4 -4
- package/src/util/table.ts +68 -65
- package/dist/lib/browser/_deprecated/index.mjs +0 -1483
- package/dist/lib/browser/_deprecated/index.mjs.map +0 -7
- package/dist/lib/browser/chunk-3FR6NHPD.mjs.map +0 -7
- package/dist/lib/node/_deprecated/index.cjs +0 -1511
- package/dist/lib/node/_deprecated/index.cjs.map +0 -7
- package/dist/lib/node/chunk-NB3SFHGA.cjs.map +0 -7
- package/dist/lib/node-esm/_deprecated/index.mjs +0 -1485
- package/dist/lib/node-esm/_deprecated/index.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-RLVVOZW5.mjs.map +0 -7
- package/dist/types/src/_deprecated/components/Cell/Cell.d.ts +0 -12
- package/dist/types/src/_deprecated/components/Cell/Cell.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/Cell/CellCombobox.d.ts +0 -13
- package/dist/types/src/_deprecated/components/Cell/CellCombobox.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/Cell/index.d.ts +0 -2
- package/dist/types/src/_deprecated/components/Cell/index.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.d.ts +0 -23
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.stories.d.ts +0 -36
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.stories.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.d.ts +0 -15
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.stories.d.ts +0 -84
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.stories.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/ColumnMenu/index.d.ts +0 -3
- package/dist/types/src/_deprecated/components/ColumnMenu/index.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/Table/Table.d.ts +0 -20
- package/dist/types/src/_deprecated/components/Table/Table.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts +0 -116
- package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/Table/TableBody.d.ts +0 -12
- package/dist/types/src/_deprecated/components/Table/TableBody.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/Table/TableContext.d.ts +0 -13
- package/dist/types/src/_deprecated/components/Table/TableContext.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/Table/TableHead.d.ts +0 -9
- package/dist/types/src/_deprecated/components/Table/TableHead.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/Table/TableRootContext.d.ts +0 -17
- package/dist/types/src/_deprecated/components/Table/TableRootContext.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/Table/index.d.ts +0 -5
- package/dist/types/src/_deprecated/components/Table/index.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/Table/props.d.ts +0 -42
- package/dist/types/src/_deprecated/components/Table/props.d.ts.map +0 -1
- package/dist/types/src/_deprecated/components/index.d.ts +0 -4
- package/dist/types/src/_deprecated/components/index.d.ts.map +0 -1
- package/dist/types/src/_deprecated/helpers.d.ts +0 -91
- package/dist/types/src/_deprecated/helpers.d.ts.map +0 -1
- package/dist/types/src/_deprecated/hooks/index.d.ts +0 -5
- package/dist/types/src/_deprecated/hooks/index.d.ts.map +0 -1
- package/dist/types/src/_deprecated/hooks/useColumnSizing.d.ts +0 -12
- package/dist/types/src/_deprecated/hooks/useColumnSizing.d.ts.map +0 -1
- package/dist/types/src/_deprecated/hooks/useColumnSorting.d.ts +0 -15
- package/dist/types/src/_deprecated/hooks/useColumnSorting.d.ts.map +0 -1
- package/dist/types/src/_deprecated/hooks/usePinLastRow.d.ts +0 -3
- package/dist/types/src/_deprecated/hooks/usePinLastRow.d.ts.map +0 -1
- package/dist/types/src/_deprecated/hooks/useRowSelection.d.ts +0 -7
- package/dist/types/src/_deprecated/hooks/useRowSelection.d.ts.map +0 -1
- package/dist/types/src/_deprecated/index.d.ts +0 -8
- package/dist/types/src/_deprecated/index.d.ts.map +0 -1
- package/dist/types/src/_deprecated/schema/Schema.stories.d.ts +0 -11
- package/dist/types/src/_deprecated/schema/Schema.stories.d.ts.map +0 -1
- package/dist/types/src/_deprecated/schema/column-utils.d.ts +0 -7
- package/dist/types/src/_deprecated/schema/column-utils.d.ts.map +0 -1
- package/dist/types/src/_deprecated/schema/index.d.ts +0 -3
- package/dist/types/src/_deprecated/schema/index.d.ts.map +0 -1
- package/dist/types/src/_deprecated/schema/types.d.ts +0 -27
- package/dist/types/src/_deprecated/schema/types.d.ts.map +0 -1
- package/dist/types/src/_deprecated/theme.d.ts +0 -29
- package/dist/types/src/_deprecated/theme.d.ts.map +0 -1
- package/dist/types/src/_deprecated/translations.d.ts +0 -21
- package/dist/types/src/_deprecated/translations.d.ts.map +0 -1
- package/dist/types/src/_deprecated/types.d.ts +0 -26
- package/dist/types/src/_deprecated/types.d.ts.map +0 -1
- package/src/_deprecated/components/Cell/Cell.tsx +0 -88
- package/src/_deprecated/components/Cell/CellCombobox.tsx +0 -103
- package/src/_deprecated/components/Cell/index.ts +0 -5
- package/src/_deprecated/components/ColumnMenu/ColumnMenu.stories.tsx +0 -129
- package/src/_deprecated/components/ColumnMenu/ColumnMenu.tsx +0 -182
- package/src/_deprecated/components/ColumnMenu/ColumnSettings.stories.tsx +0 -108
- package/src/_deprecated/components/ColumnMenu/ColumnSettings.tsx +0 -207
- package/src/_deprecated/components/ColumnMenu/index.ts +0 -6
- package/src/_deprecated/components/Table/Table.stories.tsx +0 -508
- package/src/_deprecated/components/Table/Table.tsx +0 -301
- package/src/_deprecated/components/Table/TableBody.tsx +0 -82
- package/src/_deprecated/components/Table/TableContext.tsx +0 -34
- package/src/_deprecated/components/Table/TableHead.tsx +0 -78
- package/src/_deprecated/components/Table/TableRootContext.ts +0 -39
- package/src/_deprecated/components/Table/index.ts +0 -8
- package/src/_deprecated/components/Table/props.ts +0 -60
- package/src/_deprecated/components/index.ts +0 -7
- package/src/_deprecated/helpers.tsx +0 -526
- package/src/_deprecated/hooks/index.ts +0 -8
- package/src/_deprecated/hooks/useColumnSizing.ts +0 -46
- package/src/_deprecated/hooks/useColumnSorting.ts +0 -64
- package/src/_deprecated/hooks/usePinLastRow.ts +0 -47
- package/src/_deprecated/hooks/useRowSelection.ts +0 -40
- package/src/_deprecated/index.ts +0 -12
- package/src/_deprecated/schema/Schema.stories.tsx +0 -59
- package/src/_deprecated/schema/column-utils.ts +0 -54
- package/src/_deprecated/schema/index.ts +0 -6
- package/src/_deprecated/schema/types.ts +0 -40
- package/src/_deprecated/theme.ts +0 -82
- package/src/_deprecated/translations.ts +0 -26
- package/src/_deprecated/types.ts +0 -38
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type Primitive } from '@radix-ui/react-primitive';
|
|
6
|
-
import { Slot } from '@radix-ui/react-slot';
|
|
7
|
-
import {
|
|
8
|
-
type GroupingState,
|
|
9
|
-
type Row,
|
|
10
|
-
type RowData,
|
|
11
|
-
getCoreRowModel,
|
|
12
|
-
getExpandedRowModel,
|
|
13
|
-
getGroupedRowModel,
|
|
14
|
-
getSortedRowModel,
|
|
15
|
-
useReactTable,
|
|
16
|
-
} from '@tanstack/react-table';
|
|
17
|
-
import React, {
|
|
18
|
-
type ComponentPropsWithoutRef,
|
|
19
|
-
type ReactNode,
|
|
20
|
-
Fragment,
|
|
21
|
-
memo,
|
|
22
|
-
useCallback,
|
|
23
|
-
useEffect,
|
|
24
|
-
useState,
|
|
25
|
-
useContext,
|
|
26
|
-
} from 'react';
|
|
27
|
-
|
|
28
|
-
import { type ThemedClassName, useDefaultValue } from '@dxos/react-ui';
|
|
29
|
-
import { mx } from '@dxos/react-ui-theme';
|
|
30
|
-
|
|
31
|
-
import { TableBody } from './TableBody';
|
|
32
|
-
import { type TypedTableProvider, TableProvider as UntypedTableProvider, useTableContext } from './TableContext';
|
|
33
|
-
import { TableHead } from './TableHead';
|
|
34
|
-
import { TableRootContext, useTableRootContext } from './TableRootContext';
|
|
35
|
-
import { type TableProps } from './props';
|
|
36
|
-
import { useColumnResizing, useColumnSorting, usePinLastRow, useRowSelection } from '../../hooks';
|
|
37
|
-
import { groupTh, tableRoot } from '../../theme';
|
|
38
|
-
|
|
39
|
-
type TableRootProps = { children: ReactNode };
|
|
40
|
-
|
|
41
|
-
const TableRoot = ({ children }: TableRootProps) => {
|
|
42
|
-
const contextValue = useTableRootContext();
|
|
43
|
-
return <TableRootContext.Provider value={contextValue}>{children}</TableRootContext.Provider>;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
type TableViewportProps = ThemedClassName<ComponentPropsWithoutRef<typeof Primitive.div>> & {
|
|
47
|
-
asChild?: boolean;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const TableViewport = ({ children, classNames, asChild, ...props }: TableViewportProps) => {
|
|
51
|
-
const { scrollContextRef } = useContext(TableRootContext);
|
|
52
|
-
|
|
53
|
-
const classes = mx(classNames, 'overflow-auto');
|
|
54
|
-
return asChild ? (
|
|
55
|
-
<Slot ref={scrollContextRef} className={classes} {...props}>
|
|
56
|
-
{children}
|
|
57
|
-
</Slot>
|
|
58
|
-
) : (
|
|
59
|
-
<div role='none' className={classes} ref={scrollContextRef} {...props}>
|
|
60
|
-
{children}
|
|
61
|
-
</div>
|
|
62
|
-
);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export const TablePrimitive = <TData extends RowData>(props: TableProps<TData>) => {
|
|
66
|
-
const {
|
|
67
|
-
role,
|
|
68
|
-
header = true,
|
|
69
|
-
rowsSelectable,
|
|
70
|
-
debug,
|
|
71
|
-
pinLastRow,
|
|
72
|
-
columnVisibility,
|
|
73
|
-
onColumnResize,
|
|
74
|
-
onDataSelectionChange,
|
|
75
|
-
} = props;
|
|
76
|
-
|
|
77
|
-
const columns = useDefaultValue(props.columns, () => []);
|
|
78
|
-
const incomingData = useDefaultValue(props.data, () => []);
|
|
79
|
-
|
|
80
|
-
const [data, setData] = useState([...incomingData]);
|
|
81
|
-
|
|
82
|
-
// Reactivity workaround: https://github.com/dxos/dxos/issues/6376.
|
|
83
|
-
const forceUpdate = useCallback(() => setData([...incomingData]), [incomingData]);
|
|
84
|
-
useEffect(() => forceUpdate(), [JSON.stringify(incomingData), forceUpdate]);
|
|
85
|
-
|
|
86
|
-
const TableProvider = UntypedTableProvider as TypedTableProvider<TData>;
|
|
87
|
-
|
|
88
|
-
const { columnSizing, setColumnSizing, columnSizingInfo, setColumnSizingInfo } = useColumnResizing({
|
|
89
|
-
columns,
|
|
90
|
-
onColumnResize,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const { rowSelection, handleRowSelectionChange } = useRowSelection(props);
|
|
94
|
-
|
|
95
|
-
const [grouping, handleGroupingChange] = useState<GroupingState>(props.grouping ?? []);
|
|
96
|
-
useEffect(() => handleGroupingChange(props.grouping ?? []), [handleGroupingChange, props.grouping]);
|
|
97
|
-
|
|
98
|
-
const columnSorting = useColumnSorting();
|
|
99
|
-
|
|
100
|
-
const table = useReactTable({
|
|
101
|
-
// Data
|
|
102
|
-
meta: {},
|
|
103
|
-
data,
|
|
104
|
-
|
|
105
|
-
// Columns
|
|
106
|
-
columns,
|
|
107
|
-
defaultColumn: {
|
|
108
|
-
size: 400, // Required in order remove default width.
|
|
109
|
-
maxSize: 1024,
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
// State
|
|
113
|
-
state: {
|
|
114
|
-
columnVisibility,
|
|
115
|
-
columnSizing,
|
|
116
|
-
columnSizingInfo,
|
|
117
|
-
sorting: columnSorting.sorting,
|
|
118
|
-
rowSelection,
|
|
119
|
-
grouping,
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
// Resize columns
|
|
123
|
-
columnResizeMode: 'onChange',
|
|
124
|
-
enableColumnResizing: true,
|
|
125
|
-
onColumnSizingChange: setColumnSizing,
|
|
126
|
-
onColumnSizingInfoChange: setColumnSizingInfo,
|
|
127
|
-
|
|
128
|
-
// Rows
|
|
129
|
-
getCoreRowModel: getCoreRowModel(),
|
|
130
|
-
getSortedRowModel: getSortedRowModel(),
|
|
131
|
-
getExpandedRowModel: getExpandedRowModel(),
|
|
132
|
-
|
|
133
|
-
// Grouping
|
|
134
|
-
getGroupedRowModel: grouping.length > 1 ? getGroupedRowModel() : undefined,
|
|
135
|
-
onGroupingChange: handleGroupingChange,
|
|
136
|
-
|
|
137
|
-
enableMultiRowSelection: rowsSelectable === 'multi' ? true : undefined,
|
|
138
|
-
enableRowSelection: rowsSelectable === true ? true : undefined,
|
|
139
|
-
|
|
140
|
-
onRowSelectionChange: handleRowSelectionChange,
|
|
141
|
-
|
|
142
|
-
enableSorting: true,
|
|
143
|
-
enableColumnPinning: true,
|
|
144
|
-
|
|
145
|
-
// Debug
|
|
146
|
-
debugTable: debug,
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
useEffect(() => {
|
|
150
|
-
onDataSelectionChange?.(Object.keys(rowSelection).map((id) => table.getRowModel().rowsById[id].original));
|
|
151
|
-
}, [onDataSelectionChange, rowSelection, table]);
|
|
152
|
-
|
|
153
|
-
usePinLastRow(pinLastRow, table, data);
|
|
154
|
-
|
|
155
|
-
// Create additional expansion column if all columns have fixed width.
|
|
156
|
-
const expand = false; // columns.map((column) => column.size).filter(Boolean).length === columns?.length;
|
|
157
|
-
|
|
158
|
-
return (
|
|
159
|
-
<TableProvider
|
|
160
|
-
{...{ ...props, ...columnSorting }}
|
|
161
|
-
table={table}
|
|
162
|
-
header={header}
|
|
163
|
-
expand={expand}
|
|
164
|
-
isGrid={role === 'grid' || role === 'treegrid'}
|
|
165
|
-
>
|
|
166
|
-
<TableImpl<TData> debug={false} {...props} />
|
|
167
|
-
</TableProvider>
|
|
168
|
-
);
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
// TODO(zan): Smush this into the Table component.
|
|
172
|
-
/**
|
|
173
|
-
* Pure implementation of table outside of context set-up.
|
|
174
|
-
*/
|
|
175
|
-
const TableImpl = <TData extends RowData>(props: TableProps<TData>) => {
|
|
176
|
-
const { debug, classNames, role, grouping, fullWidth } = props;
|
|
177
|
-
const { table } = useTableContext<TData>();
|
|
178
|
-
|
|
179
|
-
if (debug) {
|
|
180
|
-
return (
|
|
181
|
-
<pre className='font-mono text-xs text-neutral-500 m-1 p-2 ring'>
|
|
182
|
-
<code>{JSON.stringify(table.getState(), undefined, 2)}</code>
|
|
183
|
-
</pre>
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const isResizingColumn = table.getState().columnSizingInfo.isResizingColumn;
|
|
188
|
-
|
|
189
|
-
const TableComponent = isResizingColumn ? MemoizedVirtualizedTableContent : VirtualizedTableContent;
|
|
190
|
-
|
|
191
|
-
return (
|
|
192
|
-
<table
|
|
193
|
-
role={role}
|
|
194
|
-
className={tableRoot(props, classNames)}
|
|
195
|
-
style={{
|
|
196
|
-
// borderCollapse: 'separate',
|
|
197
|
-
borderSpacing: 0,
|
|
198
|
-
...(!fullWidth && { width: table.getTotalSize() }),
|
|
199
|
-
}}
|
|
200
|
-
>
|
|
201
|
-
<TableHead />
|
|
202
|
-
|
|
203
|
-
{grouping?.length !== 0 ? <TableComponent /> : <GroupedTableContent />}
|
|
204
|
-
</table>
|
|
205
|
-
);
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
const VirtualizedTableContent = () => {
|
|
209
|
-
const { table } = useTableContext();
|
|
210
|
-
const { virtualizer, dispatch } = useContext(TableRootContext);
|
|
211
|
-
|
|
212
|
-
const centerRows = table.getCenterRows();
|
|
213
|
-
let pinnedRows = [] as Row<unknown>[];
|
|
214
|
-
|
|
215
|
-
useEffect(() => {
|
|
216
|
-
dispatch({ type: 'updateTableCount', count: centerRows.length });
|
|
217
|
-
}, [centerRows.length]);
|
|
218
|
-
|
|
219
|
-
try {
|
|
220
|
-
// TODO(zan): Work out how to sync the row pinning with rendering
|
|
221
|
-
// This is a hack because the first call to this function after a row is deleted will throw an error
|
|
222
|
-
// because the row index is no longer in the table
|
|
223
|
-
// The pin last row hook updates the pinned row key after the row is deleted
|
|
224
|
-
pinnedRows = table.getBottomRows();
|
|
225
|
-
} catch (_) {} // Ignore error
|
|
226
|
-
|
|
227
|
-
const { getTotalSize, getVirtualItems } = virtualizer;
|
|
228
|
-
|
|
229
|
-
const virtualRows = getVirtualItems();
|
|
230
|
-
const totalSize = getTotalSize();
|
|
231
|
-
|
|
232
|
-
const paddingTop = virtualRows.length > 0 ? virtualRows?.[0]?.start || 0 : 0;
|
|
233
|
-
const paddingBottom = virtualRows.length > 0 ? totalSize - (virtualRows?.[virtualRows.length - 1]?.end || 0) : 0;
|
|
234
|
-
|
|
235
|
-
const rowsToRender = [...virtualRows.map((virtualRow) => centerRows[virtualRow.index]), ...pinnedRows].filter(
|
|
236
|
-
(r) => !!r,
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
return (
|
|
240
|
-
<Fragment>
|
|
241
|
-
{paddingTop > 0 && (
|
|
242
|
-
<tbody role='none'>
|
|
243
|
-
<tr role='none'>
|
|
244
|
-
<td style={{ height: `${paddingTop}px` }} role='none' />
|
|
245
|
-
</tr>
|
|
246
|
-
</tbody>
|
|
247
|
-
)}
|
|
248
|
-
<TableBody rows={rowsToRender} />
|
|
249
|
-
{paddingBottom > 0 && (
|
|
250
|
-
<tbody role='none'>
|
|
251
|
-
<tr role='none'>
|
|
252
|
-
<td style={{ height: `${paddingBottom}px` }} role='none' />
|
|
253
|
-
</tr>
|
|
254
|
-
</tbody>
|
|
255
|
-
)}
|
|
256
|
-
</Fragment>
|
|
257
|
-
);
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
export const MemoizedVirtualizedTableContent = memo(VirtualizedTableContent);
|
|
261
|
-
|
|
262
|
-
const GroupedTableContent = () => {
|
|
263
|
-
const {
|
|
264
|
-
table: { getGroupedRowModel, getHeaderGroups, getState },
|
|
265
|
-
debug,
|
|
266
|
-
} = useTableContext();
|
|
267
|
-
|
|
268
|
-
return (
|
|
269
|
-
<>
|
|
270
|
-
{getGroupedRowModel().rows.map((row, i) => {
|
|
271
|
-
return (
|
|
272
|
-
<Fragment key={i}>
|
|
273
|
-
{/* TODO(burdon): Customize group header renderer. */}
|
|
274
|
-
<thead>
|
|
275
|
-
<tr>
|
|
276
|
-
{debug && <th />}
|
|
277
|
-
<th
|
|
278
|
-
// TODO(burdon): Calculate row span.
|
|
279
|
-
colSpan={getHeaderGroups()[0].headers.length}
|
|
280
|
-
className={groupTh({})}
|
|
281
|
-
>
|
|
282
|
-
{getState().grouping[0]}[{String(row.getGroupingValue(getState().grouping[0]))}]
|
|
283
|
-
</th>
|
|
284
|
-
</tr>
|
|
285
|
-
</thead>
|
|
286
|
-
<TableBody rows={row.subRows} />
|
|
287
|
-
</Fragment>
|
|
288
|
-
);
|
|
289
|
-
})}
|
|
290
|
-
</>
|
|
291
|
-
);
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
// TODO(burdon): Floating "add row" jumps by 1 pixel on scroll.
|
|
295
|
-
// TODO(burdon): Blue focus highlight is clipped by 1px on the left.
|
|
296
|
-
// TODO(burdon): Focused row and focus ring passes over the sticky header.
|
|
297
|
-
export const Table = {
|
|
298
|
-
Root: TableRoot,
|
|
299
|
-
Viewport: TableViewport,
|
|
300
|
-
Main: TablePrimitive,
|
|
301
|
-
};
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { useArrowNavigationGroup } from '@fluentui/react-tabster';
|
|
6
|
-
import { flexRender, type Row, type RowData } from '@tanstack/react-table';
|
|
7
|
-
import React, { useContext } from 'react';
|
|
8
|
-
|
|
9
|
-
import { useTableContext } from './TableContext';
|
|
10
|
-
import { TableRootContext } from './TableRootContext';
|
|
11
|
-
import { tbodyTr } from '../../theme';
|
|
12
|
-
import { Cell } from '../Cell/Cell';
|
|
13
|
-
|
|
14
|
-
const TABLE_BODY_NAME = 'TableBody';
|
|
15
|
-
|
|
16
|
-
type TableBodyProps = {
|
|
17
|
-
rows: Row<RowData>[];
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const TableBody = ({ rows }: TableBodyProps) => {
|
|
21
|
-
const { table, keyAccessor, currentDatum, debug, expand, isGrid, onDatumClick } = useTableContext();
|
|
22
|
-
|
|
23
|
-
const rowSelection = table.getState().rowSelection;
|
|
24
|
-
const arrowNavigationAttrs = useArrowNavigationGroup({ axis: 'grid' });
|
|
25
|
-
const canBeCurrent = !isGrid && !!onDatumClick;
|
|
26
|
-
|
|
27
|
-
const { virtualizer } = useContext(TableRootContext);
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<tbody {...(isGrid && arrowNavigationAttrs)}>
|
|
31
|
-
{rows.map((row) => {
|
|
32
|
-
const isCurrent = currentDatum === row.original;
|
|
33
|
-
const isSelected = rowSelection?.[row.id];
|
|
34
|
-
|
|
35
|
-
const isPinned = row.getIsPinned();
|
|
36
|
-
|
|
37
|
-
const classNames = tbodyTr({ canBeCurrent, isPinned: isPinned !== false });
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<tr
|
|
41
|
-
key={keyAccessor ? keyAccessor(row.original) : row.id}
|
|
42
|
-
className={classNames}
|
|
43
|
-
data-index={row.index}
|
|
44
|
-
data-testid={'table.data-row'}
|
|
45
|
-
ref={virtualizer.measureElement}
|
|
46
|
-
{...(isCurrent && { 'aria-current': 'location' })}
|
|
47
|
-
{...(isSelected && { 'aria-selected': 'true' })}
|
|
48
|
-
{...(canBeCurrent && {
|
|
49
|
-
tabIndex: 0,
|
|
50
|
-
onClick: () => {
|
|
51
|
-
onDatumClick(row.original);
|
|
52
|
-
},
|
|
53
|
-
onKeyUp: ({ key }) => {
|
|
54
|
-
if (key === 'Enter' || key === ' ') {
|
|
55
|
-
onDatumClick(row.original);
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
})}
|
|
59
|
-
>
|
|
60
|
-
{debug && <td>{row.id}</td>}
|
|
61
|
-
|
|
62
|
-
{row.getVisibleCells().map((cell) => {
|
|
63
|
-
return (
|
|
64
|
-
<Cell key={cell.id} cell={cell}>
|
|
65
|
-
{flexRender(cell.column.columnDef.cell, { ...cell.getContext() })}
|
|
66
|
-
</Cell>
|
|
67
|
-
);
|
|
68
|
-
})}
|
|
69
|
-
|
|
70
|
-
{expand && <td />}
|
|
71
|
-
</tr>
|
|
72
|
-
);
|
|
73
|
-
})}
|
|
74
|
-
</tbody>
|
|
75
|
-
);
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
TableBody.displayName = TABLE_BODY_NAME;
|
|
79
|
-
|
|
80
|
-
export { TableBody };
|
|
81
|
-
|
|
82
|
-
export type { TableBodyProps };
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type RowData } from '@tanstack/react-table';
|
|
6
|
-
import React, {
|
|
7
|
-
useContext,
|
|
8
|
-
createContext,
|
|
9
|
-
type Context,
|
|
10
|
-
type JSX,
|
|
11
|
-
type PropsWithChildren,
|
|
12
|
-
type ReactNode,
|
|
13
|
-
} from 'react';
|
|
14
|
-
|
|
15
|
-
import { raise } from '@dxos/debug';
|
|
16
|
-
|
|
17
|
-
import { type TableContextValue } from './props';
|
|
18
|
-
|
|
19
|
-
export const TABLE_NAME = 'Table';
|
|
20
|
-
|
|
21
|
-
const TableContext = createContext<TableContextValue<RowData> | undefined>(undefined);
|
|
22
|
-
|
|
23
|
-
export type TypedTableProvider<TData extends RowData> = {
|
|
24
|
-
(props: TableContextValue<TData> & { children: ReactNode }): JSX.Element;
|
|
25
|
-
displayName: string;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const TableProvider = ({ children, ...value }: PropsWithChildren<TableContextValue<RowData>>) => {
|
|
29
|
-
return <TableContext.Provider value={value}>{children}</TableContext.Provider>;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export const useTableContext = <TData extends RowData>(): TableContextValue<TData> => {
|
|
33
|
-
return useContext(TableContext as Context<TableContextValue<TData>>) ?? raise(new Error('Missing TableContext'));
|
|
34
|
-
};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { flexRender } from '@tanstack/react-table';
|
|
6
|
-
import React from 'react';
|
|
7
|
-
|
|
8
|
-
import { defaultSizeCol } from '@dxos/react-ui-grid';
|
|
9
|
-
|
|
10
|
-
import { useTableContext } from './TableContext';
|
|
11
|
-
import { theadResizeRoot, theadRoot, theadTh, theadTr } from '../../theme';
|
|
12
|
-
|
|
13
|
-
const TABLE_HEAD_NAME = 'TableHeader';
|
|
14
|
-
|
|
15
|
-
type TableHeadProps = {};
|
|
16
|
-
|
|
17
|
-
const TableHead = (_props: TableHeadProps) => {
|
|
18
|
-
const tableContext = useTableContext();
|
|
19
|
-
const headerGroups = tableContext.table.getHeaderGroups();
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<thead className={theadRoot(tableContext)}>
|
|
23
|
-
{headerGroups.map((headerGroup) => {
|
|
24
|
-
return (
|
|
25
|
-
// Group element to hover resize handles.
|
|
26
|
-
<tr key={headerGroup.id} className={theadTr(tableContext)}>
|
|
27
|
-
{/* TODO(burdon): Calc. width. */}
|
|
28
|
-
{tableContext.debug && (
|
|
29
|
-
<th className='font-mono' style={{ width: defaultSizeCol }}>
|
|
30
|
-
#
|
|
31
|
-
</th>
|
|
32
|
-
)}
|
|
33
|
-
|
|
34
|
-
{headerGroup.headers.map((header) => {
|
|
35
|
-
const isResizing = header.column.getIsResizing();
|
|
36
|
-
const onResize = header.getResizeHandler();
|
|
37
|
-
const resizable = header.column.columnDef.meta?.resizable;
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<th
|
|
41
|
-
key={header.id}
|
|
42
|
-
style={{ width: header.getSize() }}
|
|
43
|
-
className={theadTh(tableContext, header.column.columnDef.meta?.header?.classNames)}
|
|
44
|
-
data-testid='table.header-cell'
|
|
45
|
-
>
|
|
46
|
-
{!header || header.isPlaceholder
|
|
47
|
-
? null
|
|
48
|
-
: flexRender(header.column.columnDef.header, header.getContext())}
|
|
49
|
-
|
|
50
|
-
{/*
|
|
51
|
-
* Resize handle.
|
|
52
|
-
* https://codesandbox.io/p/sandbox/github/tanstack/table/tree/main/examples/react/column-sizing
|
|
53
|
-
*/}
|
|
54
|
-
{resizable && (
|
|
55
|
-
<div
|
|
56
|
-
className={theadResizeRoot({ isResizing })}
|
|
57
|
-
onDoubleClick={header.column.resetSize} // TODO(zan): How should non-pointer users reset column sizing?
|
|
58
|
-
onMouseDown={onResize}
|
|
59
|
-
onTouchStart={onResize}
|
|
60
|
-
/>
|
|
61
|
-
)}
|
|
62
|
-
</th>
|
|
63
|
-
);
|
|
64
|
-
})}
|
|
65
|
-
|
|
66
|
-
{tableContext.expand && <th />}
|
|
67
|
-
</tr>
|
|
68
|
-
);
|
|
69
|
-
})}
|
|
70
|
-
</thead>
|
|
71
|
-
);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
TableHead.displayName = TABLE_HEAD_NAME;
|
|
75
|
-
|
|
76
|
-
export { TableHead };
|
|
77
|
-
|
|
78
|
-
export type { TableHeadProps };
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
6
|
-
import { createContext, useRef, useState } from 'react';
|
|
7
|
-
|
|
8
|
-
type TableRootContextActions = { type: 'updateTableCount'; count: number };
|
|
9
|
-
|
|
10
|
-
export const useTableRootContext = () => {
|
|
11
|
-
const scrollContextRef = useRef<HTMLDivElement>(null);
|
|
12
|
-
const [tableCount, setTableCount] = useState(0);
|
|
13
|
-
|
|
14
|
-
const virtualizer = useVirtualizer({
|
|
15
|
-
getScrollElement: () => scrollContextRef?.current ?? null,
|
|
16
|
-
count: tableCount,
|
|
17
|
-
overscan: 8,
|
|
18
|
-
estimateSize: () => 40,
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
const dispatch = (action: TableRootContextActions) => {
|
|
22
|
-
switch (action.type) {
|
|
23
|
-
case 'updateTableCount':
|
|
24
|
-
setTableCount(action.count);
|
|
25
|
-
break;
|
|
26
|
-
|
|
27
|
-
default:
|
|
28
|
-
break;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
return { scrollContextRef, virtualizer, dispatch };
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export type TableRootContextValue = ReturnType<typeof useTableRootContext>;
|
|
36
|
-
|
|
37
|
-
// Create the context without a default value.
|
|
38
|
-
// The expectation is that the provider will always supply a value, so no need to define a default here.
|
|
39
|
-
export const TableRootContext = createContext<TableRootContextValue>({} as TableRootContextValue);
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type RowData, type RowSelectionState, type Table, type VisibilityState } from '@tanstack/react-table';
|
|
6
|
-
|
|
7
|
-
import { type ClassNameValue } from '@dxos/react-ui-types';
|
|
8
|
-
|
|
9
|
-
import { type ColumnSorting } from '../../hooks';
|
|
10
|
-
import { type KeyValue, type TableColumnDef } from '../../types';
|
|
11
|
-
|
|
12
|
-
export type TableFlags = Partial<{
|
|
13
|
-
role: 'table' | 'grid' | 'treegrid';
|
|
14
|
-
grouping: string[];
|
|
15
|
-
header: boolean;
|
|
16
|
-
border: boolean;
|
|
17
|
-
fullWidth: boolean;
|
|
18
|
-
debug: boolean;
|
|
19
|
-
expand: boolean;
|
|
20
|
-
stickyHeader: boolean;
|
|
21
|
-
rowsSelectable: boolean | 'multi';
|
|
22
|
-
}>;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* This is ‘current’ in the `aria-current` sense.
|
|
26
|
-
*/
|
|
27
|
-
export type TableCurrent<TData extends RowData> = Partial<{
|
|
28
|
-
// App state.
|
|
29
|
-
currentDatum: TData;
|
|
30
|
-
onDatumClick: (datum: TData) => void;
|
|
31
|
-
}>;
|
|
32
|
-
|
|
33
|
-
export type TableProps<TData extends RowData> = TableFlags &
|
|
34
|
-
TableCurrent<TData> &
|
|
35
|
-
Partial<{
|
|
36
|
-
keyAccessor: KeyValue<TData>;
|
|
37
|
-
data: TData[];
|
|
38
|
-
columns: TableColumnDef<TData>[];
|
|
39
|
-
onColumnResize: (state: Record<string, number>) => void;
|
|
40
|
-
onColumnReorder: (columnId: string, direction: 'left' | 'right') => void;
|
|
41
|
-
columnVisibility: VisibilityState;
|
|
42
|
-
// Controllable row selection.
|
|
43
|
-
rowSelection: RowSelectionState;
|
|
44
|
-
defaultRowSelection: RowSelectionState;
|
|
45
|
-
onRowSelectionChange: (rowSelection: RowSelectionState) => void;
|
|
46
|
-
// Derived from row selection.
|
|
47
|
-
onDataSelectionChange: (dataSelection: TData[]) => void;
|
|
48
|
-
// `table` element props.
|
|
49
|
-
classNames: ClassNameValue;
|
|
50
|
-
pinLastRow: boolean;
|
|
51
|
-
}>;
|
|
52
|
-
|
|
53
|
-
export type { RowSelectionState, VisibilityState, TableColumnDef, KeyValue };
|
|
54
|
-
|
|
55
|
-
export type TableContextValue<TData> = TableFlags &
|
|
56
|
-
TableCurrent<TData> &
|
|
57
|
-
Pick<TableProps<TData>, 'keyAccessor'> & {
|
|
58
|
-
table: Table<TData>;
|
|
59
|
-
isGrid: boolean;
|
|
60
|
-
} & ColumnSorting;
|