@dxos/react-ui-table 0.8.4-main.f9ba587 → 0.8.4-main.fcfe5033a5

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 (172) hide show
  1. package/dist/lib/browser/chunk-BF54SSNL.mjs +70 -0
  2. package/dist/lib/browser/chunk-BF54SSNL.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-F7Y374KL.mjs +1751 -0
  4. package/dist/lib/browser/chunk-F7Y374KL.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +1195 -2846
  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 +114 -0
  9. package/dist/lib/browser/testing/index.mjs.map +7 -0
  10. package/dist/lib/browser/types/index.mjs +3 -5
  11. package/dist/lib/node-esm/chunk-CCJ4LOVM.mjs +1753 -0
  12. package/dist/lib/node-esm/chunk-CCJ4LOVM.mjs.map +7 -0
  13. package/dist/lib/node-esm/chunk-SIRDIPHZ.mjs +71 -0
  14. package/dist/lib/node-esm/chunk-SIRDIPHZ.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +1195 -2846
  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 +115 -0
  19. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  20. package/dist/lib/node-esm/types/index.mjs +3 -5
  21. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +2 -3
  22. package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/ColumnSettings.d.ts +4 -2
  24. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  25. package/dist/types/src/components/Table/DynamicTable.d.ts +7 -7
  26. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  27. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +35 -3
  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 +110 -0
  30. package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -0
  31. package/dist/types/src/components/Table/RowActionsMenu.d.ts +1 -1
  32. package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
  33. package/dist/types/src/components/Table/Table.d.ts +21 -18
  34. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  35. package/dist/types/src/components/Table/Table.stories.d.ts +109 -6
  36. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/Table/TableContent.d.ts +17 -0
  38. package/dist/types/src/components/Table/TableContent.d.ts.map +1 -0
  39. package/dist/types/src/components/Table/TableToolbar.d.ts +21 -0
  40. package/dist/types/src/components/Table/TableToolbar.d.ts.map +1 -0
  41. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +1 -1
  42. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
  43. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +14 -9
  44. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  45. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +12 -18
  46. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  47. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +38 -5
  48. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  49. package/dist/types/src/components/TableCellEditor/index.d.ts +1 -0
  50. package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -1
  51. package/dist/types/src/components/index.d.ts +0 -1
  52. package/dist/types/src/components/index.d.ts.map +1 -1
  53. package/dist/types/src/components/testing.d.ts +26 -56
  54. package/dist/types/src/components/testing.d.ts.map +1 -1
  55. package/dist/types/src/hooks/index.d.ts +2 -1
  56. package/dist/types/src/hooks/index.d.ts.map +1 -1
  57. package/dist/types/src/hooks/useAddRow.d.ts +6 -6
  58. package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
  59. package/dist/types/src/hooks/useProjectionModel.d.ts +6 -0
  60. package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -0
  61. package/dist/types/src/hooks/useTableModel.d.ts +11 -10
  62. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  63. package/dist/types/src/index.d.ts +0 -1
  64. package/dist/types/src/index.d.ts.map +1 -1
  65. package/dist/types/src/model/modal-controller.d.ts +5 -8
  66. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  67. package/dist/types/src/model/selection-model.d.ts +17 -7
  68. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  69. package/dist/types/src/model/table-model.d.ts +116 -34
  70. package/dist/types/src/model/table-model.d.ts.map +1 -1
  71. package/dist/types/src/model/table-presentation.d.ts +5 -2
  72. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  73. package/dist/types/src/playwright/TableManager.d.ts +2 -1
  74. package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
  75. package/dist/types/src/testing/index.d.ts +2 -0
  76. package/dist/types/src/testing/index.d.ts.map +1 -0
  77. package/dist/types/src/testing/useTestTableModel.d.ts +25 -0
  78. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -0
  79. package/dist/types/src/translations.d.ts +21 -23
  80. package/dist/types/src/translations.d.ts.map +1 -1
  81. package/dist/types/src/types/Table.d.ts +26 -0
  82. package/dist/types/src/types/Table.d.ts.map +1 -0
  83. package/dist/types/src/types/index.d.ts +1 -1
  84. package/dist/types/src/types/index.d.ts.map +1 -1
  85. package/dist/types/src/util/dynamic-table.d.ts +15 -14
  86. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  87. package/dist/types/src/util/dynamic-table.test.d.ts +2 -0
  88. package/dist/types/src/util/dynamic-table.test.d.ts.map +1 -0
  89. package/dist/types/src/util/index.d.ts +2 -1
  90. package/dist/types/src/util/index.d.ts.map +1 -1
  91. package/dist/types/src/util/query-ast.d.ts +7 -0
  92. package/dist/types/src/util/query-ast.d.ts.map +1 -0
  93. package/dist/types/src/util/schema.d.ts +1 -1
  94. package/dist/types/src/util/schema.d.ts.map +1 -1
  95. package/dist/types/src/util/sort.d.ts +12 -0
  96. package/dist/types/src/util/sort.d.ts.map +1 -0
  97. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  98. package/dist/types/src/util/table-controls.d.ts.map +1 -1
  99. package/dist/types/tsconfig.tsbuildinfo +1 -1
  100. package/package.json +70 -55
  101. package/src/components/Table/ColumnActionsMenu.tsx +16 -12
  102. package/src/components/Table/ColumnSettings.tsx +18 -15
  103. package/src/components/Table/DynamicTable.stories.tsx +38 -35
  104. package/src/components/Table/DynamicTable.tsx +38 -34
  105. package/src/components/Table/Relations.stories.tsx +245 -0
  106. package/src/components/Table/RowActionsMenu.tsx +26 -17
  107. package/src/components/Table/Table.stories.tsx +196 -218
  108. package/src/components/Table/Table.tsx +47 -376
  109. package/src/components/Table/TableContent.tsx +421 -0
  110. package/src/components/Table/TableToolbar.tsx +111 -0
  111. package/src/components/TableCellEditor/CellValidationMessage.tsx +6 -6
  112. package/src/components/TableCellEditor/FormCellEditor.tsx +152 -49
  113. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +37 -77
  114. package/src/components/TableCellEditor/TableCellEditor.tsx +104 -233
  115. package/src/components/TableCellEditor/index.ts +1 -0
  116. package/src/components/index.ts +0 -1
  117. package/src/components/testing.ts +46 -37
  118. package/src/hooks/index.ts +2 -1
  119. package/src/hooks/useAddRow.ts +14 -14
  120. package/src/hooks/useProjectionModel.ts +39 -0
  121. package/src/hooks/useTableModel.ts +41 -35
  122. package/src/index.ts +0 -1
  123. package/src/model/modal-controller.ts +24 -41
  124. package/src/model/selection-model.ts +75 -41
  125. package/src/model/table-model.test.ts +91 -56
  126. package/src/model/table-model.ts +468 -187
  127. package/src/model/table-presentation.test.ts +69 -59
  128. package/src/model/table-presentation.ts +112 -66
  129. package/src/playwright/TableManager.ts +13 -6
  130. package/src/playwright/playwright.config.ts +1 -1
  131. package/src/playwright/smoke.spec.ts +180 -43
  132. package/src/testing/index.ts +5 -0
  133. package/src/testing/useTestTableModel.ts +133 -0
  134. package/src/translations.ts +20 -22
  135. package/src/types/Table.ts +79 -0
  136. package/src/types/index.ts +2 -2
  137. package/src/util/dynamic-table.test.ts +70 -0
  138. package/src/util/dynamic-table.ts +51 -36
  139. package/src/util/index.ts +2 -1
  140. package/src/util/query-ast.ts +22 -0
  141. package/src/util/schema.ts +4 -4
  142. package/src/util/sort.ts +90 -0
  143. package/src/util/table-buttons.ts +4 -3
  144. package/src/util/table-controls.ts +6 -3
  145. package/dist/lib/browser/chunk-Q5QQXJUO.mjs +0 -27
  146. package/dist/lib/browser/chunk-Q5QQXJUO.mjs.map +0 -7
  147. package/dist/lib/node-esm/chunk-ZNOU6LHG.mjs +0 -29
  148. package/dist/lib/node-esm/chunk-ZNOU6LHG.mjs.map +0 -7
  149. package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
  150. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
  151. package/dist/types/src/components/Table/relations.stories.d.ts +0 -9
  152. package/dist/types/src/components/Table/relations.stories.d.ts.map +0 -1
  153. package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
  154. package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
  155. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +0 -21
  156. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +0 -1
  157. package/dist/types/src/components/TableToolbar/index.d.ts +0 -2
  158. package/dist/types/src/components/TableToolbar/index.d.ts.map +0 -1
  159. package/dist/types/src/model/table-sorting.d.ts +0 -53
  160. package/dist/types/src/model/table-sorting.d.ts.map +0 -1
  161. package/dist/types/src/types/table.d.ts +0 -56
  162. package/dist/types/src/types/table.d.ts.map +0 -1
  163. package/dist/types/src/util/table.d.ts +0 -14
  164. package/dist/types/src/util/table.d.ts.map +0 -1
  165. package/src/components/Table/CreateRefPanel.tsx +0 -84
  166. package/src/components/Table/relations.stories.tsx +0 -123
  167. package/src/components/TableCellEditor/extension.ts +0 -61
  168. package/src/components/TableToolbar/TableToolbar.tsx +0 -102
  169. package/src/components/TableToolbar/index.ts +0 -5
  170. package/src/model/table-sorting.ts +0 -216
  171. package/src/types/table.ts +0 -27
  172. package/src/util/table.ts +0 -127
