@dxos/react-ui-table 0.8.4-main.406dc2a → 0.8.4-main.422d1c7879

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 (148) 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-G5EDJPD2.mjs +1751 -0
  4. package/dist/lib/browser/chunk-G5EDJPD2.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +1191 -1033
  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 +32 -44
  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-SIRDIPHZ.mjs +71 -0
  12. package/dist/lib/node-esm/chunk-SIRDIPHZ.mjs.map +7 -0
  13. package/dist/lib/node-esm/chunk-ZZ3SYTIL.mjs +1753 -0
  14. package/dist/lib/node-esm/chunk-ZZ3SYTIL.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +1191 -1033
  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 +32 -44
  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 +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 +21 -37
  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 +84 -81
  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 +20 -21
  33. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  34. package/dist/types/src/components/Table/Table.stories.d.ts +92 -26
  35. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  36. package/dist/types/src/components/Table/TableContent.d.ts +17 -0
  37. package/dist/types/src/components/Table/TableContent.d.ts.map +1 -0
  38. package/dist/types/src/components/Table/TableToolbar.d.ts +21 -0
  39. package/dist/types/src/components/Table/TableToolbar.d.ts.map +1 -0
  40. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +1 -1
  41. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +10 -12
  42. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  43. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +5 -7
  44. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  45. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +24 -26
  46. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  47. package/dist/types/src/components/index.d.ts +0 -1
  48. package/dist/types/src/components/index.d.ts.map +1 -1
  49. package/dist/types/src/components/testing.d.ts +22 -15
  50. package/dist/types/src/components/testing.d.ts.map +1 -1
  51. package/dist/types/src/hooks/index.d.ts +2 -1
  52. package/dist/types/src/hooks/index.d.ts.map +1 -1
  53. package/dist/types/src/hooks/useAddRow.d.ts +5 -6
  54. package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
  55. package/dist/types/src/hooks/useProjectionModel.d.ts +6 -0
  56. package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -0
  57. package/dist/types/src/hooks/useTableModel.d.ts +9 -9
  58. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  59. package/dist/types/src/model/modal-controller.d.ts +5 -1
  60. package/dist/types/src/model/modal-controller.d.ts.map +1 -1
  61. package/dist/types/src/model/selection-model.d.ts +17 -8
  62. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  63. package/dist/types/src/model/table-model.d.ts +105 -25
  64. package/dist/types/src/model/table-model.d.ts.map +1 -1
  65. package/dist/types/src/model/table-presentation.d.ts +3 -1
  66. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  67. package/dist/types/src/playwright/TableManager.d.ts +2 -1
  68. package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
  69. package/dist/types/src/testing/useTestTableModel.d.ts +18 -15
  70. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
  71. package/dist/types/src/translations.d.ts +21 -23
  72. package/dist/types/src/translations.d.ts.map +1 -1
  73. package/dist/types/src/types/Table.d.ts +26 -0
  74. package/dist/types/src/types/Table.d.ts.map +1 -0
  75. package/dist/types/src/types/index.d.ts +1 -1
  76. package/dist/types/src/types/index.d.ts.map +1 -1
  77. package/dist/types/src/util/dynamic-table.d.ts +14 -11
  78. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  79. package/dist/types/src/util/dynamic-table.test.d.ts +2 -0
  80. package/dist/types/src/util/dynamic-table.test.d.ts.map +1 -0
  81. package/dist/types/src/util/index.d.ts +2 -0
  82. package/dist/types/src/util/index.d.ts.map +1 -1
  83. package/dist/types/src/util/query-ast.d.ts +7 -0
  84. package/dist/types/src/util/query-ast.d.ts.map +1 -0
  85. package/dist/types/src/util/sort.d.ts +12 -0
  86. package/dist/types/src/util/sort.d.ts.map +1 -0
  87. package/dist/types/tsconfig.tsbuildinfo +1 -1
  88. package/package.json +55 -68
  89. package/src/components/Table/ColumnActionsMenu.tsx +15 -11
  90. package/src/components/Table/ColumnSettings.tsx +8 -9
  91. package/src/components/Table/DynamicTable.stories.tsx +27 -28
  92. package/src/components/Table/DynamicTable.tsx +32 -32
  93. package/src/components/Table/Relations.stories.tsx +110 -78
  94. package/src/components/Table/RowActionsMenu.tsx +24 -15
  95. package/src/components/Table/Table.stories.tsx +121 -107
  96. package/src/components/Table/Table.tsx +43 -407
  97. package/src/components/Table/TableContent.tsx +421 -0
  98. package/src/components/Table/TableToolbar.tsx +111 -0
  99. package/src/components/TableCellEditor/CellValidationMessage.tsx +5 -5
  100. package/src/components/TableCellEditor/FormCellEditor.tsx +117 -134
  101. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +24 -20
  102. package/src/components/TableCellEditor/TableCellEditor.tsx +35 -33
  103. package/src/components/index.ts +0 -1
  104. package/src/components/testing.ts +43 -17
  105. package/src/hooks/index.ts +2 -1
  106. package/src/hooks/useAddRow.ts +8 -10
  107. package/src/hooks/useProjectionModel.ts +39 -0
  108. package/src/hooks/useTableModel.ts +36 -34
  109. package/src/model/modal-controller.ts +23 -12
  110. package/src/model/selection-model.ts +75 -44
  111. package/src/model/table-model.test.ts +82 -55
  112. package/src/model/table-model.ts +436 -170
  113. package/src/model/table-presentation.test.ts +59 -50
  114. package/src/model/table-presentation.ts +43 -38
  115. package/src/playwright/TableManager.ts +13 -6
  116. package/src/playwright/playwright.config.ts +1 -1
  117. package/src/playwright/smoke.spec.ts +59 -13
  118. package/src/testing/useTestTableModel.ts +48 -41
  119. package/src/translations.ts +20 -22
  120. package/src/types/Table.ts +79 -0
  121. package/src/types/index.ts +1 -1
  122. package/src/util/dynamic-table.test.ts +70 -0
  123. package/src/util/dynamic-table.ts +41 -28
  124. package/src/util/index.ts +2 -0
  125. package/src/util/query-ast.ts +22 -0
  126. package/src/util/sort.ts +90 -0
  127. package/src/util/table-buttons.ts +1 -1
  128. package/src/util/table-controls.ts +2 -2
  129. package/dist/lib/browser/chunk-4K7JPALT.mjs +0 -66
  130. package/dist/lib/browser/chunk-4K7JPALT.mjs.map +0 -7
  131. package/dist/lib/browser/chunk-OZTXLZGM.mjs +0 -1804
  132. package/dist/lib/browser/chunk-OZTXLZGM.mjs.map +0 -7
  133. package/dist/lib/node-esm/chunk-MK6OVUF6.mjs +0 -67
  134. package/dist/lib/node-esm/chunk-MK6OVUF6.mjs.map +0 -7
  135. package/dist/lib/node-esm/chunk-S56Z4V4X.mjs +0 -1805
  136. package/dist/lib/node-esm/chunk-S56Z4V4X.mjs.map +0 -7
  137. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +0 -21
  138. package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +0 -1
  139. package/dist/types/src/components/TableToolbar/index.d.ts +0 -2
  140. package/dist/types/src/components/TableToolbar/index.d.ts.map +0 -1
  141. package/dist/types/src/model/table-sorting.d.ts +0 -52
  142. package/dist/types/src/model/table-sorting.d.ts.map +0 -1
  143. package/dist/types/src/types/schema.d.ts +0 -28
  144. package/dist/types/src/types/schema.d.ts.map +0 -1
  145. package/src/components/TableToolbar/TableToolbar.tsx +0 -102
  146. package/src/components/TableToolbar/index.ts +0 -5
  147. package/src/model/table-sorting.ts +0 -225
  148. package/src/types/schema.ts +0 -73
@@ -2,545 +2,668 @@ import {
2
2
  BUTTON_IDENTIFIERS,
3
3
  CONTROL_IDENTIFIERS,
4
4
  CheckboxStory,
5
- ModalController,
6
5
  SwitchStory,
7
6
  TableModel,
8
7
  TablePresentation,
9
8
  cellClassesForRowSelection,
10
- getBaseSchema,
11
- makeDynamicTable,
12
- narrowSchema,
9
+ compareValues,
10
+ createDirectChangeCallback,
11
+ createEchoChangeCallback,
12
+ extractOrder,
13
+ getSortValue,
13
14
  tableButtons,
14
15
  tableControls,
15
- touch,
16
16
  useAddRow,
17
+ useProjectionModel,
17
18
  useTableModel
18
- } from "./chunk-OZTXLZGM.mjs";
19
- import "./chunk-4K7JPALT.mjs";
19
+ } from "./chunk-G5EDJPD2.mjs";
20
+ import {
21
+ Table_exports
22
+ } from "./chunk-BF54SSNL.mjs";
20
23
 
21
24
  // src/translations.ts
22
- var translationKey = "react-ui-table";
25
+ var translationKey = "@dxos/react-ui-table";
23
26
  var translations = [
24
27
  {
25
28
  "en-US": {
26
29
  [translationKey]: {
27
- "object placeholder": "New table",
28
- "create object label": "Create table",
29
- "table name placeholder": "Table name",
30
- "settings title": "Table settings",
31
- "table schema label": "Record type",
32
- "new schema": "New record type",
33
- "continue label": "Continue",
34
- "create stack section label": "Create table",
35
- "add row label": "Add row",
36
- "create comment": "Create thread",
37
- "column action sort descending": "Sort Descending",
38
- "column action sort ascending": "Sort Ascending",
39
- "column action clear sorting": "Clear Sorting",
40
- "column action settings": "Column Settings",
41
- "column action delete": "Delete Column",
42
- "delete row label": "Delete row",
43
- "bulk delete row label": "Delete selected rows",
44
- "column deleted label": "Column deleted",
45
- "new column button label": "Create column",
46
- "create new object label": "Create new object \u201C{{text}}\u201D",
47
- "save view label": "Save changes to view"
30
+ "object.placeholder": "New table",
31
+ "create-object.label": "Create table",
32
+ "table-name.placeholder": "Table name",
33
+ "settings.title": "Table settings",
34
+ "table-schema.label": "Type",
35
+ "continue.label": "Continue",
36
+ "create-stack-section.label": "Create table",
37
+ "add-row.label": "Add row",
38
+ "column-action-sort-descending.menu": "Sort Descending",
39
+ "column-action-sort-ascending.menu": "Sort Ascending",
40
+ "column-action-clear-sorting.menu": "Clear Sorting",
41
+ "column-action-settings.menu": "Column Settings",
42
+ "column-action-delete.menu": "Delete Column",
43
+ "delete-row.label": "Delete row",
44
+ "bulk-delete-row.label": "Delete selected rows",
45
+ "column-deleted.label": "Column deleted",
46
+ "new-column-button.label": "Create column",
47
+ "create-new-object.label": "Create new object \u201C{{text}}\u201D",
48
+ "save-view.label": "Save changes to view"
48
49
  }
49
50
  }
50
51
  }
51
52
  ];
52
53
 
53
54
  // src/components/Table/Table.tsx
54
- import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
55
+ import { Atom as Atom4 } from "@effect-atom/atom-react";
56
+ import { createContext } from "@radix-ui/react-context";
57
+ import React9, { forwardRef, useImperativeHandle, useRef as useRef3 } from "react";
58
+
59
+ // src/components/Table/TableContent.tsx
60
+ import { Atom as Atom2, RegistryContext, useAtomValue as useAtomValue4 } from "@effect-atom/atom-react";
55
61
  import * as String2 from "effect/String";
56
- import React7, { forwardRef, useCallback as useCallback4, useEffect as useEffect3, useImperativeHandle, useMemo as useMemo4, useState as useState4 } from "react";
62
+ import React7, { useCallback as useCallback4, useContext, useEffect as useEffect3, useMemo as useMemo4, useState as useState4 } from "react";
63
+ import { log } from "@dxos/log";
57
64
  import { useAttention } from "@dxos/react-ui-attention";
58
65
  import { Grid, closestCell, gridSeparatorBlockEnd, gridSeparatorInlineEnd } from "@dxos/react-ui-grid";
59
66
  import { DxEditRequest } from "@dxos/react-ui-grid";
