@dxos/react-ui-table 0.8.4-main.3eb6e50203 → 0.8.4-main.4a85c3132b
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-OZBLY7XM.mjs → chunk-DSR2MRZB.mjs} +10 -6
- package/dist/lib/browser/chunk-DSR2MRZB.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GTGYBRJA.mjs → chunk-PTHMYAAM.mjs} +25 -22
- package/dist/lib/browser/chunk-PTHMYAAM.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +179 -175
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +2 -2
- package/dist/lib/browser/testing/index.mjs.map +1 -1
- package/dist/lib/browser/types/index.mjs +1 -1
- package/dist/lib/node-esm/{chunk-DPNSZHU5.mjs → chunk-GI72MQSG.mjs} +25 -22
- package/dist/lib/node-esm/chunk-GI72MQSG.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-WNZSKIRF.mjs → chunk-HTZJSULI.mjs} +10 -6
- package/dist/lib/node-esm/chunk-HTZJSULI.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +179 -175
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +2 -2
- package/dist/lib/node-esm/testing/index.mjs.map +1 -1
- package/dist/lib/node-esm/types/index.mjs +1 -1
- package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts +2 -2
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +7 -7
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +3 -3
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +2 -2
- 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/TableToolbar/TableToolbar.d.ts +1 -1
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
- package/dist/types/src/hooks/useProjectionModel.d.ts +1 -1
- package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +2 -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/testing/useTestTableModel.d.ts +2 -2
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
- package/dist/types/src/types/Table.d.ts +1 -1
- package/dist/types/src/types/Table.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts +2 -2
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/query-ast.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +36 -36
- package/src/components/Table/ColumnSettings.tsx +3 -4
- package/src/components/Table/DynamicTable.stories.tsx +2 -2
- package/src/components/Table/DynamicTable.tsx +7 -7
- package/src/components/Table/Relations.stories.tsx +12 -9
- package/src/components/Table/Table.stories.tsx +34 -25
- package/src/components/Table/Table.tsx +53 -57
- package/src/components/TableCellEditor/CellValidationMessage.tsx +4 -4
- package/src/components/TableCellEditor/FormCellEditor.tsx +11 -5
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +3 -2
- package/src/components/TableCellEditor/TableCellEditor.tsx +3 -3
- package/src/components/TableToolbar/TableToolbar.tsx +6 -6
- package/src/hooks/useAddRow.ts +1 -1
- package/src/hooks/useProjectionModel.ts +3 -3
- package/src/model/table-model.test.ts +4 -4
- package/src/model/table-model.ts +2 -1
- package/src/model/table-presentation.test.ts +4 -4
- package/src/model/table-presentation.ts +12 -11
- package/src/playwright/playwright.config.ts +1 -1
- package/src/testing/useTestTableModel.ts +2 -2
- package/src/types/Table.ts +9 -4
- package/src/util/dynamic-table.test.ts +2 -2
- package/src/util/dynamic-table.ts +7 -6
- package/src/util/query-ast.ts +3 -0
- package/src/util/table-buttons.ts +1 -1
- package/src/util/table-controls.ts +2 -2
- package/dist/lib/browser/chunk-GTGYBRJA.mjs.map +0 -7
- package/dist/lib/browser/chunk-OZBLY7XM.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-DPNSZHU5.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-WNZSKIRF.mjs.map +0 -7
|
@@ -6,11 +6,12 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
8
|
import { Obj } from '@dxos/echo';
|
|
9
|
+
import { View } from '@dxos/echo';
|
|
9
10
|
import { faker } from '@dxos/random';
|
|
10
11
|
import { withClientProvider } from '@dxos/react-client/testing';
|
|
11
12
|
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
12
13
|
import { Grid, type GridEditing, defaultRowSize } from '@dxos/react-ui-grid';
|
|
13
|
-
import {
|
|
14
|
+
import { ViewModel } from '@dxos/schema';
|
|
14
15
|
import { Task } from '@dxos/types';
|
|
15
16
|
|
|
16
17
|
import { useTestTableModel } from '../../testing';
|
|
@@ -52,7 +53,7 @@ const meta = {
|
|
|
52
53
|
createIdentity: true,
|
|
53
54
|
createSpace: true,
|
|
54
55
|
onCreateSpace: async ({ space }) => {
|
|
55
|
-
const { view, jsonSchema } = await
|
|
56
|
+
const { view, jsonSchema } = await ViewModel.makeFromDatabase({ db: space.db, typename: Task.Task.typename });
|
|
56
57
|
const table = Table.make({ view, jsonSchema });
|
|
57
58
|
space.db.add(table);
|
|
58
59
|
Array.from({ length: 10 }).forEach(() => {
|
|
@@ -31,7 +31,7 @@ import { FormCellEditor, type OnCreateHandler } from './FormCellEditor';
|
|
|
31
31
|
|
|
32
32
|
const editorSlots = {
|
|
33
33
|
scroll: {
|
|
34
|
-
className: '!
|
|
34
|
+
className: '!py-(--dx-grid-cell-editor-padding-block)',
|
|
35
35
|
},
|
|
36
36
|
};
|
|
37
37
|
|
|
@@ -42,7 +42,7 @@ export type QueryResult = Pick<Completion, 'label'> & {
|
|
|
42
42
|
data: any;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
export type TableCellEditorProps<T extends Type.
|
|
45
|
+
export type TableCellEditorProps<T extends Type.AnyEntity = Type.AnyEntity> = {
|
|
46
46
|
schema?: T;
|
|
47
47
|
model?: TableModel;
|
|
48
48
|
modals?: ModalController;
|
|
@@ -51,7 +51,7 @@ export type TableCellEditorProps<T extends Type.Entity.Any = Type.Entity.Any> =
|
|
|
51
51
|
onSave?: () => void;
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
-
export const TableValueEditor = <T extends Type.
|
|
54
|
+
export const TableValueEditor = <T extends Type.AnyEntity = Type.AnyEntity>({
|
|
55
55
|
__gridScope,
|
|
56
56
|
schema,
|
|
57
57
|
model,
|
|
@@ -10,9 +10,8 @@ import {
|
|
|
10
10
|
type ActionGraphEdges,
|
|
11
11
|
type ActionGraphNodes,
|
|
12
12
|
type ActionGraphProps,
|
|
13
|
+
Menu,
|
|
13
14
|
type MenuAction,
|
|
14
|
-
MenuProvider,
|
|
15
|
-
ToolbarMenu,
|
|
16
15
|
createGapSeparator,
|
|
17
16
|
createMenuAction,
|
|
18
17
|
useMenuActions,
|
|
@@ -75,7 +74,7 @@ const createTableToolbarActions = ({
|
|
|
75
74
|
}
|
|
76
75
|
const gap = createGapSeparator();
|
|
77
76
|
nodes.push(...gap.nodes);
|
|
78
|
-
const edges: ActionGraphEdges = nodes.map(({ id: target }) => ({ source: 'root', target }));
|
|
77
|
+
const edges: ActionGraphEdges = nodes.map(({ id: target }) => ({ source: 'root', target, relation: 'child' }));
|
|
79
78
|
if (customActions) {
|
|
80
79
|
const custom = get(customActions);
|
|
81
80
|
nodes.push(...custom.nodes);
|
|
@@ -95,6 +94,7 @@ export const TableToolbar = ({
|
|
|
95
94
|
onAdd,
|
|
96
95
|
onSave,
|
|
97
96
|
customActions,
|
|
97
|
+
...props
|
|
98
98
|
}: TableToolbarProps) => {
|
|
99
99
|
const registry = useContext(RegistryContext);
|
|
100
100
|
const stateAtom = useMemo(() => Atom.make<TableToolbarState>({ viewDirty }), []);
|
|
@@ -111,8 +111,8 @@ export const TableToolbar = ({
|
|
|
111
111
|
const menu = useMenuActions(actionsCreator);
|
|
112
112
|
|
|
113
113
|
return (
|
|
114
|
-
<
|
|
115
|
-
<
|
|
116
|
-
</
|
|
114
|
+
<Menu.Root {...menu} attendableId={attendableId}>
|
|
115
|
+
<Menu.Toolbar {...props} classNames={classNames} />
|
|
116
|
+
</Menu.Root>
|
|
117
117
|
);
|
|
118
118
|
};
|
package/src/hooks/useAddRow.ts
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
import { type Registry } from '@effect-atom/atom-react';
|
|
6
6
|
import { useState } from 'react';
|
|
7
7
|
|
|
8
|
-
import { Type } from '@dxos/echo';
|
|
8
|
+
import { JsonSchema, Type } from '@dxos/echo';
|
|
9
9
|
import { useAsyncEffect } from '@dxos/react-ui';
|
|
10
10
|
import { ProjectionModel, createEchoChangeCallback } from '@dxos/schema';
|
|
11
11
|
|
|
12
12
|
import { type Table } from '../types';
|
|
13
13
|
|
|
14
|
-
export const useProjectionModel = <S extends Type.
|
|
14
|
+
export const useProjectionModel = <S extends Type.AnyEntity>(
|
|
15
15
|
schema: S | undefined,
|
|
16
16
|
table: Table.Table | undefined,
|
|
17
17
|
registry: Registry.Registry,
|
|
@@ -23,7 +23,7 @@ export const useProjectionModel = <S extends Type.Entity.Any>(
|
|
|
23
23
|
const view = await table.view.load();
|
|
24
24
|
// For mutable schemas (EchoSchema), use the live jsonSchema reference for reactivity.
|
|
25
25
|
// For immutable schemas, create a snapshot.
|
|
26
|
-
const jsonSchema = Type.isMutable(schema) ? schema.jsonSchema :
|
|
26
|
+
const jsonSchema = Type.isMutable(schema) ? schema.jsonSchema : JsonSchema.toJsonSchema(schema);
|
|
27
27
|
|
|
28
28
|
// Always use createEchoChangeCallback since the view is ECHO-backed.
|
|
29
29
|
// Pass schema only when mutable to allow schema mutations.
|
|
@@ -6,9 +6,9 @@ import { Registry } from '@effect-atom/atom-react';
|
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
import { afterEach, beforeEach, describe, expect, test } from 'vitest';
|
|
8
8
|
|
|
9
|
-
import { Filter, Query, Type } from '@dxos/echo';
|
|
9
|
+
import { Filter, JsonSchema, Query, Type } from '@dxos/echo';
|
|
10
10
|
import { createEchoSchema } from '@dxos/echo/testing';
|
|
11
|
-
import { ProjectionModel,
|
|
11
|
+
import { ProjectionModel, ViewModel, createDirectChangeCallback } from '@dxos/schema';
|
|
12
12
|
|
|
13
13
|
import { Table } from '../types';
|
|
14
14
|
|
|
@@ -128,7 +128,7 @@ const Test = Schema.Struct({
|
|
|
128
128
|
|
|
129
129
|
const createTableModel = (registry: Registry.Registry, props: Partial<TableModelProps> = {}): TableModel => {
|
|
130
130
|
const schema = createEchoSchema(Test);
|
|
131
|
-
const view =
|
|
131
|
+
const view = ViewModel.make({
|
|
132
132
|
query: Query.select(Filter.type(schema)),
|
|
133
133
|
jsonSchema: schema.jsonSchema,
|
|
134
134
|
});
|
|
@@ -137,7 +137,7 @@ const createTableModel = (registry: Registry.Registry, props: Partial<TableModel
|
|
|
137
137
|
registry,
|
|
138
138
|
view,
|
|
139
139
|
baseSchema: schema.jsonSchema,
|
|
140
|
-
change: createDirectChangeCallback(view.projection,
|
|
140
|
+
change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(schema)),
|
|
141
141
|
});
|
|
142
142
|
projection.normalizeView();
|
|
143
143
|
return new TableModel({
|
package/src/model/table-model.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Atom, type Registry } from '@effect-atom/atom-react';
|
|
|
6
6
|
|
|
7
7
|
import { Resource } from '@dxos/context';
|
|
8
8
|
import { type Database, Format, Obj, Order, Query, type QueryAST, Ref } from '@dxos/echo';
|
|
9
|
+
import { type View } from '@dxos/echo';
|
|
9
10
|
import { type JsonProp, type JsonSchemaType, type Mutable, toEffectSchema } from '@dxos/echo/internal';
|
|
10
11
|
import { getSnapshot } from '@dxos/echo/internal';
|
|
11
12
|
import { getValue, setValue } from '@dxos/effect';
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
type DxGridPlaneRange,
|
|
20
21
|
type DxGridPosition,
|
|
21
22
|
} from '@dxos/react-ui-grid';
|
|
22
|
-
import { type ProjectionModel, type PropertyType, type ValidationError,
|
|
23
|
+
import { type ProjectionModel, type PropertyType, type ValidationError, validateSchema } from '@dxos/schema';
|
|
23
24
|
|
|
24
25
|
import { type Table } from '../types';
|
|
25
26
|
import { extractOrder } from '../util';
|
|
@@ -6,9 +6,9 @@ import { Registry } from '@effect-atom/atom-react';
|
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
import { beforeEach, describe, expect, it } from 'vitest';
|
|
8
8
|
|
|
9
|
-
import { Filter, Query, Type } from '@dxos/echo';
|
|
9
|
+
import { Filter, JsonSchema, Query, Type } from '@dxos/echo';
|
|
10
10
|
import { createEchoSchema } from '@dxos/echo/testing';
|
|
11
|
-
import { ProjectionModel,
|
|
11
|
+
import { ProjectionModel, ViewModel, createDirectChangeCallback } from '@dxos/schema';
|
|
12
12
|
|
|
13
13
|
import { Table } from '../types';
|
|
14
14
|
|
|
@@ -99,7 +99,7 @@ const Test = Schema.Struct({
|
|
|
99
99
|
|
|
100
100
|
const createTableModel = (registry: Registry.Registry, props: Partial<TableModelProps> = {}): TableModel => {
|
|
101
101
|
const schema = createEchoSchema(Test);
|
|
102
|
-
const view =
|
|
102
|
+
const view = ViewModel.make({
|
|
103
103
|
query: Query.select(Filter.type(schema)),
|
|
104
104
|
jsonSchema: schema.jsonSchema,
|
|
105
105
|
});
|
|
@@ -108,7 +108,7 @@ const createTableModel = (registry: Registry.Registry, props: Partial<TableModel
|
|
|
108
108
|
registry,
|
|
109
109
|
view,
|
|
110
110
|
baseSchema: schema.jsonSchema,
|
|
111
|
-
change: createDirectChangeCallback(view.projection,
|
|
111
|
+
change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(schema)),
|
|
112
112
|
});
|
|
113
113
|
projection.normalizeView();
|
|
114
114
|
return new TableModel({ registry, object, projection, ...props });
|
|
@@ -6,6 +6,7 @@ import { Atom, type Registry } from '@effect-atom/atom-react';
|
|
|
6
6
|
import * as Predicate from 'effect/Predicate';
|
|
7
7
|
|
|
8
8
|
import { Obj } from '@dxos/echo';
|
|
9
|
+
import { type View } from '@dxos/echo';
|
|
9
10
|
import { Format, TypeEnum, getValue } from '@dxos/echo/internal';
|
|
10
11
|
import { cellClassesForFieldType, formatForDisplay } from '@dxos/react-ui-form';
|
|
11
12
|
import {
|
|
@@ -15,7 +16,7 @@ import {
|
|
|
15
16
|
type DxGridPlaneRange,
|
|
16
17
|
toPlaneCellIndex,
|
|
17
18
|
} from '@dxos/react-ui-grid';
|
|
18
|
-
import {
|
|
19
|
+
import { VIEW_FIELD_LIMIT } from '@dxos/schema';
|
|
19
20
|
import { mx } from '@dxos/ui-theme';
|
|
20
21
|
|
|
21
22
|
import { tableButtons, tableControls } from '../util';
|
|
@@ -107,7 +108,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
107
108
|
private createDataCell(
|
|
108
109
|
cells: DxGridPlaneCells,
|
|
109
110
|
obj: T,
|
|
110
|
-
field: FieldType,
|
|
111
|
+
field: View.FieldType,
|
|
111
112
|
colIndex: number,
|
|
112
113
|
displayIndex: number,
|
|
113
114
|
): void {
|
|
@@ -210,7 +211,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
210
211
|
const targetObj = getValue(obj, field.path)?.target;
|
|
211
212
|
if (targetObj) {
|
|
212
213
|
const dxn = Obj.getDXN(targetObj)?.toString();
|
|
213
|
-
cell.accessoryHtml = `<div role="none" class="absolute
|
|
214
|
+
cell.accessoryHtml = `<div role="none" class="absolute end-0 inset-y-0 p-(--dx-grid-cell-content-padding-block)"><dx-anchor dxn=${dxn} class="dx-button w-6 aspect-square min-h-0" data-dx-grid-action="accessory"><dx-icon icon="ph--link-simple--regular"/></dx-anchor></div>`;
|
|
214
215
|
}
|
|
215
216
|
}
|
|
216
217
|
|
|
@@ -335,11 +336,11 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
335
336
|
value: '',
|
|
336
337
|
resizeHandle: 'col',
|
|
337
338
|
accessoryHtml: `
|
|
338
|
-
<span class="grow min-
|
|
339
|
+
<span class="grow min-w-0 truncate">${props.title ?? field.path}</span>
|
|
339
340
|
${direction !== undefined ? tableButtons.sort.render({ fieldId: field.id, direction }) : ''}
|
|
340
341
|
${tableButtons.columnSettings.render({ fieldId: field.id })}
|
|
341
342
|
`,
|
|
342
|
-
className: '!bg-
|
|
343
|
+
className: '!bg-toolbar-surface text-description! [&>div]:flex [&>div]:items-stretch',
|
|
343
344
|
};
|
|
344
345
|
}
|
|
345
346
|
|
|
@@ -382,7 +383,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
382
383
|
if (!this.model.features.selection.enabled || this.model.selection.selectionMode === 'single') {
|
|
383
384
|
return {
|
|
384
385
|
[toPlaneCellIndex({ col: 0, row: 0 })]: {
|
|
385
|
-
className: '!bg-
|
|
386
|
+
className: '!bg-toolbar-surface',
|
|
386
387
|
readonly: true,
|
|
387
388
|
value: '',
|
|
388
389
|
},
|
|
@@ -396,7 +397,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
396
397
|
header: true,
|
|
397
398
|
checked: this.model.selection.allRowsSelected,
|
|
398
399
|
}),
|
|
399
|
-
className: '!bg-
|
|
400
|
+
className: '!bg-toolbar-surface',
|
|
400
401
|
readonly: true,
|
|
401
402
|
value: '',
|
|
402
403
|
},
|
|
@@ -411,7 +412,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
411
412
|
disabled: (this.model.projection?.getFields()?.length ?? 0) >= VIEW_FIELD_LIMIT,
|
|
412
413
|
})
|
|
413
414
|
: undefined,
|
|
414
|
-
className: '!bg-
|
|
415
|
+
className: '!bg-toolbar-surface',
|
|
415
416
|
readonly: true,
|
|
416
417
|
value: '',
|
|
417
418
|
},
|
|
@@ -465,7 +466,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
|
|
|
465
466
|
export const cellClassesForRowSelection = (selected: boolean, selectionMode: SelectionMode) => {
|
|
466
467
|
if (!selected) {
|
|
467
468
|
if (selectionMode === 'single') {
|
|
468
|
-
return ['
|
|
469
|
+
return ['cursor-pointer!'];
|
|
469
470
|
} else {
|
|
470
471
|
return undefined;
|
|
471
472
|
}
|
|
@@ -473,8 +474,8 @@ export const cellClassesForRowSelection = (selected: boolean, selectionMode: Sel
|
|
|
473
474
|
|
|
474
475
|
switch (selectionMode) {
|
|
475
476
|
case 'single':
|
|
476
|
-
return ['
|
|
477
|
+
return ['dx-grid__cell--no-focus-unfurl !bg-current-surface hover:bg-hover-surface cursor-pointer!'];
|
|
477
478
|
case 'multiple':
|
|
478
|
-
return ['!bg-
|
|
479
|
+
return ['!bg-grid-cell-selected'];
|
|
479
480
|
}
|
|
480
481
|
};
|
|
@@ -10,7 +10,7 @@ export default defineConfig({
|
|
|
10
10
|
...e2ePreset(import.meta.dirname),
|
|
11
11
|
// TODO(wittjosiah): Avoid hard-coding ports.
|
|
12
12
|
webServer: {
|
|
13
|
-
command: '
|
|
13
|
+
command: 'pnpm storybook dev --ci --quiet --port=9004 --config-dir=.storybook',
|
|
14
14
|
port: 9004,
|
|
15
15
|
reuseExistingServer: false,
|
|
16
16
|
},
|
|
@@ -20,7 +20,7 @@ import { Table } from '../types';
|
|
|
20
20
|
|
|
21
21
|
faker.seed(0); // NOTE(ZaymonFC): Required for smoke tests.
|
|
22
22
|
|
|
23
|
-
export type TestTableModel<T extends Type.
|
|
23
|
+
export type TestTableModel<T extends Type.AnyObj = Type.AnyObj> = {
|
|
24
24
|
schema: T | undefined;
|
|
25
25
|
table: Table.Table | undefined;
|
|
26
26
|
projection: ProjectionModel | undefined;
|
|
@@ -38,7 +38,7 @@ export type TestTableModel<T extends Type.Obj.Any = Type.Obj.Any> = {
|
|
|
38
38
|
* Custom hook to create and manage a test table model for storybook demonstrations.
|
|
39
39
|
* Provides table data, schema, and handlers for table operations.
|
|
40
40
|
*/
|
|
41
|
-
export const useTestTableModel = <T extends Type.
|
|
41
|
+
export const useTestTableModel = <T extends Type.AnyObj = Type.AnyObj>(): TestTableModel<T> => {
|
|
42
42
|
const registry = useContext(RegistryContext);
|
|
43
43
|
const { space } = useClientStory();
|
|
44
44
|
const db = space?.db;
|
package/src/types/Table.ts
CHANGED
|
@@ -6,14 +6,15 @@ import * as Match from 'effect/Match';
|
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
import * as SchemaAST from 'effect/SchemaAST';
|
|
8
8
|
|
|
9
|
-
import { Obj, Ref, Type } from '@dxos/echo';
|
|
9
|
+
import { Annotation, JsonSchema, Obj, Ref, Type } from '@dxos/echo';
|
|
10
|
+
import { View } from '@dxos/echo';
|
|
10
11
|
import { FormInputAnnotation, type JsonPath, type JsonSchemaType, LabelAnnotation } from '@dxos/echo/internal';
|
|
11
|
-
import {
|
|
12
|
+
import { ViewAnnotation } from '@dxos/schema';
|
|
12
13
|
|
|
13
14
|
export const Table = Schema.Struct({
|
|
14
15
|
name: Schema.String.pipe(Schema.optional),
|
|
15
16
|
|
|
16
|
-
view:
|
|
17
|
+
view: Ref.Ref(View.View).pipe(FormInputAnnotation.set(false)),
|
|
17
18
|
|
|
18
19
|
sizes: Schema.Record({
|
|
19
20
|
// TODO(wittjosiah): Should be JsonPath.
|
|
@@ -27,6 +28,10 @@ export const Table = Schema.Struct({
|
|
|
27
28
|
}),
|
|
28
29
|
LabelAnnotation.set(['name']),
|
|
29
30
|
ViewAnnotation.set(true),
|
|
31
|
+
Annotation.IconAnnotation.set({
|
|
32
|
+
icon: 'ph--table--regular',
|
|
33
|
+
hue: 'green',
|
|
34
|
+
}),
|
|
30
35
|
);
|
|
31
36
|
|
|
32
37
|
export interface Table extends Schema.Schema.Type<typeof Table> {}
|
|
@@ -47,7 +52,7 @@ export const make = ({ name, sizes = {}, view, jsonSchema }: MakeProps): Table =
|
|
|
47
52
|
|
|
48
53
|
// Preset sizes.
|
|
49
54
|
if (jsonSchema) {
|
|
50
|
-
const schema =
|
|
55
|
+
const schema = JsonSchema.toEffectSchema(jsonSchema);
|
|
51
56
|
const properties = SchemaAST.getPropertySignatures(schema.ast);
|
|
52
57
|
for (const property of properties) {
|
|
53
58
|
const name = property.name.toString() as JsonPath;
|
|
@@ -11,7 +11,7 @@ import { type TablePropertyDefinition, getBaseSchema, makeDynamicTable } from '.
|
|
|
11
11
|
|
|
12
12
|
describe('makeDynamicTable', () => {
|
|
13
13
|
/**
|
|
14
|
-
* Base case: plain jsonSchema (not from Echo /
|
|
14
|
+
* Base case: plain jsonSchema (not from Echo / JsonSchema.toJsonSchema). Does not exercise the path
|
|
15
15
|
* where projection or schema are reactive, so this does not reproduce the Obj.change regression.
|
|
16
16
|
* Confirms makeDynamicTable + setProperties (title) works with plain objects.
|
|
17
17
|
*/
|
|
@@ -44,7 +44,7 @@ describe('makeDynamicTable', () => {
|
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Regression test for the path where jsonSchema comes from getBaseSchema(typename, properties).
|
|
47
|
-
* That path uses Echo (
|
|
47
|
+
* That path uses Echo (ViewModel.make, JsonSchema.toJsonSchema); mutations must run inside Obj.change and on a
|
|
48
48
|
* cloned schema. This test ensures that flow does not throw.
|
|
49
49
|
*/
|
|
50
50
|
test('makeDynamicTable with jsonSchema from getBaseSchema(typename, properties) and properties with title does not throw', () => {
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
import { type Registry } from '@effect-atom/atom-react';
|
|
6
6
|
import type * as Types from 'effect/Types';
|
|
7
7
|
|
|
8
|
-
import { Filter,
|
|
8
|
+
import { Filter, JsonSchema, Obj, Order, Query, type QueryAST, Ref, Type } from '@dxos/echo';
|
|
9
|
+
import { type View } from '@dxos/echo';
|
|
9
10
|
import {
|
|
10
11
|
ProjectionModel,
|
|
11
12
|
type SchemaPropertyDefinition,
|
|
12
|
-
|
|
13
|
+
ViewModel,
|
|
13
14
|
createEchoChangeCallback,
|
|
14
15
|
getSchemaFromPropertyDefinitions,
|
|
15
16
|
} from '@dxos/schema';
|
|
@@ -35,16 +36,16 @@ export const getBaseSchema = ({
|
|
|
35
36
|
properties,
|
|
36
37
|
jsonSchema,
|
|
37
38
|
}: {
|
|
38
|
-
schema?: Type.
|
|
39
|
+
schema?: Type.AnyEntity;
|
|
39
40
|
typename?: string;
|
|
40
41
|
properties?: TablePropertyDefinition[];
|
|
41
42
|
jsonSchema?: Types.DeepMutable<JsonSchema.JsonSchema>;
|
|
42
43
|
}): { typename: string; jsonSchema: Types.DeepMutable<JsonSchema.JsonSchema> } => {
|
|
43
44
|
if (typename && properties) {
|
|
44
45
|
const schema = getSchemaFromPropertyDefinitions(typename, properties);
|
|
45
|
-
return { typename: schema.typename, jsonSchema:
|
|
46
|
+
return { typename: schema.typename, jsonSchema: JsonSchema.toJsonSchema(schema) };
|
|
46
47
|
} else if (schema) {
|
|
47
|
-
return { typename: Type.getTypename(schema)!, jsonSchema:
|
|
48
|
+
return { typename: Type.getTypename(schema)!, jsonSchema: JsonSchema.toJsonSchema(schema) };
|
|
48
49
|
} else if (typename && jsonSchema) {
|
|
49
50
|
return { typename, jsonSchema };
|
|
50
51
|
} else {
|
|
@@ -61,7 +62,7 @@ export const makeDynamicTable = ({
|
|
|
61
62
|
jsonSchema: Types.DeepMutable<JsonSchema.JsonSchema>;
|
|
62
63
|
properties?: TablePropertyDefinition[];
|
|
63
64
|
}): { projection: ProjectionModel; object: Table.Table } => {
|
|
64
|
-
const view =
|
|
65
|
+
const view = ViewModel.make({
|
|
65
66
|
query: Query.select(Filter.everything()),
|
|
66
67
|
jsonSchema,
|
|
67
68
|
...(properties && { fields: properties.map((property) => property.name) }),
|
package/src/util/query-ast.ts
CHANGED
|
@@ -15,5 +15,8 @@ export const extractOrder = (queryAst: QueryAST.Query): readonly QueryAST.Order[
|
|
|
15
15
|
if (queryAst.type === 'options') {
|
|
16
16
|
return extractOrder(queryAst.query);
|
|
17
17
|
}
|
|
18
|
+
if (queryAst.type === 'from') {
|
|
19
|
+
return extractOrder(queryAst.query);
|
|
20
|
+
}
|
|
18
21
|
return undefined;
|
|
19
22
|
};
|
|
@@ -39,7 +39,7 @@ const createButton = ({
|
|
|
39
39
|
.map(([k, v]) => `${k}="${v}"`)
|
|
40
40
|
.join(' ');
|
|
41
41
|
|
|
42
|
-
return `<button ${attr} data-testid="${testId}" class="dx-button
|
|
42
|
+
return `<button ${attr} data-testid="${testId}" class="dx-button w-6 aspect-square px-0.5 min-h-0" ${dataAttrs} ${disabled ? 'disabled' : ''} data-dx-grid-action="accessory"><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
const addColumnButton = {
|
|
@@ -25,8 +25,8 @@ export const CONTROL_IDENTIFIERS = {
|
|
|
25
25
|
} as const;
|
|
26
26
|
|
|
27
27
|
const BASE_CLASSES = {
|
|
28
|
-
checkbox: 'absolute inset-
|
|
29
|
-
switch: 'absolute inset-
|
|
28
|
+
checkbox: 'absolute inset-y-[.375rem] end-[.375rem] dx-checkbox',
|
|
29
|
+
switch: 'absolute inset-y-[.25rem] end-[.25rem] dx-checkbox--switch',
|
|
30
30
|
} as const;
|
|
31
31
|
|
|
32
32
|
const renderAttributes = (data: Record<string, string>) => {
|