@@ -2,161 +2,94 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import * as Schema from 'effect/Schema';
7
+ import React, { useCallback } from 'react';
6
8
 
7
- import { type StoryObj, type Meta } from '@storybook/react-vite';
8
- import { Schema } from 'effect';
9
- import React, { useCallback, useMemo, useRef } from 'react';
10
-
11
- import { Obj, Type } from '@dxos/echo';
12
- import { FormatEnum, isMutable, toJsonSchema, EchoObject, GeneratorAnnotation } from '@dxos/echo-schema';
9
+ import { Annotation, type Database, Format, Obj, type QueryAST, Ref, Type } from '@dxos/echo';
10
+ import { View } from '@dxos/echo';
11
+ import { type Mutable, PropertyMetaAnnotationId } from '@dxos/echo/internal';
13
12
  import { invariant } from '@dxos/invariant';
14
- import { useGlobalFilteredObjects } from '@dxos/plugin-search';
15
- import { faker } from '@dxos/random';
16
- import { useClient } from '@dxos/react-client';
17
- import { Filter, useQuery, useSchema, live } from '@dxos/react-client/echo';
18
- import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
19
- import { ViewEditor } from '@dxos/react-ui-form';
13
+ import { random } from '@dxos/random';
14
+ import { PublicKey } from '@dxos/react-client';
15
+ import { withClientProvider } from '@dxos/react-client/testing';
16
+ import { Panel, ScrollArea } from '@dxos/react-ui';
17
+ import { ViewEditor, translations as formTranslations } from '@dxos/react-ui-form';
20
18
  import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