60
- import { mx } from "@dxos/react-ui-theme";
67
+ import { composable, composableProps, mx } from "@dxos/ui-theme";
68
+
69
+ // src/util/dynamic-table.ts
70
+ import { Filter, JsonSchema, Obj, Order, Query, Ref, Type } from "@dxos/echo";
71
+ import { ProjectionModel, ViewModel, createEchoChangeCallback as createEchoChangeCallback2, getSchemaFromPropertyDefinitions } from "@dxos/schema";
72
+ var getBaseSchema = ({ schema, typename, properties, jsonSchema }) => {
73
+ if (typename && properties) {
74
+ const schema2 = getSchemaFromPropertyDefinitions(typename, properties);
75
+ return {
76
+ typename: schema2.typename,
77
+ jsonSchema: JsonSchema.toJsonSchema(schema2)
78
+ };
79
+ } else if (schema) {
80
+ return {
81
+ typename: Type.getTypename(schema),
82
+ jsonSchema: JsonSchema.toJsonSchema(schema)
83
+ };
84
+ } else if (typename && jsonSchema) {
85
+ return {
86
+ typename,
87
+ jsonSchema
88
+ };
89
+ } else {
90
+ throw new Error("invalid properties");
91
+ }
92
+ };
93
+ var makeDynamicTable = ({ registry, jsonSchema, properties }) => {
94
+ const view = ViewModel.make({
95
+ query: Query.select(Filter.everything()),
96
+ jsonSchema,
97
+ ...properties && {
98
+ fields: properties.map((property) => property.name)
99
+ }
100
+ });
101
+ const object = Obj.make(Table_exports.Table, {
102
+ view: Ref.make(view),
103
+ sizes: {}
104
+ });
105
+ const projection = new ProjectionModel({
106
+ registry,
107
+ view,
108
+ baseSchema: jsonSchema,
109
+ change: createEchoChangeCallback2(view, jsonSchema)
110
+ });
111
+ projection.normalizeView();
112
+ if (properties && projection.getFields()) {
113
+ setProperties(view, projection, object, properties);
114
+ }
115
+ return {
116
+ projection,
117
+ object
118
+ };
119
+ };
120
+ var setProperties = (view, projection, table, properties) => {
121
+ for (const property of properties) {
122
+ const field = projection.getFields().find((field2) => field2.path === property.name);
123
+ if (field) {
124
+ if (property.size !== void 0) {
125
+ Obj.change(table, (table2) => {
126
+ table2.sizes[field.path] = property.size;
127
+ });
128
+ }
129
+ if (property.title !== void 0) {
130
+ const fieldProjection = projection.getFieldProjection(field.id);
131
+ projection.setFieldProjection({
132
+ ...fieldProjection,
133
+ props: {
134
+ ...fieldProjection.props,
135
+ title: property.title
136
+ }
137
+ });
138
+ }
139
+ if (property.sort) {
140
+ const currentQuery = Query.fromAst(Obj.getSnapshot(view).query.ast);
141
+ const newQuery = currentQuery.orderBy(Order.property(field.path, property.sort));
142
+ Obj.change(view, (view2) => {
143
+ view2.query.ast = newQuery.ast;
144
+ });
145
+ }
146
+ }
147
+ }
148
+ };
149
+
150
+ // src/util/signals.ts
151
+ var touch = (value) => value;
152
+
153
+ // src/util/schema.ts
154
+ import * as Schema from "effect/Schema";
155
+ import * as SchemaAST from "effect/SchemaAST";
156
+ var narrowSchema = (schema, paths) => {
157
+ const ast = schema?.ast;
158
+ if (SchemaAST.isTypeLiteral(ast)) {
159
+ const propertySignatures = ast.propertySignatures.filter((signature) => paths.includes(signature.name.toString()));
160
+ if (propertySignatures.length > 0) {
161
+ const narrowType = new SchemaAST.TypeLiteral(propertySignatures, []);
162
+ return Schema.make(narrowType);
163
+ }
164
+ }
165
+ return void 0;
166
+ };
167
+
168
+ // src/model/modal-controller.ts
169
+ import { Atom } from "@effect-atom/atom-react";
170
+ var ModalController = class {
171
+ _registry;
172
+ _state;
173
+ _triggerRef = {
174
+ current: null
175
+ };
176
+ constructor(registry) {
177
+ this._registry = registry;
178
+ this._state = Atom.make({
179
+ type: "closed"
180
+ });
181
+ }
182
+ get state() {
183
+ return this._state;
184
+ }
185
+ get stateValue() {
186
+ return this._registry.get(this._state);
187
+ }
188
+ get trigger() {
189
+ return this._triggerRef;
190
+ }
191
+ setTrigger = (trigger) => {
192
+ this._triggerRef.current = trigger;
193
+ };
194
+ showRowMenu = (rowIndex) => {
195
+ this._registry.set(this._state, {
196
+ type: "row",
197
+ rowIndex
198
+ });
199
+ };
200
+ showColumnMenu = (fieldId) => {
201
+ this._registry.set(this._state, {
202
+ type: "column",
203
+ fieldId
204
+ });
205
+ };
206
+ showColumnCreator = () => {
207
+ this._registry.set(this._state, {
208
+ type: "columnSettings",
209
+ mode: {
210
+ type: "create"
211
+ }
212
+ });
213
+ };
214
+ showReferencePanel = (targetId, schemaId) => {
215
+ this._registry.set(this._state, {
216
+ type: "refPanel",
217
+ targetId,
218
+ typename: schemaId
219
+ });
220
+ };
221
+ openColumnSettings = () => {
222
+ const currentState = this._registry.get(this._state);
223
+ if (currentState.type === "column") {
224
+ const fieldId = currentState.fieldId;
225
+ requestAnimationFrame(() => {
226
+ this._registry.set(this._state, {
227
+ type: "columnSettings",
228
+ mode: {
229
+ type: "edit",
230
+ fieldId
231
+ }
232
+ });
233
+ });
234
+ }
235
+ };
236
+ close = () => {
237
+ this._registry.set(this._state, {
238
+ type: "closed"
239
+ });
240
+ };
241
+ };
61
242
 
62
243
  // src/components/TableCellEditor/TableCellEditor.tsx
63
- import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
64
244
  import { EditorView } from "@codemirror/view";
