@dxos/react-ui-table 0.8.4-main.1da679c → 0.8.4-main.21d9917

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