@dxos/react-ui-table 0.8.2-main.fbd8ed0 → 0.8.2-staging.7ac8446

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 (95) hide show
  1. package/dist/lib/browser/{chunk-PFFO5LYM.mjs → chunk-YWNRUF4J.mjs} +6 -7
  2. package/dist/lib/browser/chunk-YWNRUF4J.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +181 -330
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/types/index.mjs +1 -1
  7. package/dist/lib/node/{chunk-VREQOYRW.cjs → chunk-TGG6OZ54.cjs} +8 -9
  8. package/dist/lib/node/chunk-TGG6OZ54.cjs.map +7 -0
  9. package/dist/lib/node/index.cjs +160 -306
  10. package/dist/lib/node/index.cjs.map +4 -4
  11. package/dist/lib/node/meta.json +1 -1
  12. package/dist/lib/node/types/index.cjs +3 -3
  13. package/dist/lib/node/types/index.cjs.map +1 -1
  14. package/dist/lib/node-esm/{chunk-34JG3SDI.mjs → chunk-KKLP54L3.mjs} +6 -7
  15. package/dist/lib/node-esm/chunk-KKLP54L3.mjs.map +7 -0
  16. package/dist/lib/node-esm/index.mjs +181 -330
  17. package/dist/lib/node-esm/index.mjs.map +4 -4
  18. package/dist/lib/node-esm/meta.json +1 -1
  19. package/dist/lib/node-esm/types/index.mjs +1 -1
  20. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  21. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  22. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/DynamicTable.d.ts +4 -3
  24. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  25. package/dist/types/src/components/Table/RefPanel.d.ts +9 -0
  26. package/dist/types/src/components/Table/RefPanel.d.ts.map +1 -0
  27. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  28. package/dist/types/src/components/Table/Table.d.ts +0 -2
  29. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  30. package/dist/types/src/components/Table/Table.stories.d.ts +0 -1
  31. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  32. package/dist/types/src/components/Table/relations.stories.d.ts.map +1 -1
  33. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +0 -3
  34. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  35. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +1 -1
  37. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +2 -2
  38. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
  39. package/dist/types/src/components/testing.d.ts +40 -40
  40. package/dist/types/src/components/testing.d.ts.map +1 -1
  41. package/dist/types/src/hooks/useTableModel.d.ts +2 -2
  42. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  43. package/dist/types/src/model/modal-controller.d.ts +3 -3
  44. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  45. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  46. package/dist/types/src/model/table-model.d.ts.map +1 -1
  47. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  48. package/dist/types/src/types/table.d.ts +43 -44
  49. package/dist/types/src/types/table.d.ts.map +1 -1
  50. package/dist/types/src/util/dynamic-table.d.ts +3 -4
  51. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  52. package/dist/types/src/util/index.d.ts +0 -1
  53. package/dist/types/src/util/index.d.ts.map +1 -1
  54. package/dist/types/src/util/signals.d.ts.map +1 -1
  55. package/dist/types/src/util/table-buttons.d.ts +14 -0
  56. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  57. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  58. package/dist/types/src/util/table.d.ts +2 -2
  59. package/dist/types/src/util/table.d.ts.map +1 -1
  60. package/dist/types/tsconfig.tsbuildinfo +1 -1
  61. package/package.json +33 -34
  62. package/src/components/Table/CreateRefPanel.tsx +5 -5
  63. package/src/components/Table/DynamicTable.stories.tsx +4 -4
  64. package/src/components/Table/DynamicTable.tsx +5 -4
  65. package/src/components/Table/RefPanel.tsx +52 -0
  66. package/src/components/Table/Table.stories.tsx +27 -73
  67. package/src/components/Table/Table.tsx +28 -25
  68. package/src/components/Table/relations.stories.tsx +31 -38
  69. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +10 -11
  70. package/src/components/TableCellEditor/TableCellEditor.tsx +4 -45
  71. package/src/components/TableToolbar/TableToolbar.tsx +13 -12
  72. package/src/components/testing.ts +9 -10
  73. package/src/hooks/useTableModel.ts +2 -2
  74. package/src/model/modal-controller.ts +3 -3
  75. package/src/model/table-model.test.ts +6 -7
  76. package/src/model/table-model.ts +2 -19
  77. package/src/model/table-presentation.test.ts +6 -7
  78. package/src/model/table-presentation.ts +10 -54
  79. package/src/types/table.ts +7 -15
  80. package/src/util/dynamic-table.ts +6 -9
  81. package/src/util/index.ts +0 -1
  82. package/src/util/table-buttons.ts +23 -0
  83. package/src/util/table.ts +16 -13
  84. package/dist/lib/browser/chunk-PFFO5LYM.mjs.map +0 -7
  85. package/dist/lib/node/chunk-VREQOYRW.cjs.map +0 -7
  86. package/dist/lib/node-esm/chunk-34JG3SDI.mjs.map +0 -7
  87. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +0 -13
  88. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +0 -1
  89. package/dist/types/src/util/schema.d.ts +0 -12
  90. package/dist/types/src/util/schema.d.ts.map +0 -1
  91. package/dist/types/src/util/tag.d.ts +0 -11
  92. package/dist/types/src/util/tag.d.ts.map +0 -1
  93. package/src/components/TableCellEditor/FormCellEditor.tsx +0 -94
  94. package/src/util/schema.ts +0 -36
  95. package/src/util/tag.ts +0 -33
