@dxos/react-ui-table 0.8.2-main.f11618f → 0.8.2-staging.42af850
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-U6LL2AVU.mjs +26 -0
- package/dist/lib/browser/chunk-U6LL2AVU.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1074 -828
- 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-TGG6OZ54.cjs → chunk-CXDGXPM6.cjs} +12 -12
- package/dist/lib/node/chunk-CXDGXPM6.cjs.map +7 -0
- package/dist/lib/node/index.cjs +1080 -837
- 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-KKLP54L3.mjs → chunk-EFSM52KQ.mjs} +10 -10
- package/dist/lib/node-esm/chunk-EFSM52KQ.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1074 -828
- 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/CreateRefPanel.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts +3 -4
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +2 -0
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +1 -0
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/relations.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +13 -0
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -0
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +3 -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/TableCellEditor/extension.d.ts.map +1 -1
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +6 -3
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +39 -39
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/model/modal-controller.d.ts.map +1 -1
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/types/table.d.ts +46 -45
- package/dist/types/src/types/table.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts +4 -3
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- 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/schema.d.ts +12 -0
- package/dist/types/src/util/schema.d.ts.map +1 -0
- package/dist/types/src/util/signals.d.ts.map +1 -1
- package/dist/types/src/util/table-controls.d.ts.map +1 -1
- package/dist/types/src/util/table.d.ts +2 -2
- package/dist/types/src/util/table.d.ts.map +1 -1
- package/dist/types/src/util/tag.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +41 -34
- package/src/components/Table/CreateRefPanel.tsx +3 -3
- package/src/components/Table/DynamicTable.stories.tsx +2 -2
- package/src/components/Table/DynamicTable.tsx +4 -5
- package/src/components/Table/Table.stories.tsx +76 -42
- package/src/components/Table/Table.tsx +8 -5
- package/src/components/Table/relations.stories.tsx +17 -20
- package/src/components/TableCellEditor/FormCellEditor.tsx +94 -0
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +10 -8
- package/src/components/TableCellEditor/TableCellEditor.tsx +45 -4
- package/src/components/TableToolbar/TableToolbar.tsx +63 -33
- package/src/components/testing.ts +7 -6
- package/src/hooks/useTableModel.ts +4 -2
- package/src/model/selection-model.ts +1 -1
- package/src/model/table-model.test.ts +4 -3
- package/src/model/table-model.ts +1 -1
- package/src/model/table-presentation.test.ts +4 -3
- package/src/model/table-presentation.ts +53 -7
- package/src/types/table.ts +16 -11
- package/src/util/dynamic-table.ts +7 -4
- package/src/util/index.ts +1 -0
- package/src/util/schema.ts +36 -0
- package/src/util/table-buttons.ts +1 -1
- package/src/util/table.ts +11 -10
- package/dist/lib/browser/chunk-YWNRUF4J.mjs +0 -26
- package/dist/lib/browser/chunk-YWNRUF4J.mjs.map +0 -7
- package/dist/lib/node/chunk-TGG6OZ54.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-KKLP54L3.mjs.map +0 -7
|
@@ -2,19 +2,23 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import { Rx } from '@effect-rx/rx-react';
|
|
6
|
+
import React, { useMemo } from 'react';
|
|
6
7
|
|
|
7
8
|
import { live } from '@dxos/live-object';
|
|
8
9
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
9
10
|
import {
|
|
11
|
+
type ActionGraphEdges,
|
|
12
|
+
type ActionGraphNodes,
|
|
13
|
+
type ActionGraphProps,
|
|
10
14
|
createGapSeparator,
|
|
11
15
|
createMenuAction,
|
|
12
16
|
type MenuAction,
|
|
13
|
-
type MenuActionHandler,
|
|
14
17
|
MenuProvider,
|
|
15
18
|
ToolbarMenu,
|
|
16
19
|
useMenuActions,
|
|
17
20
|
} from '@dxos/react-ui-menu';
|
|
21
|
+
import { rxFromSignal } from '@dxos/react-ui-menu';
|
|
18
22
|
|
|
19
23
|
import { translationKey } from '../../translations';
|
|
20
24
|
|
|
@@ -27,45 +31,71 @@ export type TableToolbarActionType = 'add-row' | 'comment' | 'save-view';
|
|
|
27
31
|
type TableToolbarState = Partial<{ viewDirty: boolean }>;
|
|
28
32
|
|
|
29
33
|
export type TableToolbarProps = ThemedClassName<
|
|
30
|
-
TableToolbarState & {
|
|
34
|
+
TableToolbarState & {
|
|
35
|
+
onAdd: () => void;
|
|
36
|
+
onSave: () => void;
|
|
37
|
+
attendableId?: string;
|
|
38
|
+
customActions?: Rx.Rx<ActionGraphProps>;
|
|
39
|
+
}
|
|
31
40
|
>;
|
|
32
41
|
|
|
33
|
-
const createTableToolbarActions = (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
const createTableToolbarActions = ({
|
|
43
|
+
state,
|
|
44
|
+
onAdd,
|
|
45
|
+
onSave,
|
|
46
|
+
customActions,
|
|
47
|
+
}: {
|
|
48
|
+
state: TableToolbarState;
|
|
49
|
+
onAdd: () => void;
|
|
50
|
+
onSave: () => void;
|
|
51
|
+
customActions?: Rx.Rx<ActionGraphProps>;
|
|
52
|
+
}) =>
|
|
53
|
+
Rx.make((get) => {
|
|
54
|
+
const add = createMenuAction<TableToolbarActionProperties>('add-row', onAdd, {
|
|
55
|
+
type: 'add-row' as const,
|
|
56
|
+
icon: 'ph--plus--regular',
|
|
57
|
+
label: ['add row', { ns: translationKey }],
|
|
58
|
+
testId: 'table.toolbar.add-row',
|
|
59
|
+
});
|
|
60
|
+
const save = createMenuAction<TableToolbarActionProperties>('save-view', onSave, {
|
|
61
|
+
type: 'save-view' as const,
|
|
62
|
+
icon: 'ph--floppy-disk--regular',
|
|
63
|
+
label: ['save view label', { ns: translationKey }],
|
|
64
|
+
testId: 'table.toolbar.save-view',
|
|
65
|
+
iconOnly: false,
|
|
66
|
+
hidden: get(rxFromSignal(() => !state.viewDirty)),
|
|
67
|
+
});
|
|
68
|
+
const gap = createGapSeparator();
|
|
69
|
+
const nodes: ActionGraphNodes = [add, save, ...gap.nodes];
|
|
70
|
+
const edges: ActionGraphEdges = nodes.map(({ id: target }) => ({ source: 'root', target }));
|
|
71
|
+
if (customActions) {
|
|
72
|
+
const custom = get(customActions);
|
|
73
|
+
nodes.push(...custom.nodes);
|
|
74
|
+
edges.push(...custom.edges);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
nodes,
|
|
78
|
+
edges,
|
|
79
|
+
};
|
|
39
80
|
});
|
|
40
|
-
const save = createMenuAction<TableToolbarActionProperties>('save-view', {
|
|
41
|
-
type: 'save-view',
|
|
42
|
-
icon: 'ph--floppy-disk--regular',
|
|
43
|
-
label: ['save view label', { ns: translationKey }],
|
|
44
|
-
testId: 'table.toolbar.save-view',
|
|
45
|
-
iconOnly: false,
|
|
46
|
-
hidden: !state.viewDirty,
|
|
47
|
-
});
|
|
48
|
-
const gap = createGapSeparator();
|
|
49
|
-
const comment = createMenuAction('comment', {
|
|
50
|
-
type: 'comment',
|
|
51
|
-
icon: 'ph--chat-text--regular',
|
|
52
|
-
label: ['create comment', { ns: translationKey }],
|
|
53
|
-
testId: 'table.toolbar.comment',
|
|
54
|
-
});
|
|
55
|
-
const nodes = [add, save, ...gap.nodes, comment];
|
|
56
|
-
return {
|
|
57
|
-
nodes,
|
|
58
|
-
edges: nodes.map(({ id: target }) => ({ source: 'root', target })),
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
81
|
|
|
62
|
-
export const TableToolbar = ({
|
|
82
|
+
export const TableToolbar = ({
|
|
83
|
+
classNames,
|
|
84
|
+
viewDirty,
|
|
85
|
+
attendableId,
|
|
86
|
+
onAdd,
|
|
87
|
+
onSave,
|
|
88
|
+
customActions,
|
|
89
|
+
}: TableToolbarProps) => {
|
|
63
90
|
const state = useMemo(() => live<TableToolbarState>({ viewDirty }), []);
|
|
64
|
-
const actionsCreator =
|
|
91
|
+
const actionsCreator = useMemo(
|
|
92
|
+
() => createTableToolbarActions({ state, onAdd, onSave, customActions }),
|
|
93
|
+
[state, onAdd, onSave, customActions],
|
|
94
|
+
);
|
|
65
95
|
const menu = useMenuActions(actionsCreator);
|
|
66
96
|
|
|
67
97
|
return (
|
|
68
|
-
<MenuProvider {...menu} attendableId={attendableId}
|
|
98
|
+
<MenuProvider {...menu} attendableId={attendableId}>
|
|
69
99
|
<ToolbarMenu classNames={classNames} />
|
|
70
100
|
</MenuProvider>
|
|
71
101
|
);
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Schema } from 'effect';
|
|
5
6
|
import { useEffect } from 'react';
|
|
6
7
|
|
|
7
|
-
import { setValue, toJsonSchema,
|
|
8
|
+
import { setValue, toJsonSchema, TypeEnum, TypedObject, FormatEnum, ObjectId } from '@dxos/echo-schema';
|
|
8
9
|
import { faker } from '@dxos/random';
|
|
9
10
|
import { live, makeRef } from '@dxos/react-client/echo';
|
|
10
11
|
import { createView, type ViewProjection } from '@dxos/schema';
|
|
@@ -12,11 +13,11 @@ import { createView, type ViewProjection } from '@dxos/schema';
|
|
|
12
13
|
import { TableType } from '../types';
|
|
13
14
|
|
|
14
15
|
export const TestSchema = TypedObject({ typename: 'example.com/type/Test', version: '0.1.0' })({
|
|
15
|
-
id:
|
|
16
|
-
name:
|
|
17
|
-
age:
|
|
18
|
-
active:
|
|
19
|
-
netWorth:
|
|
16
|
+
id: ObjectId,
|
|
17
|
+
name: Schema.optional(Schema.String),
|
|
18
|
+
age: Schema.optional(Schema.Number),
|
|
19
|
+
active: Schema.optional(Schema.Boolean),
|
|
20
|
+
netWorth: Schema.optional(Schema.Number),
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
export const createTable = (schema = TestSchema) => {
|
|
@@ -70,7 +70,9 @@ export const useTableModel = <T extends TableRow = TableRow>({
|
|
|
70
70
|
}
|
|
71
71
|
}, [model, rows]);
|
|
72
72
|
|
|
73
|
-
const {
|
|
73
|
+
const { multiSelect, clear } = useSelectionActions(
|
|
74
|
+
[table?.id, table?.view?.target?.query.typename].filter(isNonNullable),
|
|
75
|
+
);
|
|
74
76
|
|
|
75
77
|
useEffect(() => {
|
|
76
78
|
if (!model) {
|
|
@@ -79,7 +81,7 @@ export const useTableModel = <T extends TableRow = TableRow>({
|
|
|
79
81
|
|
|
80
82
|
const unsubscribe = effect(() => {
|
|
81
83
|
const selectedItems = [...model.selection.selection.value];
|
|
82
|
-
|
|
84
|
+
multiSelect(selectedItems);
|
|
83
85
|
onSelectionChanged?.(selectedItems);
|
|
84
86
|
});
|
|
85
87
|
|
|
@@ -43,7 +43,7 @@ export class SelectionModel<T extends TableRow> extends Resource {
|
|
|
43
43
|
super();
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
protected override async _open() {
|
|
46
|
+
protected override async _open(): Promise<void> {
|
|
47
47
|
const selectionWatcher = effect(() => {
|
|
48
48
|
touch(this._selection.value);
|
|
49
49
|
this._onSelectionChanged?.();
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { computed } from '@preact/signals-core';
|
|
6
|
+
import { Schema } from 'effect';
|
|
6
7
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
7
8
|
|
|
8
|
-
import {
|
|
9
|
+
import { TypedObject } from '@dxos/echo-schema';
|
|
9
10
|
import { updateCounter } from '@dxos/echo-schema/testing';
|
|
10
11
|
import { registerSignalsRuntime } from '@dxos/echo-signals';
|
|
11
12
|
import { createEchoSchema } from '@dxos/live-object/testing';
|
|
@@ -99,8 +100,8 @@ describe('TableModel', () => {
|
|
|
99
100
|
});
|
|
100
101
|
|
|
101
102
|
class Test extends TypedObject({ typename: 'example.com/type/Test', version: '0.1.0' })({
|
|
102
|
-
title:
|
|
103
|
-
completed:
|
|
103
|
+
title: Schema.String,
|
|
104
|
+
completed: Schema.Boolean,
|
|
104
105
|
}) {}
|
|
105
106
|
|
|
106
107
|
const createTableModel = (props: Partial<TableModelProps> = {}): TableModel => {
|
package/src/model/table-model.ts
CHANGED
|
@@ -202,7 +202,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
|
|
|
202
202
|
// Initialisation
|
|
203
203
|
//
|
|
204
204
|
|
|
205
|
-
protected override async _open() {
|
|
205
|
+
protected override async _open(): Promise<void> {
|
|
206
206
|
this.initializeColumnMeta();
|
|
207
207
|
this.initializeEffects();
|
|
208
208
|
this._selection = new SelectionModel(this._sorting.sortedRows, this._features.selection.mode ?? 'multiple', () =>
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Schema } from 'effect';
|
|
5
6
|
import { describe, expect, it, beforeEach } from 'vitest';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
+
import { TypedObject } from '@dxos/echo-schema';
|
|
8
9
|
import { live, makeRef } from '@dxos/live-object';
|
|
9
10
|
import { createEchoSchema } from '@dxos/live-object/testing';
|
|
10
11
|
import { createView, ViewProjection } from '@dxos/schema';
|
|
@@ -89,8 +90,8 @@ describe('TablePresentation', () => {
|
|
|
89
90
|
});
|
|
90
91
|
|
|
91
92
|
class Test extends TypedObject({ typename: 'example.com/type/Test', version: '0.1.0' })({
|
|
92
|
-
title:
|
|
93
|
-
completed:
|
|
93
|
+
title: Schema.String,
|
|
94
|
+
completed: Schema.Boolean,
|
|
94
95
|
}) {}
|
|
95
96
|
|
|
96
97
|
const createTableModel = (props: Partial<TableModelProps> = {}): TableModel => {
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { signal } from '@preact/signals-core';
|
|
6
|
+
import { isNotNullable } from 'effect/Predicate';
|
|
6
7
|
|
|
7
|
-
import { FormatEnum, getDXN, getValue } from '@dxos/echo-schema';
|
|
8
|
+
import { FormatEnum, getDXN, getValue, TypeEnum } from '@dxos/echo-schema';
|
|
8
9
|
import { cellClassesForFieldType, formatForDisplay } from '@dxos/react-ui-form';
|
|
9
10
|
import {
|
|
10
11
|
type DxGridPlane,
|
|
@@ -84,6 +85,10 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
84
85
|
return '';
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
if (props.type === 'array') {
|
|
89
|
+
return '';
|
|
90
|
+
}
|
|
91
|
+
|
|
87
92
|
switch (props.format) {
|
|
88
93
|
case FormatEnum.Boolean:
|
|
89
94
|
case FormatEnum.SingleSelect:
|
|
@@ -121,11 +126,52 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
121
126
|
cell.className = mx(classes.flat());
|
|
122
127
|
}
|
|
123
128
|
|
|
129
|
+
if (props.type === TypeEnum.Array) {
|
|
130
|
+
const targetArray = getValue(obj, field.path);
|
|
131
|
+
if (targetArray && Array.isArray(targetArray)) {
|
|
132
|
+
// TODO(ZaymonFC): For arrays of objects, objects should have a 'label' annotation on the field
|
|
133
|
+
// that can be used to render tags.
|
|
134
|
+
// TODO(ZaymonFC): Move to util.
|
|
135
|
+
const getLabel = (value: any) => {
|
|
136
|
+
// If the value is falsy, return undefined
|
|
137
|
+
// If the object is an array, check for 'name' property
|
|
138
|
+
// If the object is a primitive type (string, number, boolean) stringify
|
|
139
|
+
// If the object is an array return 'Array'
|
|
140
|
+
if (!value) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
144
|
+
return String(value);
|
|
145
|
+
}
|
|
146
|
+
if (Array.isArray(value)) {
|
|
147
|
+
return 'Array';
|
|
148
|
+
}
|
|
149
|
+
if (typeof value === 'object' && value.name) {
|
|
150
|
+
return value.name;
|
|
151
|
+
}
|
|
152
|
+
if (typeof value === 'object' && value.value) {
|
|
153
|
+
return `${value.value}`;
|
|
154
|
+
}
|
|
155
|
+
return 'Object';
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const tags = targetArray
|
|
159
|
+
.map(getLabel)
|
|
160
|
+
.filter(isNotNullable)
|
|
161
|
+
.map((title) => {
|
|
162
|
+
return `<span class="dx-tag rounded-xl" data-hue="neutral">${title}</span>`;
|
|
163
|
+
})
|
|
164
|
+
.join('');
|
|
165
|
+
|
|
166
|
+
cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1 overflow-x-auto">${tags}</div>`;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
124
170
|
if (props.format === FormatEnum.Ref && props.referenceSchema) {
|
|
125
171
|
const targetObj = getValue(obj, field.path)?.target;
|
|
126
172
|
if (targetObj) {
|
|
127
173
|
const dxn = getDXN(targetObj)?.toString();
|
|
128
|
-
cell.accessoryHtml = `<dx-ref-tag
|
|
174
|
+
cell.accessoryHtml = `<dx-ref-tag refId=${dxn} class="dx-button block is-6 pli-[3px] plb-[3px] pbe-[2px] min-bs-0 absolute inline-end-1"><dx-icon icon="ph--link-simple--regular"/></dx-ref-tag>`;
|
|
129
175
|
}
|
|
130
176
|
}
|
|
131
177
|
|
|
@@ -166,7 +212,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
166
212
|
.join(' ');
|
|
167
213
|
|
|
168
214
|
if (tags) {
|
|
169
|
-
cell.accessoryHtml = tags
|
|
215
|
+
cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1">${tags}</div>`;
|
|
170
216
|
}
|
|
171
217
|
}
|
|
172
218
|
}
|
|
@@ -206,7 +252,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
206
252
|
${direction !== undefined ? tableButtons.sort.render({ fieldId: field.id, direction }) : ''}
|
|
207
253
|
${tableButtons.columnSettings.render({ fieldId: field.id })}
|
|
208
254
|
`,
|
|
209
|
-
className: '!bg-
|
|
255
|
+
className: '!bg-toolbarSurface',
|
|
210
256
|
};
|
|
211
257
|
}
|
|
212
258
|
|
|
@@ -249,7 +295,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
249
295
|
if (!this.model.features.selection.enabled || this.model.selection.selectionMode === 'single') {
|
|
250
296
|
return {
|
|
251
297
|
[toPlaneCellIndex({ col: 0, row: 0 })]: {
|
|
252
|
-
className: '!bg-
|
|
298
|
+
className: '!bg-toolbarSurface',
|
|
253
299
|
readonly: true,
|
|
254
300
|
value: '',
|
|
255
301
|
},
|
|
@@ -263,7 +309,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
263
309
|
header: true,
|
|
264
310
|
checked: this.model.selection.allRowsSeleted.value,
|
|
265
311
|
}),
|
|
266
|
-
className: '!bg-
|
|
312
|
+
className: '!bg-toolbarSurface',
|
|
267
313
|
readonly: true,
|
|
268
314
|
value: '',
|
|
269
315
|
},
|
|
@@ -278,7 +324,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
278
324
|
disabled: (this.model.view?.fields?.length ?? 0) >= VIEW_FIELD_LIMIT,
|
|
279
325
|
})
|
|
280
326
|
: undefined,
|
|
281
|
-
className: '!bg-
|
|
327
|
+
className: '!bg-toolbarSurface',
|
|
282
328
|
readonly: true,
|
|
283
329
|
value: '',
|
|
284
330
|
},
|
package/src/types/table.ts
CHANGED
|
@@ -2,20 +2,25 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Schema } from 'effect';
|
|
6
|
+
|
|
6
7
|
// import { ThreadType } from '@dxos/plugin-space/types';
|
|
8
|
+
import { ObjectId, Ref, Expando, EchoObject, LabelAnnotation } from '@dxos/echo-schema';
|
|
7
9
|
import { ViewType } from '@dxos/schema';
|
|
8
10
|
|
|
9
|
-
export const TableSchema =
|
|
11
|
+
export const TableSchema = Schema.Struct({
|
|
10
12
|
id: ObjectId,
|
|
11
|
-
name:
|
|
12
|
-
view:
|
|
13
|
+
name: Schema.optional(Schema.String),
|
|
14
|
+
view: Schema.optional(Ref(ViewType)),
|
|
13
15
|
// TODO(burdon): Document why threads is included here?
|
|
14
|
-
threads:
|
|
15
|
-
}).
|
|
16
|
-
// TODO(burdon): Move annotation to property.
|
|
17
|
-
[LabelAnnotationId]: 'name',
|
|
18
|
-
});
|
|
16
|
+
threads: Schema.optional(Schema.Array(Ref(Expando /* ThreadType */))),
|
|
17
|
+
}).pipe(LabelAnnotation.set(['name']));
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
export
|
|
19
|
+
// TODO(burdon): Move out of react-ui-xxx.
|
|
20
|
+
export const TableType = TableSchema.pipe(
|
|
21
|
+
EchoObject({
|
|
22
|
+
typename: 'dxos.org/type/Table',
|
|
23
|
+
version: '0.1.0',
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
export interface TableType extends Schema.Schema.Type<typeof TableType> {}
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import { type Schema } from 'effect';
|
|
6
|
+
|
|
7
|
+
import { getTypename, toJsonSchema } from '@dxos/echo-schema';
|
|
8
|
+
import type { JsonSchemaType, SortDirectionType } from '@dxos/echo-schema';
|
|
6
9
|
import { live, makeRef } from '@dxos/live-object';
|
|
7
10
|
import {
|
|
8
11
|
createView,
|
|
@@ -27,7 +30,7 @@ export type TablePropertyDefinition = SchemaPropertyDefinition & Partial<Propert
|
|
|
27
30
|
* @deprecated
|
|
28
31
|
*/
|
|
29
32
|
// TODO(burdon): Remove variance.
|
|
30
|
-
export const
|
|
33
|
+
export const getBaseSchema = ({
|
|
31
34
|
typename,
|
|
32
35
|
properties,
|
|
33
36
|
jsonSchema,
|
|
@@ -36,13 +39,13 @@ export const getBaseSchems = ({
|
|
|
36
39
|
typename?: string;
|
|
37
40
|
properties?: TablePropertyDefinition[];
|
|
38
41
|
jsonSchema?: JsonSchemaType;
|
|
39
|
-
schema?:
|
|
42
|
+
schema?: Schema.Schema.AnyNoContext;
|
|
40
43
|
}): { typename: string; jsonSchema: JsonSchemaType } => {
|
|
41
44
|
if (typename && properties) {
|
|
42
45
|
const schema = getSchemaFromPropertyDefinitions(typename, properties);
|
|
43
46
|
return { typename: schema.typename, jsonSchema: schema.jsonSchema };
|
|
44
47
|
} else if (schema) {
|
|
45
|
-
return { typename: schema
|
|
48
|
+
return { typename: getTypename(schema)!, jsonSchema: toJsonSchema(schema) };
|
|
46
49
|
} else if (typename && jsonSchema) {
|
|
47
50
|
return { typename, jsonSchema };
|
|
48
51
|
} else {
|
package/src/util/index.ts
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Schema } from 'effect';
|
|
6
|
+
import { isTypeLiteral, TypeLiteral } from 'effect/SchemaAST';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates a narrowed schema from an original schema that only includes
|
|
10
|
+
* the specified paths. This allows form components to only display
|
|
11
|
+
* and edit/validate specific fields rather than the entire object.
|
|
12
|
+
*
|
|
13
|
+
* @param schema The original schema to narrow
|
|
14
|
+
* @param paths Array of field paths to extract
|
|
15
|
+
* @returns A narrowed Schema instance containing only the properties at the specified paths
|
|
16
|
+
*/
|
|
17
|
+
export const narrowSchema = <S extends Schema.Schema.AnyNoContext>(
|
|
18
|
+
schema: S,
|
|
19
|
+
paths: string[],
|
|
20
|
+
): Schema.Schema<unknown, unknown> | undefined => {
|
|
21
|
+
const ast = (schema as any)?.ast;
|
|
22
|
+
|
|
23
|
+
if (isTypeLiteral(ast)) {
|
|
24
|
+
// Filter property signatures that match any of the provided paths
|
|
25
|
+
const propertySignatures = ast.propertySignatures.filter((signature) => paths.includes(signature.name.toString()));
|
|
26
|
+
|
|
27
|
+
// If we found at least one matching property
|
|
28
|
+
if (propertySignatures.length > 0) {
|
|
29
|
+
// Create a new TypeLiteral with only the matching properties
|
|
30
|
+
const narrowType = new TypeLiteral(propertySignatures, []);
|
|
31
|
+
return Schema.make(narrowType);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return undefined;
|
|
36
|
+
};
|
|
@@ -38,7 +38,7 @@ const createButton = ({
|
|
|
38
38
|
.join(' ');
|
|
39
39
|
|
|
40
40
|
const positionClass = type === 'primary' ? 'inline-end-2' : 'inline-end-9';
|
|
41
|
-
return `<button ${attr} data-testid="${testId}" class="dx-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 ${positionClass}" ${dataAttrs} ${disabled ? 'disabled' : ''}><svg><use href="/icons.svg#${icon}"/></svg></button>`;
|
|
41
|
+
return `<button ${attr} data-testid="${testId}" class="dx-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 ${positionClass}" ${dataAttrs} ${disabled ? 'disabled' : ''}><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
const addColumnButton = {
|
package/src/util/table.ts
CHANGED
|
@@ -2,19 +2,20 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Schema } from 'effect';
|
|
6
|
+
|
|
5
7
|
import {
|
|
6
|
-
AST,
|
|
7
8
|
type EchoSchema,
|
|
8
9
|
Format,
|
|
9
10
|
FormatEnum,
|
|
10
11
|
type JsonPath,
|
|
11
12
|
type JsonProp,
|
|
12
|
-
|
|
13
|
+
Ref,
|
|
13
14
|
TypedObject,
|
|
14
15
|
TypeEnum,
|
|
15
16
|
} from '@dxos/echo-schema';
|
|
16
17
|
import { type Client, PublicKey } from '@dxos/react-client';
|
|
17
|
-
import { live,
|
|
18
|
+
import { live, type Space } from '@dxos/react-client/echo';
|
|
18
19
|
import { createFieldId, createView, getSchemaProperties, ViewProjection, type ViewType } from '@dxos/schema';
|
|
19
20
|
|
|
20
21
|
import { type TableType } from '../types';
|
|
@@ -34,7 +35,7 @@ export const initializeTable = async ({
|
|
|
34
35
|
table,
|
|
35
36
|
typename,
|
|
36
37
|
initialRow = true,
|
|
37
|
-
}: InitialiseTableProps): Promise<
|
|
38
|
+
}: InitialiseTableProps): Promise<Schema.Schema.AnyNoContext> => {
|
|
38
39
|
if (typename) {
|
|
39
40
|
const schema = await space.db.graph.getSchemaByTypename(typename, space.db);
|
|
40
41
|
if (!schema) {
|
|
@@ -43,7 +44,7 @@ export const initializeTable = async ({
|
|
|
43
44
|
|
|
44
45
|
const fields = getSchemaProperties(schema.ast).map((prop) => prop.name);
|
|
45
46
|
|
|
46
|
-
table.view =
|
|
47
|
+
table.view = Ref.make(
|
|
47
48
|
createView({
|
|
48
49
|
// TODO(ZaymonFC): Don't hardcode name?
|
|
49
50
|
name: 'View',
|
|
@@ -58,7 +59,7 @@ export const initializeTable = async ({
|
|
|
58
59
|
const [schema] = await space.db.schemaRegistry.register([ContactSchema]);
|
|
59
60
|
const fields = ContactFields;
|
|
60
61
|
|
|
61
|
-
table.view =
|
|
62
|
+
table.view = Ref.make(
|
|
62
63
|
createView({
|
|
63
64
|
name: 'View',
|
|
64
65
|
typename: schema.typename,
|
|
@@ -82,10 +83,10 @@ const ContactSchema = TypedObject({
|
|
|
82
83
|
typename: `example.com/type/${PublicKey.random().truncate()}`,
|
|
83
84
|
version: '0.1.0',
|
|
84
85
|
})({
|
|
85
|
-
name:
|
|
86
|
-
active:
|
|
87
|
-
email:
|
|
88
|
-
salary:
|
|
86
|
+
name: Schema.optional(Schema.String).annotations({ title: 'Name' }),
|
|
87
|
+
active: Schema.optional(Schema.Boolean),
|
|
88
|
+
email: Schema.optional(Format.Email),
|
|
89
|
+
salary: Schema.optional(Format.Currency()).annotations({ title: 'Salary' }),
|
|
89
90
|
});
|
|
90
91
|
|
|
91
92
|
const ContactFields = ['name', 'email', 'salary', 'active'];
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// packages/ui/react-ui-table/src/types/table.ts
|
|
2
|
-
import { EchoObject, Expando, LabelAnnotationId, ObjectId, Ref, S } from "@dxos/echo-schema";
|
|
3
|
-
import { ViewType } from "@dxos/schema";
|
|
4
|
-
var TableSchema = S.Struct({
|
|
5
|
-
id: ObjectId,
|
|
6
|
-
name: S.optional(S.String),
|
|
7
|
-
view: S.optional(Ref(ViewType)),
|
|
8
|
-
// TODO(burdon): Document why threads is included here?
|
|
9
|
-
threads: S.optional(S.Array(Ref(
|
|
10
|
-
Expando
|
|
11
|
-
/* ThreadType */
|
|
12
|
-
)))
|
|
13
|
-
}).annotations({
|
|
14
|
-
// TODO(burdon): Move annotation to property.
|
|
15
|
-
[LabelAnnotationId]: "name"
|
|
16
|
-
});
|
|
17
|
-
var TableType = TableSchema.pipe(EchoObject({
|
|
18
|
-
typename: "dxos.org/type/Table",
|
|
19
|
-
version: "0.1.0"
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
export {
|
|
23
|
-
TableSchema,
|
|
24
|
-
TableType
|
|
25
|
-
};
|
|
26
|
-
//# sourceMappingURL=chunk-YWNRUF4J.mjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/types/table.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { EchoObject, Expando, LabelAnnotationId, ObjectId, Ref, S } from '@dxos/echo-schema';\n// import { ThreadType } from '@dxos/plugin-space/types';\nimport { ViewType } from '@dxos/schema';\n\nexport const TableSchema = S.Struct({\n id: ObjectId,\n name: S.optional(S.String),\n view: S.optional(Ref(ViewType)),\n // TODO(burdon): Document why threads is included here?\n threads: S.optional(S.Array(Ref(Expando /* ThreadType */))),\n}).annotations({\n // TODO(burdon): Move annotation to property.\n [LabelAnnotationId]: 'name',\n});\n\nexport const TableType = TableSchema.pipe(EchoObject({ typename: 'dxos.org/type/Table', version: '0.1.0' }));\nexport interface TableType extends S.Schema.Type<typeof TableType> {}\n"],
|
|
5
|
-
"mappings": ";AAIA,SAASA,YAAYC,SAASC,mBAAmBC,UAAUC,KAAKC,SAAS;AAEzE,SAASC,gBAAgB;AAElB,IAAMC,cAAcC,EAAEC,OAAO;EAClCC,IAAIC;EACJC,MAAMJ,EAAEK,SAASL,EAAEM,MAAM;EACzBC,MAAMP,EAAEK,SAASG,IAAIC,QAAAA,CAAAA;;EAErBC,SAASV,EAAEK,SAASL,EAAEW,MAAMH;IAAII;;EAAsB,CAAA,CAAA;AACxD,CAAA,EAAGC,YAAY;;EAEb,CAACC,iBAAAA,GAAoB;AACvB,CAAA;AAEO,IAAMC,YAAYhB,YAAYiB,KAAKC,WAAW;EAAEC,UAAU;EAAuBC,SAAS;AAAQ,CAAA,CAAA;",
|
|
6
|
-
"names": ["EchoObject", "Expando", "LabelAnnotationId", "ObjectId", "Ref", "S", "ViewType", "TableSchema", "S", "Struct", "id", "ObjectId", "name", "optional", "String", "view", "Ref", "ViewType", "threads", "Array", "Expando", "annotations", "LabelAnnotationId", "TableType", "pipe", "EchoObject", "typename", "version"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/types/table.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { EchoObject, Expando, LabelAnnotationId, ObjectId, Ref, S } from '@dxos/echo-schema';\n// import { ThreadType } from '@dxos/plugin-space/types';\nimport { ViewType } from '@dxos/schema';\n\nexport const TableSchema = S.Struct({\n id: ObjectId,\n name: S.optional(S.String),\n view: S.optional(Ref(ViewType)),\n // TODO(burdon): Document why threads is included here?\n threads: S.optional(S.Array(Ref(Expando /* ThreadType */))),\n}).annotations({\n // TODO(burdon): Move annotation to property.\n [LabelAnnotationId]: 'name',\n});\n\nexport const TableType = TableSchema.pipe(EchoObject({ typename: 'dxos.org/type/Table', version: '0.1.0' }));\nexport interface TableType extends S.Schema.Type<typeof TableType> {}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAIA,yBAAyE;AAEzE,oBAAyB;AAElB,IAAMA,cAAcC,qBAAEC,OAAO;EAClCC,IAAIC;EACJC,MAAMJ,qBAAEK,SAASL,qBAAEM,MAAM;EACzBC,MAAMP,qBAAEK,aAASG,wBAAIC,sBAAAA,CAAAA;;EAErBC,SAASV,qBAAEK,SAASL,qBAAEW,UAAMH;IAAII;;EAAsB,CAAA,CAAA;AACxD,CAAA,EAAGC,YAAY;;EAEb,CAACC,oCAAAA,GAAoB;AACvB,CAAA;AAEO,IAAMC,YAAYhB,YAAYiB,SAAKC,+BAAW;EAAEC,UAAU;EAAuBC,SAAS;AAAQ,CAAA,CAAA;",
|
|
6
|
-
"names": ["TableSchema", "S", "Struct", "id", "ObjectId", "name", "optional", "String", "view", "Ref", "ViewType", "threads", "Array", "Expando", "annotations", "LabelAnnotationId", "TableType", "pipe", "EchoObject", "typename", "version"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/types/table.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { EchoObject, Expando, LabelAnnotationId, ObjectId, Ref, S } from '@dxos/echo-schema';\n// import { ThreadType } from '@dxos/plugin-space/types';\nimport { ViewType } from '@dxos/schema';\n\nexport const TableSchema = S.Struct({\n id: ObjectId,\n name: S.optional(S.String),\n view: S.optional(Ref(ViewType)),\n // TODO(burdon): Document why threads is included here?\n threads: S.optional(S.Array(Ref(Expando /* ThreadType */))),\n}).annotations({\n // TODO(burdon): Move annotation to property.\n [LabelAnnotationId]: 'name',\n});\n\nexport const TableType = TableSchema.pipe(EchoObject({ typename: 'dxos.org/type/Table', version: '0.1.0' }));\nexport interface TableType extends S.Schema.Type<typeof TableType> {}\n"],
|
|
5
|
-
"mappings": ";;;AAIA,SAASA,YAAYC,SAASC,mBAAmBC,UAAUC,KAAKC,SAAS;AAEzE,SAASC,gBAAgB;AAElB,IAAMC,cAAcC,EAAEC,OAAO;EAClCC,IAAIC;EACJC,MAAMJ,EAAEK,SAASL,EAAEM,MAAM;EACzBC,MAAMP,EAAEK,SAASG,IAAIC,QAAAA,CAAAA;;EAErBC,SAASV,EAAEK,SAASL,EAAEW,MAAMH;IAAII;;EAAsB,CAAA,CAAA;AACxD,CAAA,EAAGC,YAAY;;EAEb,CAACC,iBAAAA,GAAoB;AACvB,CAAA;AAEO,IAAMC,YAAYhB,YAAYiB,KAAKC,WAAW;EAAEC,UAAU;EAAuBC,SAAS;AAAQ,CAAA,CAAA;",
|
|
6
|
-
"names": ["EchoObject", "Expando", "LabelAnnotationId", "ObjectId", "Ref", "S", "ViewType", "TableSchema", "S", "Struct", "id", "ObjectId", "name", "optional", "String", "view", "Ref", "ViewType", "threads", "Array", "Expando", "annotations", "LabelAnnotationId", "TableType", "pipe", "EchoObject", "typename", "version"]
|
|
7
|
-
}
|