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