@dxos/react-ui-table 0.8.4-main.5ea62a8 → 0.8.4-main.60689f5b1c

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