@dxos/react-ui-table 0.8.4-main.d05673bc65 → 0.8.4-main.d9fc60f731

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 (126) hide show
  1. package/LICENSE +102 -5
  2. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  3. package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
  4. package/dist/lib/browser/{chunk-PTHMYAAM.mjs → chunk-X7A7G6RR.mjs} +28 -83
  5. package/dist/lib/browser/chunk-X7A7G6RR.mjs.map +7 -0
  6. package/dist/lib/browser/{chunk-BF54SSNL.mjs → chunk-YURROGGF.mjs} +12 -15
  7. package/dist/lib/browser/chunk-YURROGGF.mjs.map +7 -0
  8. package/dist/lib/browser/index.mjs +230 -280
  9. package/dist/lib/browser/index.mjs.map +4 -4
  10. package/dist/lib/browser/meta.json +1 -1
  11. package/dist/lib/browser/testing/index.mjs +10 -9
  12. package/dist/lib/browser/testing/index.mjs.map +3 -3
  13. package/dist/lib/browser/translations.mjs +36 -0
  14. package/dist/lib/browser/translations.mjs.map +7 -0
  15. package/dist/lib/browser/types/index.mjs +2 -1
  16. package/dist/lib/node-esm/{chunk-SIRDIPHZ.mjs → chunk-DLAGRBKD.mjs} +12 -15
  17. package/dist/lib/node-esm/chunk-DLAGRBKD.mjs.map +7 -0
  18. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  19. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
  20. package/dist/lib/node-esm/{chunk-GI72MQSG.mjs → chunk-Q4HSBRJJ.mjs} +28 -83
  21. package/dist/lib/node-esm/chunk-Q4HSBRJJ.mjs.map +7 -0
  22. package/dist/lib/node-esm/index.mjs +230 -280
  23. package/dist/lib/node-esm/index.mjs.map +4 -4
  24. package/dist/lib/node-esm/meta.json +1 -1
  25. package/dist/lib/node-esm/testing/index.mjs +10 -9
  26. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  27. package/dist/lib/node-esm/translations.mjs +37 -0
  28. package/dist/lib/node-esm/translations.mjs.map +7 -0
  29. package/dist/lib/node-esm/types/index.mjs +2 -1
  30. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  31. package/dist/types/src/components/Table/ColumnSettings.d.ts +2 -2
  32. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  33. package/dist/types/src/components/Table/DynamicTable.d.ts +3 -4
  34. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  35. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +21 -22
  36. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/Table/Relations.stories.d.ts +83 -82
  38. package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -1
  39. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  40. package/dist/types/src/components/Table/Table.d.ts +20 -21
  41. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  42. package/dist/types/src/components/Table/Table.stories.d.ts +85 -84
  43. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  44. package/dist/types/src/components/Table/TableContent.d.ts +18 -0
  45. package/dist/types/src/components/Table/TableContent.d.ts.map +1 -0
  46. package/dist/types/src/components/Table/TableToolbar.d.ts +21 -0
  47. package/dist/types/src/components/Table/TableToolbar.d.ts.map +1 -0
  48. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
  49. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +1 -1
  50. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  51. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  52. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +22 -24
  53. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  54. package/dist/types/src/components/index.d.ts +0 -1
  55. package/dist/types/src/components/index.d.ts.map +1 -1
  56. package/dist/types/src/components/testing.d.ts.map +1 -1
  57. package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
  58. package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -1
  59. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  60. package/dist/types/src/index.d.ts +0 -2
  61. package/dist/types/src/index.d.ts.map +1 -1
  62. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  63. package/dist/types/src/model/selection-model.d.ts +1 -1
  64. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  65. package/dist/types/src/model/table-model.d.ts +4 -5
  66. package/dist/types/src/model/table-model.d.ts.map +1 -1
  67. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  68. package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
  69. package/dist/types/src/playwright/playwright.config.d.ts.map +1 -1
  70. package/dist/types/src/testing/useTestTableModel.d.ts +1 -1
  71. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  72. package/dist/types/src/translations.d.ts +19 -21
  73. package/dist/types/src/translations.d.ts.map +1 -1
  74. package/dist/types/src/types/Table.d.ts +11 -5
  75. package/dist/types/src/types/Table.d.ts.map +1 -1
  76. package/dist/types/src/util/dynamic-table.d.ts +6 -6
  77. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  78. package/dist/types/src/util/query-ast.d.ts.map +1 -1
  79. package/dist/types/src/util/schema.d.ts.map +1 -1
  80. package/dist/types/src/util/signals.d.ts.map +1 -1
  81. package/dist/types/src/util/sort.d.ts.map +1 -1
  82. package/dist/types/src/util/table-buttons.d.ts +20 -20
  83. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  84. package/dist/types/src/util/table-controls.d.ts +4 -4
  85. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  86. package/dist/types/src/util/tag.d.ts.map +1 -1
  87. package/dist/types/tsconfig.tsbuildinfo +1 -1
  88. package/package.json +55 -64
  89. package/src/components/Table/ColumnActionsMenu.tsx +7 -6
  90. package/src/components/Table/ColumnSettings.tsx +2 -2
  91. package/src/components/Table/DynamicTable.stories.tsx +19 -19
  92. package/src/components/Table/DynamicTable.tsx +13 -22
  93. package/src/components/Table/Relations.stories.tsx +76 -34
  94. package/src/components/Table/RowActionsMenu.tsx +3 -2
  95. package/src/components/Table/Table.stories.tsx +46 -51
  96. package/src/components/Table/Table.tsx +37 -426
  97. package/src/components/Table/TableContent.tsx +426 -0
  98. package/src/components/{TableToolbar → Table}/TableToolbar.tsx +34 -41
  99. package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -2
  100. package/src/components/TableCellEditor/FormCellEditor.tsx +7 -6
  101. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +14 -12
  102. package/src/components/TableCellEditor/TableCellEditor.tsx +10 -8
  103. package/src/components/index.ts +0 -1
  104. package/src/components/testing.ts +11 -16
  105. package/src/hooks/useProjectionModel.ts +5 -6
  106. package/src/hooks/useTableModel.ts +1 -1
  107. package/src/index.ts +0 -4
  108. package/src/model/table-model.test.ts +4 -10
  109. package/src/model/table-model.ts +15 -15
  110. package/src/model/table-presentation.test.ts +4 -10
  111. package/src/model/table-presentation.ts +5 -7
  112. package/src/playwright/smoke.spec.ts +3 -3
  113. package/src/testing/useTestTableModel.ts +7 -8
  114. package/src/translations.ts +19 -21
  115. package/src/types/Table.ts +12 -13
  116. package/src/util/dynamic-table.test.ts +13 -20
  117. package/src/util/dynamic-table.ts +21 -20
  118. package/dist/lib/browser/chunk-BF54SSNL.mjs.map +0 -7
  119. package/dist/lib/browser/chunk-PTHMYAAM.mjs.map +0 -7
  120. package/dist/lib/node-esm/chunk-GI72MQSG.mjs.map +0 -7
  121. package/dist/lib/node-esm/chunk-SIRDIPHZ.mjs.map +0 -7
  122. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +0 -21
  123. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +0 -1
  124. package/dist/types/src/components/TableToolbar/index.d.ts +0 -2
  125. package/dist/types/src/components/TableToolbar/index.d.ts.map +0 -1
  126. package/src/components/TableToolbar/index.ts +0 -5