65
245
  import React3, { useCallback as useCallback2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
66
246
  import { debounce } from "@dxos/async";
67
- import { FormatEnum as FormatEnum2, TypeEnum } from "@dxos/echo/internal";
247
+ import { Format, TypeEnum } from "@dxos/echo/internal";
68
248
  import { invariant as invariant2 } from "@dxos/invariant";
69
249
  import { GridCellEditor, editorKeys, parseCellIndex as parseCellIndex2, useGridContext as useGridContext3 } from "@dxos/react-ui-grid";
70
250
 
71
251
  // src/components/TableCellEditor/CellValidationMessage.tsx
72
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
73
252
  import React from "react";
74
253
  import { useGridContext } from "@dxos/react-ui-grid";
75
- var CellValidationMessage = ({ validationError, variant = "error", __gridScope }) => {
76
- var _effect = _useSignals();
77
- try {
78
- const { editing, editBox: box } = useGridContext("GridSheetCellEditor", __gridScope);
79
- if (!editing || !validationError) {
80
- return null;
81
- }
82
- const bgClass = variant === "error" ? "bg-errorSurface" : "bg-warningSurface";
83
- const textClass = variant === "error" ? "text-errorSurfaceText" : "text-warningSurfaceText";
84
- return /* @__PURE__ */ React.createElement("div", {
85
- role: "none",
86
- className: `absolute ${bgClass} ${textClass} rounded-bs-sm text-xs p-1`,
87
- style: {
88
- ...{
89
- "--dx-gridCellWidth": `${box?.inlineSize ?? 200}px`
90
- },
91
- zIndex: 10,
92
- insetBlockEnd: `calc(100% - ${box.insetBlockStart}px)`,
93
- insetInlineStart: box.insetInlineStart,
94
- inlineSize: box.inlineSize
95
- }
96
- }, validationError);
97
- } finally {
98
- _effect.f();
254
+ var CellValidationMessage = ({ __gridScope, validationError, variant = "error" }) => {
255
+ const { editing, editBox: box } = useGridContext("GridSheetCellEditor", __gridScope);
256
+ if (!editing || !validationError) {
257
+ return null;
99
258
  }
259
+ const bgClass = variant === "error" ? "bg-error-surface" : "bg-warning-surface";
260
+ const textClass = variant === "error" ? "text-error-surface-text" : "text-warning-surface-text";
261
+ return /* @__PURE__ */ React.createElement("div", {
262
+ role: "none",
263
+ className: `absolute ${bgClass} ${textClass} rounded-h-sm text-xs p-1`,
264
+ style: {
265
+ ...{
266
+ "--dx-grid-cell-width": `${box?.inlineSize ?? 200}px`
267
+ },
268
+ zIndex: 10,
269
+ insetBlockEnd: `calc(100% - ${box.insetBlockStart}px)`,
270
+ insetInlineStart: box.insetInlineStart,
271
+ inlineSize: box.inlineSize
272
+ }
273
+ }, validationError);
100
274
  };
101
275
 
102
276
  // src/components/TableCellEditor/FormCellEditor.tsx
103
- import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
104
- import * as Schema from "effect/Schema";
105
277
  import React2, { useCallback, useEffect, useMemo, useRef, useState } from "react";
106
- import { Filter, Obj } from "@dxos/echo";
107
- import { FormatEnum, Ref, getValue } from "@dxos/echo/internal";
278
+ import { Entity } from "@dxos/echo";
279
+ import { Ref as Ref2, getValue } from "@dxos/echo/internal";
108
280
  import { invariant } from "@dxos/invariant";
109
- import { getSnapshot } from "@dxos/live-object";
110
- import { getSpace } from "@dxos/react-client/echo";
111
281
  import { Popover } from "@dxos/react-ui";
112
282
  import { Form } from "@dxos/react-ui-form";
113
283
  import { parseCellIndex, useGridContext as useGridContext2 } from "@dxos/react-ui-grid";
114
284
  import { getDeep, isTruthy, setDeep } from "@dxos/util";
115
285
  var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
116
286
  var createOptionLabel = [
117
- "create new object label",
287
+ "create-new-object.label",
118
288
  {
119
289
  ns: translationKey
120
290
  }
121
291
  ];
122
- var FormCellEditor = ({ fieldProjection, model, schema, onSave, client, modals, onCreate, __gridScope, ...formProps }) => {
123
- var _effect = _useSignals2();
124
- try {
125
- const { editing: contextEditing, setEditing, id: gridId } = useGridContext2("ArrayEditor", __gridScope);
126
- const [editing, setLocalEditing] = useState(false);
127
- const anchorRef = useRef(null);
128
- const getSchema = useCallback((typeAnnotation) => {
129
- const space = getSpace(model.view);
130
- invariant(space, void 0, {
131
- F: __dxlog_file,
132
- L: 57,
133
- S: void 0,
134
- A: [
135
- "space",
136
- ""
137
- ]
138
- });
139
- let schema2;
140
- if (client) {
141
- schema2 = client.graph.schemaRegistry.getSchema(typeAnnotation.typename);
142
- }
143
- if (!schema2) {
144
- schema2 = space.db.schemaRegistry.getSchema(typeAnnotation.typename);
145
- }
146
- return {
147
- space,
148
- schema: schema2
149
- };
150
- }, [
151
- client,
152
- model
153
- ]);
154
- const handleQueryRefOptions = useCallback(async (typeAnnotation) => {
155
- const { schema: schema2, space } = getSchema(typeAnnotation);
156
- if (model && schema2 && space) {
157
- const { objects } = await space.db.query(Filter.type(schema2)).run();
158
- return objects.map((obj) => {
159
- return {
160
- dxn: Obj.getDXN(obj),
161
- label: getValue(obj, fieldProjection.field.referencePath) || obj.id.toString()
162
- };
163
- }).filter(isTruthy);
164
- }
165
- return [];
166
- }, [
167
- client,
168
- model
169
- ]);
170
- const originalRow = useMemo(() => {
171
- if (model && contextEditing) {
172
- const cell = parseCellIndex(contextEditing.index);
173
- if (model.isDraftCell(cell)) {
174
- const draftRow = model.draftRows.value[cell.row];
175
- invariant(draftRow, void 0, {
176
- F: __dxlog_file,
177
- L: 98,
178
- S: void 0,
179
- A: [
180
- "draftRow",
181
- ""
182
- ]
183
- });
184
- return draftRow.data;
185
- } else {
186
- const row = model.getRowAt(cell.row);
187
- invariant(row, void 0, {
188
- F: __dxlog_file,
189
- L: 102,
190
- S: void 0,
191
- A: [
192
- "row",
193
- ""
194
- ]
195
- });
196
- return row;
197
- }
198
- }
199
- return void 0;
200
- }, [
201
- model,
202
- contextEditing
203
- ]);
204
- const handleSave = useCallback((values) => {
205
- const path = fieldProjection.field.path;
206
- const value = getDeep(values, [
207
- path
208
- ]);
209
- setDeep(originalRow, [
210
- path
211
- ], value);
212
- contextEditing?.cellElement?.focus();
213
- setEditing(null);
292
+ var FormCellEditor = ({ __gridScope, schema, model, fieldProjection, onSave, onCreate, ...formProps }) => {
293
+ const anchorRef = useRef(null);
294
+ const { id: _gridId, editing: contextEditing, setEditing } = useGridContext2("ArrayEditor", __gridScope);
295
+ const [editing, setLocalEditing] = useState(false);
296
+ useEffect(() => {
297
+ if (contextEditing && contextEditing.cellElement) {
298
+ anchorRef.current = contextEditing.cellElement.querySelector(".dx-grid__cell__content");
299
+ setLocalEditing(true);
300
+ } else {
301
+ anchorRef.current = null;
214
302
  setLocalEditing(false);
215
- onSave?.();
216
- }, [
217
- fieldProjection.field.path,
218
- onSave,
219
- contextEditing,
220
- originalRow
221
- ]);
222
- useEffect(() => {
223
- if (contextEditing && contextEditing.cellElement) {
224
- anchorRef.current = contextEditing.cellElement.querySelector(".dx-grid__cell__content");
225
- setLocalEditing(true);
226
- } else {
227
- anchorRef.current = null;
228
- setLocalEditing(false);
229
- }
230
- }, [
231
- contextEditing
232
- ]);
233
- const narrowedSchema = useMemo(() => {
234
- if (!schema) {
235
- return void 0;
236
- }
237
- return narrowSchema(schema, [
238
- fieldProjection.field.path
239
- ]);
240
- }, [
241
- JSON.stringify(schema),
303
+ }
304
+ }, [
305
+ contextEditing
306
+ ]);
307
+ const narrowedSchema = useMemo(() => {
308
+ if (!schema) {
309
+ return void 0;
310
+ }
311
+ return narrowSchema(schema, [
242
312
  fieldProjection.field.path
243
313
  ]);
244
- const formValues = useMemo(() => originalRow ? getSnapshot(originalRow) : {}, [
245
- originalRow
246
- ]);
247
- const handleOpenChange = useCallback((nextOpen) => {
248
- if (nextOpen === false) {
249
- setEditing(null);
250
- onSave?.();
251
- }
252
- setLocalEditing(nextOpen);
253
- }, []);
254
- const createSchema = useMemo(() => {
255
- if (fieldProjection.props.format === FormatEnum.Ref && fieldProjection.props.referenceSchema) {
256
- const { schema: refSchema } = getSchema({
257
- typename: fieldProjection.props.referenceSchema
314
+ }, [
315
+ JSON.stringify(schema),
316
+ fieldProjection.field.path
317
+ ]);
318
+ const originalRow = useMemo(() => {
319
+ if (model && contextEditing) {
320
+ const cell = parseCellIndex(contextEditing.index);
321
+ if (model.isDraftCell(cell)) {
322
+ const draftRow = model.getDraftRows()[cell.row];
323
+ invariant(draftRow, void 0, {
324
+ F: __dxlog_file,
325
+ L: 74,
326
+ S: void 0,
327
+ A: [
328
+ "draftRow",
329
+ ""
330
+ ]
258
331
  });
259
- if (!refSchema) {
260
- return null;
261
- }
262
- const omit2 = Schema.omit("id");
263
- return omit2(refSchema);
264
- }
265
- return null;
266
- }, [
267
- fieldProjection.props.format,
268
- fieldProjection.props.referenceSchema,
269
- getSchema
270
- ]);
271
- const handleCreate = useCallback((values) => {
272
- if (schema && onCreate) {
273
- const objectWithId = onCreate(schema, values);
274
- if (objectWithId) {
275
- const ref = Ref.make(objectWithId);
276
- const path = fieldProjection.field.path;
277
- setDeep(originalRow, [
278
- path
279
- ], ref);
280
- }
332
+ return draftRow.data;
333
+ } else {
334
+ const row = model.getRowAt(cell.row);
335
+ invariant(row, void 0, {
336
+ F: __dxlog_file,
337
+ L: 78,
338
+ S: void 0,
339
+ A: [
340
+ "row",
341
+ ""
342
+ ]
343
+ });
344
+ return row;
281
345
  }
282
- contextEditing?.cellElement?.focus();
346
+ }
347
+ return void 0;
348
+ }, [
349
+ model,
350
+ contextEditing
351
+ ]);
352
+ const initialFormValues = useMemo(() => originalRow ? JSON.parse(JSON.stringify(originalRow)) : {}, [
353
+ originalRow
354
+ ]);
355
+ const [formValues, setFormValues] = useState(initialFormValues);
356
+ const handleValuesChanged = useCallback((values) => {
357
+ setFormValues(values);
358
+ }, []);
359
+ const handleOpenChange = useCallback((nextOpen) => {
360
+ if (nextOpen === false) {
283
361
  setEditing(null);
284
- setLocalEditing(false);
285
362
  onSave?.();
286
- }, [
287
- fieldProjection.field.path,
288
- onSave,
289
- contextEditing,
290
- originalRow,
291
- createSchema,
292
- onCreate
363
+ }
364
+ setLocalEditing(nextOpen);
365
+ }, []);
366
+ const handleSave = useCallback((values) => {
367
+ if (!originalRow) {
368
+ return;
369
+ }
370
+ const path = fieldProjection.field.path;
371
+ const value = getDeep(values, [
372
+ path
293
373
  ]);
294
- if (!editing) {
295
- return null;
374
+ if (model) {
375
+ model.changeRow(originalRow, (mutableRow) => {
376
+ setDeep(mutableRow, [
377
+ path
378
+ ], value);
379
+ });
380
+ } else {
381
+ setDeep(originalRow, [
382
+ path
383
+ ], value);
296
384
  }
297
- return /* @__PURE__ */ React2.createElement(Popover.Root, {
298
- open: editing,
299
- onOpenChange: handleOpenChange
300
- }, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
301
- virtualRef: anchorRef
302
- }), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
303
- tabIndex: -1,
304
- classNames: "popover-card-width density-fine"
305
- }, /* @__PURE__ */ React2.createElement(Popover.Arrow, null), /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(Form, {
306
- autoFocus: true,
307
- values: formValues,
308
- schema: narrowedSchema,
309
- onSave: handleSave,
310
- ...formProps,
311
- onQueryRefOptions: handleQueryRefOptions,
312
- ...createSchema && {
313
- onCreate: handleCreate,
314
- createSchema,
315
- createInitialValuePath: fieldProjection.field.referencePath,
316
- createOptionIcon: "ph--plus--regular",
317
- createOptionLabel
385
+ contextEditing?.cellElement?.focus();
386
+ setEditing(null);
387
+ setLocalEditing(false);
388
+ onSave?.();
389
+ }, [
390
+ fieldProjection.field.path,
391
+ onSave,
392
+ contextEditing,
393
+ originalRow,
394
+ model
395
+ ]);
396
+ const handleCreate = useCallback((schema2, values) => {
397
+ const objectWithId = onCreate?.(schema2, values);
398
+ if (objectWithId && originalRow) {
399
+ const ref = Ref2.make(objectWithId);
400
+ const path = fieldProjection.field.path;
401
+ if (model) {
402
+ model.changeRow(originalRow, (mutableRow) => {
403
+ setDeep(mutableRow, [
404
+ path
405
+ ], ref);
406
+ });
407
+ } else {
408
+ setDeep(originalRow, [
409
+ path
410
+ ], ref);
318
411
  }
319
- })))));
320
- } finally {
321
- _effect.f();
412
+ }
413
+ contextEditing?.cellElement?.focus();
414
+ setEditing(null);
415
+ setLocalEditing(false);
416
+ onSave?.();
417
+ }, [
418
+ fieldProjection.field.path,
419
+ onSave,
420
+ contextEditing,
421
+ originalRow,
422
+ onCreate,
423
+ model
424
+ ]);
425
+ const getOptions = useCallback((results) => results.map((obj) => {
426
+ return {
427
+ id: Entity.getDXN(obj).toString(),
428
+ label: getValue(obj, fieldProjection.field.referencePath) || obj.id.toString()
429
+ };
430
+ }).filter(isTruthy), [
431
+ fieldProjection
432
+ ]);
433
+ if (!editing) {
434
+ return null;
322
435
  }
436
+ return /* @__PURE__ */ React2.createElement(Popover.Root, {
437
+ open: editing,
438
+ onOpenChange: handleOpenChange
439
+ }, /* @__PURE__ */ React2.createElement(Popover.VirtualTrigger, {
440
+ virtualRef: anchorRef
441
+ }), /* @__PURE__ */ React2.createElement(Popover.Portal, null, /* @__PURE__ */ React2.createElement(Popover.Content, {
442
+ tabIndex: -1,
443
+ classNames: "dx-card-popover-width dx-density-fine"
444
+ }, /* @__PURE__ */ React2.createElement(Popover.Arrow, null), /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(Form.Root, {
445
+ ...formProps,
446
+ autoFocus: true,
447
+ schema: narrowedSchema,
448
+ values: formValues,
449
+ onValuesChanged: handleValuesChanged,
450
+ projection: model?.projection,
451
+ createInitialValuePath: fieldProjection.field.referencePath,
452
+ createOptionIcon: "ph--plus--regular",
453
+ createOptionLabel,
454
+ db: model?.db,
455
+ getOptions,
456
+ onCreate: handleCreate,
457
+ onSave: handleSave
458
+ }, /* @__PURE__ */ React2.createElement(Form.Viewport, null, /* @__PURE__ */ React2.createElement(Form.Content, null, /* @__PURE__ */ React2.createElement(Form.FieldSet, null), /* @__PURE__ */ React2.createElement(Form.Actions, null))))))));
323
459
  };
324
460
 
325
461
  // src/components/TableCellEditor/TableCellEditor.tsx
326
462
  var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
327
- var adaptValidationMessage = (message) => message ? message.endsWith("is missing") ? "Can\u2019t be blank" : message : null;
328
- var TableValueEditor = ({ model, modals, schema, onFocus, onSave, onCreate, client, __gridScope }) => {
329
- var _effect = _useSignals3();
330
- try {
331
- const { editing } = useGridContext3("TableValueEditor", __gridScope);
332
- const fieldProjection = useMemo2(() => {
333
- if (!model || !editing) {
334
- return;
335
- }
336
- const { col } = parseCellIndex2(editing.index);
337
- const field = model.projection.fields[col];
338
- const fieldProjection2 = model.projection.getFieldProjection(field.id);
339
- invariant2(fieldProjection2, void 0, {
340
- F: __dxlog_file2,
341
- L: 71,
342
- S: void 0,
343
- A: [
344
- "fieldProjection",
345
- ""
346
- ]
347
- });
348
- return fieldProjection2;
349
- }, [
350
- model,
351
- editing
352
- ]);
353
- if (fieldProjection?.props.type === TypeEnum.Array || fieldProjection?.props.format === FormatEnum2.SingleSelect || fieldProjection?.props.format === FormatEnum2.Ref) {
354
- return /* @__PURE__ */ React3.createElement(FormCellEditor, {
355
- fieldProjection,
356
- model,
357
- schema,
358
- __gridScope,
359
- onSave,
360
- onCreate,
361
- client,
362
- modals
363
- });
463
+ var TableValueEditor = ({ __gridScope, schema, model, modals, onFocus, onSave, onCreate }) => {
464
+ const { editing } = useGridContext3("TableValueEditor", __gridScope);
465
+ const fieldProjection = useMemo2(() => {
466
+ if (!model || !editing) {
467
+ return;
364
468
  }
365
- return /* @__PURE__ */ React3.createElement(TableCellEditor, {
469
+ const { col } = parseCellIndex2(editing.index);
470
+ const field = model.projection.getFields()[col];
471
+ const fieldProjection2 = model.projection.getFieldProjection(field.id);
472
+ invariant2(fieldProjection2, void 0, {
473
+ F: __dxlog_file2,
474
+ L: 66,
475
+ S: void 0,
476
+ A: [
477
+ "fieldProjection",
478
+ ""
479
+ ]
480
+ });
481
+ return fieldProjection2;
482
+ }, [
483
+ model,
484
+ editing
485
+ ]);
486
+ if (fieldProjection?.props.type === TypeEnum.Array || fieldProjection?.props.format === Format.TypeFormat.SingleSelect || fieldProjection?.props.format === Format.TypeFormat.Ref) {
487
+ return /* @__PURE__ */ React3.createElement(FormCellEditor, {
488
+ __gridScope,
489
+ schema,
366
490
  model,
491
+ fieldProjection,
367
492
  modals,
368
- onFocus,
369
493
  onSave,
370
- __gridScope
494
+ onCreate
371
495
  });
372
- } finally {
373
- _effect.f();
374
- }
375
- };
376
- var editorSlots = {
377
- scroll: {
378
- className: "!plb-[--dx-grid-cell-editor-padding-block]"
379
496
  }
497
+ return /* @__PURE__ */ React3.createElement(TableCellEditor, {
498
+ model,
499
+ modals,
500
+ onFocus,
501
+ onSave,
502
+ __gridScope
503
+ });
380
504
  };
381
- var TableCellEditor = ({ model, modals, onFocus, onSave, __gridScope }) => {
382
- var _effect = _useSignals3();
383
- try {
384
- const { editing, setEditing } = useGridContext3("TableCellEditor", __gridScope);
385
- const suppressNextBlur = useRef2(false);
386
- const [validationError, setValidationError] = useState2(null);
387
- const [validationVariant, setValidationVariant] = useState2("error");
388
- const fieldProjection = useMemo2(() => {
389
- if (!model || !editing) {
390
- return;
391
- }
392
- const { col } = parseCellIndex2(editing.index);
393
- const field = model.projection.fields[col];
394
- const fieldProjection2 = model.projection.getFieldProjection(field.id);
395
- invariant2(fieldProjection2, void 0, {
396
- F: __dxlog_file2,
397
- L: 121,
398
- S: void 0,
399
- A: [
400
- "fieldProjection",
401
- ""
402
- ]
403
- });
404
- return fieldProjection2;
405
- }, [
406
- model,
407
- editing
408
- ]);
409
- const handleEnter = useCallback2(async (value) => {
410
- if (!model || !editing) {
411
- return;
412
- }
413
- const cell = parseCellIndex2(editing.index);
414
- const validationResult = await model.validateCellData(cell, value);
415
- if (validationResult.valid) {
416
- setValidationError(null);
417
- model.setCellData(cell, value);
418
- onFocus?.();
419
- setEditing(null);
420
- onSave?.();
421
- } else {
422
- setValidationError(adaptValidationMessage(validationResult.error));
423
- setValidationVariant("error");
424
- }
425
- }, [
426
- model,
427
- editing,
428
- onFocus,
429
- setEditing
430
- ]);
431
- const handleBlur = useCallback2(async (value) => {
432
- if (suppressNextBlur.current) {
433
- suppressNextBlur.current = false;
434
- } else if (model && editing) {
435
- const cell = parseCellIndex2(editing.index);
436
- if (value !== void 0) {
437
- const result = await model.validateCellData(cell, value);
438
- if (result.valid) {
439
- setValidationError(null);
440
- model.setCellData(cell, value);
441
- setEditing(null);
442
- onSave?.();
443
- }
444
- }
445
- }
446
- }, [
447
- model,
448
- editing
449
- ]);
450
- const handleClose = useCallback2(async (value, event) => {
451
- if (!model || !editing || !fieldProjection) {
452
- return;
453
- }
505
+ var TableCellEditor = ({ __gridScope, model, modals, onFocus, onSave }) => {
506
+ const { editing, setEditing } = useGridContext3("TableCellEditor", __gridScope);
507
+ const suppressNextBlur = useRef2(false);
508
+ const [validationError, setValidationError] = useState2(null);
509
+ const [validationVariant, setValidationVariant] = useState2("error");
510
+ const fieldProjection = useMemo2(() => {
511
+ if (!model || !editing) {
512
+ return;
513
+ }
514
+ const { col } = parseCellIndex2(editing.index);
515
+ const field = model.projection.getFields()[col];
516
+ const fieldProjection2 = model.projection.getFieldProjection(field.id);
517
+ invariant2(fieldProjection2, void 0, {
518
+ F: __dxlog_file2,
519
+ L: 113,
520
+ S: void 0,
521
+ A: [
522
+ "fieldProjection",
523
+ ""
524
+ ]
525
+ });
526
+ return fieldProjection2;
527
+ }, [
528
+ model,
529
+ editing
530
+ ]);
531
+ const handleEnter = useCallback2(async (value) => {
532
+ if (!model || !editing) {
533
+ return;
534
+ }
535
+ const cell = parseCellIndex2(editing.index);
536
+ const validationResult = await model.validateCellData(cell, value);
537
+ if (validationResult.valid) {
538
+ setValidationError(null);
539
+ model.setCellData(cell, value);
540
+ onFocus?.();
541
+ setEditing(null);
542
+ onSave?.();
543
+ } else {
544
+ setValidationError(validationResult.error);
545
+ setValidationVariant("error");
546
+ }
547
+ }, [
548
+ model,
549
+ editing,
550
+ onFocus,
551
+ setEditing
552
+ ]);
553
+ const handleBlur = useCallback2(async (value) => {
554
+ if (suppressNextBlur.current) {
555
+ suppressNextBlur.current = false;
556
+ } else if (model && editing) {
454
557
  const cell = parseCellIndex2(editing.index);
455
558
  if (value !== void 0) {
456
559
  const result = await model.validateCellData(cell, value);
457
560
  if (result.valid) {
458
- suppressNextBlur.current = true;
459
561
  setValidationError(null);
460
562
  model.setCellData(cell, value);
461
563
  setEditing(null);
462
564
  onSave?.();
463
- if (event && onFocus) {
464
- onFocus(determineNavigationAxis(event), determineNavigationDelta(event), cell);
465
- }
466
- } else {
467
- setValidationError(result.error);
468
- setValidationVariant("error");
469
565
  }
470
- } else {
566
+ }
567
+ }
568
+ }, [
569
+ model,
570
+ editing
571
+ ]);
572
+ const handleClose = useCallback2(async (value, event) => {
573
+ if (!model || !editing || !fieldProjection) {
574
+ return;
575
+ }
576
+ const cell = parseCellIndex2(editing.index);
577
+ if (value !== void 0) {
578
+ const result = await model.validateCellData(cell, value);
579
+ if (result.valid) {
471
580
  suppressNextBlur.current = true;
472
581
  setValidationError(null);
582
+ model.setCellData(cell, value);
473
583
  setEditing(null);
474
584
  onSave?.();
475
585
  if (event && onFocus) {
476
- onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
586
+ onFocus(determineNavigationAxis(event), determineNavigationDelta(event), cell);
477
587
  }
588
+ } else {
589
+ setValidationError(result.error);
590
+ setValidationVariant("error");
478
591
  }
479
- }, [
480
- model,
481
- editing,
482
- onFocus,
483
- fieldProjection,
484
- setEditing,
485
- onSave
486
- ]);
487
- const extensions = useMemo2(() => {
488
- if (!fieldProjection) {
489
- return [];
490
- }
491
- const extensions2 = [
492
- editorKeys({
493
- onClose: handleClose,
494
- ...editing?.initialContent && {
495
- onNav: handleClose
496
- }
497
- })
498
- ];
499
- if (model && editing) {
500
- extensions2.push(EditorView.updateListener.of(debounce((update) => {
501
- const content = update.state.doc.toString();
502
- const cell = parseCellIndex2(editing.index);
503
- void model.validateCellData(cell, content).then((result) => {
504
- if (result.valid) {
505
- setValidationError(null);
506
- } else {
507
- setValidationError(result.error);
508
- setValidationVariant("error");
509
- }
510
- });
511
- }, 10)));
592
+ } else {
593
+ suppressNextBlur.current = true;
594
+ setValidationError(null);
595
+ setEditing(null);
596
+ onSave?.();
597
+ if (event && onFocus) {
598
+ onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
512
599
  }
513
- return extensions2;
514
- }, [
515
- model,
516
- modals,
517
- editing,
518
- fieldProjection,
519
- handleClose
520
- ]);
521
- const getCellContent = useCallback2(() => {
522
- if (model && editing) {
600
+ }
601
+ }, [
602
+ model,
603
+ editing,
604
+ onFocus,
605
+ fieldProjection,
606
+ setEditing,
607
+ onSave
608
+ ]);
609
+ const extensions = useMemo2(() => {
610
+ if (!fieldProjection) {
611
+ return [];
612
+ }
613
+ const extensions2 = [
614
+ editorKeys({
615
+ onClose: handleClose,
616
+ ...editing?.initialContent && {
617
+ onNav: handleClose
618
+ }
619
+ })
620
+ ];
621
+ if (model && editing) {
622
+ extensions2.push(EditorView.updateListener.of(debounce((update) => {
623
+ const content = update.state.doc.toString();
523
624
  const cell = parseCellIndex2(editing.index);
524
- const value = model.getCellData(cell);
525
- return value !== void 0 ? String(value) : "";
625
+ void model.validateCellData(cell, content).then((result) => {
626
+ if (result.valid) {
627
+ setValidationError(null);
628
+ } else {
629
+ setValidationError(result.error);
630
+ setValidationVariant("error");
631
+ }
632
+ });
633
+ }, 10)));
634
+ }
635
+ return extensions2;
636
+ }, [
637
+ model,
638
+ modals,
639
+ editing,
640
+ fieldProjection,
641
+ handleClose
642
+ ]);
643
+ const getCellContent = useCallback2(() => {
644
+ if (model && editing) {
645
+ const cell = parseCellIndex2(editing.index);
646
+ const value = model.getCellData(cell);
647
+ return value !== void 0 ? String(value) : "";
648
+ }
649
+ }, [
650
+ model,
651
+ editing
652
+ ]);
653
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(CellValidationMessage, {
654
+ validationError,
655
+ variant: validationVariant,
656
+ __gridScope
657
+ }), /* @__PURE__ */ React3.createElement(GridCellEditor, {
658
+ extensions,
659
+ slots: {
660
+ content: {
661
+ className: "!py-(--dx-grid-cell-editor-padding-block)"
526
662
  }
527
- }, [
528
- model,
529
- editing
530
- ]);
531
- return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(CellValidationMessage, {
532
- validationError,
533
- variant: validationVariant,
534
- __gridScope
535
- }), /* @__PURE__ */ React3.createElement(GridCellEditor, {
536
- extensions,
537
- getCellContent,
538
- onBlur: handleBlur,
539
- slots: editorSlots
540
- }));
541
- } finally {
542
- _effect.f();
543
- }
663
+ },
664
+ getCellContent,
665
+ onBlur: handleBlur
666
+ }));
544
667
  };
545
668
  var determineNavigationAxis = ({ key }) => {
546
669
  switch (key) {
@@ -568,154 +691,140 @@ var determineNavigationDelta = ({ key, shift }) => {
568
691
  };
569
692
 
570
693
  // src/components/Table/ColumnActionsMenu.tsx
571
- import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
694
+ import { useAtomValue } from "@effect-atom/atom-react";
572
695
  import React4 from "react";
573
696
  import { DropdownMenu, useTranslation } from "@dxos/react-ui";
574
697
  var ColumnActionsMenu = ({ model, modals }) => {
575
- var _effect = _useSignals4();
576
- try {
577
- const { t } = useTranslation(translationKey);
578
- const state = modals.state.value;
579
- if (state?.type !== "column") {
580
- return null;
581
- }
582
- const currentSort = model.sorting?.sorting;
583
- const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
584
- return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
585
- modal: false,
586
- open: true,
587
- onOpenChange: modals.close
588
- }, /* @__PURE__ */ React4.createElement(DropdownMenu.VirtualTrigger, {
589
- virtualRef: modals.trigger
590
- }), /* @__PURE__ */ React4.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React4.createElement(DropdownMenu.Content, null, /* @__PURE__ */ React4.createElement(DropdownMenu.Viewport, null, (!isCurrentColumnSorted || currentSort?.direction === "asc") && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
591
- "data-testid": "column-sort-descending",
592
- onClick: () => model.sorting?.setSort(state.fieldId, "desc")
593
- }, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
594
- "data-testid": "column-sort-ascending",
595
- onClick: () => model.sorting?.setSort(state.fieldId, "asc")
596
- }, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
597
- "data-testid": "column-clear-sort",
598
- onClick: () => model.sorting?.clearSort()
599
- }, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
600
- "data-testid": "column-delete",
601
- onClick: () => model.deleteColumn(state.fieldId)
602
- }, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
603
- "data-testid": "column-settings",
604
- onClick: () => modals.openColumnSettings()
605
- }, t("column action settings"))), /* @__PURE__ */ React4.createElement(DropdownMenu.Arrow, null))));
606
- } finally {
607
- _effect.f();
698
+ const { t } = useTranslation(translationKey);
699
+ const state = useAtomValue(modals.state);
700
+ if (state?.type !== "column") {
701
+ return null;
608
702
  }
703
+ const currentSort = model.getSorting();
704
+ const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
705
+ return /* @__PURE__ */ React4.createElement(DropdownMenu.Root, {
706
+ modal: false,
707
+ open: true,
708
+ onOpenChange: modals.close
709
+ }, /* @__PURE__ */ React4.createElement(DropdownMenu.VirtualTrigger, {
710
+ virtualRef: modals.trigger
711
+ }), /* @__PURE__ */ React4.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React4.createElement(DropdownMenu.Content, null, /* @__PURE__ */ React4.createElement(DropdownMenu.Viewport, null, (!isCurrentColumnSorted || currentSort?.direction === "asc") && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
712
+ "data-testid": "column-sort-descending",
713
+ onClick: () => model.setSort(state.fieldId, "desc")
714
+ }, t("column-action-sort-descending.menu")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
715
+ "data-testid": "column-sort-ascending",
716
+ onClick: () => model.setSort(state.fieldId, "asc")
717
+ }, t("column-action-sort-ascending.menu")), isCurrentColumnSorted && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
718
+ "data-testid": "column-clear-sort",
719
+ onClick: () => model.clearSort()
720
+ }, t("column-action-clear-sorting.menu")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
721
+ "data-testid": "column-delete",
722
+ onClick: () => model.deleteColumn(state.fieldId)
723
+ }, t("column-action-delete.menu")), model.features.schemaEditable && /* @__PURE__ */ React4.createElement(DropdownMenu.Item, {
724
+ "data-testid": "column-settings",
725
+ onClick: () => modals.openColumnSettings()
726
+ }, t("column-action-settings.menu"))), /* @__PURE__ */ React4.createElement(DropdownMenu.Arrow, null))));
609
727
  };
