@dxos/react-ui-table 0.8.4-main.2c6827d → 0.8.4-main.3c1ae3b

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.
Files changed (103) hide show
  1. package/dist/lib/browser/chunk-CJQ6T4LL.mjs +77 -0
  2. package/dist/lib/browser/chunk-CJQ6T4LL.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-GS2UNGJK.mjs → chunk-V7A7ZA5E.mjs} +119 -111
  4. package/dist/lib/browser/chunk-V7A7ZA5E.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +162 -147
  6. package/dist/lib/browser/index.mjs.map +3 -3
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +15 -31
  9. package/dist/lib/browser/testing/index.mjs.map +3 -3
  10. package/dist/lib/browser/types/index.mjs +3 -3
  11. package/dist/lib/node-esm/{chunk-TRR3C5NX.mjs → chunk-P73ALX3N.mjs} +119 -111
  12. package/dist/lib/node-esm/chunk-P73ALX3N.mjs.map +7 -0
  13. package/dist/lib/node-esm/chunk-T6PXZQ6W.mjs +78 -0
  14. package/dist/lib/node-esm/chunk-T6PXZQ6W.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +162 -147
  16. package/dist/lib/node-esm/index.mjs.map +3 -3
  17. package/dist/lib/node-esm/meta.json +1 -1
  18. package/dist/lib/node-esm/testing/index.mjs +15 -31
  19. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  20. package/dist/lib/node-esm/types/index.mjs +3 -3
  21. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +1 -2
  22. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/ColumnSettings.d.ts +2 -2
  24. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  25. package/dist/types/src/components/Table/DynamicTable.d.ts +4 -5
  26. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  27. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +3 -17
  28. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/Table/Relations.stories.d.ts +10 -6
  30. package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -1
  31. package/dist/types/src/components/Table/Table.d.ts +8 -8
  32. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  33. package/dist/types/src/components/Table/Table.stories.d.ts +70 -4
  34. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  35. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +1 -1
  36. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +10 -11
  37. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  38. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +5 -7
  39. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  40. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +3 -3
  41. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  42. package/dist/types/src/components/testing.d.ts +0 -2
  43. package/dist/types/src/components/testing.d.ts.map +1 -1
  44. package/dist/types/src/hooks/index.d.ts +2 -1
  45. package/dist/types/src/hooks/index.d.ts.map +1 -1
  46. package/dist/types/src/hooks/useProjectionModel.d.ts +5 -0
  47. package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -0
  48. package/dist/types/src/hooks/useTableModel.d.ts +4 -5
  49. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  50. package/dist/types/src/model/table-model.d.ts +6 -8
  51. package/dist/types/src/model/table-model.d.ts.map +1 -1
  52. package/dist/types/src/model/table-sorting.d.ts +7 -3
  53. package/dist/types/src/model/table-sorting.d.ts.map +1 -1
  54. package/dist/types/src/playwright/TableManager.d.ts +1 -1
  55. package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
  56. package/dist/types/src/testing/useTestTableModel.d.ts +19 -15
  57. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  58. package/dist/types/src/translations.d.ts +2 -2
  59. package/dist/types/src/types/Table.d.ts +28 -0
  60. package/dist/types/src/types/Table.d.ts.map +1 -0
  61. package/dist/types/src/types/index.d.ts +1 -1
  62. package/dist/types/src/types/index.d.ts.map +1 -1
  63. package/dist/types/src/util/dynamic-table.d.ts +9 -9
  64. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  65. package/dist/types/tsconfig.tsbuildinfo +1 -1
  66. package/package.json +38 -38
  67. package/src/components/Table/ColumnActionsMenu.tsx +4 -1
  68. package/src/components/Table/ColumnSettings.tsx +2 -3
  69. package/src/components/Table/DynamicTable.stories.tsx +7 -9
  70. package/src/components/Table/DynamicTable.tsx +18 -10
  71. package/src/components/Table/Relations.stories.tsx +9 -18
  72. package/src/components/Table/Table.stories.tsx +52 -59
  73. package/src/components/Table/Table.tsx +317 -304
  74. package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -1
  75. package/src/components/TableCellEditor/FormCellEditor.tsx +101 -108
  76. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +11 -8
  77. package/src/components/TableCellEditor/TableCellEditor.tsx +29 -29
  78. package/src/components/TableToolbar/TableToolbar.tsx +1 -1
  79. package/src/components/testing.ts +3 -3
  80. package/src/hooks/index.ts +2 -1
  81. package/src/hooks/useProjectionModel.ts +19 -0
  82. package/src/hooks/useTableModel.ts +11 -13
  83. package/src/model/table-model.test.ts +4 -4
  84. package/src/model/table-model.ts +29 -38
  85. package/src/model/table-presentation.test.ts +4 -4
  86. package/src/model/table-presentation.ts +9 -9
  87. package/src/model/table-sorting.ts +21 -12
  88. package/src/playwright/TableManager.ts +5 -5
  89. package/src/playwright/smoke.spec.ts +1 -1
  90. package/src/testing/useTestTableModel.ts +31 -27
  91. package/src/translations.ts +2 -2
  92. package/src/types/Table.ts +90 -0
  93. package/src/types/index.ts +1 -1
  94. package/src/util/dynamic-table.ts +11 -16
  95. package/dist/lib/browser/chunk-2PFAPQL4.mjs +0 -66
  96. package/dist/lib/browser/chunk-2PFAPQL4.mjs.map +0 -7
  97. package/dist/lib/browser/chunk-GS2UNGJK.mjs.map +0 -7
  98. package/dist/lib/node-esm/chunk-6POOFFYF.mjs +0 -67
  99. package/dist/lib/node-esm/chunk-6POOFFYF.mjs.map +0 -7
  100. package/dist/lib/node-esm/chunk-TRR3C5NX.mjs.map +0 -7
  101. package/dist/types/src/types/schema.d.ts +0 -28
  102. package/dist/types/src/types/schema.d.ts.map +0 -1
  103. package/src/types/schema.ts +0 -73
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-table",
3
- "version": "0.8.4-main.2c6827d",
3
+ "version": "0.8.4-main.3c1ae3b",
4
4
  "description": "A table component.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -65,33 +65,33 @@