@@ -25,16 +25,9 @@ import {
25
25
  import { type FieldProjection } from '@dxos/schema';
26
26
 
27
27
  import { type ModalController, type TableModel } from '../../model';
28
-
29
28
  import { CellValidationMessage } from './CellValidationMessage';
30
29
  import { FormCellEditor, type OnCreateHandler } from './FormCellEditor';
31
30
 
32
- const editorSlots = {
33
- scroll: {
34
- className: '!py-(--dx-grid-cell-editor-padding-block)',
35
- },
36
- };
37
-
38
31
  /**
39
32
  * Option to create new object/value.
40
33
  */
@@ -250,7 +243,16 @@ export const TableCellEditor = ({
250
243
  return (
251
244
  <>
252
245
  <CellValidationMessage validationError={validationError} variant={validationVariant} __gridScope={__gridScope} />
253
- <GridCellEditor extensions={extensions} getCellContent={getCellContent} onBlur={handleBlur} slots={editorSlots} />
246
+ <GridCellEditor
247
+ extensions={extensions}
248
+ slots={{
249
+ content: {
250
+ className: '!py-(--dx-grid-cell-editor-padding-block)',
251
+ },
252
+ }}
253
+ getCellContent={getCellContent}
254
+ onBlur={handleBlur}
255
+ />
254
256
  </>
255
257
  );
256
258
  };
@@ -3,4 +3,3 @@
3
3
  //
4
4
 
5
5
  export * from './Table';
6
- export * from './TableToolbar';
@@ -6,10 +6,10 @@ import { Atom } from '@effect-atom/atom-react';
6
6
  import * as Schema from 'effect/Schema';
7
7
  import { useEffect } from 'react';
8
8
 
9
- import { Format, Type } from '@dxos/echo';
9
+ import { DXN, Format, Type } from '@dxos/echo';
10
10
  import { TypeEnum } from '@dxos/echo/internal';
11
11
  import { setValue } from '@dxos/effect';
12
- import { faker } from '@dxos/random';
12
+ import { random } from '@dxos/random';
13
13
  import { type ProjectionModel } from '@dxos/schema';
14
14
 
15
15
  export const TestSchema = Schema.Struct({
@@ -17,12 +17,7 @@ export const TestSchema = Schema.Struct({
17
17
  age: Schema.optional(Schema.Number),
18
18
  active: Schema.optional(Schema.Boolean),
19
19
  netWorth: Schema.optional(Schema.Number),
20
- }).pipe(
21
- Type.object({
22
- typename: 'com.example.type.test',
23
- version: '0.1.0',
24
- }),
25
- );
20
+ }).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
26
21
 
27
22
  export type TestItem = {
28
23
  name: string;
@@ -37,10 +32,10 @@ export type TestItem = {
37
32
  export const createItemsAtom = (n: number) => {
38
33
  return Atom.make<{ data: TestItem[] }>({
39
34
  data: Array.from({ length: n }, () => ({
40
- name: faker.person.fullName(),
41
- age: faker.number.int({ min: 20, max: 70 }),
42
- active: faker.datatype.boolean(),
43
- netWorth: faker.number.int(),
35
+ name: random.person.fullName(),
36
+ age: random.number.int({ min: 20, max: 70 }),
37
+ active: random.datatype.boolean(),
38
+ netWorth: random.number.int(),
44
39
  })),
45
40
  }).pipe(Atom.keepAlive);
46
41
  };
@@ -50,10 +45,10 @@ export const createItemsAtom = (n: number) => {
50
45
  */
51
46
  export const createItems = (n: number): TestItem[] => {
52
47
  return Array.from({ length: n }, () => ({
53
- name: faker.person.fullName(),
54
- age: faker.number.int({ min: 20, max: 70 }),
55
- active: faker.datatype.boolean(),
56
- netWorth: faker.number.int(),
48
+ name: random.person.fullName(),
49
+ age: random.number.int({ min: 20, max: 70 }),
50
+ active: random.datatype.boolean(),
51
+ netWorth: random.number.int(),
57
52
  }));
58
53
  };
59
54
 
@@ -5,7 +5,7 @@
5
5
  import { type Registry } from '@effect-atom/atom-react';
6
6
  import { useState } from 'react';
7
7
 
8
- import { JsonSchema, Type } from '@dxos/echo';
8
+ import { Type } from '@dxos/echo';
9
9
  import { useAsyncEffect } from '@dxos/react-ui';
10
10
  import { ProjectionModel, createEchoChangeCallback } from '@dxos/schema';
11
11
 
@@ -21,13 +21,12 @@ export const useProjectionModel = <S extends Type.AnyEntity>(
21
21
  useAsyncEffect(async () => {
22
22
  if (schema && table) {
23
23
  const view = await table.view.load();
24
- // For mutable schemas (EchoSchema), use the live jsonSchema reference for reactivity.
25
- // For immutable schemas, create a snapshot.
26
- const jsonSchema = Type.isMutable(schema) ? schema.jsonSchema : JsonSchema.toJsonSchema(schema);
24
+ // Use the live jsonSchema reference for reactivity.
25
+ const jsonSchema = schema.jsonSchema;
27
26
 
28
27
  // Always use createEchoChangeCallback since the view is ECHO-backed.
29
- // Pass schema only when mutable to allow schema mutations.
30
- const change = createEchoChangeCallback(view, Type.isMutable(schema) ? schema : undefined);
28
+ // Pass the type entity only when stored, to allow schema mutations.
29
+ const change = createEchoChangeCallback(view, Type.getDatabase(schema) != null ? schema : undefined);
31
30
 
32
31
  const projection = new ProjectionModel({ registry, view, baseSchema: jsonSchema, change });
33
32
  projection.normalizeView();
@@ -44,7 +44,7 @@ export const useTableModel = <T extends TableRow = TableRow>({
44
44
  ...props
45
45
  }: UseTableModelProps<T>): TableModel<T> | undefined => {
46
46
  const registry = useContext(RegistryContext);
47
- const selected = useSelected(object && Obj.getDXN(object).toString(), 'multi');
47
+ const selected = useSelected(object && Obj.getURI(object), 'multi');
48
48
  const initialSelection = useMemo(() => selected, [object]);
49
49
 
50
50
  const [model, setModel] = useState<TableModel<T>>();
package/src/index.ts CHANGED
@@ -2,11 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { translations } from './translations';
6
-
7
5
  export * from './components';
8
6
  export * from './hooks';
9
7
  export * from './model';
10
8
  export * from './util';
11
-
12
- export { translations };
@@ -6,12 +6,11 @@ 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, JsonSchema, Query, Type } from '@dxos/echo';
9
+ import { DXN, Filter, JsonSchema, Query, Type } from '@dxos/echo';
10
10
  import { createEchoSchema } from '@dxos/echo/testing';
11
11
  import { ProjectionModel, ViewModel, createDirectChangeCallback } from '@dxos/schema';
12
12
 
13
13
  import { Table } from '../types';
14
-
15
14
  import {
16
15
  TableModel,
17
16
  type TableModelProps,
@@ -119,15 +118,10 @@ describe('TableModel', () => {
119
118
  const Test = Schema.Struct({
120
119
  title: Schema.String,
121
120
  completed: Schema.Boolean,
122
- }).pipe(
123
- Type.object({
124
- typename: 'com.example.type.test',
125
- version: '0.1.0',
126
- }),
127
- );
121
+ }).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
128
122
 
129
123
  const createTableModel = (registry: Registry.Registry, props: Partial<TableModelProps> = {}): TableModel => {
130
- const schema = createEchoSchema(Test);
124
+ const schema = createEchoSchema(Type.getSchema(Test));
131
125
  const view = ViewModel.make({
132
126
  query: Query.select(Filter.type(schema)),
133
127
  jsonSchema: schema.jsonSchema,
@@ -137,7 +131,7 @@ const createTableModel = (registry: Registry.Registry, props: Partial<TableModel
137
131
  registry,
138
132
  view,
139
133
  baseSchema: schema.jsonSchema,
140
- change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(schema)),
134
+ change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(Type.getSchema(schema))),
141
135
  });
142
136
  projection.normalizeView();
143
137
  return new TableModel({
@@ -5,13 +5,12 @@
5
5
  import { Atom, type Registry } from '@effect-atom/atom-react';
6
6
 
7
7
  import { Resource } from '@dxos/context';
8
- import { type Database, Format, Obj, Order, Query, type QueryAST, Ref } from '@dxos/echo';
9
- import { type View } from '@dxos/echo';
8
+ import { type Database, Format, Obj, Order, Query, type QueryAST, Ref, Type, type View } from '@dxos/echo';
10
9
  import { type JsonProp, type JsonSchemaType, type Mutable, toEffectSchema } from '@dxos/echo/internal';
11
10
  import { getSnapshot } from '@dxos/echo/internal';
12
11
  import { getValue, setValue } from '@dxos/effect';
13
12
  import { invariant } from '@dxos/invariant';
14
- import { ObjectId } from '@dxos/keys';
13
+ import { EntityId } from '@dxos/keys';
15
14
  import { type Label } from '@dxos/react-ui';
16
15
  import { formatForEditing, parseValue } from '@dxos/react-ui-form';
17
16
  import {
@@ -38,7 +37,7 @@ export type FieldSortType = {
38
37
  import { type SelectionMode, SelectionModel } from './selection-model';
39
38
 
40
39
  /**
41
- * Callback type for wrapping mutations in Obj.change().
40
+ * Callback type for wrapping mutations in Obj.update().
42
41
  * Contains separate callbacks for table object and row mutations.
43
42
  */
44
43
  export type TableChangeCallback<T extends TableRow> = {
@@ -53,10 +52,10 @@ export type TableChangeCallback<T extends TableRow> = {
53
52
  * Use this when the table and rows are stored in the ECHO database.
54
53
  */
55
54
  export const createEchoChangeCallback = <T extends TableRow>(table: Table.Table): TableChangeCallback<T> => ({
56
- table: (mutate) => Obj.change(table, (mutableTable) => mutate(mutableTable as unknown as Table.Table)),
55
+ table: (mutate) => Obj.update(table, (table) => mutate(table as unknown as Table.Table)),
57
56
  row: (row, mutate) => {
58
57
  if (Obj.isObject(row)) {
59
- Obj.change(row, (mutableRow) => mutate(mutableRow as T));
58
+ Obj.update(row, (row) => mutate(row as T));
60
59
  } else {
61
60
  mutate(row);
62
61
  }
@@ -112,7 +111,7 @@ export type TableModelProps<T extends TableRow = TableRow> = {
112
111
  projection: ProjectionModel;
113
112
  db?: Database.Database;
114
113
  /**
115
- * Callbacks to wrap mutations in Obj.change().
114
+ * Callbacks to wrap mutations in Obj.update().
116
115
  * Use createEchoChangeCallback() for ECHO-backed objects or createDirectChangeCallback() for plain objects.
117
116
  */
118
117
  change?: TableChangeCallback<T>;
@@ -300,7 +299,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
300
299
  }
301
300
 
302
301
  public get id(): string {
303
- return Obj.getDXN(this._object).toString();
302
+ return Obj.getURI(this._object);
304
303
  }
305
304
 
306
305
  public get view(): View.View {
@@ -524,7 +523,7 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
524
523
  }
525
524
 
526
525
  // NOTE(ZaymonFC): This is initialized with id because it's required in all schemata?
527
- const draftData = { id: ObjectId.random() } as any as T;
526
+ const draftData = { id: EntityId.random() } as any as T;
528
527
  const validationErrors = this.validateDraftRowData(draftData);
529
528
 
530
529
  const draftRow: DraftRow<T> = {
@@ -695,8 +694,9 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
695
694
  const snapshot = { ...getSnapshot(currentRow) };
696
695
  setValue(snapshot, field.path, transformedValue);
697
696
 
698
- const schema = Obj.getSchema(currentRow);
699
- invariant(schema);
697
+ const type = Obj.getType(currentRow as unknown as Obj.Unknown);
698
+ invariant(type);
699
+ const schema = Type.getSchema(type);
700
700
 
701
701
  const validationResult = validateSchema(schema, snapshot);
702
702
  if (validationResult && validationResult.length > 0) {
@@ -894,14 +894,14 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
894
894
  if (field) {
895
895
  // Persist sort to view.query.ast
896
896
  const newQuery = baseQuery.orderBy(Order.property<any>(field.path as string, inMemorySort.direction));
897
- Obj.change(view, (v) => {
898
- v.query.ast = newQuery.ast as Mutable<typeof newQuery.ast>;
897
+ Obj.update(view, (view) => {
898
+ view.query.ast = newQuery.ast as Mutable<typeof newQuery.ast>;
899
899
  });
900
900
  }
901
901
  } else {
902
902
  // Clear sort from view.query.ast
903
- Obj.change(view, (v) => {
904
- v.query.ast = baseQuery.ast as Mutable<typeof baseQuery.ast>;
903
+ Obj.update(view, (view) => {
904
+ view.query.ast = baseQuery.ast as Mutable<typeof baseQuery.ast>;
905
905
  });
906
906
  }
907
907
 
@@ -6,12 +6,11 @@ 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, JsonSchema, Query, Type } from '@dxos/echo';
9
+ import { DXN, Filter, JsonSchema, Query, Type } from '@dxos/echo';
10
10
  import { createEchoSchema } from '@dxos/echo/testing';
11
11
  import { ProjectionModel, ViewModel, createDirectChangeCallback } from '@dxos/schema';
12
12
 
13
13
  import { Table } from '../types';
14
-
15
14
  import { TableModel, type TableModelProps } from './table-model';
16
15
  import { TablePresentation } from './table-presentation';
17
16
 
@@ -90,15 +89,10 @@ describe('TablePresentation', () => {
90
89
  const Test = Schema.Struct({
91
90
  title: Schema.String,
92
91
  count: Schema.Number,
93
- }).pipe(
94
- Type.object({
95
- typename: 'com.example.type.test',
96
- version: '0.1.0',
97
- }),
98
- );
92
+ }).pipe(Type.makeObject(DXN.make('com.example.type.test', '0.1.0')));
99
93
 
100
94
  const createTableModel = (registry: Registry.Registry, props: Partial<TableModelProps> = {}): TableModel => {
101
- const schema = createEchoSchema(Test);
95
+ const schema = createEchoSchema(Type.getSchema(Test));
102
96
  const view = ViewModel.make({
103
97
  query: Query.select(Filter.type(schema)),
104
98
  jsonSchema: schema.jsonSchema,
@@ -108,7 +102,7 @@ const createTableModel = (registry: Registry.Registry, props: Partial<TableModel
108
102
  registry,
109
103
  view,
110
104
  baseSchema: schema.jsonSchema,
111
- change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(schema)),
105
+ change: createDirectChangeCallback(view.projection, JsonSchema.toJsonSchema(Type.getSchema(schema))),
112
106
  });
113
107
  projection.normalizeView();
114
108
  return new TableModel({ registry, object, projection, ...props });
@@ -5,8 +5,7 @@
5
5
  import { Atom, type Registry } from '@effect-atom/atom-react';
6
6
  import * as Predicate from 'effect/Predicate';
7
7
 
8
- import { Obj } from '@dxos/echo';
9
- import { type View } from '@dxos/echo';
8
+ import { Obj, type View } from '@dxos/echo';
10
9
  import { Format, TypeEnum, getValue } from '@dxos/echo/internal';
11
10
  import { cellClassesForFieldType, formatForDisplay } from '@dxos/react-ui-form';
12
11
  import {
@@ -20,7 +19,6 @@ import { VIEW_FIELD_LIMIT } from '@dxos/schema';
20
19
  import { mx } from '@dxos/ui-theme';
21
20
 
22
21
  import { tableButtons, tableControls } from '../util';
23
-
24
22
  import { type SelectionMode } from './selection-model';
25
23
  import { type TableModel, type TableRow } from './table-model';
26
24
 
@@ -210,8 +208,8 @@ export class TablePresentation<T extends TableRow = TableRow> {
210
208
  if (props.format === Format.TypeFormat.Ref && props.referenceSchema) {
211
209
  const targetObj = getValue(obj, field.path)?.target;
212
210
  if (targetObj) {
213
- const dxn = Obj.getDXN(targetObj)?.toString();
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>`;
211
+ const uri = Obj.getURI(targetObj);
212
+ cell.accessoryHtml = `<div role="none" class="absolute end-0 inset-y-0 p-(--dx-grid-cell-content-padding-block)"><dx-anchor uri=${uri} 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>`;
215
213
  }
216
214
  }
217
215
 
@@ -474,8 +472,8 @@ export const cellClassesForRowSelection = (selected: boolean, selectionMode: Sel
474
472
 
475
473
  switch (selectionMode) {
476
474
  case 'single':
477
- return ['dx-grid__cell--no-focus-unfurl !bg-current-surface hover:bg-hover-surface cursor-pointer!'];
475
+ return ['dx-grid__cell--no-focus-unfurl bg-current-surface! hover:bg-hover-surface cursor-pointer!'];
478
476
  case 'multiple':
479
- return ['!bg-grid-cell-selected'];
477
+ return ['bg-grid-cell-selected!'];
480
478
  }
481
479
  };
@@ -5,7 +5,7 @@
5
5
  import { expect, test } from '@playwright/test';
6
6
 
7
7
  import { type DxGrid } from '@dxos/lit-grid';
8
- import { faker } from '@dxos/random';
8
+ import { random } from '@dxos/random';
9
9
  import { setupPage, storybookUrl } from '@dxos/test-utils/playwright';
10
10
 
11
11
  import { TableManager } from './TableManager';
@@ -13,7 +13,7 @@ import { TableManager } from './TableManager';
13
13
  const storyUrl = storybookUrl('ui-react-ui-table-table--default', 9004);
14
14
  const relationsStoryUrl = storybookUrl('ui-react-ui-table-relations--default', 9004);
15
15
 
16
- // NOTE(ZaymonFC): This test suite relies on the faker seed being set to 0 in the story.
16
+ // NOTE(ZaymonFC): This test suite relies on the random seed being set to 0 in the story.
17
17
  test.describe('Table', () => {
18
18
  test('Loads', async ({ browser, browserName }) => {
19
19
  test.skip(browserName === 'webkit');
@@ -310,7 +310,7 @@ test.describe('Table', () => {
310
310
  dxGridElement.scrollToColumn(6);
311
311
  });
312
312
 
313
- const nonRefContent = faker.lorem.words(3);
313
+ const nonRefContent = random.lorem.words(3);
314
314
  const nonRefCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="6"]');
315
315
  await nonRefCell.click();
316
316
  await page.keyboard.press('Enter');
@@ -5,12 +5,11 @@
5
5
  import { RegistryContext } from '@effect-atom/atom-react';
6
6
  import { type RefObject, useCallback, useContext, useMemo, useRef } from 'react';
7
7
 
8
- import { type Database, type Type } from '@dxos/echo';
9
- import { isMutable } from '@dxos/echo/internal';
10
- import { faker } from '@dxos/random';
11
- import { Filter, useQuery, useSchema } from '@dxos/react-client/echo';
8
+ import { type Database, Filter, Type } from '@dxos/echo';
9
+ import { random } from '@dxos/random';
10
+ import { useQuery, useType } from '@dxos/react-client/echo';
12
11
  import { useClientStory } from '@dxos/react-client/testing';
13
- import { useGlobalFilteredObjects } from '@dxos/react-ui-searchlist';
12
+ import { useGlobalFilteredObjects } from '@dxos/react-ui-search';
14
13
  import { type ProjectionModel, getTypenameFromQuery } from '@dxos/schema';
15
14
 
16
15
  import { type TableController } from '../components';
@@ -18,7 +17,7 @@ import { useAddRow, useProjectionModel, useTableModel } from '../hooks';
18
17
  import { type TableModel, TablePresentation } from '../model';
19
18
  import { Table } from '../types';
20
19
 
21
- faker.seed(0); // NOTE(ZaymonFC): Required for smoke tests.
20
+ random.seed(0); // NOTE(ZaymonFC): Required for smoke tests.
22
21
 
23
22
  export type TestTableModel<T extends Type.AnyObj = Type.AnyObj> = {
24
23
  schema: T | undefined;
@@ -46,14 +45,14 @@ export const useTestTableModel = <T extends Type.AnyObj = Type.AnyObj>(): TestTa
46
45
  const tables = useQuery(space?.db, Filter.type(Table.Table));
47
46
  const table = tables.at(0);
48
47
  const typename = table?.view.target?.query ? getTypenameFromQuery(table.view.target.query.ast) : undefined;
49
- const schema = useSchema<T>(space?.db, typename);
48
+ const schema = useType<T>(space?.db, typename);
50
49
  const projection = useProjectionModel(schema, table, registry);
51
50
 
52
51
  const features = useMemo(
53
52
  () => ({
54
53
  selection: { enabled: true, mode: 'multiple' as const },
55
54
  dataEditable: true,
56
- schemaEditable: schema && isMutable(schema),
55
+ schemaEditable: schema != null && Type.getDatabase(schema) != null,
57
56
  }),
58
57
  [schema],
59
58
  );
@@ -10,27 +10,25 @@ export const translations = [
10
10
  {
11
11
  'en-US': {
12
12
  [translationKey]: {
13
- 'object placeholder': 'New table',
14
- 'create object label': 'Create table',
15
- 'table name placeholder': 'Table name',
16
- 'settings title': 'Table settings',
17
- 'table schema label': 'Type',
18
- 'new schema': 'New type',
19
- 'continue label': 'Continue',
20
- 'create stack section label': 'Create table',
21
- 'add row label': 'Add row',
22
- 'create comment': 'Create thread',
23
- 'column action sort descending': 'Sort Descending',
24
- 'column action sort ascending': 'Sort Ascending',
25
- 'column action clear sorting': 'Clear Sorting',
26
- 'column action settings': 'Column Settings',
27
- 'column action delete': 'Delete Column',
28
- 'delete row label': 'Delete row',
29
- 'bulk delete row label': 'Delete selected rows',
30
- 'column deleted label': 'Column deleted',
31
- 'new column button label': 'Create column',
32
- 'create new object label': 'Create new object “{{text}}”',
33
- 'save view label': 'Save changes to view',
13
+ 'object.placeholder': 'New table',
14
+ 'create-object.label': 'Create table',
15
+ 'table-name.placeholder': 'Table name',
16
+ 'settings.title': 'Table settings',
17
+ 'table-schema.label': 'Type',
18
+ 'continue.label': 'Continue',
19
+ 'create-stack-section.label': 'Create table',
20
+ 'add-row.label': 'Add row',
21
+ 'column-action-sort-descending.menu': 'Sort Descending',
22
+ 'column-action-sort-ascending.menu': 'Sort Ascending',
23
+ 'column-action-clear-sorting.menu': 'Clear Sorting',
24
+ 'column-action-settings.menu': 'Column Settings',
25
+ 'column-action-delete.menu': 'Delete Column',
26
+ 'delete-row.label': 'Delete row',
27
+ 'bulk-delete-row.label': 'Delete selected rows',
28
+ 'column-deleted.label': 'Column deleted',
29
+ 'new-column-button.label': 'Create column',
30
+ 'create-new-object.label': 'Create new object “{{text}}”',
31
+ 'save-view.label': 'Save changes to view',
34
32
  },
35
33
  },
36
34
  },
@@ -6,12 +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 { Annotation, JsonSchema, Obj, Ref, Type } from '@dxos/echo';
10
- import { View } from '@dxos/echo';
9
+ // QueryAST is referenced indirectly through `Type.InstanceType<typeof TableSchema>`
10
+ // (Ref.Ref(View.View) → View.View → QueryAST.Query) in the emitted .d.ts; the
11
+ // namespace import keeps the inferred types portable.
12
+ // eslint-disable-next-line unused-imports/no-unused-imports
13
+ import { DXN, Annotation, JsonSchema, Obj, QueryAST, Ref, Type, View } from '@dxos/echo';
11
14
  import { FormInputAnnotation, type JsonPath, type JsonSchemaType, LabelAnnotation } from '@dxos/echo/internal';
12
15
  import { ViewAnnotation } from '@dxos/schema';
13
16
 
14
- export const Table = Schema.Struct({
17
+ const TableSchema = Schema.Struct({
15
18
  name: Schema.String.pipe(Schema.optional),
16
19
 
17
20
  view: Ref.Ref(View.View).pipe(FormInputAnnotation.set(false)),
@@ -22,19 +25,15 @@ export const Table = Schema.Struct({
22
25
  value: Schema.Number,
23
26
  }).pipe(Schema.mutable, FormInputAnnotation.set(false)),
24
27
  }).pipe(
25
- Type.object({
26
- typename: 'org.dxos.type.table',
27
- version: '0.1.0',
28
- }),
29
28
  LabelAnnotation.set(['name']),
30
- ViewAnnotation.set(true),
31
- Annotation.IconAnnotation.set({
32
- icon: 'ph--table--regular',
33
- hue: 'green',
34
- }),
29
+ ViewAnnotation.set(['view']),
30
+ Annotation.IconAnnotation.set({ icon: 'ph--table--regular', hue: 'green' }),
31
+ Type.makeObject(DXN.make('org.dxos.type.table', '0.1.0')),
35
32
  );
36
33
 
37
- export interface Table extends Schema.Schema.Type<typeof Table> {}
34
+ // TODO(wittjosiah): Try to clean up this type inference.
35
+ export interface Table extends Type.InstanceType<typeof TableSchema> {}
36
+ export const Table = TableSchema;
38
37
 
39
38
  type MakeProps = {
40
39
  name?: string;
@@ -11,13 +11,14 @@ import { type TablePropertyDefinition, getBaseSchema, makeDynamicTable } from '.
11
11
 
12
12
  describe('makeDynamicTable', () => {
13
13
  /**
14
- * Base case: plain jsonSchema (not from Echo / JsonSchema.toJsonSchema). Does not exercise the path
15
- * where projection or schema are reactive, so this does not reproduce the Obj.change regression.
16
- * Confirms makeDynamicTable + setProperties (title) works with plain objects.
14
+ * Builds the Type entity from a JSON schema, then makes the table.
15
+ * Confirms makeDynamicTable + setProperties (title) works for the jsonSchema path.
17
16
  */
18
- test('makeDynamicTable with plain jsonSchema and properties with title does not throw', () => {
17
+ test('makeDynamicTable from a jsonSchema with properties with title does not throw', () => {
19
18
  const registry = Registry.make();
20
19
  const jsonSchema = {
20
+ typename: 'com.example.type.dynamicTablePlain',
21
+ version: '0.1.0',
21
22
  type: 'object' as const,
22
23
  properties: {
23
24
  id: { type: 'string' as const },
@@ -31,11 +32,8 @@ describe('makeDynamicTable', () => {
31
32
  ];
32
33
 
33
34
  expect(() => {
34
- const { projection, object } = makeDynamicTable({
35
- registry,
36
- jsonSchema,
37
- properties,
38
- });
35
+ const { type } = getBaseSchema({ jsonSchema });
36
+ const { projection, object } = makeDynamicTable({ registry, type, properties });
39
37
  expect(projection).toBeDefined();
40
38
  expect(object).toBeDefined();
41
39
  expect(projection.getFields().length).toBeGreaterThan(0);
@@ -43,25 +41,20 @@ describe('makeDynamicTable', () => {
43
41
  });
44
42
 
45
43
  /**
46
- * Regression test for the path where jsonSchema comes from getBaseSchema(typename, properties).
47
- * That path uses Echo (ViewModel.make, JsonSchema.toJsonSchema); mutations must run inside Obj.change and on a
48
- * cloned schema. This test ensures that flow does not throw.
44
+ * Builds the Type entity from property definitions, then makes the table.
45
+ * Confirms makeDynamicTable + setProperties (title) works for the property-definitions path.
49
46
  */
50
- test('makeDynamicTable with jsonSchema from getBaseSchema(typename, properties) and properties with title does not throw', () => {
47
+ test('makeDynamicTable from getBaseSchema(typename, properties) with properties with title does not throw', () => {
51
48
  const registry = Registry.make();
52
- const typename = 'com.example.type.dynamic-table-test';
49
+ const typename = 'com.example.type.dynamicTableTest';
53
50
  const properties: TablePropertyDefinition[] = [
54
51
  { name: 'id', format: Format.TypeFormat.String },
55
52
  { name: 'name', format: Format.TypeFormat.String, title: 'Name' },
56
53
  ];
57
- const { jsonSchema } = getBaseSchema({ typename, properties });
58
54
 
59
55
  expect(() => {
60
- const { projection, object } = makeDynamicTable({
61
- registry,
62
- jsonSchema,
63
- properties,
64
- });
56
+ const { type } = getBaseSchema({ typename, properties });
57
+ const { projection, object } = makeDynamicTable({ registry, type, properties });
65
58
  expect(projection).toBeDefined();
66
59
  expect(object).toBeDefined();
67
60
  expect(projection.getFields().length).toBeGreaterThan(0);