610
728
 
611
729
  // src/components/Table/ColumnSettings.tsx
612
- import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
730
+ import { useAtomValue as useAtomValue2 } from "@effect-atom/atom-react";
613
731
  import React5, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo3, useState as useState3 } from "react";
614
732
  import { Popover as Popover2 } from "@dxos/react-ui";
615
733
  import { FieldEditor } from "@dxos/react-ui-form";
616
734
  var ColumnSettings = ({ registry, model, modals, onNewColumn }) => {
617
- var _effect = _useSignals5();
618
- try {
619
- const [newField, setNewField] = useState3();
620
- const state = modals.state.value;
621
- useEffect2(() => {
622
- if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
623
- setNewField(model.projection.createFieldProjection());
624
- requestAnimationFrame(() => {
625
- onNewColumn();
626
- });
627
- } else {
628
- setNewField(void 0);
629
- }
630
- }, [
631
- model?.projection,
632
- state
633
- ]);
634
- const existingField = useMemo3(() => {
635
- if (state?.type === "columnSettings") {
636
- const { mode } = state;
637
- if (mode.type === "edit") {
638
- return model?.projection?.fields.find((f) => f.id === mode.fieldId);
639
- }
640
- }
641
- return void 0;
642
- }, [
643
- model?.projection?.fields,
644
- state
645
- ]);
646
- const field = existingField ?? newField;
647
- const handleSave = useCallback3(() => {
648
- modals.close();
649
- }, [
650
- modals
651
- ]);
652
- const handleCancel = useCallback3(() => {
653
- if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
654
- model?.projection.deleteFieldProjection(newField.id);
735
+ const [newField, setNewField] = useState3();
736
+ const state = useAtomValue2(modals.state);
737
+ useEffect2(() => {
738
+ if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
739
+ setNewField(model.projection.createFieldProjection());
740
+ requestAnimationFrame(() => {
741
+ onNewColumn();
742
+ });
743
+ } else {
744
+ setNewField(void 0);
745
+ }
746
+ }, [
747
+ model?.projection,
748
+ state
749
+ ]);
750
+ const existingField = useMemo3(() => {
751
+ if (state?.type === "columnSettings") {
752
+ const { mode } = state;
753
+ if (mode.type === "edit") {
754
+ return model?.projection?.getFields().find((f) => f.id === mode.fieldId);
655
755
  }
656
- }, [
657
- model?.projection,
658
- state,
659
- newField
660
- ]);
661
- if (!model?.projection || !field) {
662
- return null;
663
756
  }
664
- return /* @__PURE__ */ React5.createElement(Popover2.Root, {
665
- modal: false,
666
- open: state?.type === "columnSettings"
667
- }, /* @__PURE__ */ React5.createElement(Popover2.VirtualTrigger, {
668
- virtualRef: modals.trigger
669
- }), /* @__PURE__ */ React5.createElement(Popover2.Portal, null, /* @__PURE__ */ React5.createElement(Popover2.Content, {
670
- classNames: "md:is-64"
671
- }, /* @__PURE__ */ React5.createElement(Popover2.Viewport, null, /* @__PURE__ */ React5.createElement(FieldEditor, {
672
- projection: model.projection,
673
- field,
674
- registry,
675
- onSave: handleSave,
676
- onCancel: handleCancel
677
- })), /* @__PURE__ */ React5.createElement(Popover2.Arrow, null))));
678
- } finally {
679
- _effect.f();
757
+ return void 0;
758
+ }, [
759
+ model?.projection,
760
+ state
761
+ ]);
762
+ const field = existingField ?? newField;
763
+ const handleSave = useCallback3(() => {
764
+ modals.close();
765
+ }, [
766
+ modals
767
+ ]);
768
+ const handleCancel = useCallback3(() => {
769
+ if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
770
+ model?.projection.deleteFieldProjection(newField.id);
771
+ }
772
+ }, [
773
+ model?.projection,
774
+ state,
775
+ newField
776
+ ]);
777
+ if (!model?.projection || !field) {
778
+ return null;
680
779
  }
