@dxos/react-ui-table 0.8.4-main.1da679c → 0.8.4-main.21d9917

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 (140) hide show
  1. package/dist/lib/browser/chunk-MNZKOFMA.mjs +1746 -0
  2. package/dist/lib/browser/chunk-MNZKOFMA.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-OZBLY7XM.mjs +76 -0
  4. package/dist/lib/browser/chunk-OZBLY7XM.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +1134 -1150
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +29 -39
  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-2ATAIIAO.mjs +1748 -0
  12. package/dist/lib/node-esm/chunk-2ATAIIAO.mjs.map +7 -0
  13. package/dist/lib/node-esm/chunk-WNZSKIRF.mjs +77 -0
  14. package/dist/lib/node-esm/chunk-WNZSKIRF.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +1134 -1150
  16. package/dist/lib/node-esm/index.mjs.map +4 -4
  17. package/dist/lib/node-esm/meta.json +1 -1
  18. package/dist/lib/node-esm/testing/index.mjs +29 -39
  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 +5 -6
  26. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  27. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +6 -20
  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 +77 -10
  30. package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -1
  31. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  32. package/dist/types/src/components/Table/Table.d.ts +11 -8
  33. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  34. package/dist/types/src/components/Table/Table.stories.d.ts +76 -11
  35. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +1 -1
  37. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +12 -12
  38. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  39. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +7 -7
  40. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  41. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +5 -6
  42. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  43. package/dist/types/src/components/TableCellEditor/index.d.ts +1 -0
  44. package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -1
  45. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +4 -4
  46. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +1 -1
  47. package/dist/types/src/components/testing.d.ts +23 -16
  48. package/dist/types/src/components/testing.d.ts.map +1 -1
  49. package/dist/types/src/hooks/index.d.ts +2 -1
  50. package/dist/types/src/hooks/index.d.ts.map +1 -1
  51. package/dist/types/src/hooks/useAddRow.d.ts +5 -6
  52. package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
  53. package/dist/types/src/hooks/useProjectionModel.d.ts +6 -0
  54. package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -0
  55. package/dist/types/src/hooks/useTableModel.d.ts +8 -8
  56. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  57. package/dist/types/src/model/modal-controller.d.ts +5 -8
  58. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  59. package/dist/types/src/model/selection-model.d.ts +17 -8
  60. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  61. package/dist/types/src/model/table-model.d.ts +103 -24
  62. package/dist/types/src/model/table-model.d.ts.map +1 -1
  63. package/dist/types/src/model/table-presentation.d.ts +3 -1
  64. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  65. package/dist/types/src/playwright/TableManager.d.ts +1 -1
  66. package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
  67. package/dist/types/src/testing/useTestTableModel.d.ts +18 -15
  68. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  69. package/dist/types/src/translations.d.ts +4 -4
  70. package/dist/types/src/translations.d.ts.map +1 -1
  71. package/dist/types/src/types/Table.d.ts +31 -0
  72. package/dist/types/src/types/Table.d.ts.map +1 -0
  73. package/dist/types/src/types/index.d.ts +1 -1
  74. package/dist/types/src/types/index.d.ts.map +1 -1
  75. package/dist/types/src/util/dynamic-table.d.ts +13 -12
  76. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  77. package/dist/types/src/util/index.d.ts +2 -0
  78. package/dist/types/src/util/index.d.ts.map +1 -1
  79. package/dist/types/src/util/query-ast.d.ts +7 -0
  80. package/dist/types/src/util/query-ast.d.ts.map +1 -0
  81. package/dist/types/src/util/schema.d.ts +1 -1
  82. package/dist/types/src/util/schema.d.ts.map +1 -1
  83. package/dist/types/src/util/sort.d.ts +12 -0
  84. package/dist/types/src/util/sort.d.ts.map +1 -0
  85. package/dist/types/tsconfig.tsbuildinfo +1 -1
  86. package/package.json +56 -56
  87. package/src/components/Table/ColumnActionsMenu.tsx +10 -6
  88. package/src/components/Table/ColumnSettings.tsx +6 -6
  89. package/src/components/Table/DynamicTable.stories.tsx +18 -18
  90. package/src/components/Table/DynamicTable.tsx +23 -19
  91. package/src/components/Table/Relations.stories.tsx +143 -39
  92. package/src/components/Table/RowActionsMenu.tsx +24 -15
  93. package/src/components/Table/Table.stories.tsx +92 -95
  94. package/src/components/Table/Table.tsx +339 -307
  95. package/src/components/TableCellEditor/CellValidationMessage.tsx +1 -1
  96. package/src/components/TableCellEditor/FormCellEditor.tsx +116 -129
  97. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +23 -47
  98. package/src/components/TableCellEditor/TableCellEditor.tsx +35 -122
  99. package/src/components/TableCellEditor/index.ts +1 -0
  100. package/src/components/TableToolbar/TableToolbar.tsx +47 -31
  101. package/src/components/testing.ts +39 -13
  102. package/src/hooks/index.ts +2 -1
  103. package/src/hooks/useAddRow.ts +8 -10
  104. package/src/hooks/useProjectionModel.ts +40 -0
  105. package/src/hooks/useTableModel.ts +35 -33
  106. package/src/model/modal-controller.ts +23 -40
  107. package/src/model/selection-model.ts +75 -44
  108. package/src/model/table-model.test.ts +91 -58
  109. package/src/model/table-model.ts +429 -163
  110. package/src/model/table-presentation.test.ts +64 -57
  111. package/src/model/table-presentation.ts +34 -30
  112. package/src/playwright/TableManager.ts +5 -5
  113. package/src/playwright/playwright.config.ts +1 -1
  114. package/src/playwright/smoke.spec.ts +11 -8
  115. package/src/testing/useTestTableModel.ts +44 -35
  116. package/src/translations.ts +3 -3
  117. package/src/types/Table.ts +90 -0
  118. package/src/types/index.ts +1 -1
  119. package/src/util/dynamic-table.ts +41 -30
  120. package/src/util/index.ts +2 -0
  121. package/src/util/query-ast.ts +19 -0
  122. package/src/util/schema.ts +4 -4
  123. package/src/util/sort.ts +90 -0
  124. package/dist/lib/browser/chunk-63UUF4IG.mjs +0 -66
  125. package/dist/lib/browser/chunk-63UUF4IG.mjs.map +0 -7
  126. package/dist/lib/browser/chunk-BBXDTWCX.mjs +0 -1822
  127. package/dist/lib/browser/chunk-BBXDTWCX.mjs.map +0 -7
  128. package/dist/lib/node-esm/chunk-K734DJB7.mjs +0 -67
  129. package/dist/lib/node-esm/chunk-K734DJB7.mjs.map +0 -7
  130. package/dist/lib/node-esm/chunk-RNQDU7IQ.mjs +0 -1823
  131. package/dist/lib/node-esm/chunk-RNQDU7IQ.mjs.map +0 -7
  132. package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
  133. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
  134. package/dist/types/src/model/table-sorting.d.ts +0 -52
  135. package/dist/types/src/model/table-sorting.d.ts.map +0 -1
  136. package/dist/types/src/types/schema.d.ts +0 -28
  137. package/dist/types/src/types/schema.d.ts.map +0 -1
  138. package/src/components/Table/CreateRefPanel.tsx +0 -103
  139. package/src/model/table-sorting.ts +0 -225
  140. package/src/types/schema.ts +0 -73
