@dxos/react-ui-table 0.8.4-main.7ace549 → 0.8.4-main.8baae0fced

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