@dxos/react-ui-table 0.8.1-main.ba2dec9 → 0.8.1-staging.31c3ee1
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 +38 -37
- 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 +1 -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
|
@@ -4,61 +4,73 @@
|
|
|
4
4
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
|
-
import { type Meta } from '@storybook/react';
|
|
8
|
-
import React, { useCallback,
|
|
7
|
+
import { type StoryObj, type Meta } from '@storybook/react';
|
|
8
|
+
import React, { useCallback, useMemo, useRef } from 'react';
|
|
9
9
|
|
|
10
|
+
import { FormatEnum, ImmutableSchema } from '@dxos/echo-schema';
|
|
10
11
|
import { invariant } from '@dxos/invariant';
|
|
11
12
|
import { useGlobalFilteredObjects } from '@dxos/plugin-search';
|
|
12
13
|
import { faker } from '@dxos/random';
|
|
14
|
+
import { useClient } from '@dxos/react-client';
|
|
13
15
|
import { Filter, useQuery, useSchema, create } from '@dxos/react-client/echo';
|
|
14
16
|
import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
|
|
15
|
-
import { useDefaultValue } from '@dxos/react-ui';
|
|
16
17
|
import { ViewEditor } from '@dxos/react-ui-form';
|
|
17
18
|
import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
|
|
18
|
-
import { ViewProjection, ViewType } from '@dxos/schema';
|
|
19
|
+
import { getSchemaFromPropertyDefinitions, ViewProjection, ViewType } from '@dxos/schema';
|
|
20
|
+
import { Testing, createObjectFactory } from '@dxos/schema/testing';
|
|
19
21
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
20
22
|
|
|
21
23
|
import { Table, type TableController } from './Table';
|
|
22
|
-
import { useTableModel
|
|
24
|
+
import { useTableModel } from '../../hooks';
|
|
23
25
|
import { TablePresentation } from '../../model';
|
|
24
26
|
import translations from '../../translations';
|
|
25
27
|
import { TableType } from '../../types';
|
|
26
28
|
import { initializeTable } from '../../util';
|
|
27
29
|
import { TableToolbar } from '../TableToolbar';
|
|
28
|
-
import { createItems, createTable, type SimulatorProps, useSimulator } from '../testing';
|
|
29
30
|
|
|
30
31
|
// NOTE(ZaymonFC): We rely on this seed being 0 in the smoke tests.
|
|
31
32
|
faker.seed(0);
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
34
|
+
/**
|
|
35
|
+
* Custom hook to create and manage a test table model for storybook demonstrations.
|
|
36
|
+
* Provides table data, schema, and handlers for table operations.
|
|
37
|
+
*/
|
|
38
|
+
const useTestTableModel = () => {
|
|
39
|
+
const client = useClient();
|
|
38
40
|
const { space } = useClientProvider();
|
|
39
|
-
invariant(space);
|
|
40
|
-
|
|
41
|
-
const tables = useQuery(space, Filter.schema(TableType));
|
|
42
|
-
const [table, setTable] = useState<TableType>();
|
|
43
|
-
const schema = useSchema(space, table?.view?.target?.query.typename);
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
setTable(table);
|
|
50
|
-
}
|
|
51
|
-
}, [space, tables]);
|
|
42
|
+
const filter = useMemo(() => Filter.schema(TableType), []);
|
|
43
|
+
const tables = useQuery(space, filter);
|
|
44
|
+
const table = useMemo(() => tables.at(0), [tables]);
|
|
45
|
+
const schema = useSchema(client, space, table?.view?.target?.query.typename);
|
|
52
46
|
|
|
53
47
|
const projection = useMemo(() => {
|
|
54
48
|
if (schema && table?.view?.target) {
|
|
55
|
-
return new ViewProjection(schema, table.view.target);
|
|
49
|
+
return new ViewProjection(schema.jsonSchema, table.view.target);
|
|
56
50
|
}
|
|
57
51
|
}, [schema, table?.view?.target]);
|
|
58
52
|
|
|
53
|
+
const features = useMemo(
|
|
54
|
+
() => ({
|
|
55
|
+
selection: { enabled: true, mode: 'multiple' as const },
|
|
56
|
+
dataEditable: true,
|
|
57
|
+
schemaEditable: !(schema instanceof ImmutableSchema),
|
|
58
|
+
}),
|
|
59
|
+
[schema],
|
|
60
|
+
);
|
|
61
|
+
|
|
59
62
|
const objects = useQuery(space, schema ? Filter.schema(schema) : Filter.nothing());
|
|
60
63
|
const filteredObjects = useGlobalFilteredObjects(objects);
|
|
61
64
|
|
|
65
|
+
const tableRef = useRef<TableController>(null);
|
|
66
|
+
const handleCellUpdate = useCallback((cell: any) => {
|
|
67
|
+
tableRef.current?.update?.(cell);
|
|
68
|
+
}, []);
|
|
69
|
+
|
|
70
|
+
const handleRowOrderChange = useCallback(() => {
|
|
71
|
+
tableRef.current?.update?.();
|
|
72
|
+
}, []);
|
|
73
|
+
|
|
62
74
|
const handleInsertRow = useCallback(() => {
|
|
63
75
|
if (space && schema) {
|
|
64
76
|
space.db.add(create(schema, {}));
|
|
@@ -68,7 +80,7 @@ const DefaultStory = () => {
|
|
|
68
80
|
const handleDeleteRows = useCallback(
|
|
69
81
|
(_: number, objects: any[]) => {
|
|
70
82
|
for (const object of objects) {
|
|
71
|
-
space
|
|
83
|
+
space?.db.remove(object);
|
|
72
84
|
}
|
|
73
85
|
},
|
|
74
86
|
[space],
|
|
@@ -80,27 +92,19 @@ const DefaultStory = () => {
|
|
|
80
92
|
projection.deleteFieldProjection(fieldId);
|
|
81
93
|
}
|
|
82
94
|
},
|
|
83
|
-
[
|
|
95
|
+
[projection],
|
|
84
96
|
);
|
|
85
97
|
|
|
86
|
-
const tableRef = useRef<TableController>(null);
|
|
87
|
-
const handleCellUpdate = useCallback((cell: any) => {
|
|
88
|
-
tableRef.current?.update?.(cell);
|
|
89
|
-
}, []);
|
|
90
|
-
|
|
91
|
-
const handleRowOrderChanged = useCallback(() => {
|
|
92
|
-
tableRef.current?.update?.();
|
|
93
|
-
}, []);
|
|
94
|
-
|
|
95
98
|
const model = useTableModel({
|
|
96
99
|
table,
|
|
97
100
|
projection,
|
|
98
|
-
|
|
101
|
+
features,
|
|
102
|
+
rows: filteredObjects,
|
|
99
103
|
onInsertRow: handleInsertRow,
|
|
100
104
|
onDeleteRows: handleDeleteRows,
|
|
101
105
|
onDeleteColumn: handleDeleteColumn,
|
|
102
106
|
onCellUpdate: handleCellUpdate,
|
|
103
|
-
|
|
107
|
+
onRowOrderChange: handleRowOrderChange,
|
|
104
108
|
});
|
|
105
109
|
|
|
106
110
|
const presentation = useMemo(() => {
|
|
@@ -109,7 +113,7 @@ const DefaultStory = () => {
|
|
|
109
113
|
}
|
|
110
114
|
}, [model]);
|
|
111
115
|
|
|
112
|
-
const
|
|
116
|
+
const handleToolbarAction = useCallback(
|
|
113
117
|
(action: { type: string }) => {
|
|
114
118
|
switch (action.type) {
|
|
115
119
|
case 'on-thread-create': {
|
|
@@ -129,16 +133,55 @@ const DefaultStory = () => {
|
|
|
129
133
|
[table, model],
|
|
130
134
|
);
|
|
131
135
|
|
|
132
|
-
|
|
136
|
+
return {
|
|
137
|
+
schema,
|
|
138
|
+
table,
|
|
139
|
+
tableRef,
|
|
140
|
+
model,
|
|
141
|
+
presentation,
|
|
142
|
+
space,
|
|
143
|
+
handleToolbarAction,
|
|
144
|
+
handleDeleteRows,
|
|
145
|
+
handleDeleteColumn,
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const StoryViewEditor = () => {
|
|
150
|
+
const { table, space, schema, handleDeleteColumn } = useTestTableModel();
|
|
151
|
+
|
|
152
|
+
const handleTypenameChanged = useCallback(
|
|
133
153
|
(typename: string) => {
|
|
134
154
|
if (table?.view?.target) {
|
|
135
|
-
schema
|
|
155
|
+
invariant(schema);
|
|
156
|
+
schema.mutable.updateTypename(typename);
|
|
136
157
|
table.view.target.query.typename = typename;
|
|
137
158
|
}
|
|
138
159
|
},
|
|
139
|
-
[table?.view?.target
|
|
160
|
+
[schema, table?.view?.target],
|
|
140
161
|
);
|
|
141
162
|
|
|
163
|
+
if (!table || !schema || !table.view?.target) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<ViewEditor
|
|
169
|
+
registry={space?.db.schemaRegistry}
|
|
170
|
+
schema={schema}
|
|
171
|
+
view={table.view.target!}
|
|
172
|
+
onTypenameChanged={handleTypenameChanged}
|
|
173
|
+
onDelete={handleDeleteColumn}
|
|
174
|
+
/>
|
|
175
|
+
);
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
//
|
|
179
|
+
// Story components.
|
|
180
|
+
//
|
|
181
|
+
|
|
182
|
+
const DefaultStory = () => {
|
|
183
|
+
const { schema, table, tableRef, model, presentation, handleToolbarAction } = useTestTableModel();
|
|
184
|
+
|
|
142
185
|
if (!schema || !table) {
|
|
143
186
|
return <div />;
|
|
144
187
|
}
|
|
@@ -146,22 +189,13 @@ const DefaultStory = () => {
|
|
|
146
189
|
return (
|
|
147
190
|
<div className='grow grid grid-cols-[1fr_350px]'>
|
|
148
191
|
<div className='grid grid-rows-[min-content_1fr] min-bs-0 overflow-hidden'>
|
|
149
|
-
<TableToolbar classNames='border-
|
|
192
|
+
<TableToolbar classNames='border-be border-separator' onAction={handleToolbarAction} />
|
|
150
193
|
<Table.Root>
|
|
151
194
|
<Table.Main ref={tableRef} model={model} presentation={presentation} ignoreAttention />
|
|
152
195
|
</Table.Root>
|
|
153
196
|
</div>
|
|
154
197
|
<div className='flex flex-col h-full border-l border-separator overflow-y-auto'>
|
|
155
|
-
|
|
156
|
-
<ViewEditor
|
|
157
|
-
registry={space?.db.schemaRegistry}
|
|
158
|
-
schema={schema}
|
|
159
|
-
view={table.view.target!}
|
|
160
|
-
onTypenameChanged={onTypenameChanged}
|
|
161
|
-
onDelete={handleDeleteColumn}
|
|
162
|
-
/>
|
|
163
|
-
)}
|
|
164
|
-
|
|
198
|
+
<StoryViewEditor />
|
|
165
199
|
<SyntaxHighlighter language='json' className='w-full text-xs'>
|
|
166
200
|
{JSON.stringify({ view: table.view?.target, schema }, null, 2)}
|
|
167
201
|
</SyntaxHighlighter>
|
|
@@ -170,57 +204,16 @@ const DefaultStory = () => {
|
|
|
170
204
|
);
|
|
171
205
|
};
|
|
172
206
|
|
|
173
|
-
type StoryProps = {
|
|
174
|
-
rows?: number;
|
|
175
|
-
} & Pick<SimulatorProps, 'insertInterval' | 'updateInterval'>;
|
|
176
|
-
|
|
177
|
-
const _TablePerformanceStory = (props: StoryProps) => {
|
|
178
|
-
const getDefaultRows = useCallback(() => 10, []);
|
|
179
|
-
const rows = useDefaultValue(props.rows, getDefaultRows);
|
|
180
|
-
const table = useMemo(() => createTable(), []);
|
|
181
|
-
const items = useMemo(() => createItems(rows), [rows]);
|
|
182
|
-
const itemsRef = useRef(items);
|
|
183
|
-
const simulatorProps = useMemo(() => ({ table, items, ...props }), [table, items, props]);
|
|
184
|
-
useSimulator(simulatorProps);
|
|
185
|
-
|
|
186
|
-
const handleDeleteRows = useCallback<NonNullable<UseTableModelParams<any>['onDeleteRows']>>((row) => {
|
|
187
|
-
itemsRef.current.splice(row, 1);
|
|
188
|
-
}, []);
|
|
189
|
-
|
|
190
|
-
const handleDeleteColumn = useCallback<NonNullable<UseTableModelParams<any>['onDeleteColumn']>>(
|
|
191
|
-
(fieldId) => {
|
|
192
|
-
if (table && table.view?.target) {
|
|
193
|
-
const fieldPosition = table.view.target!.fields.findIndex((field) => field.id === fieldId);
|
|
194
|
-
table.view.target!.fields.splice(fieldPosition, 1);
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
[table],
|
|
198
|
-
);
|
|
199
|
-
|
|
200
|
-
const tableRef = useRef<TableController>(null);
|
|
201
|
-
const model = useTableModel({
|
|
202
|
-
table,
|
|
203
|
-
objects: items as any[],
|
|
204
|
-
onDeleteRows: handleDeleteRows,
|
|
205
|
-
onDeleteColumn: handleDeleteColumn,
|
|
206
|
-
onCellUpdate: (cell) => tableRef.current?.update?.(cell),
|
|
207
|
-
onRowOrderChanged: () => tableRef.current?.update?.(),
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
return (
|
|
211
|
-
<Table.Root>
|
|
212
|
-
<Table.Main ref={tableRef} model={model} />
|
|
213
|
-
</Table.Root>
|
|
214
|
-
);
|
|
215
|
-
};
|
|
207
|
+
type StoryProps = { rows?: number };
|
|
216
208
|
|
|
217
209
|
//
|
|
218
210
|
// Story definitions.
|
|
219
211
|
//
|
|
220
212
|
|
|
213
|
+
// TODO(burdon): Need super simple story.
|
|
214
|
+
|
|
221
215
|
const meta: Meta<StoryProps> = {
|
|
222
216
|
title: 'ui/react-ui-table/Table',
|
|
223
|
-
component: Table.Main as any,
|
|
224
217
|
render: DefaultStory,
|
|
225
218
|
parameters: { translations },
|
|
226
219
|
decorators: [
|
|
@@ -228,9 +221,9 @@ const meta: Meta<StoryProps> = {
|
|
|
228
221
|
types: [TableType, ViewType],
|
|
229
222
|
createIdentity: true,
|
|
230
223
|
createSpace: true,
|
|
231
|
-
onSpaceCreated: async ({ space }) => {
|
|
224
|
+
onSpaceCreated: async ({ client, space }) => {
|
|
232
225
|
const table = space.db.add(create(TableType, {}));
|
|
233
|
-
const schema = await initializeTable({ space, table, initialRow: false });
|
|
226
|
+
const schema = await initializeTable({ client, space, table, initialRow: false });
|
|
234
227
|
Array.from({ length: 10 }).map(() => {
|
|
235
228
|
return space.db.add(
|
|
236
229
|
create(schema, {
|
|
@@ -249,20 +242,82 @@ export default meta;
|
|
|
249
242
|
|
|
250
243
|
export const Default = {};
|
|
251
244
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
245
|
+
export const StaticSchema: StoryObj = {
|
|
246
|
+
render: DefaultStory,
|
|
247
|
+
parameters: { translations },
|
|
248
|
+
decorators: [
|
|
249
|
+
withClientProvider({
|
|
250
|
+
types: [TableType, ViewType, Testing.Contact, Testing.Org],
|
|
251
|
+
createIdentity: true,
|
|
252
|
+
createSpace: true,
|
|
253
|
+
onSpaceCreated: async ({ client, space }) => {
|
|
254
|
+
const table = space.db.add(create(TableType, {}));
|
|
255
|
+
await initializeTable({ client, space, table, typename: Testing.Contact.typename });
|
|
256
|
+
|
|
257
|
+
const factory = createObjectFactory(space.db, faker as any);
|
|
258
|
+
await factory([
|
|
259
|
+
{ type: Testing.Contact, count: 10 },
|
|
260
|
+
{ type: Testing.Org, count: 1 },
|
|
261
|
+
]);
|
|
262
|
+
},
|
|
263
|
+
}),
|
|
264
|
+
withTheme,
|
|
265
|
+
withLayout({ fullscreen: true, tooltips: true }),
|
|
266
|
+
],
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
export const Tags: Meta<StoryProps> = {
|
|
270
|
+
title: 'ui/react-ui-table/Table',
|
|
271
|
+
render: DefaultStory,
|
|
272
|
+
parameters: { translations },
|
|
273
|
+
decorators: [
|
|
274
|
+
withClientProvider({
|
|
275
|
+
types: [TableType, ViewType],
|
|
276
|
+
createIdentity: true,
|
|
277
|
+
createSpace: true,
|
|
278
|
+
onSpaceCreated: async ({ client, space }) => {
|
|
279
|
+
// Configure schema.
|
|
280
|
+
const typename = 'example.com/SingleSelect';
|
|
281
|
+
const selectOptions = [
|
|
282
|
+
{ id: 'one', title: 'One', color: 'emerald' },
|
|
283
|
+
{ id: 'two', title: 'Two', color: 'blue' },
|
|
284
|
+
{ id: 'three', title: 'Three', color: 'indigo' },
|
|
285
|
+
{ id: 'four', title: 'Four', color: 'red' },
|
|
286
|
+
{ id: 'longer_option', title: 'LONGER OPTION', color: 'amber' },
|
|
287
|
+
];
|
|
288
|
+
|
|
289
|
+
const selectOptionIds = selectOptions.map((o) => o.id);
|
|
290
|
+
|
|
291
|
+
const schema = getSchemaFromPropertyDefinitions(typename, [
|
|
292
|
+
{
|
|
293
|
+
name: 'single',
|
|
294
|
+
format: FormatEnum.SingleSelect,
|
|
295
|
+
config: { options: selectOptions },
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
name: 'multiple',
|
|
299
|
+
format: FormatEnum.MultiSelect,
|
|
300
|
+
config: { options: selectOptions },
|
|
301
|
+
},
|
|
302
|
+
]);
|
|
303
|
+
const [storedSchema] = await space.db.schemaRegistry.register([schema]);
|
|
304
|
+
|
|
305
|
+
// Initialize table.
|
|
306
|
+
const table = space.db.add(create(TableType, {}));
|
|
307
|
+
await initializeTable({ client, space, table, initialRow: false, typename });
|
|
308
|
+
|
|
309
|
+
// Populate.
|
|
310
|
+
Array.from({ length: 10 }).map(() => {
|
|
311
|
+
return space.db.add(
|
|
312
|
+
create(storedSchema, {
|
|
313
|
+
single: faker.helpers.arrayElement([...selectOptionIds, undefined]),
|
|
314
|
+
multiple: faker.helpers.randomSubset(selectOptionIds),
|
|
315
|
+
}),
|
|
316
|
+
);
|
|
317
|
+
});
|
|
318
|
+
},
|
|
319
|
+
}),
|
|
320
|
+
withTheme,
|
|
321
|
+
withLayout({ fullscreen: true, tooltips: true }),
|
|
322
|
+
],
|
|
323
|
+
};
|
|
@@ -3,24 +3,25 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import React, {
|
|
6
|
-
|
|
6
|
+
type MouseEvent,
|
|
7
7
|
type PropsWithChildren,
|
|
8
|
+
type WheelEvent,
|
|
9
|
+
forwardRef,
|
|
8
10
|
useCallback,
|
|
9
11
|
useImperativeHandle,
|
|
10
12
|
useState,
|
|
11
|
-
type WheelEvent,
|
|
12
|
-
type MouseEvent,
|
|
13
13
|
useMemo,
|
|
14
|
+
useEffect,
|
|
14
15
|
} from 'react';
|
|
15
16
|
|
|
16
17
|
import { getValue } from '@dxos/echo-schema';
|
|
17
18
|
import { invariant } from '@dxos/invariant';
|
|
18
|
-
import { Filter
|
|
19
|
+
import { Filter } from '@dxos/react-client/echo';
|
|
19
20
|
import { useTranslation } from '@dxos/react-ui';
|
|
20
21
|
import { useAttention } from '@dxos/react-ui-attention';
|
|
21
|
-
import { type DxGridElement,
|
|
22
|
+
import { closestCell, type DxGridElement, type DxGridPosition, type GridContentProps, Grid } from '@dxos/react-ui-grid';
|
|
22
23
|
import { mx } from '@dxos/react-ui-theme';
|
|
23
|
-
import { isNotFalsy } from '@dxos/util';
|
|
24
|
+
import { isNotFalsy, safeParseInt } from '@dxos/util';
|
|
24
25
|
|
|
25
26
|
import { ColumnActionsMenu } from './ColumnActionsMenu';
|
|
26
27
|
import { ColumnSettings } from './ColumnSettings';
|
|
@@ -39,10 +40,8 @@ const inlineEndLine =
|
|
|
39
40
|
const blockEndLine =
|
|
40
41
|
'[&>.dx-grid]:before:absolute [&>.dx-grid]:before:inset-inline-0 [&>.dx-grid]:before:-block-end-px [&>.dx-grid]:before:bs-px [&>.dx-grid]:before:bg-separator';
|
|
41
42
|
|
|
42
|
-
const frozen = { frozenRowsStart: 1, frozenColsStart: 1, frozenColsEnd: 1 };
|
|
43
|
-
|
|
44
43
|
//
|
|
45
|
-
// Root
|
|
44
|
+
// Table.Root
|
|
46
45
|
//
|
|
47
46
|
|
|
48
47
|
export type TableRootProps = PropsWithChildren<{ role?: string }>;
|
|
@@ -52,8 +51,8 @@ const TableRoot = ({ children, role }: TableRootProps) => {
|
|
|
52
51
|
<div
|
|
53
52
|
role='none'
|
|
54
53
|
className={mx(
|
|
55
|
-
'relative
|
|
56
|
-
role === 'section'
|
|
54
|
+
'relative !border-separator',
|
|
55
|
+
role === 'section' // TODO(burdon): This leaks composer plugin concepts? Standardize for react-ui?
|
|
57
56
|
? 'attention-surface overflow-hidden [&_.dx-grid]:max-is-[--dx-grid-content-inline-size]'
|
|
58
57
|
: 'flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:bs-0 [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]',
|
|
59
58
|
)}
|
|
@@ -64,7 +63,7 @@ const TableRoot = ({ children, role }: TableRootProps) => {
|
|
|
64
63
|
};
|
|
65
64
|
|
|
66
65
|
//
|
|
67
|
-
// Main
|
|
66
|
+
// Table.Main
|
|
68
67
|
//
|
|
69
68
|
|
|
70
69
|
export type TableController = {
|
|
@@ -74,16 +73,46 @@ export type TableController = {
|
|
|
74
73
|
export type TableMainProps = {
|
|
75
74
|
model?: TableModel;
|
|
76
75
|
presentation?: TablePresentation;
|
|
76
|
+
// TODO(burdon): Rename since attention isn't a useful concept here? Standardize across other components. Pass property into useAttention.
|
|
77
77
|
ignoreAttention?: boolean;
|
|
78
|
+
onRowClick?: (row: any) => void;
|
|
78
79
|
};
|
|
79
80
|
|
|
80
81
|
const TableMain = forwardRef<TableController, TableMainProps>(
|
|
81
|
-
({ model, presentation, ignoreAttention }, forwardedRef) => {
|
|
82
|
+
({ model, presentation, ignoreAttention, onRowClick }, forwardedRef) => {
|
|
82
83
|
const [dxGrid, setDxGrid] = useState<DxGridElement | null>(null);
|
|
83
|
-
const { hasAttention } = useAttention(model?.
|
|
84
|
+
const { hasAttention } = useAttention(model?.id ?? 'table');
|
|
84
85
|
const { t } = useTranslation(translationKey);
|
|
85
86
|
const modals = useMemo(() => new ModalController(), []);
|
|
86
87
|
|
|
88
|
+
const frozen = useMemo(() => {
|
|
89
|
+
const noActionColumn =
|
|
90
|
+
model?.features.dataEditable === false &&
|
|
91
|
+
model?.features.schemaEditable === false &&
|
|
92
|
+
model.rowActions.length === 0;
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
frozenRowsStart: 1,
|
|
96
|
+
frozenColsStart: model?.features.selection.enabled ? 1 : 0,
|
|
97
|
+
frozenColsEnd: noActionColumn ? 0 : 1,
|
|
98
|
+
};
|
|
99
|
+
}, [model]);
|
|
100
|
+
|
|
101
|
+
// TODO(burdon): Replace useEffect below.
|
|
102
|
+
// const getCells = useCallback<GridContentProps['getCells']>(
|
|
103
|
+
// (range: DxGridRange, plane: DxGridPlane) => presentation?.getCells(range, plane) ?? {},
|
|
104
|
+
// [presentation],
|
|
105
|
+
// );
|
|
106
|
+
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (!presentation || !dxGrid) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// TODO(burdon): Pass to Grid.Content?
|
|
113
|
+
dxGrid.getCells = (range, plane) => presentation.getCells(range, plane);
|
|
114
|
+
}, [presentation, dxGrid]);
|
|
115
|
+
|
|
87
116
|
/**
|
|
88
117
|
* Provides an external controller that can be called to repaint the table.
|
|
89
118
|
*/
|
|
@@ -94,7 +123,6 @@ const TableMain = forwardRef<TableController, TableMainProps>(
|
|
|
94
123
|
return {};
|
|
95
124
|
}
|
|
96
125
|
|
|
97
|
-
dxGrid.getCells = (range, plane) => presentation.getCells(range, plane);
|
|
98
126
|
return {
|
|
99
127
|
update: (cell) => {
|
|
100
128
|
if (cell) {
|
|
@@ -111,6 +139,18 @@ const TableMain = forwardRef<TableController, TableMainProps>(
|
|
|
111
139
|
|
|
112
140
|
const handleGridClick = useCallback(
|
|
113
141
|
(event: MouseEvent) => {
|
|
142
|
+
const rowIndex = safeParseInt((event.target as HTMLElement).ariaRowIndex ?? '');
|
|
143
|
+
if (rowIndex != null) {
|
|
144
|
+
if (onRowClick) {
|
|
145
|
+
const row = model?.getRowAt(rowIndex);
|
|
146
|
+
row && onRowClick(row);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (model?.features.selection.enabled && model?.selection.selectionMode === 'single') {
|
|
150
|
+
model.selection.toggleSelectionForRowIndex(rowIndex);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
114
154
|
if (!modals) {
|
|
115
155
|
return;
|
|
116
156
|
}
|
|
@@ -197,6 +237,10 @@ const TableMain = forwardRef<TableController, TableMainProps>(
|
|
|
197
237
|
|
|
198
238
|
const handleEnter = useCallback<NonNullable<TableCellEditorProps['onEnter']>>(
|
|
199
239
|
(cell) => {
|
|
240
|
+
if (!model?.features.dataEditable) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
200
244
|
// TODO(burdon): Insert row only if bottom row isn't completely blank already.
|
|
201
245
|
if (model && cell.row === model.getRowCount() - 1) {
|
|
202
246
|
model.insertRow(cell.row);
|
|
@@ -213,6 +257,10 @@ const TableMain = forwardRef<TableController, TableMainProps>(
|
|
|
213
257
|
|
|
214
258
|
const handleKeyDown = useCallback<NonNullable<GridContentProps['onKeyDown']>>(
|
|
215
259
|
(event) => {
|
|
260
|
+
if (!model?.features.dataEditable) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
216
264
|
const cell = closestCell(event.target);
|
|
217
265
|
if (!model || !cell) {
|
|
218
266
|
return;
|
|
@@ -260,7 +308,7 @@ const TableMain = forwardRef<TableController, TableMainProps>(
|
|
|
260
308
|
const handleQuery = useCallback<NonNullable<TableCellEditorProps['onQuery']>>(
|
|
261
309
|
async ({ field, props }, text) => {
|
|
262
310
|
if (model && props.referenceSchema && field.referencePath) {
|
|
263
|
-
const space =
|
|
311
|
+
const space = model.space;
|
|
264
312
|
invariant(space);
|
|
265
313
|
const schema = space.db.schemaRegistry.getSchema(props.referenceSchema);
|
|
266
314
|
if (schema) {
|
|
@@ -291,7 +339,7 @@ const TableMain = forwardRef<TableController, TableMainProps>(
|
|
|
291
339
|
|
|
292
340
|
return [];
|
|
293
341
|
},
|
|
294
|
-
[model],
|
|
342
|
+
[model, t],
|
|
295
343
|
);
|
|
296
344
|
|
|
297
345
|
if (!model || !modals) {
|
|
@@ -299,7 +347,7 @@ const TableMain = forwardRef<TableController, TableMainProps>(
|
|
|
299
347
|
}
|
|
300
348
|
|
|
301
349
|
return (
|
|
302
|
-
<Grid.Root id={model.
|
|
350
|
+
<Grid.Root id={model.id ?? 'table-grid'}>
|
|
303
351
|
<TableCellEditor
|
|
304
352
|
model={model}
|
|
305
353
|
modals={modals}
|
|
@@ -308,32 +356,29 @@ const TableMain = forwardRef<TableController, TableMainProps>(
|
|
|
308
356
|
onQuery={handleQuery}
|
|
309
357
|
/>
|
|
310
358
|
<Grid.Content
|
|
311
|
-
onWheelCapture={handleWheel}
|
|
312
359
|
className={mx('[--dx-grid-base:var(--surface-bg)]', inlineEndLine, blockEndLine)}
|
|
313
360
|
frozen={frozen}
|
|
361
|
+
// getCells={getCells}
|
|
314
362
|
columns={model.columnMeta.value}
|
|
315
363
|
limitRows={model.getRowCount() ?? 0}
|
|
316
|
-
limitColumns={model.
|
|
364
|
+
limitColumns={model.view?.fields?.length ?? 0}
|
|
365
|
+
overscroll='trap'
|
|
317
366
|
onAxisResize={handleAxisResize}
|
|
318
367
|
onClick={handleGridClick}
|
|
319
368
|
onKeyDown={handleKeyDown}
|
|
320
|
-
|
|
369
|
+
onWheelCapture={handleWheel}
|
|
321
370
|
ref={setDxGrid}
|
|
322
371
|
/>
|
|
323
372
|
<RowActionsMenu model={model} modals={modals} />
|
|
324
373
|
<ColumnActionsMenu model={model} modals={modals} />
|
|
325
374
|
<ColumnSettings model={model} modals={modals} onNewColumn={handleNewColumn} />
|
|
326
|
-
<RefPanel model={model} modals={modals} />
|
|
327
375
|
<CreateRefPanel model={model} modals={modals} />
|
|
376
|
+
<RefPanel model={model} modals={modals} />
|
|
328
377
|
</Grid.Root>
|
|
329
378
|
);
|
|
330
379
|
},
|
|
331
380
|
);
|
|
332
381
|
|
|
333
|
-
//
|
|
334
|
-
// CellEditor
|
|
335
|
-
//
|
|
336
|
-
|
|
337
382
|
export const Table = {
|
|
338
383
|
Root: TableRoot,
|
|
339
384
|
Main: TableMain,
|