@dxos/react-ui-table 0.8.4-main.1f223c7 → 0.8.4-main.2244d791bb

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