@@ -12,9 +12,9 @@ export type CellValidationMessageProps = {
12
12
  };
13
13
 
14
14
  export const CellValidationMessage = ({
15
+ __gridScope,
15
16
  validationError,
16
17
  variant = 'error',
17
- __gridScope,
18
18
  }: GridScopedProps<CellValidationMessageProps>) => {
19
19
  const { editing, editBox: box } = useGridContext('GridSheetCellEditor', __gridScope);
20
20
 
@@ -2,95 +2,75 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Schema } from 'effect';
5
+ import type * as Schema from 'effect/Schema';
6
6
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
7
7
 
8
- import { Filter, Obj } from '@dxos/echo';
9
- import { Ref, type TypeAnnotation, getValue } from '@dxos/echo-schema';
8
+ import { Entity, type Type } from '@dxos/echo';
9
+ import { Ref, getValue } from '@dxos/echo/internal';
10
10
  import { invariant } from '@dxos/invariant';
11
- import { getSnapshot } from '@dxos/live-object';
12
- import { type Client } from '@dxos/react-client';
13
- import { getSpace } from '@dxos/react-client/echo';
14
- import { Popover } from '@dxos/react-ui';
15
- import { Form, type FormProps } from '@dxos/react-ui-form';
16
- import { cellQuery, parseCellIndex, useGridContext } from '@dxos/react-ui-grid';
11
+ import { type Label, Popover } from '@dxos/react-ui';
12
+ import { Form, type FormRootProps, type RefFieldProps } from '@dxos/react-ui-form';
13
+ import { parseCellIndex, useGridContext } from '@dxos/react-ui-grid';
17
14
  import { type FieldProjection } from '@dxos/schema';