@@ -4,12 +4,13 @@
4
4
 
5
5
  import React, { useCallback, useMemo } from 'react';
6
6
 
7
- import { live } from '@dxos/live-object';
7
+ import { create } from '@dxos/live-object';
8
8
  import { type ThemedClassName } from '@dxos/react-ui';
9
9
  import {
10
10
  createGapSeparator,
11
11
  createMenuAction,
12
12
  type MenuAction,
13
+ type MenuActionHandler,
13
14
  MenuProvider,
14
15
  ToolbarMenu,
15
16
  useMenuActions,
@@ -26,18 +27,18 @@ export type TableToolbarActionType = 'add-row' | 'comment' | 'save-view';
26
27
  type TableToolbarState = Partial<{ viewDirty: boolean }>;
27
28
 
28
29
  export type TableToolbarProps = ThemedClassName<
29
- TableToolbarState & { onAction: (action: TableToolbarAction) => void; attendableId?: string }
30
+ TableToolbarState & { onAction?: MenuActionHandler<TableToolbarAction>; attendableId?: string }
30
31
  >;
31
32
 
32
- const createTableToolbarActions = (state: TableToolbarState, onAction: (action: TableToolbarAction) => void) => {
33
- const add = createMenuAction<TableToolbarActionProperties>('add-row', () => onAction(add), {
34
- type: 'add-row' as const,
33
+ const createTableToolbarActions = (state: TableToolbarState) => {
34
+ const add = createMenuAction<TableToolbarActionProperties>('add-row', {
35
+ type: 'add-row',
35
36
  icon: 'ph--plus--regular',
36
37
  label: ['add row', { ns: translationKey }],
37
38
  testId: 'table.toolbar.add-row',
38
39
  });
39
- const save = createMenuAction<TableToolbarActionProperties>('save-view', () => onAction(save), {
40
- type: 'save-view' as const,
40
+ const save = createMenuAction<TableToolbarActionProperties>('save-view', {
41
+ type: 'save-view',
41
42
  icon: 'ph--floppy-disk--regular',
42
43
  label: ['save view label', { ns: translationKey }],
43
44
  testId: 'table.toolbar.save-view',
@@ -45,8 +46,8 @@ const createTableToolbarActions = (state: TableToolbarState, onAction: (action:
45
46
  hidden: !state.viewDirty,
46
47
  });
47
48
  const gap = createGapSeparator();
48
- const comment = createMenuAction('comment', () => onAction(comment), {
49
- type: 'comment' as const,
49
+ const comment = createMenuAction('comment', {
50
+ type: 'comment',
50
51
  icon: 'ph--chat-text--regular',
51
52
  label: ['create comment', { ns: translationKey }],
52
53
  testId: 'table.toolbar.comment',
@@ -59,12 +60,12 @@ const createTableToolbarActions = (state: TableToolbarState, onAction: (action:
59
60
  };
60
61
 
61
62
  export const TableToolbar = ({ classNames, viewDirty, attendableId, onAction }: TableToolbarProps) => {
62
- const state = useMemo(() => live<TableToolbarState>({ viewDirty }), []);
63
- const actionsCreator = useCallback(() => createTableToolbarActions(state, onAction), [state, onAction]);
63
+ const state = useMemo(() => create<TableToolbarState>({ viewDirty }), []);
64
+ const actionsCreator = useCallback(() => createTableToolbarActions(state), [state]);
64
65
  const menu = useMenuActions(actionsCreator);
65
66
 
66
67
  return (
67
- <MenuProvider {...menu} attendableId={attendableId}>
68
+ <MenuProvider {...menu} attendableId={attendableId} onAction={onAction as MenuActionHandler}>
68
69
  <ToolbarMenu classNames={classNames} />
69
70
  </MenuProvider>
70
71
  );
@@ -2,26 +2,25 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
6
5
  import { useEffect } from 'react';
7
6
 
8
- import { setValue, toJsonSchema, TypeEnum, TypedObject, FormatEnum, ObjectId } from '@dxos/echo-schema';
7
+ import { setValue, toJsonSchema, S, TypeEnum, TypedObject, FormatEnum } from '@dxos/echo-schema';
9
8
  import { faker } from '@dxos/random';
10
- import { live, makeRef } from '@dxos/react-client/echo';
9
+ import { create, makeRef } from '@dxos/react-client/echo';
11
10
  import { createView, type ViewProjection } from '@dxos/schema';
12
11
 
13
12
  import { TableType } from '../types';
14
13
 
15
14
  export const TestSchema = TypedObject({ typename: 'example.com/type/Test', version: '0.1.0' })({
16
- id: ObjectId,
17
- name: Schema.optional(Schema.String),
18
- age: Schema.optional(Schema.Number),
19
- active: Schema.optional(Schema.Boolean),
20
- netWorth: Schema.optional(Schema.Number),
15
+ id: S.String,
16
+ name: S.optional(S.String),
17
+ age: S.optional(S.Number),
18
+ active: S.optional(S.Boolean),
19
+ netWorth: S.optional(S.Number),
21
20
  });
22
21
 
23
22
  export const createTable = (schema = TestSchema) => {
24
- return live(TableType, {
23
+ return create(TableType, {
25
24
  view: makeRef(
26
25
  createView({
27
26
  name: 'Test',
@@ -33,7 +32,7 @@ export const createTable = (schema = TestSchema) => {
33
32
  };
34
33
 
35
34
  export const createItems = (n: number) => {
36
- const { data } = live({
35
+ const { data } = create({
37
36
  data: Array.from({ length: n }, () => ({
38
37
  name: faker.person.fullName(),
39
38
  age: faker.number.int({ min: 20, max: 70 }),
@@ -5,7 +5,7 @@
5
5
  import { effect } from '@preact/signals-core';
6
6
  import { useEffect, useState } from 'react';
7
7
 
8
- import { fullyQualifiedId, getSpace, type Live } from '@dxos/react-client/echo';
8
+ import { fullyQualifiedId, getSpace, type ReactiveObject } from '@dxos/react-client/echo';
9
9
  import { useSelectionActions } from '@dxos/react-ui-attention';
10
10
  import { type ViewProjection } from '@dxos/schema';
11
11
  import { isNonNullable } from '@dxos/util';
@@ -16,7 +16,7 @@ import { type TableType } from '../types';
16
16
  export type UseTableModelParams<T extends TableRow = TableRow> = {
17
17
  table?: TableType;
18
18
  projection?: ViewProjection;
19
- rows?: Live<T>[];
19
+ rows?: ReactiveObject<T>[];
20
20
  rowActions?: TableRowAction[];
21
21
  onSelectionChanged?: (selection: string[]) => void;
22
22
  onRowAction?: (actionId: string, data: T) => void;
@@ -5,7 +5,7 @@
5
5
  import { signal } from '@preact/signals-core';
6
6
  import { type RefObject, type MutableRefObject } from 'react';
7
7
 
8
- import { type Live } from '@dxos/live-object';
8
+ import { type ReactiveObject } from '@dxos/live-object';
9
9
  import { log } from '@dxos/log';
10
10
 
11
11
  export type ColumnSettingsMode = { type: 'create' } | { type: 'edit'; fieldId: string };
@@ -18,7 +18,7 @@ export type ModalState =
18
18
  type: 'createRefPanel';
19
19
  typename: string;
20
20
  initialValues?: Record<string, string>;
21
- onCreate?: (obj: Live<any>) => void;
21
+ onCreate?: (obj: ReactiveObject<any>) => void;
22
22
  }
23
23
  | { type: 'columnSettings'; mode: ColumnSettingsMode }
24
24
  | { type: 'closed' };
@@ -72,7 +72,7 @@ export class ModalController {
72
72
  typename: string,
73
73
  anchorCell: Element | null,
74
74
  initialValues?: Record<string, string>,
75
- onCreate?: (obj: Live<any>) => void,
75
+ onCreate?: (obj: ReactiveObject<any>) => void,
76
76
  ) => {
77
77
  if (anchorCell) {
78
78
  this._triggerRef.current = anchorCell as HTMLElement;
@@ -3,14 +3,13 @@
3
3
  //
4
4
 
5
5
  import { computed } from '@preact/signals-core';
6
- import { Schema } from 'effect';
7
6
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
8
7
 
9
- import { TypedObject } from '@dxos/echo-schema';
8
+ import { S, TypedObject } from '@dxos/echo-schema';
10
9
  import { updateCounter } from '@dxos/echo-schema/testing';
11
10
  import { registerSignalsRuntime } from '@dxos/echo-signals';
12
11
  import { createEchoSchema } from '@dxos/live-object/testing';
13
- import { live, makeRef } from '@dxos/react-client/echo';
12
+ import { create, makeRef } from '@dxos/react-client/echo';
14
13
  import { createView, ViewProjection } from '@dxos/schema';
15
14
 
16
15
  import { TableModel, type TableModelProps } from './table-model';
@@ -70,7 +69,7 @@ describe('TableModel', () => {
70
69
 
71
70
  describe('reactivity', () => {
72
71
  it('pure signals should nest', () => {
73
- const signal$ = live({ arr: [{ thingInside: 1 }, { thingInside: 2 }] });
72
+ const signal$ = create({ arr: [{ thingInside: 1 }, { thingInside: 2 }] });
74
73
 
75
74
  const computed$ = computed(() => {
76
75
  return signal$.arr.map((row) =>
@@ -100,14 +99,14 @@ describe('TableModel', () => {
100
99
  });
101
100
 
102
101
  class Test extends TypedObject({ typename: 'example.com/type/Test', version: '0.1.0' })({
103
- title: Schema.String,
104
- completed: Schema.Boolean,
102
+ title: S.String,
103
+ completed: S.Boolean,
105
104
  }) {}
106
105
 
107
106
  const createTableModel = (props: Partial<TableModelProps> = {}): TableModel => {
108
107
  const schema = createEchoSchema(Test);
109
108
  const view = createView({ name: 'Test', typename: schema.typename, jsonSchema: schema.jsonSchema });
110
109
  const projection = new ViewProjection(schema.jsonSchema, view);
111
- const table = live(TableType, { view: makeRef(view) });
110
+ const table = create(TableType, { view: makeRef(view) });
112
111
  return new TableModel({ id: table.id, space: undefined, view, projection, ...props });
113
112
  };
@@ -8,7 +8,7 @@ import { type Space } from '@dxos/client/echo';
8
8
  import { Resource } from '@dxos/context';
9
9
  import { type FieldSortType, FormatEnum, getValue, setValue, type JsonProp } from '@dxos/echo-schema';
10
10
  import { invariant } from '@dxos/invariant';
11
- import { isLiveObject, makeRef } from '@dxos/live-object';
11
+ import { isReactiveObject, makeRef } from '@dxos/live-object';
12
12
  import { formatForEditing, parseValue } from '@dxos/react-ui-form';
13
13
  import {
14
14
  type DxGridAxisMeta,
@@ -21,7 +21,6 @@ import { type ViewType, type ViewProjection } from '@dxos/schema';
21
21
  import { type SelectionMode, SelectionModel } from './selection-model';
22
22
  import { TableSorting } from './table-sorting';
23
23
  import { touch } from '../util';
24
- import { extractTagIds } from '../util/tag';
25
24
 
26
25
  // TODO(burdon): Use schema types.
27
26
  export type TableRow = Record<JsonProp, any> & { id: string };
@@ -343,28 +342,12 @@ export class TableModel<T extends TableRow = TableRow> extends Resource {
343
342
  case FormatEnum.Ref: {
344
343
  // TODO(ZaymonFC): This get's called an additional time by the cell editor onBlur, but with the cell editors
345
344
  // plain string value. Maybe onBlur should be called with the actual value?
346
- if (isLiveObject(value)) {
345
+ if (isReactiveObject(value)) {
347
346
  setValue(this._rows.value[rowIdx], field.path, makeRef(value));
348
347
  }
349
348
  break;
350
349
  }
351
350
 
352
- case FormatEnum.SingleSelect: {
353
- const ids = extractTagIds(value);
354
- if (ids && ids.length > 0) {
355
- setValue(this._rows.value[rowIdx], field.path, ids[0]);
356
- }
357
- break;
358
- }
359
-
360
- case FormatEnum.MultiSelect: {
361
- const ids = extractTagIds(value);
362
- if (ids) {
363
- setValue(this._rows.value[rowIdx], field.path, ids);
364
- }
365
- break;
366
- }
367
-
368
351
  default: {
369
352
  setValue(
370
353
  this._rows.value[rowIdx],
@@ -2,11 +2,10 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
6
5
  import { describe, expect, it, beforeEach } from 'vitest';
7
6
 
8
- import { TypedObject } from '@dxos/echo-schema';
9
- import { live, makeRef } from '@dxos/live-object';
7
+ import { S, TypedObject } from '@dxos/echo-schema';
8
+ import { create, makeRef } from '@dxos/live-object';
10
9
  import { createEchoSchema } from '@dxos/live-object/testing';
11
10
  import { createView, ViewProjection } from '@dxos/schema';
12
11
 
@@ -23,7 +22,7 @@ describe('TablePresentation', () => {
23
22
 
24
23
  beforeEach(async () => {
25
24
  updateCount = 0;
26
- ({ data } = live({
25
+ ({ data } = create({
27
26
  data: [
28
27
  { col1: 'A', col2: 1, col3: true },
29
28
  { col1: 'B', col2: 2, col3: false },
@@ -90,14 +89,14 @@ describe('TablePresentation', () => {
90
89
  });
91
90
 
92
91
  class Test extends TypedObject({ typename: 'example.com/type/Test', version: '0.1.0' })({
93
- title: Schema.String,
94
- completed: Schema.Boolean,
92
+ title: S.String,
93
+ completed: S.Boolean,
95
94
  }) {}
96
95
 
97
96
  const createTableModel = (props: Partial<TableModelProps> = {}): TableModel => {
98
97
  const schema = createEchoSchema(Test);
99
98
  const view = createView({ name: 'Test', typename: schema.typename, jsonSchema: schema.jsonSchema });
100
99
  const projection = new ViewProjection(schema.jsonSchema, view);
101
- const table = live(TableType, { view: makeRef(view) });
100
+ const table = create(TableType, { view: makeRef(view) });
102
101
  return new TableModel({ id: table.id, view, projection, ...props });
103
102
  };
@@ -3,9 +3,8 @@
3
3
  //
4
4
 
5
5
  import { signal } from '@preact/signals-core';
6
- import { isNotNullable } from 'effect/Predicate';
7
6
 
8
- import { FormatEnum, getDXN, getValue, TypeEnum } from '@dxos/echo-schema';
7
+ import { FormatEnum, getValue } from '@dxos/echo-schema';
9
8
  import { cellClassesForFieldType, formatForDisplay } from '@dxos/react-ui-form';
10
9
  import {
11
10
  type DxGridPlane,
@@ -85,10 +84,6 @@ export class TablePresentation<T extends TableRow = TableRow> {
85
84
  return '';
86
85
  }
87
86
 
88
- if (props.type === 'array') {
89
- return '';
90
- }
91
-
92
87
  switch (props.format) {
93
88
  case FormatEnum.Boolean:
94
89
  case FormatEnum.SingleSelect:
@@ -126,52 +121,13 @@ export class TablePresentation<T extends TableRow = TableRow> {
126
121
  cell.className = mx(classes.flat());
127
122
  }
128
123
 
129
- if (props.type === TypeEnum.Array) {
130
- const targetArray = getValue(obj, field.path);
131
- if (targetArray && Array.isArray(targetArray)) {
132
- // TODO(ZaymonFC): For arrays of objects, objects should have a 'label' annotation on the field
133
- // that can be used to render tags.
134
- // TODO(ZaymonFC): Move to util.
135
- const getLabel = (value: any) => {
136
- // If the value is falsy, return undefined
137
- // If the object is an array, check for 'name' property
138
- // If the object is a primitive type (string, number, boolean) stringify
139
- // If the object is an array return 'Array'
140
- if (!value) {
141
- return undefined;
142
- }
143
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
144
- return String(value);
145
- }
146
- if (Array.isArray(value)) {
147
- return 'Array';
148
- }
149
- if (typeof value === 'object' && value.name) {
150
- return value.name;
151
- }
152
- if (typeof value === 'object' && value.value) {
153
- return `${value.value}`;
154
- }
155
- return 'Object';
156
- };
157
-
158
- const tags = targetArray
159
- .map(getLabel)
160
- .filter(isNotNullable)
161
- .map((title) => {
162
- return `<span class="dx-tag rounded-xl" data-hue="neutral">${title}</span>`;
163
- })
164
- .join('');
165
-
166
- cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1 overflow-x-auto">${tags}</div>`;
167
- }
168
- }
169
-
170
124
  if (props.format === FormatEnum.Ref && props.referenceSchema) {
171
125
  const targetObj = getValue(obj, field.path)?.target;
172
126
  if (targetObj) {
173
- const dxn = getDXN(targetObj)?.toString();
174
- cell.accessoryHtml = `<dx-ref-tag ref=${dxn} class="dx-button block is-6 pli-[3px] plb-[3px] pbe-[2px] min-bs-0 absolute inline-end-1"><dx-icon icon="ph--link-simple--regular"/></dx-ref-tag>`;
127
+ cell.accessoryHtml = tableButtons.referencedCell.render({
128
+ targetId: targetObj.id as any as string,
129
+ schemaId: props.referenceSchema,
130
+ });
175
131
  }
176
132
  }
177
133
 
@@ -212,7 +168,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
212
168
  .join(' ');
213
169
 
214
170
  if (tags) {
215
- cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1">${tags}</div>`;
171
+ cell.accessoryHtml = tags;
216
172
  }
217
173
  }
218
174
  }
@@ -252,7 +208,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
252
208
  ${direction !== undefined ? tableButtons.sort.render({ fieldId: field.id, direction }) : ''}
253
209
  ${tableButtons.columnSettings.render({ fieldId: field.id })}
254
210
  `,
255
- className: '!bg-toolbarSurface',
211
+ className: '!bg-gridHeader',
256
212
  };
257
213
  }
258
214
 
@@ -295,7 +251,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
295
251
  if (!this.model.features.selection.enabled || this.model.selection.selectionMode === 'single') {
296
252
  return {
297
253
  [toPlaneCellIndex({ col: 0, row: 0 })]: {
298
- className: '!bg-toolbarSurface',
254
+ className: '!bg-gridHeader',
299
255
  readonly: true,
300
256
  value: '',
301
257
  },
@@ -309,7 +265,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
309
265
  header: true,
310
266
  checked: this.model.selection.allRowsSeleted.value,
311
267
  }),
312
- className: '!bg-toolbarSurface',
268
+ className: '!bg-gridHeader',
313
269
  readonly: true,
314
270
  value: '',
315
271
  },
@@ -324,7 +280,7 @@ export class TablePresentation<T extends TableRow = TableRow> {
324
280
  disabled: (this.model.view?.fields?.length ?? 0) >= VIEW_FIELD_LIMIT,
325
281
  })
326
282
  : undefined,
327
- className: '!bg-toolbarSurface',
283
+ className: '!bg-gridHeader',
328
284
  readonly: true,
329
285
  value: '',
330
286
  },
@@ -2,28 +2,20 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
6
-
5
+ import { EchoObject, Expando, LabelAnnotationId, ObjectId, Ref, S } from '@dxos/echo-schema';
7
6
  // import { ThreadType } from '@dxos/plugin-space/types';
8
- import { LabelAnnotationId, ObjectId, Ref, Expando, EchoObject } from '@dxos/echo-schema';
9
7
  import { ViewType } from '@dxos/schema';
10
8
 
11
- export const TableSchema = Schema.Struct({
9
+ export const TableSchema = S.Struct({
12
10
  id: ObjectId,
13
- name: Schema.optional(Schema.String),
14
- view: Schema.optional(Ref(ViewType)),
11
+ name: S.optional(S.String),
12
+ view: S.optional(Ref(ViewType)),
15
13
  // TODO(burdon): Document why threads is included here?
16
- threads: Schema.optional(Schema.Array(Ref(Expando /* ThreadType */))),
14
+ threads: S.optional(S.Array(Ref(Expando /* ThreadType */))),
17
15
  }).annotations({
18
16
  // TODO(burdon): Move annotation to property.
19
17
  [LabelAnnotationId]: 'name',
20
18
  });
21
19
 
22
- // TODO(burdon): Move out of react-ui-xxx.
23
- export const TableType = TableSchema.pipe(
24
- EchoObject({
25
- typename: 'dxos.org/type/Table',
26
- version: '0.1.0',
27
- }),
28
- );
29
- export interface TableType extends Schema.Schema.Type<typeof TableType> {}
20
+ export const TableType = TableSchema.pipe(EchoObject({ typename: 'dxos.org/type/Table', version: '0.1.0' }));
21
+ export interface TableType extends S.Schema.Type<typeof TableType> {}
@@ -2,11 +2,8 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Schema } from 'effect';
6
-
7
- import { getTypename, toJsonSchema } from '@dxos/echo-schema';
8
- import type { JsonSchemaType, SortDirectionType } from '@dxos/echo-schema';
9
- import { live, makeRef } from '@dxos/live-object';
5
+ import type { BaseSchema, JsonSchemaType, SortDirectionType } from '@dxos/echo-schema';
6
+ import { create, makeRef } from '@dxos/live-object';
10
7
  import {
11
8
  createView,
12
9
  getSchemaFromPropertyDefinitions,
@@ -30,7 +27,7 @@ export type TablePropertyDefinition = SchemaPropertyDefinition & Partial<Propert
30
27
  * @deprecated
31
28
  */
32
29
  // TODO(burdon): Remove variance.
33
- export const getBaseSchema = ({
30
+ export const getBaseSchems = ({
34
31
  typename,
35
32
  properties,
36
33
  jsonSchema,
@@ -39,13 +36,13 @@ export const getBaseSchema = ({
39
36
  typename?: string;
40
37
  properties?: TablePropertyDefinition[];
41
38
  jsonSchema?: JsonSchemaType;
42
- schema?: Schema.Schema.AnyNoContext;
39
+ schema?: BaseSchema;
43
40
  }): { typename: string; jsonSchema: JsonSchemaType } => {
44
41
  if (typename && properties) {
45
42
  const schema = getSchemaFromPropertyDefinitions(typename, properties);
46
43
  return { typename: schema.typename, jsonSchema: schema.jsonSchema };
47
44
  } else if (schema) {
48
- return { typename: getTypename(schema)!, jsonSchema: toJsonSchema(schema) };
45
+ return { typename: schema.typename, jsonSchema: schema.jsonSchema };
49
46
  } else if (typename && jsonSchema) {
50
47
  return { typename, jsonSchema };
51
48
  } else {
@@ -69,7 +66,7 @@ export const makeDynamicTable = ({
69
66
  ...(properties && { fields: properties.map((property) => property.name) }),
70
67
  });
71
68
 
72
- const table = live(TableType, { name: 'dynamic-table', view: makeRef(view) });
69
+ const table = create(TableType, { name: 'dynamic-table', view: makeRef(view) });
73
70
  const projection = new ViewProjection(jsonSchema, view);
74
71
  if (properties && view.fields) {
75
72
  setProperties(view, projection, properties);
package/src/util/index.ts CHANGED
@@ -7,4 +7,3 @@ export * from './signals';
7
7
  export * from './table';
8
8
  export * from './table-buttons';
9
9
  export * from './table-controls';
10
- export * from './schema';
@@ -15,6 +15,7 @@ export const BUTTON_IDENTIFIERS: { [K in TableButton]: string } = {
15
15
  type ButtonData =
16
16
  | { type: 'columnSettings'; fieldId: string }
17
17
  | { type: 'newColumn'; disabled?: boolean }
18
+ | { type: 'referencedCell'; schemaId: string; targetId: string }
18
19
  | { type: 'rowMenu'; rowIndex: number }
19
20
  | { type: 'sort'; fieldId: string; direction?: 'asc' | 'desc' };
20
21
 
@@ -75,6 +76,27 @@ const columnSettingsButton = {
75
76
  }),
76
77
  } as const;
77
78
 
79
+ const referencedCellButton = {
80
+ attr: BUTTON_IDENTIFIERS.referencedCell,
81
+ icon: 'ph--link-simple-horizontal--regular',
82
+ render: ({ targetId, schemaId }: Omit<Extract<ButtonData, { type: 'referencedCell' }>, 'type'>) => {
83
+ return createButton({
84
+ attr: BUTTON_IDENTIFIERS.referencedCell,
85
+ icon: referencedCellButton.icon,
86
+ data: {
87
+ 'data-target-id': targetId,
88
+ 'data-schema-id': schemaId,
89
+ },
90
+ testId: 'table-ref-cell-button',
91
+ });
92
+ },
93
+ getData: (el: HTMLElement): Extract<ButtonData, { type: 'referencedCell' }> => ({
94
+ type: 'referencedCell',
95
+ targetId: el.getAttribute('data-target-id')!,
96
+ schemaId: el.getAttribute('data-schema-id')!,
97
+ }),
98
+ } as const;
99
+
78
100
  const rowMenuButton = {
79
101
  attr: BUTTON_IDENTIFIERS.rowMenu,
80
102
  icon: 'ph--dots-three--regular',
@@ -121,6 +143,7 @@ const sortButton = {
121
143
  export const tableButtons = {
122
144
  addColumn: addColumnButton,
123
145
  columnSettings: columnSettingsButton,
146
+ referencedCell: referencedCellButton,
124
147
  rowMenu: rowMenuButton,
125
148
  sort: sortButton,
126
149
  } as const;
package/src/util/table.ts CHANGED
@@ -2,20 +2,19 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Schema, SchemaAST } from 'effect';
6
-
7
5
  import {
6
+ AST,
8
7
  type EchoSchema,
9
8
  Format,
10
9
  FormatEnum,
11
10
  type JsonPath,
12
11
  type JsonProp,
13
- Ref,
12
+ S,
14
13
  TypedObject,
15
14
  TypeEnum,
16
15
  } from '@dxos/echo-schema';
17
16
  import { type Client, PublicKey } from '@dxos/react-client';
18
- import { live, type Space } from '@dxos/react-client/echo';
17
+ import { create, makeRef, type Space } from '@dxos/react-client/echo';
19
18
  import { createFieldId, createView, getSchemaProperties, ViewProjection, type ViewType } from '@dxos/schema';
20
19
 
21
20
  import { type TableType } from '../types';
@@ -35,16 +34,20 @@ export const initializeTable = async ({
35
34
  table,
36
35
  typename,
37
36
  initialRow = true,
38
- }: InitialiseTableProps): Promise<Schema.Schema.AnyNoContext> => {
37
+ }: InitialiseTableProps): Promise<S.Schema.AnyNoContext> => {
39
38
  if (typename) {
40
39
  const schema = await space.db.graph.getSchemaByTypename(typename, space.db);
41
40
  if (!schema) {
42
41
  throw new Error(`Schema not found: ${typename}`);
43
42
  }
44
43
 
45
- const fields = getSchemaProperties(schema.ast).map((prop) => prop.name);
44
+ // We need to get the schema properties here.
45
+ // For now, only simple types and refs, not compound types are going to be supported.
46
+ const fields = getSchemaProperties(schema.ast)
47
+ .filter((prop) => prop.format !== FormatEnum.Ref)
48
+ .map((prop) => prop.name);
46
49
 
47
- table.view = Ref.make(
50
+ table.view = makeRef(
48
51
  createView({
49
52
  // TODO(ZaymonFC): Don't hardcode name?
50
53
  name: 'View',
@@ -59,7 +62,7 @@ export const initializeTable = async ({
59
62
  const [schema] = await space.db.schemaRegistry.register([ContactSchema]);
60
63
  const fields = ContactFields;
61
64
 
62
- table.view = Ref.make(
65
+ table.view = makeRef(
63
66
  createView({
64
67
  name: 'View',
65
68
  typename: schema.typename,
@@ -72,7 +75,7 @@ export const initializeTable = async ({
72
75
 
73
76
  if (initialRow) {
74
77
  // TODO(burdon): Last (first) row should not be in db and should be managed by the model.
75
- space.db.add(live(schema, {}));
78
+ space.db.add(create(schema, {}));
76
79
  }
77
80
 
78
81
  return schema;
@@ -83,10 +86,10 @@ const ContactSchema = TypedObject({
83
86
  typename: `example.com/type/${PublicKey.random().truncate()}`,
84
87
  version: '0.1.0',
85
88
  })({
86
- name: Schema.optional(Schema.String).annotations({ [SchemaAST.TitleAnnotationId]: 'Name' }),
87
- active: Schema.optional(Schema.Boolean),
88
- email: Schema.optional(Format.Email),
89
- salary: Schema.optional(Format.Currency()).annotations({ [SchemaAST.TitleAnnotationId]: 'Salary' }),
89
+ name: S.optional(S.String).annotations({ [AST.TitleAnnotationId]: 'Name' }),
90
+ active: S.optional(S.Boolean),
91
+ email: S.optional(Format.Email),
92
+ salary: S.optional(Format.Currency()).annotations({ [AST.TitleAnnotationId]: 'Salary' }),
90
93
  });
91
94
 
92
95
  const ContactFields = ['name', 'email', 'salary', 'active'];
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/types/table.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\n// import { ThreadType } from '@dxos/plugin-space/types';\nimport { LabelAnnotationId, ObjectId, Ref, Expando, EchoObject } from '@dxos/echo-schema';\nimport { ViewType } from '@dxos/schema';\n\nexport const TableSchema = Schema.Struct({\n id: ObjectId,\n name: Schema.optional(Schema.String),\n view: Schema.optional(Ref(ViewType)),\n // TODO(burdon): Document why threads is included here?\n threads: Schema.optional(Schema.Array(Ref(Expando /* ThreadType */))),\n}).annotations({\n // TODO(burdon): Move annotation to property.\n [LabelAnnotationId]: 'name',\n});\n\n// TODO(burdon): Move out of react-ui-xxx.\nexport const TableType = TableSchema.pipe(\n EchoObject({\n typename: 'dxos.org/type/Table',\n version: '0.1.0',\n }),\n);\nexport interface TableType extends Schema.Schema.Type<typeof TableType> {}\n"],
5
- "mappings": ";AAIA,SAASA,cAAc;AAGvB,SAASC,mBAAmBC,UAAUC,KAAKC,SAASC,kBAAkB;AACtE,SAASC,gBAAgB;AAElB,IAAMC,cAAcC,OAAOC,OAAO;EACvCC,IAAIC;EACJC,MAAMJ,OAAOK,SAASL,OAAOM,MAAM;EACnCC,MAAMP,OAAOK,SAASG,IAAIC,QAAAA,CAAAA;;EAE1BC,SAASV,OAAOK,SAASL,OAAOW,MAAMH;IAAII;;EAAsB,CAAA,CAAA;AAClE,CAAA,EAAGC,YAAY;;EAEb,CAACC,iBAAAA,GAAoB;AACvB,CAAA;AAGO,IAAMC,YAAYhB,YAAYiB,KACnCC,WAAW;EACTC,UAAU;EACVC,SAAS;AACX,CAAA,CAAA;",
6
- "names": ["Schema", "LabelAnnotationId", "ObjectId", "Ref", "Expando", "EchoObject", "ViewType", "TableSchema", "Schema", "Struct", "id", "ObjectId", "name", "optional", "String", "view", "Ref", "ViewType", "threads", "Array", "Expando", "annotations", "LabelAnnotationId", "TableType", "pipe", "EchoObject", "typename", "version"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/types/table.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\n// import { ThreadType } from '@dxos/plugin-space/types';\nimport { LabelAnnotationId, ObjectId, Ref, Expando, EchoObject } from '@dxos/echo-schema';\nimport { ViewType } from '@dxos/schema';\n\nexport const TableSchema = Schema.Struct({\n id: ObjectId,\n name: Schema.optional(Schema.String),\n view: Schema.optional(Ref(ViewType)),\n // TODO(burdon): Document why threads is included here?\n threads: Schema.optional(Schema.Array(Ref(Expando /* ThreadType */))),\n}).annotations({\n // TODO(burdon): Move annotation to property.\n [LabelAnnotationId]: 'name',\n});\n\n// TODO(burdon): Move out of react-ui-xxx.\nexport const TableType = TableSchema.pipe(\n EchoObject({\n typename: 'dxos.org/type/Table',\n version: '0.1.0',\n }),\n);\nexport interface TableType extends Schema.Schema.Type<typeof TableType> {}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAIA,oBAAuB;AAGvB,yBAAsE;AACtE,oBAAyB;AAElB,IAAMA,cAAcC,qBAAOC,OAAO;EACvCC,IAAIC;EACJC,MAAMJ,qBAAOK,SAASL,qBAAOM,MAAM;EACnCC,MAAMP,qBAAOK,aAASG,wBAAIC,sBAAAA,CAAAA;;EAE1BC,SAASV,qBAAOK,SAASL,qBAAOW,UAAMH;IAAII;;EAAsB,CAAA,CAAA;AAClE,CAAA,EAAGC,YAAY;;EAEb,CAACC,oCAAAA,GAAoB;AACvB,CAAA;AAGO,IAAMC,YAAYhB,YAAYiB,SACnCC,+BAAW;EACTC,UAAU;EACVC,SAAS;AACX,CAAA,CAAA;",
6
- "names": ["TableSchema", "Schema", "Struct", "id", "ObjectId", "name", "optional", "String", "view", "Ref", "ViewType", "threads", "Array", "Expando", "annotations", "LabelAnnotationId", "TableType", "pipe", "EchoObject", "typename", "version"]
7
- }