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