18
- import { getDeep, isNotFalsy, setDeep } from '@dxos/util';
15
+ import { getDeep, isTruthy, setDeep } from '@dxos/util';
19
16
 
20
- import { type ModalController, type TableModel } from '../../model';
17
+ import { type ModalController, type TableModel, type TableRow } from '../../model';
21
18
  import { translationKey } from '../../translations';
22
19
  import { narrowSchema } from '../../util';
23
20
 
24
- type FormCellEditorProps = {
25
- fieldProjection: FieldProjection;
21
+ const createOptionLabel: Label = ['create new object label', { ns: translationKey }];
22
+
23
+ export type OnCreateHandler = (schema: Type.Entity.Any, values: any) => Parameters<typeof Ref.make>[0];
24
+
25
+ export type FormCellEditorProps<T extends Type.Entity.Any = Type.Entity.Any> = {
26
+ __gridScope: any;
27
+ schema?: T;
26
28
  model?: TableModel;
27
- schema?: Schema.Schema.AnyNoContext;
29
+ fieldProjection: FieldProjection;
30
+ modals?: ModalController; // TODO(burdon): Not used. Remove?
28
31
  onSave?: () => void;
29
- client?: Client;
30
- modals?: ModalController;
31
- __gridScope: any;
32
- } & Omit<FormProps<any>, 'values' | 'schema'>;
32
+ onCreate?: OnCreateHandler;
33
+ } & Omit<FormRootProps<any>, 'values' | 'schema' | 'onCreate'>;
33
34
 