780
+ return /* @__PURE__ */ React5.createElement(Popover2.Root, {
781
+ modal: false,
782
+ open: state?.type === "columnSettings"
783
+ }, /* @__PURE__ */ React5.createElement(Popover2.VirtualTrigger, {
784
+ virtualRef: modals.trigger
785
+ }), /* @__PURE__ */ React5.createElement(Popover2.Portal, null, /* @__PURE__ */ React5.createElement(Popover2.Content, {
786
+ classNames: "md:w-64"
787
+ }, /* @__PURE__ */ React5.createElement(Popover2.Viewport, null, /* @__PURE__ */ React5.createElement(FieldEditor, {
788
+ projection: model.projection,
789
+ field,
790
+ registry,
791
+ onSave: handleSave,
792
+ onCancel: handleCancel
793
+ })), /* @__PURE__ */ React5.createElement(Popover2.Arrow, null))));
681
794
  };
682
795
 
683
796
  // src/components/Table/RowActionsMenu.tsx
684
- import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
797
+ import { useAtomValue as useAtomValue3 } from "@effect-atom/atom-react";
685
798
  import React6 from "react";
686
799
  import { DropdownMenu as DropdownMenu2, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
687
800
  var RowActionsMenu = ({ model, modals }) => {
688
- var _effect = _useSignals6();
689
- try {
690
- const { t } = useTranslation2(translationKey);
691
- const hasSelection = model.selection.hasSelection.value;
692
- const state = modals.state.value;
693
- if (state?.type !== "row") {
694
- return null;
695
- }
696
- return /* @__PURE__ */ React6.createElement(DropdownMenu2.Root, {
697
- modal: false,
698
- open: true,
699
- onOpenChange: modals.close
700
- }, /* @__PURE__ */ React6.createElement(DropdownMenu2.VirtualTrigger, {
701
- virtualRef: modals.trigger
702
- }), /* @__PURE__ */ React6.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React6.createElement(DropdownMenu2.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ React6.createElement(DropdownMenu2.Item, {
703
- "data-testid": "row-menu-delete",
704
- onClick: () => model.deleteRow(state.rowIndex)
705
- }, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ React6.createElement(DropdownMenu2.Item, {
706
- key: action.id,
707
- "data-testid": `row-action-${action.id}`,
708
- onClick: () => {
709
- modals.close();
710
- model.handleRowAction(action.id, state.rowIndex);
711
- }
712
- }, toLocalizedString(action.label, t)))), /* @__PURE__ */ React6.createElement(DropdownMenu2.Arrow, null)));
713
- } finally {
714
- _effect.f();
801
+ const { t } = useTranslation2(translationKey);
802
+ const hasSelection = model.selection.hasSelection;
803
+ const state = useAtomValue3(modals.state);
804
+ if (state?.type !== "row") {
805
+ return null;
715
806
  }
807
+ return /* @__PURE__ */ React6.createElement(DropdownMenu2.Root, {
808
+ modal: false,
809
+ open: true,
810
+ onOpenChange: modals.close
811
+ }, /* @__PURE__ */ React6.createElement(DropdownMenu2.VirtualTrigger, {
812
+ virtualRef: modals.trigger
813
+ }), /* @__PURE__ */ React6.createElement(DropdownMenu2.Content, null, /* @__PURE__ */ React6.createElement(DropdownMenu2.Viewport, null, model.rowActions?.length > 0 && /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(DropdownMenu2.Group, null, model.rowActions?.map((action) => /* @__PURE__ */ React6.createElement(DropdownMenu2.Item, {
814
+ key: action.id,
815
+ "data-testid": `row-action-${action.id}`,
816
+ onClick: () => {
817
+ modals.close();
818
+ model.handleRowAction(action.id, state.rowIndex);
819
+ }
820
+ }, toLocalizedString(action.label, t)))), /* @__PURE__ */ React6.createElement(DropdownMenu2.Separator, null)), model.features.dataEditable !== false && /* @__PURE__ */ React6.createElement(DropdownMenu2.Item, {
821
+ "data-testid": "row-menu-delete",
822
+ onClick: () => model.deleteRow(state.rowIndex)
823
+ }, t(hasSelection ? "bulk delete row label" : "delete row label"))), /* @__PURE__ */ React6.createElement(DropdownMenu2.Arrow, null)));
716
824
  };
717
825
 
