@dxos/react-ui-table 0.6.14-staging.e15392e → 0.7.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/dist/lib/browser/_deprecated/index.mjs +1483 -0
- package/dist/lib/browser/_deprecated/index.mjs.map +7 -0
- package/dist/lib/browser/chunk-A5W4XWPD.mjs +18 -0
- package/dist/lib/browser/chunk-A5W4XWPD.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1275 -1356
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/types/index.mjs +7 -0
- package/dist/lib/browser/types/index.mjs.map +7 -0
- package/dist/lib/node/_deprecated/index.cjs +1511 -0
- package/dist/lib/node/_deprecated/index.cjs.map +7 -0
- package/dist/lib/node/chunk-32IGMRME.cjs +40 -0
- package/dist/lib/node/chunk-32IGMRME.cjs.map +7 -0
- package/dist/lib/node/index.cjs +1381 -0
- package/dist/lib/node/index.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -0
- package/dist/lib/node/types/index.cjs +29 -0
- package/dist/lib/node/types/index.cjs.map +7 -0
- package/dist/lib/node-esm/_deprecated/index.mjs +1485 -0
- package/dist/lib/node-esm/_deprecated/index.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-DWQ4KGLD.mjs +20 -0
- package/dist/lib/node-esm/chunk-DWQ4KGLD.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1400 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/types/index.mjs +8 -0
- package/dist/lib/node-esm/types/index.mjs.map +7 -0
- package/dist/types/src/_deprecated/components/Cell/Cell.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/Cell/CellCombobox.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/Cell/index.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnMenu.stories.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.d.ts.map +1 -0
- package/dist/types/src/{components → _deprecated/components}/ColumnMenu/ColumnSettings.stories.d.ts +4 -4
- package/dist/types/src/_deprecated/components/ColumnMenu/ColumnSettings.stories.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/ColumnMenu/index.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/Table/Table.d.ts +20 -0
- package/dist/types/src/_deprecated/components/Table/Table.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts +116 -0
- package/dist/types/src/_deprecated/components/Table/Table.stories.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/Table/TableBody.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/Table/TableContext.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/Table/TableHead.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/Table/TableRootContext.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/Table/index.d.ts +5 -0
- package/dist/types/src/_deprecated/components/Table/index.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/Table/props.d.ts.map +1 -0
- package/dist/types/src/_deprecated/components/index.d.ts +4 -0
- package/dist/types/src/_deprecated/components/index.d.ts.map +1 -0
- package/dist/types/src/_deprecated/helpers.d.ts.map +1 -0
- package/dist/types/src/_deprecated/hooks/index.d.ts +5 -0
- package/dist/types/src/_deprecated/hooks/index.d.ts.map +1 -0
- package/dist/types/src/_deprecated/hooks/useColumnSizing.d.ts.map +1 -0
- package/dist/types/src/{hooks → _deprecated/hooks}/useColumnSorting.d.ts +1 -1
- package/dist/types/src/_deprecated/hooks/useColumnSorting.d.ts.map +1 -0
- package/dist/types/src/_deprecated/hooks/usePinLastRow.d.ts.map +1 -0
- package/dist/types/src/_deprecated/hooks/useRowSelection.d.ts.map +1 -0
- package/dist/types/src/_deprecated/index.d.ts +8 -0
- package/dist/types/src/_deprecated/index.d.ts.map +1 -0
- package/dist/types/src/_deprecated/schema/Schema.stories.d.ts.map +1 -0
- package/dist/types/src/{schema → _deprecated/schema}/column-utils.d.ts +3 -0
- package/dist/types/src/_deprecated/schema/column-utils.d.ts.map +1 -0
- package/dist/types/src/_deprecated/schema/index.d.ts.map +1 -0
- package/dist/types/src/{schema → _deprecated/schema}/types.d.ts +3 -2
- package/dist/types/src/_deprecated/schema/types.d.ts.map +1 -0
- package/dist/types/src/_deprecated/theme.d.ts.map +1 -0
- package/dist/types/src/_deprecated/translations.d.ts +21 -0
- package/dist/types/src/_deprecated/translations.d.ts.map +1 -0
- package/dist/types/src/_deprecated/types.d.ts.map +1 -0
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +8 -0
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -0
- package/dist/types/src/components/Table/ColumnSettings.d.ts +8 -0
- package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -0
- package/dist/types/src/components/Table/RowActionsMenu.d.ts +8 -0
- package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -0
- package/dist/types/src/components/Table/Table.d.ts +11 -14
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +10 -113
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/index.d.ts +0 -3
- package/dist/types/src/components/Table/index.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +17 -0
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -0
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +11 -0
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -0
- package/dist/types/src/components/TableCellEditor/extension.d.ts +12 -0
- package/dist/types/src/components/TableCellEditor/extension.d.ts.map +1 -0
- package/dist/types/src/components/TableCellEditor/index.d.ts +2 -0
- package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +21 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/common.d.ts +20 -0
- package/dist/types/src/components/Toolbar/common.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/index.d.ts +2 -0
- package/dist/types/src/components/Toolbar/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +97 -0
- package/dist/types/src/components/testing.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +1 -4
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTableModel.d.ts +15 -0
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +3 -4
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/model/index.d.ts +3 -0
- package/dist/types/src/model/index.d.ts.map +1 -0
- package/dist/types/src/model/modal-controller.d.ts +29 -0
- package/dist/types/src/model/modal-controller.d.ts.map +1 -0
- package/dist/types/src/model/selection-model.d.ts +22 -0
- package/dist/types/src/model/selection-model.d.ts.map +1 -0
- package/dist/types/src/model/table-model.d.ts +93 -0
- package/dist/types/src/model/table-model.d.ts.map +1 -0
- package/dist/types/src/model/table-model.test.d.ts +2 -0
- package/dist/types/src/model/table-model.test.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +23 -16
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +2 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/src/types/table.d.ts +106 -0
- package/dist/types/src/types/table.d.ts.map +1 -0
- package/dist/types/src/util/grid.d.ts +14 -0
- package/dist/types/src/util/grid.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +5 -0
- package/dist/types/src/util/index.d.ts.map +1 -0
- package/dist/types/src/util/signals.d.ts +6 -0
- package/dist/types/src/util/signals.d.ts.map +1 -0
- package/dist/types/src/util/table-buttons.d.ts +24 -0
- package/dist/types/src/util/table-buttons.d.ts.map +1 -0
- package/dist/types/src/util/table-controls.d.ts +21 -0
- package/dist/types/src/util/table-controls.d.ts.map +1 -0
- package/dist/types/src/util/table.d.ts +8 -0
- package/dist/types/src/util/table.d.ts.map +1 -0
- package/package.json +56 -22
- package/src/{components → _deprecated/components}/ColumnMenu/ColumnMenu.stories.tsx +4 -4
- package/src/{components → _deprecated/components}/ColumnMenu/ColumnSettings.stories.tsx +9 -9
- package/src/{components → _deprecated/components}/ColumnMenu/ColumnSettings.tsx +3 -3
- package/src/_deprecated/components/Table/Table.stories.tsx +508 -0
- package/src/_deprecated/components/Table/Table.tsx +301 -0
- package/src/{components → _deprecated/components}/Table/TableHead.tsx +3 -1
- package/src/_deprecated/components/Table/index.ts +8 -0
- package/src/_deprecated/components/index.ts +7 -0
- package/src/{helpers.tsx → _deprecated/helpers.tsx} +4 -3
- package/src/_deprecated/hooks/index.ts +8 -0
- package/src/_deprecated/index.ts +12 -0
- package/src/_deprecated/schema/column-utils.ts +54 -0
- package/src/{schema → _deprecated/schema}/types.ts +3 -2
- package/src/_deprecated/translations.ts +26 -0
- package/src/components/Table/ColumnActionsMenu.tsx +60 -0
- package/src/components/Table/ColumnSettings.tsx +76 -0
- package/src/components/Table/RowActionsMenu.tsx +36 -0
- package/src/components/Table/Table.stories.tsx +197 -467
- package/src/components/Table/Table.tsx +172 -256
- package/src/components/Table/index.ts +1 -4
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +114 -0
- package/src/components/TableCellEditor/TableCellEditor.tsx +155 -0
- package/src/components/TableCellEditor/extension.ts +62 -0
- package/src/components/TableCellEditor/index.ts +5 -0
- package/src/components/Toolbar/Toolbar.tsx +86 -0
- package/src/components/Toolbar/common.tsx +72 -0
- package/src/components/Toolbar/index.ts +5 -0
- package/src/components/index.ts +2 -3
- package/src/components/testing.ts +114 -0
- package/src/hooks/index.ts +1 -4
- package/src/hooks/useTableModel.ts +52 -0
- package/src/index.ts +5 -6
- package/src/model/index.ts +6 -0
- package/src/model/modal-controller.ts +83 -0
- package/src/model/selection-model.ts +99 -0
- package/src/model/table-model.test.ts +182 -0
- package/src/model/table-model.ts +565 -0
- package/src/translations.ts +20 -13
- package/src/types/index.ts +5 -0
- package/src/types/table.ts +13 -0
- package/src/util/grid.ts +23 -0
- package/src/util/index.ts +8 -0
- package/src/util/signals.ts +9 -0
- package/src/util/table-buttons.ts +48 -0
- package/src/util/table-controls.ts +27 -0
- package/src/util/table.ts +77 -0
- package/dist/types/src/components/Cell/Cell.d.ts.map +0 -1
- package/dist/types/src/components/Cell/CellCombobox.d.ts.map +0 -1
- package/dist/types/src/components/Cell/index.d.ts.map +0 -1
- package/dist/types/src/components/ColumnMenu/ColumnMenu.d.ts.map +0 -1
- package/dist/types/src/components/ColumnMenu/ColumnMenu.stories.d.ts.map +0 -1
- package/dist/types/src/components/ColumnMenu/ColumnSettings.d.ts.map +0 -1
- package/dist/types/src/components/ColumnMenu/ColumnSettings.stories.d.ts.map +0 -1
- package/dist/types/src/components/ColumnMenu/index.d.ts.map +0 -1
- package/dist/types/src/components/Table/TableBody.d.ts.map +0 -1
- package/dist/types/src/components/Table/TableContext.d.ts.map +0 -1
- package/dist/types/src/components/Table/TableHead.d.ts.map +0 -1
- package/dist/types/src/components/Table/TableRootContext.d.ts.map +0 -1
- package/dist/types/src/components/Table/props.d.ts.map +0 -1
- package/dist/types/src/helpers.d.ts.map +0 -1
- package/dist/types/src/hooks/useColumnSizing.d.ts.map +0 -1
- package/dist/types/src/hooks/useColumnSorting.d.ts.map +0 -1
- package/dist/types/src/hooks/usePinLastRow.d.ts.map +0 -1
- package/dist/types/src/hooks/useRowSelection.d.ts.map +0 -1
- package/dist/types/src/schema/Schema.stories.d.ts.map +0 -1
- package/dist/types/src/schema/column-utils.d.ts.map +0 -1
- package/dist/types/src/schema/index.d.ts.map +0 -1
- package/dist/types/src/schema/types.d.ts.map +0 -1
- package/dist/types/src/theme.d.ts.map +0 -1
- package/dist/types/src/types.d.ts.map +0 -1
- package/src/schema/column-utils.ts +0 -48
- /package/dist/types/src/{components → _deprecated/components}/Cell/Cell.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/Cell/CellCombobox.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/Cell/index.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/ColumnMenu/ColumnMenu.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/ColumnMenu/ColumnMenu.stories.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/ColumnMenu/ColumnSettings.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/ColumnMenu/index.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/Table/TableBody.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/Table/TableContext.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/Table/TableHead.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/Table/TableRootContext.d.ts +0 -0
- /package/dist/types/src/{components → _deprecated/components}/Table/props.d.ts +0 -0
- /package/dist/types/src/{helpers.d.ts → _deprecated/helpers.d.ts} +0 -0
- /package/dist/types/src/{hooks → _deprecated/hooks}/useColumnSizing.d.ts +0 -0
- /package/dist/types/src/{hooks → _deprecated/hooks}/usePinLastRow.d.ts +0 -0
- /package/dist/types/src/{hooks → _deprecated/hooks}/useRowSelection.d.ts +0 -0
- /package/dist/types/src/{schema → _deprecated/schema}/Schema.stories.d.ts +0 -0
- /package/dist/types/src/{schema → _deprecated/schema}/index.d.ts +0 -0
- /package/dist/types/src/{theme.d.ts → _deprecated/theme.d.ts} +0 -0
- /package/dist/types/src/{types.d.ts → _deprecated/types.d.ts} +0 -0
- /package/src/{components → _deprecated/components}/Cell/Cell.tsx +0 -0
- /package/src/{components → _deprecated/components}/Cell/CellCombobox.tsx +0 -0
- /package/src/{components → _deprecated/components}/Cell/index.ts +0 -0
- /package/src/{components → _deprecated/components}/ColumnMenu/ColumnMenu.tsx +0 -0
- /package/src/{components → _deprecated/components}/ColumnMenu/index.ts +0 -0
- /package/src/{components → _deprecated/components}/Table/TableBody.tsx +0 -0
- /package/src/{components → _deprecated/components}/Table/TableContext.tsx +0 -0
- /package/src/{components → _deprecated/components}/Table/TableRootContext.ts +0 -0
- /package/src/{components → _deprecated/components}/Table/props.ts +0 -0
- /package/src/{hooks → _deprecated/hooks}/useColumnSizing.ts +0 -0
- /package/src/{hooks → _deprecated/hooks}/useColumnSorting.ts +0 -0
- /package/src/{hooks → _deprecated/hooks}/usePinLastRow.ts +0 -0
- /package/src/{hooks → _deprecated/hooks}/useRowSelection.ts +0 -0
- /package/src/{schema → _deprecated/schema}/Schema.stories.tsx +0 -0
- /package/src/{schema → _deprecated/schema}/index.ts +0 -0
- /package/src/{theme.ts → _deprecated/theme.ts} +0 -0
- /package/src/{types.ts → _deprecated/types.ts} +0 -0
|
@@ -0,0 +1,301 @@
|
|
|
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
|
+
};
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
import { flexRender } from '@tanstack/react-table';
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
|
+
import { defaultSizeCol } from '@dxos/react-ui-grid';
|
|
9
|
+
|
|
8
10
|
import { useTableContext } from './TableContext';
|
|
9
11
|
import { theadResizeRoot, theadRoot, theadTh, theadTr } from '../../theme';
|
|
10
12
|
|
|
@@ -24,7 +26,7 @@ const TableHead = (_props: TableHeadProps) => {
|
|
|
24
26
|
<tr key={headerGroup.id} className={theadTr(tableContext)}>
|
|
25
27
|
{/* TODO(burdon): Calc. width. */}
|
|
26
28
|
{tableContext.debug && (
|
|
27
|
-
<th className='font-mono' style={{ width:
|
|
29
|
+
<th className='font-mono' style={{ width: defaultSizeCol }}>
|
|
28
30
|
#
|
|
29
31
|
</th>
|
|
30
32
|
)}
|
|
@@ -19,6 +19,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
19
19
|
import { type PublicKey } from '@dxos/keys';
|
|
20
20
|
import { log } from '@dxos/log';
|
|
21
21
|
import { type ClassNameValue, Input, Tooltip } from '@dxos/react-ui';
|
|
22
|
+
import { defaultSizeRow } from '@dxos/react-ui-grid';
|
|
22
23
|
import { getSize, mx } from '@dxos/react-ui-theme';
|
|
23
24
|
|
|
24
25
|
import { CellCombobox, useTableContext } from './components';
|
|
@@ -312,7 +313,7 @@ export class ColumnBuilder<TData extends RowData> {
|
|
|
312
313
|
: (cell) => {
|
|
313
314
|
let value = cell.getValue();
|
|
314
315
|
// TODO(burdon): Hack to support automerge.
|
|
315
|
-
if (typeof value === 'object' && (value as any)?.
|
|
316
|
+
if (typeof value === 'object' && (value as any)?.type === 'dxos.Text.v0') {
|
|
316
317
|
value = (value as any).content;
|
|
317
318
|
}
|
|
318
319
|
|
|
@@ -435,7 +436,7 @@ export class ColumnBuilder<TData extends RowData> {
|
|
|
435
436
|
>[0] {
|
|
436
437
|
return {
|
|
437
438
|
id,
|
|
438
|
-
size:
|
|
439
|
+
size: defaultSizeRow,
|
|
439
440
|
enableResizing: false,
|
|
440
441
|
meta: { onUpdate, cell: { classNames } },
|
|
441
442
|
header: ({ table }) => {
|
|
@@ -484,7 +485,7 @@ export class ColumnBuilder<TData extends RowData> {
|
|
|
484
485
|
const IconOn = on?.Icon ?? Check;
|
|
485
486
|
const IconOff = off?.Icon ?? X;
|
|
486
487
|
return {
|
|
487
|
-
size: size ??
|
|
488
|
+
size: size ?? defaultSizeRow,
|
|
488
489
|
// TODO(zan): Implement sort algorithm.
|
|
489
490
|
enableSorting: false,
|
|
490
491
|
header: (column) => <div className={'justify-center'}>{label ?? column.header.id}</div>,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
export { default as translations } from './translations';
|
|
6
|
+
|
|
7
|
+
export * from './components';
|
|
8
|
+
export * from './helpers';
|
|
9
|
+
export * from './hooks';
|
|
10
|
+
export * from './schema';
|
|
11
|
+
export * from './theme';
|
|
12
|
+
export * from './types';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type ColumnDef } from '@tanstack/react-table';
|
|
6
|
+
|
|
7
|
+
import { TypeEnum, type S } from '@dxos/echo-schema';
|
|
8
|
+
import { FormatEnum } from '@dxos/echo-schema';
|
|
9
|
+
import { mapSchemaToFields } from '@dxos/schema';
|
|
10
|
+
|
|
11
|
+
import { createColumnBuilder } from '../helpers';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @deprecated
|
|
15
|
+
*/
|
|
16
|
+
export const schemaToColumnDefs = <T>(schema: S.Schema<T, any>): ColumnDef<T, any>[] => {
|
|
17
|
+
const { helper, builder } = createColumnBuilder<T>();
|
|
18
|
+
|
|
19
|
+
return mapSchemaToFields(schema).map(({ property, type, format }) => {
|
|
20
|
+
const propertyKey = property.toString();
|
|
21
|
+
|
|
22
|
+
if (!format) {
|
|
23
|
+
switch (type) {
|
|
24
|
+
case TypeEnum.String: {
|
|
25
|
+
return helper.accessor(
|
|
26
|
+
propertyKey as any,
|
|
27
|
+
builder.string({ label: propertyKey, classNames: [property === 'id' && 'font-mono'] }),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
case TypeEnum.Number: {
|
|
31
|
+
return helper.accessor(propertyKey as any, builder.number({ label: propertyKey }));
|
|
32
|
+
}
|
|
33
|
+
case TypeEnum.Boolean: {
|
|
34
|
+
return helper.accessor(propertyKey as any, builder.switch({ label: propertyKey }));
|
|
35
|
+
}
|
|
36
|
+
default: {
|
|
37
|
+
throw new Error(`Unhandled scalar type: ${type}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
switch (format) {
|
|
43
|
+
case FormatEnum.Date: {
|
|
44
|
+
return helper.accessor(propertyKey as any, builder.date({ label: propertyKey }));
|
|
45
|
+
}
|
|
46
|
+
case FormatEnum.JSON: {
|
|
47
|
+
return helper.accessor(propertyKey as any, builder.json({ label: propertyKey, id: propertyKey }));
|
|
48
|
+
}
|
|
49
|
+
default: {
|
|
50
|
+
throw new Error(`Unhandled format: ${format}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type
|
|
5
|
+
import { type TypeEnum, type FormatEnum } from '@dxos/echo-schema';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @deprecated
|
|
@@ -21,7 +21,8 @@ export type TableDef = {
|
|
|
21
21
|
export type ColumnDef = {
|
|
22
22
|
id: string;
|
|
23
23
|
prop: string;
|
|
24
|
-
type:
|
|
24
|
+
type: TypeEnum;
|
|
25
|
+
format?: FormatEnum;
|
|
25
26
|
size?: number;
|
|
26
27
|
label?: string;
|
|
27
28
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
export const translationKey = 'table';
|
|
6
|
+
|
|
7
|
+
export default [
|
|
8
|
+
{
|
|
9
|
+
'en-US': {
|
|
10
|
+
[translationKey]: {
|
|
11
|
+
'no selection label': ' ',
|
|
12
|
+
'number column type label': 'Number',
|
|
13
|
+
'boolean column type label': 'Boolean',
|
|
14
|
+
'date column type label': 'Date',
|
|
15
|
+
'string column type label': 'Text',
|
|
16
|
+
'ref column type label': 'Reference',
|
|
17
|
+
'digits label': 'Decimal places',
|
|
18
|
+
'save label': 'Save',
|
|
19
|
+
'delete label': 'Delete',
|
|
20
|
+
'column label label': 'Label',
|
|
21
|
+
'property key label': 'Property',
|
|
22
|
+
'column type label': 'Type',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
];
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { DropdownMenu, useTranslation } from '@dxos/react-ui';
|
|
8
|
+
|
|
9
|
+
import { type TableModel } from '../../model';
|
|
10
|
+
import { translationKey } from '../../translations';
|
|
11
|
+
|
|
12
|
+
type ColumnActionsMenuProps = { model?: TableModel };
|
|
13
|
+
|
|
14
|
+
export const ColumnActionsMenu = ({ model }: ColumnActionsMenuProps) => {
|
|
15
|
+
const { t } = useTranslation(translationKey);
|
|
16
|
+
const state = model?.modalController.state.value;
|
|
17
|
+
|
|
18
|
+
if (!model || state?.type !== 'column') {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const currentSort = model.sorting;
|
|
23
|
+
const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<DropdownMenu.Root modal={false} open={state?.type === 'column'} onOpenChange={model.modalController.close}>
|
|
27
|
+
<DropdownMenu.VirtualTrigger virtualRef={model.modalController.trigger} />
|
|
28
|
+
<DropdownMenu.Portal>
|
|
29
|
+
<DropdownMenu.Content>
|
|
30
|
+
<DropdownMenu.Viewport>
|
|
31
|
+
{(!isCurrentColumnSorted || currentSort?.direction === 'asc') && (
|
|
32
|
+
<DropdownMenu.Item onClick={() => model.setSort(state.fieldId, 'desc')}>
|
|
33
|
+
{t('column action sort descending')}
|
|
34
|
+
</DropdownMenu.Item>
|
|
35
|
+
)}
|
|
36
|
+
{(!isCurrentColumnSorted || currentSort?.direction === 'desc') && (
|
|
37
|
+
<DropdownMenu.Item onClick={() => model.setSort(state.fieldId, 'asc')}>
|
|
38
|
+
{t('column action sort ascending')}
|
|
39
|
+
</DropdownMenu.Item>
|
|
40
|
+
)}
|
|
41
|
+
{isCurrentColumnSorted && (
|
|
42
|
+
<DropdownMenu.Item onClick={() => model.clearSort()}>
|
|
43
|
+
{t('column action clear sorting')}
|
|
44
|
+
</DropdownMenu.Item>
|
|
45
|
+
)}
|
|
46
|
+
{model.getColumnCount() > 1 && (
|
|
47
|
+
<DropdownMenu.Item onClick={() => model.deleteColumn(state.fieldId)}>
|
|
48
|
+
{t('column action delete')}
|
|
49
|
+
</DropdownMenu.Item>
|
|
50
|
+
)}
|
|
51
|
+
<DropdownMenu.Item onClick={() => model.modalController.openColumnSettings()}>
|
|
52
|
+
{t('column action settings')}
|
|
53
|
+
</DropdownMenu.Item>
|
|
54
|
+
</DropdownMenu.Viewport>
|
|
55
|
+
<DropdownMenu.Arrow />
|
|
56
|
+
</DropdownMenu.Content>
|
|
57
|
+
</DropdownMenu.Portal>
|
|
58
|
+
</DropdownMenu.Root>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { getSpace } from '@dxos/react-client/echo';
|
|
8
|
+
import { DropdownMenu } from '@dxos/react-ui';
|
|
9
|
+
import { FieldEditor } from '@dxos/react-ui-data';
|
|
10
|
+
import { type FieldType } from '@dxos/schema';
|
|
11
|
+
|
|
12
|
+
import { type TableModel } from '../../model';
|
|
13
|
+
|
|
14
|
+
type ColumnSettingsProps = { model?: TableModel };
|
|
15
|
+
|
|
16
|
+
export const ColumnSettings = ({ model }: ColumnSettingsProps) => {
|
|
17
|
+
const [newField, setNewField] = useState<FieldType>();
|
|
18
|
+
const state = model?.modalController.state.value;
|
|
19
|
+
|
|
20
|
+
const space = getSpace(model?.table);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (state?.type === 'columnSettings' && state.mode.type === 'create' && model?.projection) {
|
|
24
|
+
setNewField(model.projection.createFieldProjection());
|
|
25
|
+
} else {
|
|
26
|
+
setNewField(undefined);
|
|
27
|
+
}
|
|
28
|
+
}, [model?.projection, state]);
|
|
29
|
+
|
|
30
|
+
const existingField = useMemo(() => {
|
|
31
|
+
if (state?.type === 'columnSettings') {
|
|
32
|
+
const { mode } = state;
|
|
33
|
+
if (mode.type === 'edit') {
|
|
34
|
+
return model?.table?.view?.fields.find((f) => f.id === mode.fieldId);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}, [model?.table?.view?.fields, state]);
|
|
39
|
+
|
|
40
|
+
const field = existingField ?? newField;
|
|
41
|
+
|
|
42
|
+
const handleClose = useCallback(() => {
|
|
43
|
+
model?.modalController.close();
|
|
44
|
+
}, [model?.modalController]);
|
|
45
|
+
|
|
46
|
+
const handleCancel = useCallback(() => {
|
|
47
|
+
if (state?.type === 'columnSettings' && state.mode.type === 'create' && newField) {
|
|
48
|
+
model?.projection?.deleteFieldProjection(newField.id);
|
|
49
|
+
}
|
|
50
|
+
}, [model?.projection, state, newField]);
|
|
51
|
+
|
|
52
|
+
if (!model?.table?.view || !model.projection || !field) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<DropdownMenu.Root modal={false} open={state?.type === 'columnSettings'}>
|
|
58
|
+
<DropdownMenu.VirtualTrigger virtualRef={model.modalController.trigger} />
|
|
59
|
+
<DropdownMenu.Portal>
|
|
60
|
+
<DropdownMenu.Content classNames='md:is-64'>
|
|
61
|
+
<DropdownMenu.Viewport>
|
|
62
|
+
<FieldEditor
|
|
63
|
+
view={model.table.view}
|
|
64
|
+
projection={model.projection}
|
|
65
|
+
field={field}
|
|
66
|
+
registry={space?.db.schemaRegistry}
|
|
67
|
+
onClose={handleClose}
|
|
68
|
+
onCancel={handleCancel}
|
|
69
|
+
/>
|
|
70
|
+
</DropdownMenu.Viewport>
|
|
71
|
+
<DropdownMenu.Arrow />
|
|
72
|
+
</DropdownMenu.Content>
|
|
73
|
+
</DropdownMenu.Portal>
|
|
74
|
+
</DropdownMenu.Root>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { DropdownMenu, useTranslation } from '@dxos/react-ui';
|
|
8
|
+
|
|
9
|
+
import { type TableModel } from '../../model';
|
|
10
|
+
import { translationKey } from '../../translations';
|
|
11
|
+
|
|
12
|
+
type RowActionsMenuProps = { model: TableModel };
|
|
13
|
+
|
|
14
|
+
export const RowActionsMenu = ({ model }: RowActionsMenuProps) => {
|
|
15
|
+
const { t } = useTranslation(translationKey);
|
|
16
|
+
const state = model.modalController.state.value;
|
|
17
|
+
const hasSelection = model.selection.hasSelection.value;
|
|
18
|
+
|
|
19
|
+
if (state?.type !== 'row') {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<DropdownMenu.Root modal={false} open={true} onOpenChange={model.modalController.close}>
|
|
25
|
+
<DropdownMenu.VirtualTrigger virtualRef={model.modalController.trigger} />
|
|
26
|
+
<DropdownMenu.Content>
|
|
27
|
+
<DropdownMenu.Viewport>
|
|
28
|
+
<DropdownMenu.Item onClick={() => model.deleteRow(state.rowIndex)}>
|
|
29
|
+
{t(hasSelection ? 'bulk delete row label' : 'delete row label')}
|
|
30
|
+
</DropdownMenu.Item>
|
|
31
|
+
</DropdownMenu.Viewport>
|
|
32
|
+
<DropdownMenu.Arrow />
|
|
33
|
+
</DropdownMenu.Content>
|
|
34
|
+
</DropdownMenu.Root>
|
|
35
|
+
);
|
|
36
|
+
};
|