65
65
  "@radix-ui/react-use-controllable-state": "1.1.0",
66
66
  "date-fns": "^3.3.1",
67
67
  "lodash.orderby": "^4.6.0",
68
- "@dxos/async": "0.8.4-main.2c6827d",
69
- "@dxos/debug": "0.8.4-main.2c6827d",
70
- "@dxos/context": "0.8.4-main.2c6827d",
71
- "@dxos/effect": "0.8.4-main.2c6827d",
72
- "@dxos/invariant": "0.8.4-main.2c6827d",
73
- "@dxos/keys": "0.8.4-main.2c6827d",
74
- "@dxos/echo": "0.8.4-main.2c6827d",
75
- "@dxos/live-object": "0.8.4-main.2c6827d",
76
- "@dxos/plugin-search": "0.8.4-main.2c6827d",
77
- "@dxos/log": "0.8.4-main.2c6827d",
78
- "@dxos/echo-db": "0.8.4-main.2c6827d",
79
- "@dxos/random": "0.8.4-main.2c6827d",
80
- "@dxos/react-client": "0.8.4-main.2c6827d",
81
- "@dxos/react-ui-attention": "0.8.4-main.2c6827d",
82
- "@dxos/react-ui-components": "0.8.4-main.2c6827d",
83
- "@dxos/lit-grid": "0.8.4-main.2c6827d",
84
- "@dxos/react-ui-form": "0.8.4-main.2c6827d",
85
- "@dxos/react-ui-editor": "0.8.4-main.2c6827d",
86
- "@dxos/react-ui-grid": "0.8.4-main.2c6827d",
87
- "@dxos/react-ui-searchlist": "0.8.4-main.2c6827d",
88
- "@dxos/react-ui-menu": "0.8.4-main.2c6827d",
89
- "@dxos/react-ui-types": "0.8.4-main.2c6827d",
90
- "@dxos/react-ui-syntax-highlighter": "0.8.4-main.2c6827d",
91
- "@dxos/types": "0.8.4-main.2c6827d",
92
- "@dxos/schema": "0.8.4-main.2c6827d",
93
- "@dxos/react-ui-stack": "0.8.4-main.2c6827d",
94
- "@dxos/util": "0.8.4-main.2c6827d"
68
+ "@dxos/async": "0.8.4-main.3c1ae3b",
69
+ "@dxos/context": "0.8.4-main.3c1ae3b",
70
+ "@dxos/debug": "0.8.4-main.3c1ae3b",
71
+ "@dxos/echo": "0.8.4-main.3c1ae3b",
72
+ "@dxos/echo-db": "0.8.4-main.3c1ae3b",
73
+ "@dxos/effect": "0.8.4-main.3c1ae3b",
74
+ "@dxos/invariant": "0.8.4-main.3c1ae3b",
75
+ "@dxos/keys": "0.8.4-main.3c1ae3b",
76
+ "@dxos/lit-grid": "0.8.4-main.3c1ae3b",
77
+ "@dxos/log": "0.8.4-main.3c1ae3b",
78
+ "@dxos/live-object": "0.8.4-main.3c1ae3b",
79
+ "@dxos/random": "0.8.4-main.3c1ae3b",
80
+ "@dxos/plugin-search": "0.8.4-main.3c1ae3b",
81
+ "@dxos/react-client": "0.8.4-main.3c1ae3b",
82
+ "@dxos/react-ui-attention": "0.8.4-main.3c1ae3b",
83
+ "@dxos/react-ui-components": "0.8.4-main.3c1ae3b",
84
+ "@dxos/react-ui-editor": "0.8.4-main.3c1ae3b",
85
+ "@dxos/react-ui-form": "0.8.4-main.3c1ae3b",
86
+ "@dxos/react-ui-grid": "0.8.4-main.3c1ae3b",
87
+ "@dxos/react-ui-menu": "0.8.4-main.3c1ae3b",
88
+ "@dxos/react-ui-searchlist": "0.8.4-main.3c1ae3b",
89
+ "@dxos/react-ui-stack": "0.8.4-main.3c1ae3b",
90
+ "@dxos/react-ui-syntax-highlighter": "0.8.4-main.3c1ae3b",
91
+ "@dxos/react-ui-types": "0.8.4-main.3c1ae3b",
92
+ "@dxos/schema": "0.8.4-main.3c1ae3b",
93
+ "@dxos/types": "0.8.4-main.3c1ae3b",
94
+ "@dxos/util": "0.8.4-main.3c1ae3b"
95
95
  },