718
- // src/components/Table/Table.tsx
826
+ // src/components/Table/TableContent.tsx
827
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-table/src/components/Table/TableContent.tsx";
719
828
  var columnDefault = {
720
829
  grid: {
721
830
  minSize: 80,
@@ -728,480 +837,416 @@ var rowDefault = {
728
837
  focusUnfurl: false
729
838
  }
730
839
  };
731
- var TableRoot = ({ children, role = "article" }) => {
732
- var _effect = _useSignals7();
733
- try {
734
- return /* @__PURE__ */ React7.createElement("div", {
735
- role: "none",
736
- className: mx("relative !border-separator [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]", role === "card--popover" && "popover-card-height", role === "section" && "attention-surface", role === "card--intrinsic" && "[&_.dx-grid]:bs-[--dx-grid-content-block-size]", [
737
- "card--popover",
738
- "section",
739
- "card--extrinsic"
740
- ].includes(role) && "overflow-hidden", [
741
- "article",
742
- "slide"
743
- ].includes(role) && "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:bs-0")
744
- }, children);
745
- } finally {
746
- _effect.f();
747
- }
748
- };
749
- var TableMain = /* @__PURE__ */ forwardRef(({ model, presentation, ignoreAttention, schema, client, onCreate, onRowClick, testId }, forwardedRef) => {
750
- var _effect = _useSignals7();
751
- try {
752
- const [dxGrid, setDxGrid] = useState4(null);
753
- const { hasAttention } = useAttention(model?.id ?? "table");
754
- const modals = useMemo4(() => new ModalController(), []);
755
- const draftRowCount = model?.getDraftRowCount() ?? 0;
756
- const handleSave = useCallback4(() => {
757
- dxGrid?.updateCells(true);
758
- dxGrid?.requestUpdate();
759
- }, [
760
- dxGrid
761
- ]);
762
- const frozen = useMemo4(() => {
763
- const noActionColumn = model?.features.dataEditable === false && model?.features.schemaEditable === false && model.rowActions.length === 0;
764
- return {
765
- frozenRowsStart: 1,
766
- frozenRowsEnd: Math.max(1, draftRowCount),
767
- frozenColsStart: model?.features.selection.enabled ? 1 : 0,
768
- frozenColsEnd: noActionColumn ? 0 : 1
769
- };
770
- }, [
771
- model,
772
- draftRowCount
773
- ]);
774
- const getCells = useCallback4((range, plane) => presentation?.getCells(range, plane) ?? {}, [
775
- presentation
776
- ]);
777
- useEffect3(() => {
778
- if (!presentation || !dxGrid) {
779
- return;
780
- }
781
- dxGrid.getCells = getCells;
782
- }, [
783
- presentation,
784
- dxGrid,
785
- getCells
786
- ]);
787
- const handleInsertRowResult = useCallback4((insertResult) => {
788
- if (insertResult === "draft") {
789
- requestAnimationFrame(() => {
790
- dxGrid?.setFocus({
791
- plane: "frozenRowsEnd",
792
- col: 0,
793
- row: 0
794
- });
795
- dxGrid?.refocus();
840
+ var emptyColumnMeta = Atom2.make({
841
+ grid: {}
842
+ });
843
+ var emptyRowsAtom = Atom2.make([]);
844
+ var emptyCellUpdateAtom = Atom2.make(0);
845
+ var TABLE_CONTENT_NAME = "Table.Content";
846
+ var TableContent = composable(({ schema, model, presentation, ignoreAttention, onCreate, onRowClick, testId, ...props }, forwardedRef) => {
847
+ const registry = useContext(RegistryContext);
848
+ const [dxGrid, setDxGrid] = useState4(null);
849
+ const { hasAttention } = useAttention(model?.id ?? "table");
850
+ const modals = useMemo4(() => new ModalController(registry), [
851
+ registry
852
+ ]);
853
+ const columnMeta = useAtomValue4(model?.columnMeta ?? emptyColumnMeta);
854
+ const rows = useAtomValue4(model?.rows ?? emptyRowsAtom);
855
+ const cellUpdateCounter = useAtomValue4(model?.cellUpdate ?? emptyCellUpdateAtom);
856
+ const columnCount = Object.keys(columnMeta.grid).length || model?.projection.getFields().length || 0;
857
+ const draftRowCount = model?.getDraftRowCount() ?? 0;
858
+ const frozen = useMemo4(() => {
859
+ const noActionColumn = model?.features.dataEditable === false && model?.features.schemaEditable === false && model.rowActions.length === 0;
860
+ return {
861
+ frozenRowsStart: 1,
862
+ frozenRowsEnd: Math.max(1, draftRowCount),
863
+ frozenColsStart: model?.features.selection.enabled ? 1 : 0,
864
+ frozenColsEnd: noActionColumn ? 0 : 1
865
+ };
866
+ }, [
867
+ model,
868
+ draftRowCount
869
+ ]);
870
+ const getCells = useCallback4((range, plane) => presentation?.getCells(range, plane) ?? {}, [
871
+ presentation
872
+ ]);
873
+ useEffect3(() => {
874
+ if (!dxGrid || !presentation) {
875
+ return;
876
+ }
877
+ dxGrid.getCells = getCells;
878
+ }, [
879
+ dxGrid,
880
+ presentation,
881
+ getCells
882
+ ]);
883
+ useEffect3(() => {
884
+ if (!dxGrid) {
885
+ return;
886
+ }
887
+ dxGrid.updateCells(true);
888
+ dxGrid.requestUpdate();
889
+ }, [
890
+ dxGrid,
891
+ rows,
892
+ cellUpdateCounter
893
+ ]);
894
+ const handleInsertRowResult = useCallback4((insertResult) => {
895
+ if (insertResult === "draft") {
896
+ requestAnimationFrame(() => {
897
+ dxGrid?.setFocus({
898
+ plane: "frozenRowsEnd",
899
+ col: 0,
900
+ row: 0
796
901
  });
797
- } else {
902
+ dxGrid?.refocus();
903
+ });
904
+ } else {
905
+ requestAnimationFrame(() => {
906
+ dxGrid?.setFocus({
907
+ plane: "grid",
908
+ col: 0,
909
+ row: model ? model.getRowCount() - 1 : 0
910
+ });
911
+ dxGrid?.refocus();
912
+ });
913
+ }
914
+ }, [
915
+ model,
916
+ dxGrid
917
+ ]);
918
+ const handleSave = useCallback4(() => {
919
+ dxGrid?.updateCells(true);
920
+ dxGrid?.requestUpdate();
921
+ }, [
922
+ dxGrid
923
+ ]);
924
+ const handleSaveDraftRow = useCallback4((rowIndex = 0) => {
925
+ if (model && dxGrid) {
926
+ const didCommitSuccessfully = model.commitDraftRow(rowIndex);
927
+ if (didCommitSuccessfully) {
798
928
  requestAnimationFrame(() => {
799
- dxGrid?.setFocus({
800
- plane: "grid",
801
- col: 0,
802
- row: model ? model.getRowCount() - 1 : 0
803
- });
804
- dxGrid?.refocus();
929
+ dxGrid.scrollToEndRow();
805
930
  });
806
931
  }
807
- }, [
808
- model,
809
- dxGrid
810
- ]);
811
- useImperativeHandle(forwardedRef, () => {
812
- if (!presentation || !dxGrid) {
813
- return {};
814
- }
815
- return {
816
- update: (cell) => {
817
- if (cell) {
818
- dxGrid.updateIfWithinBounds(cell, true);
819
- } else {
820
- dxGrid.updateCells(true);
821
- dxGrid.requestUpdate();
822
- }
823
- },
824
- handleInsertRowResult
825
- };
826
- }, [
827
- presentation,
828
- dxGrid,
829
- model
830
- ]);
831
- const handleSaveDraftRow = useCallback4((rowIndex = 0) => {
832
- if (model && dxGrid) {
833
- const didCommitSuccessfully = model.commitDraftRow(rowIndex);
834
- if (didCommitSuccessfully) {
835
- requestAnimationFrame(() => {
836
- dxGrid.scrollToEndRow();
837
- });
932
+ }
933
+ }, [
934
+ model,
935
+ dxGrid
936
+ ]);
937
+ const handleGridClick = useCallback4((event) => {
938
+ const cell = closestCell(event.target);
939
+ if (cell) {
940
+ const { row: rowIndex, plane } = cell;
941
+ if (onRowClick) {
942
+ if (plane === "grid") {
943
+ const row = model?.getRowAt(rowIndex);
944
+ row && onRowClick(row);
945
+ } else {
946
+ onRowClick(cell);
838
947
  }
839
948
  }
840
- }, [
841
- model,
842
- dxGrid
843
- ]);
844
- const handleGridClick = useCallback4((event) => {
845
- const cell = closestCell(event.target);
846
- if (cell) {
847
- const { row: rowIndex, plane } = cell;
848
- if (onRowClick) {
849
- if (plane === "grid") {
850
- const row = model?.getRowAt(rowIndex);
851
- row && onRowClick(row);
852
- } else {
853
- onRowClick(cell);
854
- }
855
- }
856
- if (model?.features.selection.enabled && model?.selection.selectionMode === "single") {
857
- model.selection.toggleSelectionForRowIndex(rowIndex);
858
- }
949
+ if (model?.features.selection.enabled && model?.selection.selectionMode === "single") {
950
+ model.selection.toggleSelectionForRowIndex(rowIndex);
859
951
  }
860
- if (!modals) {
952
+ }
953
+ if (!modals) {
954
+ return;
955
+ }
956
+ const buttonSelector = Object.values(tableButtons).map((button) => `button[${button.attr}]`).join(",");
957
+ const tableButtonElement = event.target.closest(buttonSelector);
958
+ if (tableButtonElement) {
959
+ const button = Object.values(tableButtons).find((btn) => tableButtonElement.hasAttribute(btn.attr));
960
+ if (!button) {
861
961
  return;
862
962
  }
863
- const buttonSelector = Object.values(tableButtons).map((button) => `button[${button.attr}]`).join(",");
864
- const tableButtonElement = event.target.closest(buttonSelector);
865
- if (tableButtonElement) {
866
- const button = Object.values(tableButtons).find((btn) => tableButtonElement.hasAttribute(btn.attr));
867
- if (!button) {
868
- return;
963
+ modals.setTrigger(tableButtonElement);
964
+ const data = button.getData(tableButtonElement);
965
+ switch (data.type) {
966
+ case "rowMenu": {
967
+ modals.showRowMenu(data.rowIndex);
968
+ break;
869
969
  }
870
- modals.setTrigger(tableButtonElement);
871
- const data = button.getData(tableButtonElement);
872
- switch (data.type) {
873
- case "rowMenu": {
874
- modals.showRowMenu(data.rowIndex);
875
- break;
876
- }
877
- case "columnSettings": {
878
- modals.showColumnMenu(data.fieldId);
879
- break;
880
- }
881
- case "newColumn": {
882
- modals.showColumnCreator();
883
- break;
884
- }
885
- case "sort": {
886
- model?.sorting?.toggleSort(data.fieldId);
887
- break;
888
- }
889
- case "saveDraftRow": {
890
- handleSaveDraftRow();
891
- break;
892
- }
970
+ case "columnSettings": {
971
+ modals.showColumnMenu(data.fieldId);
972
+ break;
893
973
  }
894
- return;
895
- }
896
- const controlSelector = Object.values(tableControls).map((control) => `input[${control.attr}]`).join(",");
897
- const controlElement = event.target.closest(controlSelector);
898
- if (controlElement) {
899
- const control = Object.values(tableControls).find((ctrl) => controlElement.hasAttribute(ctrl.attr));
900
- if (!control) {
901
- return;
974
+ case "newColumn": {
975
+ modals.showColumnCreator();
976
+ break;
902
977
  }
903
- const data = control.getData(controlElement);
904
- switch (data.type) {
905
- case "checkbox": {
906
- if (data.header) {
907
- model?.selection.setSelection(model.selection.allRowsSeleted.value ? "none" : "all");
908
- } else {
909
- model?.selection.toggleSelectionForRowIndex(data.rowIndex);
910
- }
911
- break;
912
- }
913
- case "switch": {
914
- if (model) {
915
- model.updateCellData({
916
- row: data.rowIndex,
917
- col: data.colIndex
918
- }, (value) => !value);
919
- }
920
- break;
921
- }
978
+ case "sort": {
979
+ model?.toggleSort(data.fieldId);
980
+ break;
922
981
  }
923
- }
924
- }, [
925
- model,
926
- modals,
927
- dxGrid
928
- ]);
929
- const handleFocus = useCallback4((increment, delta, cell) => {
930
- if (dxGrid && model) {
931
- if (cell?.plane === "grid" && cell?.row >= model.getRowCount() - 1 && increment !== "col") {
932
- handleInsertRowResult(draftRowCount < 1 ? model.insertRow() : "final");
933
- } else if (cell?.plane === "frozenRowsEnd" && increment === "row") {
934
- handleSaveDraftRow(cell.row);
935
- handleInsertRowResult(model.insertRow());
936
- } else {
937
- dxGrid.refocus(increment, delta);
982
+ case "saveDraftRow": {
983
+ handleSaveDraftRow();
984
+ break;
938
985
  }
939
986
  }
940
- }, [
941
- dxGrid,
942
- model
943
- ]);
944
- const handleKeyDown = useCallback4((event) => {
945
- if (!model?.features.dataEditable) {
946
- return;
947
- }
948
- const cell = closestCell(event.target);
949
- if (!model || !cell) {
987
+ return;
988
+ }
989
+ const controlSelector = Object.values(tableControls).map((control) => `input[${control.attr}]`).join(",");
990
+ const controlElement = event.target.closest(controlSelector);
991
+ if (controlElement) {
992
+ const control = Object.values(tableControls).find((ctrl) => controlElement.hasAttribute(ctrl.attr));
993
+ if (!control) {
950
994
  return;
951
995
  }
952
- if (event.metaKey || event.ctrlKey) {
953
- switch (event.key) {
954
- case "c": {
955
- try {
956
- const cellData = model.getCellData(cell);
957
- const textContent = cellData?.toString() ?? "";
958
- void navigator.clipboard.writeText(textContent);
959
- event.preventDefault();
960
- } catch (error) {
961
- console.warn("Failed to copy cell content:", error);
962
- }
963
- break;
996
+ const data = control.getData(controlElement);
997
+ switch (data.type) {
998
+ case "checkbox": {
999
+ if (data.header) {
1000
+ model?.selection.setSelection(model.selection.allRowsSelected ? "none" : "all");
1001
+ } else {
1002
+ model?.selection.toggleSelectionForRowIndex(data.rowIndex);
964
1003
  }
965
- case "v": {
966
- event.preventDefault();
967
- void navigator.clipboard.readText().then((clipboardText) => {
968
- try {
969
- model.setCellData(cell, String2.trim(clipboardText).replace(/[\n\r]+/, " "));
970
- handleSave();
971
- } catch {
972
- const cellElement = event.target.closest('[data-dx-grid-action="cell"]');
973
- if (cellElement) {
974
- const rect = cellElement.getBoundingClientRect();
975
- const editRequest = new DxEditRequest({
976
- cellIndex: `${cell.plane},${cell.col},${cell.row}`,
977
- cellBox: {
978
- insetInlineStart: rect.left,
979
- insetBlockStart: rect.top,
980
- inlineSize: rect.width,
981
- blockSize: rect.height
982
- },
983
- cellElement,
984
- initialContent: clipboardText
985
- });
986
- cellElement.dispatchEvent(editRequest);
987
- }
988
- }
989
- });
990
- break;
1004
+ break;
1005
+ }
1006
+ case "switch": {
1007
+ if (model) {
1008
+ model.updateCellData({
1009
+ row: data.rowIndex,
1010
+ col: data.colIndex
1011
+ }, (value) => !value);
991
1012
  }
1013
+ break;
992
1014
  }
993
1015
  }
1016
+ }
1017
+ }, [
1018
+ model,
1019
+ modals,
1020
+ dxGrid
1021
+ ]);
1022
+ const handleFocus = useCallback4((increment, delta, cell) => {
1023
+ if (dxGrid && model) {
1024
+ if (cell?.plane === "grid" && cell?.row >= model.getRowCount() - 1 && increment !== "col") {
1025
+ handleInsertRowResult(draftRowCount < 1 ? model.insertRow() : "final");
1026
+ } else if (cell?.plane === "frozenRowsEnd" && increment === "row") {
1027
+ handleSaveDraftRow(cell.row);
1028
+ handleInsertRowResult(model.insertRow());
1029
+ } else {
1030
+ dxGrid.refocus(increment, delta);
1031
+ }
1032
+ }
1033
+ }, [
1034
+ dxGrid,
1035
+ model
1036
+ ]);
1037
+ const handleKeyDown = useCallback4((event) => {
1038
+ if (!model?.features.dataEditable) {
1039
+ return;
1040
+ }
1041
+ const cell = closestCell(event.target);
1042
+ if (!model || !cell) {
1043
+ return;
1044
+ }
1045
+ if (event.metaKey || event.ctrlKey) {
994
1046
  switch (event.key) {
995
- case "Backspace":
996
- case "Delete": {
1047
+ case "c": {
997
1048
  try {
998
- model.setCellData(cell, void 0);
1049
+ const cellData = model.getCellData(cell);
1050
+ const textContent = cellData?.toString() ?? "";
1051
+ void navigator.clipboard.writeText(textContent);
999
1052
  event.preventDefault();
1000
- handleSave();
1001
- } catch {
1053
+ } catch (error) {
1054
+ log.catch(error, void 0, {
1055
+ F: __dxlog_file3,
1056
+ L: 278,
1057
+ S: void 0,
1058
+ C: (f, a) => f(...a)
1059
+ });
1002
1060
  }
1003
1061
  break;
1004
1062
  }
1063
+ case "v": {
1064
+ event.preventDefault();
1065
+ void navigator.clipboard.readText().then((clipboardText) => {
1066
+ try {
1067
+ model.setCellData(cell, String2.trim(clipboardText).replace(/[\n\r]+/, " "));
1068
+ handleSave();
1069
+ } catch {
1070
+ const cellElement = event.target.closest('[data-dx-grid-action="cell"]');
1071
+ if (cellElement) {
1072
+ const rect = cellElement.getBoundingClientRect();
1073
+ const editRequest = new DxEditRequest({
1074
+ cellIndex: `${cell.plane},${cell.col},${cell.row}`,
1075
+ cellBox: {
1076
+ insetInlineStart: rect.left,
1077
+ insetBlockStart: rect.top,
1078
+ inlineSize: rect.width,
1079
+ blockSize: rect.height
1080
+ },
1081
+ cellElement,
1082
+ initialContent: clipboardText
1083
+ });
1084
+ cellElement.dispatchEvent(editRequest);
1085
+ }
1086
+ }
1087
+ });
1088
+ break;
1089
+ }
1005
1090
  }
1006
- }, [
1007
- model,
1008
- dxGrid,
1009
- handleSave
1010
- ]);
1011
- const handleAxisResize = useCallback4((event) => {
1012
- if (event.axis === "col") {
1013
- const columnIndex = parseInt(event.index, 10);
1014
- model?.setColumnWidth(columnIndex, event.size);
1015
- }
1016
- }, [
1017
- model
1018
- ]);
1019
- const handleWheel = useCallback4((event) => {
1020
- if (!ignoreAttention && !hasAttention) {
1021
- event.stopPropagation();
1022
- }
1023
- }, [
1024
- hasAttention,
1025
- ignoreAttention
1026
- ]);
1027
- const handleNewColumn = useCallback4(() => {
1028
- const columns = model?.getColumnCount();
1029
- if (dxGrid && columns) {
1030
- dxGrid.scrollToColumn(columns - 1);
1091
+ }
1092
+ switch (event.key) {
1093
+ case "Backspace":
1094
+ case "Delete": {
1095
+ try {
1096
+ model.setCellData(cell, void 0);
1097
+ event.preventDefault();
1098
+ handleSave();
1099
+ } catch {
1100
+ }
1101
+ break;
1031
1102
  }
1032
- }, [
1033
- model,
1034
- dxGrid
1035
- ]);
1036
- if (!model || !modals) {
1037
- return /* @__PURE__ */ React7.createElement("span", {
1038
- role: "none",
1039
- className: "attention-surface"
1040
- });
1041
1103
  }
1042
- return /* @__PURE__ */ React7.createElement(Grid.Root, {
1043
- id: model.id ?? "table-grid"
1044
- }, /* @__PURE__ */ React7.createElement(TableValueEditor, {
1045
- model,
1046
- modals,
1047
- schema,
1048
- onFocus: handleFocus,
1049
- onSave: handleSave,
1050
- onCreate,
1051
- client
1052
- }), /* @__PURE__ */ React7.createElement(Grid.Content, {
1053
- className: mx("[--dx-grid-base:var(--baseSurface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
1054
- frozen,
1055
- columns: model.columnMeta.value,
1056
- columnDefault,
1057
- rowDefault,
1058
- limitRows: model.getRowCount() ?? 0,
1059
- limitColumns: model.projection.fields.length,
1060
- overscroll: "trap",
1061
- onAxisResize: handleAxisResize,
1062
- onClick: handleGridClick,
1063
- onKeyDownCapture: handleKeyDown,
1064
- onWheelCapture: handleWheel,
1065
- ...testId && {
1066
- "data-testid": testId
1104
+ }, [
1105
+ model,
1106
+ dxGrid,
1107
+ handleSave
1108
+ ]);
1109
+ const handleAxisResize = useCallback4((event) => {
1110
+ if (event.axis === "col") {
1111
+ const columnIndex = parseInt(event.index, 10);
1112
+ model?.setColumnWidth(columnIndex, event.size);
1113
+ }
1114
+ }, [
1115
+ model
1116
+ ]);
1117
+ const handleWheel = useCallback4((event) => {
1118
+ if (!ignoreAttention && !hasAttention) {
1119
+ event.stopPropagation();
1120
+ }
1121
+ }, [
1122
+ hasAttention,
1123
+ ignoreAttention
1124
+ ]);
1125
+ const handleNewColumn = useCallback4(() => {
1126
+ const columns = model?.getColumnCount();
1127
+ if (dxGrid && columns) {
1128
+ dxGrid.scrollToColumn(columns - 1);
1129
+ }
1130
+ }, [
1131
+ model,
1132
+ dxGrid
1133
+ ]);
1134
+ const { controllerRef } = useTableContext(TABLE_CONTENT_NAME);
1135
+ controllerRef.current = useMemo4(() => {
1136
+ if (!dxGrid || !presentation) {
1137
+ return {};
1138
+ }
1139
+ return {
1140
+ update: (cell) => {
1141
+ if (cell) {
1142
+ dxGrid.updateIfWithinBounds(cell, true);
1143
+ } else {
1144
+ dxGrid.updateCells(true);
1145
+ dxGrid.requestUpdate();
1146
+ }
1067
1147
  },
1068
- ref: setDxGrid
1069
- }), /* @__PURE__ */ React7.createElement(RowActionsMenu, {
1070
- model,
1071
- modals
1072
- }), /* @__PURE__ */ React7.createElement(ColumnActionsMenu, {
1073
- model,
1074
- modals
1075
- }), /* @__PURE__ */ React7.createElement(ColumnSettings, {
1076
- model,
1077
- modals,
1078
- onNewColumn: handleNewColumn
1079
- }));
1080
- } finally {
1081
- _effect.f();
1148
+ handleInsertRowResult
1149
+ };
1150
+ }, [
1151
+ dxGrid,
1152
+ model,
1153
+ presentation
1154
+ ]);
1155
+ if (!model || !modals) {
1156
+ return /* @__PURE__ */ React7.createElement("span", {
1157
+ role: "none",
1158
+ className: "dx-attention-surface"
1159
+ });
1082
1160
  }
1161
+ return /* @__PURE__ */ React7.createElement("div", {
1162
+ ...composableProps(props, {
1163
+ classNames: "dx-container relative"
1164
+ }),
1165
+ ref: forwardedRef
1166
+ }, /* @__PURE__ */ React7.createElement(Grid.Root, {
1167
+ id: model.id ?? "table-grid"
1168
+ }, /* @__PURE__ */ React7.createElement(TableValueEditor, {
1169
+ model,
1170
+ modals,
1171
+ schema,
1172
+ onFocus: handleFocus,
1173
+ onSave: handleSave,
1174
+ onCreate
1175
+ }), /* @__PURE__ */ React7.createElement(Grid.Content, {
1176
+ className: mx("[--dx-grid-base:var(--base-surface)]", gridSeparatorInlineEnd, gridSeparatorBlockEnd),
1177
+ frozen,
1178
+ columns: columnMeta,
1179
+ columnDefault,
1180
+ rowDefault,
1181
+ limitRows: rows.length,
1182
+ limitColumns: columnCount,
1183
+ overscroll: "trap",
1184
+ onAxisResize: handleAxisResize,
1185
+ onClick: handleGridClick,
1186
+ onKeyDownCapture: handleKeyDown,
1187
+ onWheelCapture: handleWheel,
1188
+ ...testId && {
1189
+ "data-testid": testId
1190
+ },
1191
+ ref: setDxGrid
1192
+ }), /* @__PURE__ */ React7.createElement(RowActionsMenu, {
1193
+ model,
1194
+ modals
1195
+ }), /* @__PURE__ */ React7.createElement(ColumnActionsMenu, {
1196
+ model,
1197
+ modals
1198
+ }), /* @__PURE__ */ React7.createElement(ColumnSettings, {
1199
+ model,
1200
+ modals,
1201
+ onNewColumn: handleNewColumn
1202
+ })));
1083
1203
  });
1084
- var Table = {
1085
- Root: TableRoot,
1086
- Main: TableMain
1087
- };
1204
+ TableContent.displayName = TABLE_CONTENT_NAME;
1088
1205
 
1089
- // src/components/Table/DynamicTable.tsx
1090
- import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
1091
- import React8, { useCallback as useCallback5, useMemo as useMemo5, useRef as useRef3 } from "react";
1092
- import { useDefaultValue } from "@dxos/react-ui";
1093
- import { mx as mx2 } from "@dxos/react-ui-theme";
1094
- var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema: _jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
1095
- var _effect = _useSignals8();
1096
- try {
1097
- const { jsonSchema } = useMemo5(() => getBaseSchema({
1098
- typename: name,
1099
- properties,
1100
- jsonSchema: _jsonSchema,
1101
- schema
1102
- }), [
1103
- name,
1104
- properties,
1105
- _jsonSchema,
1106
- schema
1107
- ]);
1108
- const { projection, view } = useMemo5(() => makeDynamicTable({
1109
- jsonSchema,
1110
- properties
1111
- }), [
1112
- jsonSchema,
1113
- properties
1114
- ]);
1115
- const tableRef = useRef3(null);
1116
- const handleCellUpdate = useCallback5((cell) => {
1117
- tableRef.current?.update?.(cell);
1118
- }, []);
1119
- const handleRowOrderChange = useCallback5(() => {
1120
- tableRef.current?.update?.();
1121
- }, []);
1122
- const features = useDefaultValue(props.features, () => ({
1123
- selection: {
1124
- enabled: false
1125
- },
1126
- dataEditable: false
1127
- }));
1128
- const model = useTableModel({
1129
- rows,
1130
- view,
1131
- schema: jsonSchema,
1132
- projection,
1133
- features,
1134
- rowActions,
1135
- onCellUpdate: handleCellUpdate,
1136
- onRowOrderChange: handleRowOrderChange,
1137
- onRowAction
1206
+ // src/components/Table/TableToolbar.tsx
1207
+ import { Atom as Atom3, RegistryContext as RegistryContext2 } from "@effect-atom/atom-react";
1208
+ import React8, { useContext as useContext2, useEffect as useEffect4, useMemo as useMemo5 } from "react";
1209
+ import { Menu, createGapSeparator, createMenuAction, useMenuActions } from "@dxos/react-ui-menu";
1210
+ import { composable as composable2, composableProps as composableProps2 } from "@dxos/ui-theme";
1211
+ var createTableToolbarActions = ({ stateAtom, onAdd, onSave, customActions }) => Atom3.make((get) => {
1212
+ const nodes = [];
1213
+ if (onAdd) {
1214
+ const add = createMenuAction("add-row", onAdd, {
1215
+ type: "add-row",
1216
+ icon: "ph--plus--regular",
1217
+ label: [
1218
+ "add-row.label",
1219
+ {
1220
+ ns: translationKey
1221
+ }
1222
+ ],
1223
+ testId: "table.toolbar.add-row"
1138
1224
  });
1139
- const presentation = useMemo5(() => {
1140
- if (model) {
1141
- return new TablePresentation(model);
1142
- }
1143
- }, [
1144
- model
1145
- ]);
1146
- return /* @__PURE__ */ React8.createElement("div", {
1147
- role: "none",
1148
- className: mx2("is-full bs-full grow grid", classNames)
1149
- }, /* @__PURE__ */ React8.createElement("div", {
1150
- role: "none",
1151
- className: "grid min-bs-0 overflow-hidden"
1152
- }, /* @__PURE__ */ React8.createElement(Table.Root, null, /* @__PURE__ */ React8.createElement(Table.Main, {
1153
- ref: tableRef,
1154
- model,
1155
- presentation,
1156
- ignoreAttention: true,
1157
- onRowClick
1158
- }))));
1159
- } finally {
1160
- _effect.f();
1225
+ nodes.push(add);
1226
+ }
1227
+ if (onSave) {
1228
+ const state = get(stateAtom);
1229
+ const save = createMenuAction("save-view", onSave, {
1230
+ type: "save-view",
1231
+ icon: "ph--floppy-disk--regular",
1232
+ label: [
1233
+ "save-view.label",
1234
+ {
1235
+ ns: translationKey
1236
+ }
1237
+ ],
1238
+ testId: "table.toolbar.save-view",
1239
+ iconOnly: false,
1240
+ hidden: !state.viewDirty
1241
+ });
1242
+ nodes.push(save);
1161
1243
  }
1162
- };
1163
-
1164
- // src/components/TableToolbar/TableToolbar.tsx
1165
- import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
1166
- import { Rx } from "@effect-rx/rx-react";
1167
- import React9, { useMemo as useMemo6 } from "react";
1168
- import { live } from "@dxos/live-object";
1169
- import { MenuProvider, ToolbarMenu, createGapSeparator, createMenuAction, useMenuActions } from "@dxos/react-ui-menu";
1170
- import { rxFromSignal } from "@dxos/react-ui-menu";
1171
- var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.make((get) => {
1172
- const add = createMenuAction("add-row", onAdd, {
1173
- type: "add-row",
1174
- icon: "ph--plus--regular",
1175
- label: [
1176
- "add row",
1177
- {
1178
- ns: translationKey
1179
- }
1180
- ],
1181
- testId: "table.toolbar.add-row"
1182
- });
1183
- const save = createMenuAction("save-view", onSave, {
1184
- type: "save-view",
1185
- icon: "ph--floppy-disk--regular",
1186
- label: [
1187
- "save view label",
1188
- {
1189
- ns: translationKey
1190
- }
1191
- ],
1192
- testId: "table.toolbar.save-view",
1193
- iconOnly: false,
1194
- hidden: get(rxFromSignal(() => !state.viewDirty))
1195
- });
1196
1244
  const gap = createGapSeparator();
1197
- const nodes = [
1198
- add,
1199
- save,
1200
- ...gap.nodes
1201
- ];
1245
+ nodes.push(...gap.nodes);
1202
1246
  const edges = nodes.map(({ id: target }) => ({
1203
1247
  source: "root",
1204
- target
1248
+ target,
1249
+ relation: "child"
1205
1250
  }));
1206
1251
  if (customActions) {
1207
1252
  const custom = get(customActions);
@@ -1213,33 +1258,140 @@ var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => Rx.
1213
1258
  edges
1214
1259
  };
1215
1260
  });
1216
- var TableToolbar = ({ classNames, viewDirty, attendableId, onAdd, onSave, customActions }) => {
1217
- var _effect = _useSignals9();
1218
- try {
1219
- const state = useMemo6(() => live({
1261
+ var TableToolbar = composable2(({ attendableId, viewDirty, onAdd, onSave, customActions, ...props }, forwardedRef) => {
1262
+ const registry = useContext2(RegistryContext2);
1263
+ const stateAtom = useMemo5(() => Atom3.make({
1264
+ viewDirty
1265
+ }), []);
1266
+ useEffect4(() => {
1267
+ registry.set(stateAtom, {
1220
1268
  viewDirty
1221
- }), []);
1222
- const actionsCreator = useMemo6(() => createTableToolbarActions({
1223
- state,
1224
- onAdd,
1225
- onSave,
1226
- customActions
1227
- }), [
1228
- state,
1229
- onAdd,
1230
- onSave,
1231
- customActions
1232
- ]);
1233
- const menu = useMenuActions(actionsCreator);
1234
- return /* @__PURE__ */ React9.createElement(MenuProvider, {
1235
- ...menu,
1236
- attendableId
1237
- }, /* @__PURE__ */ React9.createElement(ToolbarMenu, {
1238
- classNames
1269
+ });
1270
+ }, [
1271
+ registry,
1272
+ stateAtom,
1273
+ viewDirty
1274
+ ]);
1275
+ const actionsCreator = useMemo5(() => createTableToolbarActions({
1276
+ stateAtom,
1277
+ onAdd,
1278
+ onSave,
1279
+ customActions
1280
+ }), [
1281
+ stateAtom,
1282
+ onAdd,
1283
+ onSave,
1284
+ customActions
1285
+ ]);
1286
+ const menuActions = useMenuActions(actionsCreator);
1287
+ return /* @__PURE__ */ React8.createElement(Menu.Root, {
1288
+ ...menuActions,
1289
+ attendableId
1290
+ }, /* @__PURE__ */ React8.createElement(Menu.Toolbar, {
1291
+ ...composableProps2(props),
1292
+ ref: forwardedRef
1293
+ }));
1294
+ });
1295
+ TableToolbar.displayName = "TableToolbar";
1296
+
1297
+ // src/components/Table/Table.tsx
1298
+ var emptyColumnMeta2 = Atom4.make({
1299
+ grid: {}
1300
+ });
1301
+ var [TableContextProvider, useTableContext] = createContext("Table");
1302
+ var TABLE_ROOT_NAME = "Table.Root";
1303
+ var TableRoot = /* @__PURE__ */ forwardRef(({ children }, forwardedRef) => {
1304
+ const controllerRef = useRef3({});
1305
+ useImperativeHandle(forwardedRef, () => ({
1306
+ update: (cell) => controllerRef.current?.update?.(cell),
1307
+ handleInsertRowResult: (result) => controllerRef.current?.handleInsertRowResult?.(result)
1308
+ }), []);
1309
+ return /* @__PURE__ */ React9.createElement(TableContextProvider, {
1310
+ controllerRef
1311
+ }, children);
1312
+ });
1313
+ TableRoot.displayName = TABLE_ROOT_NAME;
1314
+ var Table = {
1315
+ Root: TableRoot,
1316
+ Toolbar: TableToolbar,
1317
+ Content: TableContent
1318
+ };
1319
+
1320
+ // src/components/Table/DynamicTable.tsx
1321
+ import { RegistryContext as RegistryContext3 } from "@effect-atom/atom-react";
1322
+ import React10, { useCallback as useCallback5, useContext as useContext3, useEffect as useEffect5, useMemo as useMemo6, useRef as useRef4, useState as useState5 } from "react";
1323
+ import { useDefaultValue } from "@dxos/react-ui";
1324
+ import { mx as mx2 } from "@dxos/ui-theme";
1325
+ var DynamicTable = ({ classNames, schema, name = "com.example.dynamicTable", rows, properties, jsonSchema: jsonSchemaProp, rowActions, onRowClick, onRowAction, ...props }) => {
1326
+ const registry = useContext3(RegistryContext3);
1327
+ const [dynamicTable, setDynamicTable] = useState5();
1328
+ const { jsonSchema } = useMemo6(() => getBaseSchema({
1329
+ typename: name,
1330
+ properties,
1331
+ jsonSchema: jsonSchemaProp,
1332
+ schema
1333
+ }), [
1334
+ name,
1335
+ properties,
1336
+ jsonSchemaProp,
1337
+ schema
1338
+ ]);
1339
+ useEffect5(() => {
1340
+ setDynamicTable(makeDynamicTable({
1341
+ registry,
1342
+ jsonSchema,
1343
+ properties
1239
1344
  }));
1240
- } finally {
1241
- _effect.f();
1242
- }
1345
+ }, [
1346
+ registry,
1347
+ jsonSchema,
1348
+ properties
1349
+ ]);
1350
+ const tableRef = useRef4(null);
1351
+ const handleCellUpdate = useCallback5((cell) => {
1352
+ tableRef.current?.update?.(cell);
1353
+ }, []);
1354
+ const handleRowOrderChange = useCallback5(() => {
1355
+ tableRef.current?.update?.();
1356
+ }, []);
1357
+ const features = useDefaultValue(props.features, () => ({
1358
+ selection: {
1359
+ enabled: false
1360
+ },
1361
+ dataEditable: false
1362
+ }));
1363
+ const model = useTableModel({
1364
+ rows,
1365
+ object: dynamicTable?.object,
1366
+ projection: dynamicTable?.projection,
1367
+ features,
1368
+ rowActions,
1369
+ onCellUpdate: handleCellUpdate,
1370
+ onRowOrderChange: handleRowOrderChange,
1371
+ onRowAction
1372
+ });
1373
+ const presentation = useMemo6(() => {
1374
+ if (model) {
1375
+ return new TablePresentation(registry, model);
1376
+ }
1377
+ }, [
1378
+ registry,
1379
+ model
1380
+ ]);
1381
+ return /* @__PURE__ */ React10.createElement("div", {
1382
+ role: "none",
1383
+ className: mx2("dx-expander grid", classNames)
1384
+ }, /* @__PURE__ */ React10.createElement("div", {
1385
+ role: "none",
1386
+ className: "grid min-h-0 overflow-hidden"
1387
+ }, /* @__PURE__ */ React10.createElement(Table.Root, {
1388
+ ref: tableRef
1389
+ }, /* @__PURE__ */ React10.createElement(Table.Content, {
1390
+ model,
1391
+ presentation,
1392
+ ignoreAttention: true,
1393
+ onRowClick
1394
+ }))));
1243
1395
  };
1244
1396
  export {
1245
1397
  BUTTON_IDENTIFIERS,
@@ -1251,9 +1403,13 @@ export {
1251
1403
  Table,
1252
1404
  TableModel,
1253
1405
  TablePresentation,
1254
- TableToolbar,
1255
1406
  cellClassesForRowSelection,
1407
+ compareValues,
1408
+ createDirectChangeCallback,
1409
+ createEchoChangeCallback,
1410
+ extractOrder,
1256
1411
  getBaseSchema,
1412
+ getSortValue,
1257
1413
  makeDynamicTable,
1258
1414
  narrowSchema,
1259
1415
  tableButtons,
@@ -1261,6 +1417,8 @@ export {
1261
1417
  touch,
1262
1418
  translations,
1263
1419
  useAddRow,
1420
+ useProjectionModel,
1421
+ useTableContext,
1264
1422
  useTableModel
1265
1423
  };
1266
1424
  //# sourceMappingURL=index.mjs.map