@dxos/react-ui-table 0.8.4-main.70d3990 → 0.8.4-main.74a063c4e0

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