96
96
  "devDependencies": {
97
97
  "@effect-atom/atom-react": "^0.3.4",
@@ -104,14 +104,14 @@
104
104
  "react": "~19.2.0",
105
105
  "react-dom": "~19.2.0",
106
106
  "vite": "7.1.9",
107
- "@dxos/echo-signals": "0.8.4-main.2c6827d",
108
- "@dxos/lit-ui": "0.8.4-main.2c6827d",
109
- "@dxos/random": "0.8.4-main.2c6827d",
110
- "@dxos/plugin-search": "0.8.4-main.2c6827d",
111
- "@dxos/react-ui": "0.8.4-main.2c6827d",
112
- "@dxos/react-ui-theme": "0.8.4-main.2c6827d",
113
- "@dxos/test-utils": "0.8.4-main.2c6827d",
114
- "@dxos/storybook-utils": "0.8.4-main.2c6827d"
107
+ "@dxos/echo-signals": "0.8.4-main.3c1ae3b",
108
+ "@dxos/lit-ui": "0.8.4-main.3c1ae3b",
109
+ "@dxos/plugin-search": "0.8.4-main.3c1ae3b",
110
+ "@dxos/react-ui": "0.8.4-main.3c1ae3b",
111
+ "@dxos/random": "0.8.4-main.3c1ae3b",
112
+ "@dxos/react-ui-theme": "0.8.4-main.3c1ae3b",
113
+ "@dxos/storybook-utils": "0.8.4-main.3c1ae3b",
114
+ "@dxos/test-utils": "0.8.4-main.3c1ae3b"
115
115
  },
116
116
  "peerDependencies": {
117
117
  "@effect-atom/atom-react": "^0.3.4",
@@ -119,8 +119,8 @@
119
119
  "effect": "^3.13.3",
120
120
  "react": "^19.0.0",
121
121
  "react-dom": "^19.0.0",
122
- "@dxos/react-ui": "0.8.4-main.2c6827d",
123
- "@dxos/react-ui-theme": "0.8.4-main.2c6827d"
122
+ "@dxos/react-ui": "0.8.4-main.3c1ae3b",
123
+ "@dxos/react-ui-theme": "0.8.4-main.3c1ae3b"
124
124
  },
