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