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