34
- const createOptionLabel = ['create new object label', { ns: translationKey }] as [string, { ns: string }];
35
-
36
- export const FormCellEditor = ({
37
- fieldProjection,
38
- model,
35
+ export const FormCellEditor = <T extends Type.Entity.Any = Type.Entity.Any>({
36
+ __gridScope,
39
37
  schema,
38
+ model,
39
+ fieldProjection,
40
40
  onSave,
41
- client,
42
- modals,
43
- __gridScope,
41
+ onCreate,
44
42
  ...formProps
45
- }: FormCellEditorProps) => {
46
- const { editing: contextEditing, setEditing, id: gridId } = useGridContext('ArrayEditor', __gridScope);
47
- const [editing, setLocalEditing] = useState(false);
43
+ }: FormCellEditorProps<T>) => {
48
44
  const anchorRef = useRef<HTMLButtonElement | null>(null);
45
+ const { id: _gridId, editing: contextEditing, setEditing } = useGridContext('ArrayEditor', __gridScope);
46
+ const [editing, setLocalEditing] = useState(false);
49
47
 
50
- const getSchema = useCallback(
51
- (typeAnnotation: TypeAnnotation) => {
52
- const space = getSpace(model!.view);
53
- invariant(space);
54
-
55
- let schema;
56
- if (client) {
57
- schema = client.graph.schemaRegistry.getSchema(typeAnnotation.typename);
58
- }
59
- if (!schema) {
60
- schema = space.db.schemaRegistry.getSchema(typeAnnotation.typename);
61
- }
62
- return { space, schema };
63
- },
64
- [client, model],
65
- );
48
+ useEffect(() => {
49
+ if (contextEditing && contextEditing.cellElement) {
50
+ anchorRef.current = (contextEditing.cellElement as HTMLElement).querySelector(
51
+ '.dx-grid__cell__content',
52
+ ) as HTMLButtonElement;
53
+ setLocalEditing(true);
54
+ } else {
55
+ anchorRef.current = null;
56
+ setLocalEditing(false);
57
+ }
58
+ }, [contextEditing]);
66
59
 
67
- const handleQueryRefOptions = useCallback(
68
- async (typeAnnotation: TypeAnnotation) => {
69
- const { schema, space } = getSchema(typeAnnotation);
70
- if (model && schema && space) {
71
- const { objects } = await space.db.query(Filter.type(schema)).run();
72
- return objects
73
- .map((obj) => {
74
- return {
75
- dxn: Obj.getDXN(obj),
76
- label: getValue(obj, fieldProjection.field.referencePath!) || obj.id.toString(),
77
- };
78
- })
79
- .filter(isNotFalsy);
80
- }
60
+ const narrowedSchema = useMemo<Schema.Schema.AnyNoContext | undefined>(() => {
61
+ if (!schema) {
62
+ return undefined;
63
+ }
81
64
 
82
- return [];
83
- },
84
- [client, model],
85
- );
65
+ return narrowSchema(schema, [fieldProjection.field.path]);
66
+ }, [JSON.stringify(schema), fieldProjection.field.path]); // TODO(burdon): Avoid stringify.
86
67
 
87
- const originalRow = useMemo(() => {
68
+ const originalRow = useMemo<TableRow | undefined>(() => {
88
69
  if (model && contextEditing) {
89
- const cell = parseCellIndex(contextEditing.index);
90
-
91
70
  // Check if this is a draft cell and get the appropriate row data
71
+ const cell = parseCellIndex(contextEditing.index);
92
72
  if (model.isDraftCell(cell)) {
93
- const draftRow = model.draftRows.value[cell.row];
73
+ const draftRow = model.getDraftRows()[cell.row];
94
74
  invariant(draftRow);
95
75
  return draftRow.data;
96
76
  } else {
@@ -103,79 +83,77 @@ export const FormCellEditor = ({
103
83
  return undefined;
104
84
  }, [model, contextEditing]);
105
85
 
106
- const handleSave = useCallback(
107
- (values: any) => {
86
+ // NOTE: Important to get a mutable deep clone to eject from the echo object.
87
+ // TODO(wittjosiah): Consider using something like Obj.clone for this use case.
88
+ const formValues = useMemo(() => (originalRow ? JSON.parse(JSON.stringify(originalRow)) : {}), [originalRow]);
89
+
90
+ const handleOpenChange = useCallback((nextOpen: boolean) => {
91
+ if (nextOpen === false) {
92
+ setEditing(null);
93
+ onSave?.();
94
+ }
95
+ setLocalEditing(nextOpen);
96
+ }, []);
97
+
98
+ const handleSave = useCallback<NonNullable<FormRootProps<any>['onSave']>>(
99
+ (values) => {
100
+ if (!originalRow) {
101
+ return;
102
+ }
108
103
  const path = fieldProjection.field.path;
109
104
  const value = getDeep(values, [path]);
110
- setDeep(originalRow, [path], value);
105
+ // Use model's changeRow for consistent mutation handling.
106
+ if (model) {
107
+ model.changeRow(originalRow, (mutableRow) => {
108
+ setDeep(mutableRow, [path], value);
109
+ });
110
+ } else {
111
+ setDeep(originalRow, [path], value);
112
+ }
111
113
  contextEditing?.cellElement?.focus();
112
114
  setEditing(null);
113
115
  setLocalEditing(false);
114
116
  onSave?.();
115
117
  },
116
- [fieldProjection.field.path, onSave, contextEditing, originalRow],
118
+ [fieldProjection.field.path, onSave, contextEditing, originalRow, model],
117
119
  );
118
120
 
119
- const handleCreate = useCallback(
120
- (object: any) => {
121
- const ref = Ref.make(object);
122
- const path = fieldProjection.field.path;
123
- setDeep(originalRow, [path], ref);
121
+ const handleCreate = useCallback<NonNullable<FormRootProps<any>['onCreate']>>(
122
+ (schema, values) => {
123
+ const objectWithId = onCreate?.(schema, values);
124
+ if (objectWithId && originalRow) {
125
+ const ref = Ref.make(objectWithId);
126
+ const path = fieldProjection.field.path;
127
+ // Use model's changeRow for consistent mutation handling.
128
+ if (model) {
129
+ model.changeRow(originalRow, (mutableRow) => {
130
+ setDeep(mutableRow, [path], ref);
131
+ });
132
+ } else {
133
+ setDeep(originalRow, [path], ref);
134
+ }
135
+ }
124
136
  contextEditing?.cellElement?.focus();
125
137
  setEditing(null);
126
138
  setLocalEditing(false);
127
139
  onSave?.();
128
140
  },
129
- [fieldProjection.field.path, onSave, contextEditing, originalRow],
141
+ [fieldProjection.field.path, onSave, contextEditing, originalRow, onCreate, model],
130
142
  );
131
143
 
132
- const handleCreateFromQuery = useCallback(
133
- async (typeAnnotation: TypeAnnotation, query: string) => {
134
- if (model && modals && contextEditing?.index) {
135
- setLocalEditing(false);
136
- modals.openCreateRef(
137
- typeAnnotation.typename,
138
- document.querySelector(cellQuery(contextEditing.index, gridId)),
139
- {
140
- [fieldProjection.field.referencePath!]: query,
141
- },
142
- handleCreate,
143
- );
144
- }
145
- },
146
- [model, modals, client, contextEditing?.index, gridId, fieldProjection, handleSave],
144
+ const getOptions = useCallback<NonNullable<RefFieldProps['getOptions']>>(
145
+ (results) =>
146
+ results
147
+ .map((obj) => {
148
+ return {
149
+ id: Entity.getDXN(obj).toString(),
150
+ label: getValue(obj, fieldProjection.field.referencePath!) || obj.id.toString(),
151
+ };
152
+ })
153
+ .filter(isTruthy),
154
+ [fieldProjection],
147
155
  );
148
156
 
149
- useEffect(() => {
150
- if (contextEditing && contextEditing.cellElement) {
151
- anchorRef.current = (contextEditing.cellElement as HTMLElement).querySelector(
152
- '.dx-grid__cell__content',
153
- ) as HTMLButtonElement;
154
- setLocalEditing(true);
155
- } else {
156
- anchorRef.current = null;
157
- setLocalEditing(false);
158
- }
159
- }, [contextEditing]);
160
-
161
- const narrowedSchema = useMemo(() => {
162
- if (!schema) {
163
- return undefined;
164
- }
165
- return narrowSchema(schema, [fieldProjection.field.path]);
166
- }, [JSON.stringify(schema), fieldProjection.field.path]); // TODO(burdon): Avoid stringify.
167
-
168
- // NOTE: Important to get a snapshot to eject from the live object.
169
- const formValues = useMemo(() => (originalRow ? getSnapshot(originalRow) : {}), [originalRow]);
170
-
171
- const handleOpenChange = useCallback((nextOpen: boolean) => {
172
- if (nextOpen === false) {
173
- setEditing(null);
174
- onSave?.();
175
- }
176
- setLocalEditing(nextOpen);
177
- }, []);
178
-
179
157
  if (!editing) {
180
158
  return null;
181
159
  }
@@ -187,17 +165,26 @@ export const FormCellEditor = ({
187
165
  <Popover.Content tabIndex={-1} classNames='popover-card-width density-fine'>
188
166
  <Popover.Arrow />
189
167
  <Popover.Viewport>
190
- <Form
168
+ <Form.Root
169
+ {...formProps}
191
170
  autoFocus
171
+ schema={narrowedSchema}
192
172
  values={formValues}
193
- schema={narrowedSchema as any}
194
- onSave={handleSave}
195
- {...formProps}
196
- onQueryRefOptions={handleQueryRefOptions}
197
- onCreateFromQuery={handleCreateFromQuery}
173
+ createInitialValuePath={fieldProjection.field.referencePath}
198
174
  createOptionIcon='ph--plus--regular'
199
175
  createOptionLabel={createOptionLabel}
200
- />
176
+ db={model?.db}
177
+ getOptions={getOptions}
178
+ onCreate={handleCreate}
179
+ onSave={handleSave}
180
+ >
181
+ <Form.Viewport>
182
+ <Form.Content>
183
+ <Form.FieldSet />
184
+ <Form.Actions />
185
+ </Form.Content>
186
+ </Form.Viewport>
187
+ </Form.Root>
201
188
  </Popover.Viewport>
202
189
  </Popover.Content>
203
190
  </Popover.Portal>
@@ -2,23 +2,18 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
8
- import React, { useEffect, useMemo, useState } from 'react';
6
+ import React from 'react';
9
7
 
10
8
  import { Obj } from '@dxos/echo';
11
- import { type EchoSchema, isMutable } from '@dxos/echo-schema';
12
- import { invariant } from '@dxos/invariant';
13
9
  import { faker } from '@dxos/random';
14
- import { Filter, useQuery } from '@dxos/react-client/echo';
15
- import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
10
+ import { withClientProvider } from '@dxos/react-client/testing';
11
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
16
12
  import { Grid, type GridEditing, defaultRowSize } from '@dxos/react-ui-grid';
17
- import { DataType, createDefaultSchema, typenameFromQuery } from '@dxos/schema';
18
- import { withLayout, withTheme } from '@dxos/storybook-utils';
13
+ import { View } from '@dxos/schema';
14
+ import { Task } from '@dxos/types';
19
15
 
20
- import { useTableModel } from '../../hooks';
21
- import { type TableFeatures } from '../../model';
16
+ import { useTestTableModel } from '../../testing';
22
17
  import { translations } from '../../translations';
23
18
  import { Table } from '../../types';
24
19
 
@@ -28,40 +23,18 @@ type StoryProps = {
28
23
  editing: GridEditing;
29
24
  };
30
25
 
26
+ // TODO(burdon): Broken layout.
31
27
  const DefaultStory = ({ editing }: StoryProps) => {
32
- const { space } = useClientProvider();
33
- invariant(space);
34
-
35
- const views = useQuery(space, Filter.type(DataType.View));
36
- const [view, setView] = useState<DataType.View>();
37
- const [schema, setSchema] = useState<EchoSchema>();
38
- useEffect(() => {
39
- if (space && views.length && !view) {
40
- const view = views[0];
41
- setView(view);
42
- setSchema(space.db.schemaRegistry.getSchema(typenameFromQuery(view.query)!));
43
- }
44
- }, [space, views, view]);
45
-
46
- const features: Partial<TableFeatures> = useMemo(
47
- () => ({
48
- selection: { enabled: true, mode: 'multiple' },
49
- dataEditable: true,
50
- schemaEditable: schema && isMutable(schema),
51
- }),
52
- [schema],
53
- );
28
+ const { model, table } = useTestTableModel();
54
29
 
55
- const model = useTableModel({ view, schema: schema?.jsonSchema, features });
56
-
57
- if (!model || !schema || !view) {
30
+ if (!model || !table) {
58
31
  return <div />;
59
32
  }
60
33
 
61
34
  return (
62
- <div className='flex w-[300px] border border-separator' style={{ height: defaultRowSize }}>
35
+ <div className='border border-separator' style={{ height: defaultRowSize }}>
63
36
  <Grid.Root id='test' editing={editing}>
64
- <TableCellEditor model={model} schema={schema} />
37
+ <TableCellEditor model={model} schema={Task.Task} />
65
38
  </Grid.Root>
66
39
  </div>
67
40
  );
@@ -71,19 +44,20 @@ const meta = {
71
44
  title: 'ui/react-ui-table/TableCellEditor',
72
45
  component: DefaultStory,
73
46
  render: DefaultStory,
74
- parameters: { translations, layout: 'centered' },
75
47
  decorators: [
48
+ withTheme,
49
+ withLayout({ layout: 'column' }),
76
50
  withClientProvider({
77
- types: [DataType.View, Table.Table],
51
+ types: [View.View, Task.Task, Table.Table],
78
52
  createIdentity: true,
79
53
  createSpace: true,
80
- onSpaceCreated: async ({ client, space }) => {
81
- const schema = createDefaultSchema();
82
- const { view } = await Table.makeView({ client, space, typename: schema.typename });
83
- space.db.add(view);
54
+ onCreateSpace: async ({ space }) => {
55
+ const { view, jsonSchema } = await View.makeFromDatabase({ db: space.db, typename: Task.Task.typename });
56
+ const table = Table.make({ view, jsonSchema });
57
+ space.db.add(table);
84
58
  Array.from({ length: 10 }).forEach(() => {
85
59
  space.db.add(
86
- Obj.make(schema, {
60
+ Obj.make(Task.Task, {
87
61
  title: faker.person.fullName(),
88
62
  status: faker.helpers.arrayElement(['todo', 'in-progress', 'done'] as const),
89
63
  description: faker.lorem.sentence(),
@@ -92,9 +66,11 @@ const meta = {
92
66
  });
93
67
  },
94
68
  }),
95
- withTheme,
96
- withLayout(),
97
69
  ],
70
+ parameters: {
71
+ layout: 'fullscreen',
72
+ translations,
73
+ },
98
74
  } satisfies Meta<typeof DefaultStory>;
99
75
 
100
76
  export default meta;