125
125
  "publishConfig": {
126
126
  "access": "public"
@@ -9,7 +9,10 @@ import { DropdownMenu, useTranslation } from '@dxos/react-ui';
9
9
  import { type ModalController, type TableModel } from '../../model';
10
10
  import { translationKey } from '../../translations';
11
11
 
12
- type ColumnActionsMenuProps = { model: TableModel; modals: ModalController };
12
+ export type ColumnActionsMenuProps = {
13
+ model: TableModel;
14
+ modals: ModalController;
15
+ };
13
16
 
14
17
  export const ColumnActionsMenu = ({ model, modals }: ColumnActionsMenuProps) => {
15
18
  const { t } = useTranslation(translationKey);
@@ -4,8 +4,7 @@
4
4
 
5
5
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
6
6
 
7
- // TODO(burdon): Remove dependency on echo-db.
8
- import { type SchemaRegistry } from '@dxos/echo-db';
7
+ import { type SchemaRegistry } from '@dxos/echo';
9
8
  import { Popover } from '@dxos/react-ui';
10
9
  import { FieldEditor } from '@dxos/react-ui-form';
11
10
  import { type FieldType } from '@dxos/schema';
@@ -13,7 +12,7 @@ import { type FieldType } from '@dxos/schema';
13
12
  import { type ModalController, type TableModel } from '../../model';
14
13
 
15
14
  type ColumnSettingsProps = {
16
- registry?: SchemaRegistry;
15
+ registry?: SchemaRegistry.SchemaRegistry;
17
16
  model?: TableModel;
18
17
  modals: ModalController;
19
18
  onNewColumn: () => void;
@@ -6,14 +6,13 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React, { useMemo, useState } from 'react';
7
7
 
8
8
  import { Obj } from '@dxos/echo';
9
- import { FormatEnum, type JsonSchemaType } from '@dxos/echo/internal';
9
+ import { Format, type JsonSchemaType } from '@dxos/echo/internal';
10
10
  import { faker } from '@dxos/random';
11
- import { useClient } from '@dxos/react-client';
12
11
  import { Filter, useQuery, useSchema } from '@dxos/react-client/echo';
13
12
  import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
14
13
  import { withTheme } from '@dxos/react-ui/testing';
15
14
  import { type SchemaPropertyDefinition } from '@dxos/schema';
16
- import { Testing } from '@dxos/schema/testing';
15
+ import { TestSchema } from '@dxos/schema/testing';
17
16
 
18
17
  import { type TableFeatures } from '../../model';
19
18
  import { translations } from '../../translations';
@@ -25,8 +24,8 @@ faker.seed(0);
25
24
  const useTestPropertiesAndObjects = () => {
26
25
  const properties = useMemo<SchemaPropertyDefinition[]>(
27
26
  () => [
28
- { name: 'name', format: FormatEnum.String },
29
- { name: 'age', format: FormatEnum.Number },
27
+ { name: 'name', format: Format.TypeFormat.String },
28
+ { name: 'age', format: Format.TypeFormat.Number },
30
29
  ],
31
30
  [],
32
31
  );
@@ -130,9 +129,8 @@ export const WithJsonSchema: StoryObj = {
130
129
 
131
130
  export const WithEchoSchema: StoryObj = {
132
131
  render: () => {
133
- const client = useClient();
134
132
  const { space } = useClientProvider();
135
- const schema = useSchema(client, space, Testing.Person.typename);
133
+ const schema = useSchema(space, TestSchema.Person.typename);
136
134
  const objects = useQuery(space, schema ? Filter.type(schema) : Filter.nothing());
137
135
  if (!schema) {
138
136
  return <div>Loading schema...</div>;
@@ -142,13 +140,13 @@ export const WithEchoSchema: StoryObj = {
142
140
  },
143
141
  decorators: [
144
142
  withClientProvider({
145
- types: [Testing.Person],
143
+ types: [TestSchema.Person],
146
144
  createIdentity: true,
147
145
  createSpace: true,
148
146
  onCreateSpace: async ({ space }) => {
149
147
  Array.from({ length: 10 }).forEach(() => {
150
148
  space.db.add(
151
- Obj.make(Testing.Person, {
149
+ Obj.make(TestSchema.Person, {
152
150
  name: faker.person.fullName(),
153
151
  email: faker.internet.email(),
154
152
  }),
@@ -2,12 +2,13 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import type * as Schema from 'effect/Schema';
6
5
  import React, { useCallback, useMemo, useRef } from 'react';
7
6
 
7
+ import { type Type } from '@dxos/echo';
8
8
  import { type JsonSchemaType } from '@dxos/echo/internal';
9
9
  import { type ThemedClassName, useDefaultValue } from '@dxos/react-ui';
10
10
  import { mx } from '@dxos/react-ui-theme';
11
+ import { ProjectionModel } from '@dxos/schema';
11
12
 
12
13
  import { useTableModel } from '../../hooks';
13
14
  import { type TableFeatures, TablePresentation, type TableRowAction } from '../../model';
@@ -15,12 +16,12 @@ import { type TablePropertyDefinition, getBaseSchema, makeDynamicTable } from '.
15
16
 
16
17
  import { Table, type TableController } from './Table';
17
18
 
18
- type DynamicTableProps = ThemedClassName<{
19
+ export type DynamicTableProps<T extends Type.Entity.Any = Type.Entity.Any> = ThemedClassName<{
20
+ schema?: T;
19
21
  name?: string; // TODO(burdon): Remove?
20
22
  rows: any[];
21
23
  properties?: TablePropertyDefinition[];
22
24
  jsonSchema?: JsonSchemaType;
23
- schema?: Schema.Schema.AnyNoContext;
24
25
  features?: Partial<TableFeatures>;
25
26
  rowActions?: TableRowAction[];
26
27
  onRowClick?: (row: any) => void;
@@ -32,25 +33,25 @@ type DynamicTableProps = ThemedClassName<{
32
33
  */
33
34
  // TODO(burdon): Instead of creating component variants, create helpers/hooks that normalize the props.
34
35
  // TODO(burdon): Warning: Cannot update a component (`DynamicTable`) while rendering a different component (`DynamicTable`).
35
- export const DynamicTable = ({
36
+ export const DynamicTable = <T extends Type.Entity.Any = Type.Entity.Any>({
36
37
  classNames,
38
+ schema,
37
39
  name = 'example.com/dynamic-table', // Rmove default or make random; this will lead to type collisions.
38
40
  rows,
39
41
  properties,
40
42
  jsonSchema: _jsonSchema,
41
- schema,
42
43
  rowActions,
43
44
  onRowClick,
44
45
  onRowAction,
45
46
  ...props
46
- }: DynamicTableProps) => {
47
+ }: DynamicTableProps<T>) => {
47
48
  // TODO(burdon): Remove variance from the props (should be normalized externally; possibly via hooks).
48
49
  const { jsonSchema } = useMemo(
49
50
  () => getBaseSchema({ typename: name, properties, jsonSchema: _jsonSchema, schema }),
50
51
  [name, properties, _jsonSchema, schema],
51
52
  );
52
53
 
53
- const { projection, view } = useMemo(() => makeDynamicTable({ jsonSchema, properties }), [jsonSchema, properties]);
54
+ const { object, projection } = useMemo(() => makeDynamicTable({ jsonSchema, properties }), [jsonSchema, properties]);
54
55
 
55
56
  const tableRef = useRef<TableController>(null);
56
57
  const handleCellUpdate = useCallback((cell: any) => {
@@ -70,11 +71,18 @@ export const DynamicTable = ({
70
71
  }) as const,
71
72
  );
72
73
 
74
+ const projectionModel = useMemo(() => {
75
+ if (jsonSchema && projection) {
76
+ const model = new ProjectionModel(jsonSchema, projection);
77
+ model.normalizeView();
78
+ return model;
79
+ }
80
+ }, [jsonSchema, projection]);
81
+
73
82
  const model = useTableModel({
74
83
  rows,
75
- view,
76
- schema: jsonSchema,
77
- projection,
84
+ object,
85
+ projection: projectionModel,
78
86
  features,
79
87
  rowActions,
80
88
  onCellUpdate: handleCellUpdate,
@@ -8,7 +8,6 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
8
8
  import { expect, userEvent, within } from 'storybook/test';
9
9
 
10
10
  import { Obj, Type } from '@dxos/echo';
11
- import { type JsonSchemaType } from '@dxos/echo/internal';
12
11
  import { type DxGrid } from '@dxos/lit-grid';
13
12
  import '@dxos/lit-ui/dx-tag-picker.pcss';
14
13
  import { faker } from '@dxos/random';
@@ -21,7 +20,7 @@ import { View } from '@dxos/schema';
21
20
  import { type ValueGenerator, createAsyncGenerator } from '@dxos/schema/testing';
22
21
  import { Organization, Person } from '@dxos/types';
23
22
 
24
- import { useTableModel } from '../../hooks';
23
+ import { useProjectionModel, useTableModel } from '../../hooks';
25
24
  import { type TableFeatures, TablePresentation, type TableRow } from '../../model';
26
25
  import { translations } from '../../translations';
27
26
  import { Table } from '../../types';
@@ -36,10 +35,8 @@ const generator: ValueGenerator = faker as any;
36
35
  // TODO(burdon): Reconcile schemas types and utils (see API PR).
37
36
  // TODO(burdon): Base type for T (with id); see ECHO API PR?
38
37
  const useTestModel = <S extends Type.Obj.Any>(schema: S, count: number) => {
39
- const client = useClient();
40
38
  const { space } = useClientProvider();
41
- const [view, setView] = useState<View.View>();
42
- const [jsonSchema, setJsonSchema] = useState<JsonSchemaType>();
39
+ const [object, setObject] = useState<Table.Table>();
43
40
 
44
41
  const features = useMemo<TableFeatures>(
45
42
  () => ({ schemaEditable: false, dataEditable: true, selection: { enabled: false } }),
@@ -51,18 +48,14 @@ const useTestModel = <S extends Type.Obj.Any>(schema: S, count: number) => {
51
48
  return;
52
49
  }
53
50
 
54
- const {
55
- jsonSchema,
56
- schema: effectSchema,
57
- view,
58
- } = await Table.makeView({ client, space, typename: Type.getTypename(schema) });
59
- setJsonSchema(jsonSchema);
60
- setView(view);
61
- space.db.add(view);
62
- await space.db.schemaRegistry.register([effectSchema]);
63
- }, [client, space, schema]);
51
+ const { view, jsonSchema } = await View.makeFromSpace({ space, typename: Type.getTypename(schema) });
52
+ const object = Table.make({ view, jsonSchema });
53
+ setObject(object);
54
+ space.db.add(object);
55
+ }, [space, schema]);
64
56
 
65
- const model = useTableModel<TableRow>({ view, schema: jsonSchema, rows: [], features });
57
+ const projection = useProjectionModel(schema, object);
58
+ const model = useTableModel<TableRow>({ object, projection, features });
66
59
 
67
60
  useEffect(() => {
68
61
  if (!model || !space) {
@@ -107,7 +100,6 @@ const DefaultStory = () => {
107
100
  schema={Organization.Organization}
108
101
  presentation={orgPresentation}
109
102
  onCreate={handleCreate}
110
- client={client}
111
103
  ignoreAttention
112
104
  testId='relations-0'
113
105
  />
@@ -118,7 +110,6 @@ const DefaultStory = () => {
118
110
  schema={Person.Person}
119
111
  presentation={contactPresentation}
120
112
  onCreate={handleCreate}
121
- client={client}
122
113
  ignoreAttention
123
114
  testId='relations-1'
124
115
  />
@@ -6,26 +6,18 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import * as Schema from 'effect/Schema';
7
7
  import React, { useCallback } from 'react';
8
8
 
9
- import { Obj, type QueryAST, Type } from '@dxos/echo';
10
- import {
11
- EchoObject,
12
- FormatAnnotation,
13
- FormatEnum,
14
- GeneratorAnnotation,
15
- LabelAnnotation,
16
- PropertyMetaAnnotationId,
17
- } from '@dxos/echo/internal';
18
- import { live } from '@dxos/echo/internal';
9
+ import { Annotation, Format, Obj, type QueryAST, Type } from '@dxos/echo';
10
+ import { PropertyMetaAnnotationId } from '@dxos/echo/internal';
19
11
  import { invariant } from '@dxos/invariant';
20
12
  import { faker } from '@dxos/random';
21
13
  import { PublicKey } from '@dxos/react-client';
22
14
  import { type Space } from '@dxos/react-client/echo';
23
15
  import { withClientProvider } from '@dxos/react-client/testing';
24
16
  import { withTheme } from '@dxos/react-ui/testing';
25
- import { ViewEditor } from '@dxos/react-ui-form';
17
+ import { ViewEditor, translations as formTranslations } from '@dxos/react-ui-form';
26
18
  import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
27
19
  import { View, getSchemaFromPropertyDefinitions, getTypenameFromQuery } from '@dxos/schema';
28
- import { Testing, createObjectFactory } from '@dxos/schema/testing';
20
+ import { TestSchema, createObjectFactory } from '@dxos/schema/testing';
29
21
 
30
22
  import { useTestTableModel } from '../../testing';
31
23
  import { translations } from '../../translations';
@@ -34,13 +26,13 @@ import { TableToolbar } from '../TableToolbar';
34
26
 
35
27
  import { Table as TableComponent } from './Table';
36
28
 
37
- const TestSchema = Schema.Struct({
29
+ const Example = Schema.Struct({
38
30
  // TODO(wittjosiah): Should be title. Currently name to work with default label.
39
31
  name: Schema.optional(Schema.String).annotations({ title: 'Title' }),
40
32
  urgent: Schema.optional(Schema.Boolean).annotations({ title: 'Urgent' }),
41
33
  status: Schema.optional(
42
34
  Schema.Literal('todo', 'in-progress', 'done')
43
- .pipe(FormatAnnotation.set(FormatEnum.SingleSelect))
35
+ .pipe(Format.FormatAnnotation.set(Format.TypeFormat.SingleSelect))
44
36
  .annotations({
45
37
  title: 'Status',
46
38
  [PropertyMetaAnnotationId]: {
@@ -55,14 +47,14 @@ const TestSchema = Schema.Struct({
55
47
  }),
56
48
  ),
57
49
  description: Schema.optional(Schema.String).annotations({ title: 'Description' }),
58
- parent: Schema.optional(Schema.suspend((): Type.Ref<TestSchema> => Type.Ref(TestSchema))).annotations({
50
+ parent: Schema.optional(Schema.suspend((): Type.Ref<Example> => Type.Ref(Example))).annotations({
59
51
  title: 'Parent',
60
52
  }),
61
53
  }).pipe(
62
54
  Type.Obj({ typename: `example.com/type/${PublicKey.random().truncate()}`, version: '0.1.0' }),
63
- LabelAnnotation.set(['name']),
55
+ Annotation.LabelAnnotation.set(['name']),
64
56
  );
65
- interface TestSchema extends Schema.Schema.Type<typeof TestSchema> {}
57
+ interface Example extends Schema.Schema.Type<typeof Example> {}
66
58
 
67
59
  const StoryViewEditor = ({
68
60
  view,
@@ -106,20 +98,10 @@ const StoryViewEditor = ({
106
98
  //
107
99
 
108
100
  const DefaultStory = () => {
109
- const {
110
- space,
111
- schema,
112
- view,
113
- tableRef,
114
- model,
115
- presentation,
116
- client,
117
- handleInsertRow,
118
- handleSaveView,
119
- handleDeleteColumn,
120
- } = useTestTableModel();
101
+ const { space, schema, table, tableRef, model, presentation, handleInsertRow, handleSaveView, handleDeleteColumn } =
102
+ useTestTableModel();
121
103
 
122
- if (!schema || !view) {
104
+ if (!schema || !table?.view.target) {
123
105
  return <div />;
124
106
  }
125
107
 
@@ -130,18 +112,22 @@ const DefaultStory = () => {
130
112
  <TableComponent.Root>
131
113
  <TableComponent.Main
132
114
  ref={tableRef}
115
+ schema={schema}
133
116
  model={model}
134
117
  presentation={presentation}
135
- schema={schema}
136
- client={client}
137
118
  ignoreAttention
138
119
  />
139
120
  </TableComponent.Root>
140
121
  </div>
141
122
  <div className='flex flex-col bs-full border-l border-separator overflow-y-auto'>
142
- <StoryViewEditor view={view} schema={schema} space={space} handleDeleteColumn={handleDeleteColumn} />
123
+ <StoryViewEditor
124
+ view={table.view.target}
125
+ schema={schema}
126
+ space={space}
127
+ handleDeleteColumn={handleDeleteColumn}
128
+ />
143
129
  <SyntaxHighlighter language='json' className='text-xs'>
144
- {JSON.stringify({ view, schema }, null, 2)}
130
+ {JSON.stringify({ view: table.view.target, schema }, null, 2)}
145
131
  </SyntaxHighlighter>
146
132
  </div>
147
133
  </div>
@@ -165,15 +151,16 @@ const meta = {
165
151
  types: [View.View, Table.Table],
166
152
  createIdentity: true,
167
153
  createSpace: true,
168
- onCreateSpace: async ({ client, space }) => {
169
- const [schema] = await space.db.schemaRegistry.register([TestSchema]);
170
- const { view } = await Table.makeView({ client, space, typename: schema.typename });
154
+ onCreateSpace: async ({ space }) => {
155
+ const [schema] = await space.db.schemaRegistry.register([Example]);
156
+ const { view, jsonSchema } = await View.makeFromSpace({ space, typename: schema.typename });
157
+ const table = Table.make({ view, jsonSchema });
171
158
  view.projection.fields = [
172
159
  view.projection.fields.find((field: any) => field.path === 'name')!,
173
160
  ...view.projection.fields.filter((field: any) => field.path !== 'name'),
174
161
  ];
175
162
 
176
- space.db.add(view);
163
+ space.db.add(table);
177
164
 
178
165
  Array.from({ length: 10 }).map(() => {
179
166
  return space.db.add(
@@ -192,7 +179,7 @@ const meta = {
192
179
  controls: {
193
180
  disable: true,
194
181
  },
195
- translations,
182
+ translations: [...translations, ...formTranslations],
196
183
  },
197
184
  } satisfies Meta<typeof TableComponent>;
198
185
 
@@ -209,26 +196,27 @@ export const StaticSchema: StoryObj = {
209
196
  types: [View.View, Table.Table],
210
197
  createIdentity: true,
211
198
  createSpace: true,
212
- onCreateSpace: async ({ client, space }) => {
213
- const { view } = await Table.makeView({ client, space, typename: Testing.Person.typename });
214
- space.db.add(view);
199
+ onCreateSpace: async ({ space }) => {
200
+ const { view, jsonSchema } = await View.makeFromSpace({ space, typename: TestSchema.Person.typename });
201
+ const table = Table.make({ view, jsonSchema });
202
+ space.db.add(table);
215
203
 
216
204
  const factory = createObjectFactory(space.db, faker as any);
217
205
  await factory([
218
- { type: Testing.Person, count: 10 },
219
- // { type: Testing.Organization, count: 1 },
206
+ { type: TestSchema.Person, count: 10 },
207
+ // { type: TestSchema.Organization, count: 1 },
220
208
  ]);
221
209
  },
222
210
  }),
223
211
  ],
224
212
  parameters: {
225
213
  layout: 'fullscreen',
226
- translations,
214
+ translations: [...translations, ...formTranslations],
227
215
  },
228
216
  };
229
217
 
230
218
  const ContactWithArrayOfEmails = Schema.Struct({
231
- name: Schema.String.pipe(GeneratorAnnotation.set('person.fullName')),
219
+ name: Schema.String.pipe(Annotation.GeneratorAnnotation.set('person.fullName')),
232
220
  emails: Schema.optional(
233
221
  Schema.Array(
234
222
  Schema.Struct({
@@ -238,7 +226,7 @@ const ContactWithArrayOfEmails = Schema.Struct({
238
226
  ),
239
227
  ),
240
228
  }).pipe(
241
- EchoObject({
229
+ Type.Obj({
242
230
  typename: 'dxos.org/type/ContactWithArrayOfEmails',
243
231
  version: '0.1.0',
244
232
  }),
@@ -248,17 +236,21 @@ export const ArrayOfObjects: StoryObj = {
248
236
  render: DefaultStory,
249
237
  decorators: [
250
238
  withClientProvider({
251
- types: [View.View, Table.Table, Testing.Person, Testing.Organization, ContactWithArrayOfEmails],
239
+ types: [View.View, Table.Table, TestSchema.Person, TestSchema.Organization, ContactWithArrayOfEmails],
252
240
  createIdentity: true,
253
241
  createSpace: true,
254
- onCreateSpace: async ({ client, space }) => {
255
- const { view } = await Table.makeView({ client, space, typename: ContactWithArrayOfEmails.typename });
256
- space.db.add(view);
242
+ onCreateSpace: async ({ space }) => {
243
+ const { view, jsonSchema } = await View.makeFromSpace({
244
+ space,
245
+ typename: ContactWithArrayOfEmails.typename,
246
+ });
247
+ const table = Table.make({ view, jsonSchema });
248
+ space.db.add(table);
257
249
 
258
250
  const factory = createObjectFactory(space.db, faker as any);
259
251
  await factory([
260
- // { type: Testing.Person, count: 10 },
261
- // { type: Testing.Organization, count: 1 },
252
+ // { type: TestSchema.Person, count: 10 },
253
+ // { type: TestSchema.Organization, count: 1 },
262
254
  { type: ContactWithArrayOfEmails, count: 10 },
263
255
  ]);
264
256
  },
@@ -278,7 +270,7 @@ export const Tags: Meta<StoryProps> = {
278
270
  types: [View.View, Table.Table],
279
271
  createIdentity: true,
280
272
  createSpace: true,
281
- onCreateSpace: async ({ client, space }) => {
273
+ onCreateSpace: async ({ space }) => {
282
274
  // Configure schema.
283
275
  const typename = 'example.com/SingleSelect';
284
276
  const selectOptions = [
@@ -294,25 +286,26 @@ export const Tags: Meta<StoryProps> = {
294
286
  const schema = getSchemaFromPropertyDefinitions(typename, [
295
287
  {
296
288
  name: 'single',
297
- format: FormatEnum.SingleSelect,
289
+ format: Format.TypeFormat.SingleSelect,
298
290
  config: { options: selectOptions },
299
291
  },
300
292
  {
301
293
  name: 'multiple',
302
- format: FormatEnum.MultiSelect,
294
+ format: Format.TypeFormat.MultiSelect,
303
295
  config: { options: selectOptions },
304
296
  },
305
297
  ]);
306
298
  const [storedSchema] = await space.db.schemaRegistry.register([schema]);
307
299
 
308
300
  // Initialize table.
309
- const { view } = await Table.makeView({ client, space, typename });
310
- space.db.add(view);
301
+ const { view, jsonSchema } = await View.makeFromSpace({ space, typename });
302
+ const table = Table.make({ view, jsonSchema });
303
+ space.db.add(table);
311
304
 
312
305
  // Populate.
313
306
  Array.from({ length: 10 }).map(() => {
314
307
  return space.db.add(
315
- live(storedSchema, {
308
+ Obj.make(storedSchema, {
316
309
  single: faker.helpers.arrayElement([...selectOptionIds, undefined]),
317
310
  multiple: faker.helpers.randomSubset(selectOptionIds),
318
311
  }),