@dxos/react-ui-table 0.8.4-main.fd6878d → 0.9.0

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