@dxos/react-ui-table 0.8.4-main.f5c0578 → 0.8.4-main.fcc0d83b33

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