@dxos/react-ui-table 0.8.4-main.72ec0f3 → 0.8.4-main.7996785055

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