21
- import { getSchemaFromPropertyDefinitions, ViewProjection, ViewType } from '@dxos/schema';
22
- import { Testing, createObjectFactory } from '@dxos/schema/testing';
23
- import { withLayout, withTheme } from '@dxos/storybook-utils';
19
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
20
+ import { ViewModel, getSchemaFromPropertyDefinitions, getTypenameFromQuery } from '@dxos/schema';
21
+ import { TestSchema, createObjectFactory } from '@dxos/schema/testing';
22
+ import { withRegistry } from '@dxos/storybook-utils';
24
23
 
25
- import { Table, type TableController } from './Table';
26
- import { useTableModel, useAddRow } from '../../hooks';
27
- import { TablePresentation } from '../../model';
24
+ import { useTestTableModel } from '../../testing';
28
25
  import { translations } from '../../translations';
29
- import { TableType } from '../../types';
30
- import { initializeTable } from '../../util';
31
- import { TableToolbar } from '../TableToolbar';
32
-
33
- faker.seed(0); // NOTE(ZaymonFC): Required for smoke tests.
34
-
35
- /**
36
- * Custom hook to create and manage a test table model for storybook demonstrations.
37
- * Provides table data, schema, and handlers for table operations.
38
- */
39
- const useTestTableModel = () => {
40
- const client = useClient();
41
- const { space } = useClientProvider();
42
-
43
- const filter = useMemo(() => Filter.type(TableType), []);
44
- const tables = useQuery(space, filter);
45
- const table = useMemo(() => tables.at(0), [tables]);
46
- const schema = useSchema(client, space, table?.view?.target?.query.typename);
47
-
48
- const projection = useMemo(() => {
49
- if (schema && table?.view?.target) {
50
- return new ViewProjection(toJsonSchema(schema), table.view.target);
51
- }
52
- }, [schema, table?.view?.target]);
53
-
54
- const features = useMemo(
55
- () => ({
56
- selection: { enabled: true, mode: 'multiple' as const },
57
- dataEditable: true,
58
- schemaEditable: schema && isMutable(schema),
59
- }),
60
- [schema],
61
- );
62
-
63
- const objects = useQuery(space, schema ? Filter.type(schema) : Filter.nothing());
64
- const filteredObjects = useGlobalFilteredObjects(objects);
65
-
66
- const tableRef = useRef<TableController>(null);
67
- const handleCellUpdate = useCallback((cell: any) => {
68
- tableRef.current?.update?.(cell);
69
- }, []);
70
-
71
- const handleRowOrderChange = useCallback(() => {
72
- tableRef.current?.update?.();
73
- }, []);
74
-
75
- const addRow = useAddRow({ space, schema });
76
-
77
- const handleDeleteRows = useCallback(
78
- (_: number, objects: any[]) => {
79
- for (const object of objects) {
80
- space?.db.remove(object);
81
- }
82
- },
83
- [space],
84
- );
85
-
86
- const handleDeleteColumn = useCallback(
87
- (fieldId: string) => {
88
- if (projection) {
89
- projection.deleteFieldProjection(fieldId);
90
- }
91
- },
92
- [projection],
93
- );
94
-
95
- const model = useTableModel({
96
- table,
97
- projection,
98
- features,
99
- rows: filteredObjects,
100
- onInsertRow: addRow,
101
- onDeleteRows: handleDeleteRows,
102
- onDeleteColumn: handleDeleteColumn,
103
- onCellUpdate: handleCellUpdate,
104
- onRowOrderChange: handleRowOrderChange,
105
- });
106
-
107
- const handleInsertRow = useCallback(() => {
108
- model?.insertRow();
109
- }, [model]);
110
-
111
- const handleSaveView = useCallback(() => {
112
- model?.saveView();
113
- }, [model]);
114
-
115
- const presentation = useMemo(() => {
116
- if (model) {
117
- return new TablePresentation(model);
118
- }
119
- }, [model]);
120
-
121
- return {
122
- schema,
123
- table,
124
- tableRef,
125
- model,
126
- presentation,
127
- space,
128
- client,
129
- handleInsertRow,
130
- handleSaveView,
131
- handleDeleteRows,
132
- handleDeleteColumn,
133
- };
134
- };
135
-
136
- const StoryViewEditor = () => {
137
- const { table, space, schema, handleDeleteColumn } = useTestTableModel();
138
-
139
- const handleTypenameChanged = useCallback(
140
- (typename: string) => {
26
+ import { Table } from '../../types';
27
+ import { Table as TableComponent } from './Table';
28
+
29
+ const Example = Schema.Struct({
30
+ // TODO(wittjosiah): Should be title. Currently name to work with default label.
31
+ name: Schema.optional(Schema.String).annotations({ title: 'Title' }),
32
+ urgent: Schema.optional(Schema.Boolean).annotations({ title: 'Urgent' }),
33
+ status: Schema.optional(
34
+ Schema.Literal('todo', 'in-progress', 'done')
35
+ .pipe(Format.FormatAnnotation.set(Format.TypeFormat.SingleSelect))
36
+ .annotations({
37
+ title: 'Status',
38
+ [PropertyMetaAnnotationId]: {
39
+ singleSelect: {
40
+ options: [
41
+ { id: 'todo', title: 'Todo', color: 'indigo' },
42
+ { id: 'in-progress', title: 'In Progress', color: 'purple' },
43
+ { id: 'done', title: 'Done', color: 'amber' },
44
+ ],
45
+ },
46
+ },
47
+ }),
48
+ ),
49
+ description: Schema.optional(Schema.String).annotations({ title: 'Description' }),
50
+ parent: Schema.optional(Schema.suspend((): Ref.RefSchema<Example> => Ref.Ref(Example))).annotations({
51
+ title: 'Parent',
52
+ }),
53
+ }).pipe(
54
+ Type.object({ typename: `com.example.type.${PublicKey.random().truncate()}`, version: '0.1.0' }),
55
+ Annotation.LabelAnnotation.set(['name']),
56
+ );
57
+ interface Example extends Schema.Schema.Type<typeof Example> {}
58
+
59
+ const StoryViewEditor = ({
60
+ view,
61
+ schema,
62
+ db,
63
+ handleDeleteColumn,
64
+ }: {
65
+ view?: View.View;
66
+ schema?: Schema.Schema.AnyNoContext;
67
+ db?: Database.Database;
68
+ handleDeleteColumn: (fieldId: string) => void;
69
+ }) => {
70
+ const handleQueryChanged = useCallback(
71
+ (newQuery: QueryAST.Query) => {
141
72
  invariant(schema);
142
73
  invariant(Type.isMutable(schema));
143
- schema.updateTypename(typename);
144
- invariant(table?.view?.target);
145
- table.view.target.query.typename = typename;
74
+ schema.updateTypename(getTypenameFromQuery(newQuery));
75
+ invariant(view);
76
+ Obj.change(view, (view) => {
77
+ view.query.ast = newQuery as Mutable<typeof newQuery>;
78
+ });
146
79
  },
147
- [schema, table?.view?.target],
80
+ [schema, view],
148
81
  );
149
82
 
150
- if (!table || !schema || !table.view?.target) {
83
+ if (!view || !schema) {
151
84
  return null;
152
85
  }
153
86
 
154
87
  return (
155
88
  <ViewEditor
156
- registry={space?.db.schemaRegistry}
89
+ registry={db?.schemaRegistry}
157
90
  schema={schema}
158
- view={table.view.target!}
159
- onTypenameChanged={handleTypenameChanged}
91
+ view={view}
92
+ onQueryChanged={handleQueryChanged}
160
93
  onDelete={handleDeleteColumn}
161
94
  />
162
95
  );
@@ -167,108 +100,146 @@ const StoryViewEditor = () => {
167
100
  //
168
101
 
169
102
  const DefaultStory = () => {
170
- const { schema, table, tableRef, model, presentation, client, handleInsertRow, handleSaveView } = useTestTableModel();
103
+ const { db, schema, table, tableRef, model, presentation, handleInsertRow, handleSaveView, handleDeleteColumn } =
104
+ useTestTableModel();
105
+
106
+ const handleRowClick = useCallback(
107
+ (row: any) => {
108
+ if (model?.getDraftRowCount() === 0 && ['frozenRowsEnd', 'fixedEndStart', 'fixedEndEnd'].includes(row?.plane)) {
109
+ handleInsertRow();
110
+ }
111
+ },
112
+ [model, handleInsertRow],
113
+ );
171
114
 
172
- if (!schema || !table) {
115
+ if (!schema || !table?.view.target) {
173
116
  return <div />;
174
117
  }
175
118
 
176
119
  return (
177
120
  <div className='grow grid grid-cols-[1fr_350px]'>
178
- <div className='grid grid-rows-[min-content_1fr] min-bs-0 overflow-hidden'>
179
- <TableToolbar classNames='border-be border-subduedSeparator' onAdd={handleInsertRow} onSave={handleSaveView} />
180
- <Table.Root>
181
- <Table.Main
182
- ref={tableRef}
183
- model={model}
184
- presentation={presentation}
185
- schema={schema}
186
- client={client}
187
- ignoreAttention
188
- />
189
- </Table.Root>
190
- </div>
191
- <div className='flex flex-col h-full border-l border-separator overflow-y-auto'>
192
- <StoryViewEditor />
193
- <SyntaxHighlighter language='json' className='w-full text-xs'>
194
- {JSON.stringify({ view: table.view?.target, schema }, null, 2)}
195
- </SyntaxHighlighter>
196
- </div>
121
+ <TableComponent.Root ref={tableRef}>
122
+ <Panel.Root>
123
+ <Panel.Toolbar asChild>
124
+ <TableComponent.Toolbar
125
+ classNames='border-b border-subdued-separator'
126
+ onAdd={handleInsertRow}
127
+ onSave={handleSaveView}
128
+ />
129
+ </Panel.Toolbar>
130
+ <Panel.Content asChild>
131
+ <TableComponent.Content
132
+ schema={schema}
133
+ model={model}
134
+ presentation={presentation}
135
+ onRowClick={handleRowClick}
136
+ ignoreAttention
137
+ />
138
+ </Panel.Content>
139
+ </Panel.Root>
140
+ </TableComponent.Root>
141
+ <ScrollArea.Root orientation='vertical' classNames='border-l border-separator'>
142
+ <ScrollArea.Viewport>
143
+ <StoryViewEditor view={table.view.target} schema={schema} db={db} handleDeleteColumn={handleDeleteColumn} />
144
+ <SyntaxHighlighter language='json' className='text-xs'>
145
+ {JSON.stringify({ view: table.view.target, schema }, null, 2)}
146
+ </SyntaxHighlighter>
147
+ </ScrollArea.Viewport>
148
+ </ScrollArea.Root>
197
149
  </div>
198
150
  );
199
151
  };
200
152
 
201
- type StoryProps = { rows?: number };
153
+ type DefaultStoryProps = { rows?: number };
202
154
 
203
155
  //
204
156
  // Story definitions.
205
157
  //
206
158
 
207
- // TODO(burdon): Need super simple story.
159
+ // TODO(burdon): Need simpler story.
208
160
 
209
- const meta: Meta<StoryProps> = {
161
+ const meta = {
210
162
  title: 'ui/react-ui-table/Table',
211
163
  render: DefaultStory,
212
- parameters: {
213
- translations,
214
- layout: 'fullscreen',
215
- controls: {
216
- disable: true,
217
- },
218
- },
219
164
  decorators: [
220
- withTheme,
221
- withLayout({ fullscreen: true }),
165
+ withTheme(),
166
+ withLayout({ layout: 'fullscreen' }),
167
+ withRegistry,
222
168
  withClientProvider({
223
- types: [TableType, ViewType],
169
+ types: [View.View, Table.Table],
224
170
  createIdentity: true,
225
171
  createSpace: true,
226
- onSpaceCreated: async ({ client, space }) => {
227
- const table = space.db.add(Obj.make(TableType, {}));
228
- const schema = await initializeTable({ client, space, table, initialRow: false });
172
+ onCreateSpace: async ({ space }) => {
173
+ const [schema] = await space.db.schemaRegistry.register([Example]);
174
+ const { view, jsonSchema } = await ViewModel.makeFromDatabase({ db: space.db, typename: schema.typename });
175
+ const table = Table.make({ view, jsonSchema });
176
+ Obj.change(view, (view) => {
177
+ view.projection.fields = [
178
+ view.projection.fields.find((field) => field.path === 'name')!,
179
+ ...view.projection.fields.filter((field) => field.path !== 'name'),
180
+ ];
181
+ });
182
+
183
+ space.db.add(table);
184
+
229
185
  Array.from({ length: 10 }).map(() => {
230
186
  return space.db.add(
231
- live(schema, {
232
- name: faker.person.fullName(),
187
+ Obj.make(schema, {
188
+ name: random.lorem.sentence(),
189
+ status: random.helpers.arrayElement(['todo', 'in-progress', 'done'] as const),
190
+ description: random.lorem.paragraph(),
233
191
  }),
234
192
  );
235
193
  });
236
194
  },
237
195
  }),
238
196
  ],
239
- };
197
+ parameters: {
198
+ layout: 'fullscreen',
199
+ controls: {
200
+ disable: true,
201
+ },
202
+ translations: [...translations, ...formTranslations],
203
+ },
204
+ } satisfies Meta<typeof TableComponent>;
240
205
 
241
206
  export default meta;
242
207
 
243
- export const Default = {};
208
+ type Story = StoryObj<typeof meta>;
209
+
210
+ export const Default: Story = {};
244
211
 
245
212
  export const StaticSchema: StoryObj = {
246
213
  render: DefaultStory,
247
- parameters: { translations },
248
214
  decorators: [
249
215
  withClientProvider({
250
- types: [TableType, ViewType, Testing.Contact, Testing.Organization],
216
+ types: [View.View, Table.Table],
251
217
  createIdentity: true,
252
218
  createSpace: true,
253
- onSpaceCreated: async ({ client, space }) => {
254
- const table = space.db.add(Obj.make(TableType, {}));
255
- await initializeTable({ client, space, table, typename: Testing.Organization.typename });
219
+ onCreateSpace: async ({ space }) => {
220
+ const { view, jsonSchema } = await ViewModel.makeFromDatabase({
221
+ db: space.db,
222
+ typename: TestSchema.Person.typename,
223
+ });
224
+ const table = Table.make({ view, jsonSchema });
225
+ space.db.add(table);
256
226
 
257
- const factory = createObjectFactory(space.db, faker as any);
227
+ const factory = createObjectFactory(space.db, random as any);
258
228
  await factory([
259
- // { type: Testing.Contact, count: 10 },
260
- // { type: Testing.Organization, count: 1 },
261
- { type: ContactWithArrayOfEmails, count: 10 },
229
+ { type: TestSchema.Person, count: 10 },
230
+ // { type: TestSchema.Organization, count: 1 },
262
231
  ]);
263
232
  },
264
233
  }),
265
- withLayout({ fullscreen: true }),
266
- withTheme,
267
234
  ],
235
+ parameters: {
236
+ layout: 'fullscreen',
237
+ translations: [...translations, ...formTranslations],
238
+ },
268
239
  };
269
240
 
270
241
  const ContactWithArrayOfEmails = Schema.Struct({
271
- name: Schema.String.pipe(GeneratorAnnotation.set('person.fullName')),
242
+ name: Schema.String.pipe(Annotation.GeneratorAnnotation.set('person.fullName')),
272
243
  emails: Schema.optional(
273
244
  Schema.Array(
274
245
  Schema.Struct({
@@ -278,49 +249,53 @@ const ContactWithArrayOfEmails = Schema.Struct({
278
249
  ),
279
250
  ),
280
251
  }).pipe(
281
- EchoObject({
282
- typename: 'dxos.org/type/ContactWithArrayOfEmails',
252
+ Type.object({
253
+ typename: 'org.dxos.type.contactWithArrayOfEmails',
283
254
  version: '0.1.0',
284
255
  }),
285
256
  );
286
257
 
287
258
  export const ArrayOfObjects: StoryObj = {
288
259
  render: DefaultStory,
289
- parameters: { translations },
290
260
  decorators: [
291
261
  withClientProvider({
292
- types: [TableType, ViewType, Testing.Contact, Testing.Organization, ContactWithArrayOfEmails],
262
+ types: [View.View, Table.Table, TestSchema.Person, TestSchema.Organization, ContactWithArrayOfEmails],
293
263
  createIdentity: true,
294
264
  createSpace: true,
295
- onSpaceCreated: async ({ client, space }) => {
296
- const table = space.db.add(Obj.make(TableType, {}));
297
- await initializeTable({ client, space, table, typename: ContactWithArrayOfEmails.typename });
265
+ onCreateSpace: async ({ space }) => {
266
+ const { view, jsonSchema } = await ViewModel.makeFromDatabase({
267
+ db: space.db,
268
+ typename: ContactWithArrayOfEmails.typename,
269
+ });
270
+ const table = Table.make({ view, jsonSchema });
271
+ space.db.add(table);
298
272
 
299
- const factory = createObjectFactory(space.db, faker as any);
273
+ const factory = createObjectFactory(space.db, random as any);
300
274
  await factory([
301
- // { type: Testing.Contact, count: 10 },
302
- // { type: Testing.Organization, count: 1 },
275
+ // { type: TestSchema.Person, count: 10 },
276
+ // { type: TestSchema.Organization, count: 1 },
303
277
  { type: ContactWithArrayOfEmails, count: 10 },
304
278
  ]);
305
279
  },
306
280
  }),
307
- withLayout({ fullscreen: true }),
308
- withTheme,
309
281
  ],
282
+ parameters: {
283
+ layout: 'fullscreen',
284
+ translations,
285
+ },
310
286
  };
311
287
 
312
- export const Tags: Meta<StoryProps> = {
288
+ export const Tags: Meta<DefaultStoryProps> = {
313
289
  title: 'ui/react-ui-table/Table',
314
290
  render: DefaultStory,
315
- parameters: { translations },
316
291
  decorators: [
317
292
  withClientProvider({
318
- types: [TableType, ViewType],
293
+ types: [View.View, Table.Table],
319
294
  createIdentity: true,
320
295
  createSpace: true,
321
- onSpaceCreated: async ({ client, space }) => {
296
+ onCreateSpace: async ({ space }) => {
322
297
  // Configure schema.
323
- const typename = 'example.com/SingleSelect';
298
+ const typename = 'com.example.type.single-select';
324
299
  const selectOptions = [
325
300
  { id: 'one', title: 'One', color: 'emerald' },
326
301
  { id: 'two', title: 'Two', color: 'blue' },
@@ -334,33 +309,36 @@ export const Tags: Meta<StoryProps> = {
334
309
  const schema = getSchemaFromPropertyDefinitions(typename, [
335
310
  {
336
311
  name: 'single',
337
- format: FormatEnum.SingleSelect,
312
+ format: Format.TypeFormat.SingleSelect,
338
313
  config: { options: selectOptions },
339
314
  },
340
315
  {
341
316
  name: 'multiple',
342
- format: FormatEnum.MultiSelect,
317
+ format: Format.TypeFormat.MultiSelect,
343
318
  config: { options: selectOptions },
344
319
  },
345
320
  ]);
346
321
  const [storedSchema] = await space.db.schemaRegistry.register([schema]);
347
322
 
348
323
  // Initialize table.
349
- const table = space.db.add(Obj.make(TableType, {}));
350
- await initializeTable({ client, space, table, initialRow: false, typename });
324
+ const { view, jsonSchema } = await ViewModel.makeFromDatabase({ db: space.db, typename });
325
+ const table = Table.make({ view, jsonSchema });
326
+ space.db.add(table);
351
327
 
352
328
  // Populate.
353
329
  Array.from({ length: 10 }).map(() => {
354
330
  return space.db.add(
355
- live(storedSchema, {
356
- single: faker.helpers.arrayElement([...selectOptionIds, undefined]),
357
- multiple: faker.helpers.randomSubset(selectOptionIds),
331
+ Obj.make(storedSchema, {
332
+ single: random.helpers.arrayElement([...selectOptionIds, undefined]),
333
+ multiple: random.helpers.randomSubset(selectOptionIds),
358
334
  }),
359
335
  );
360
336
  });
361
337
  },
362
338
  }),
363
- withLayout({ fullscreen: true }),
364
- withTheme,
365
339
  ],
340
+ parameters: {
341
+ layout: 'fullscreen',
342
+ translations,
343
+ },
366
344
  };