@dxos/react-ui-table 0.8.3 → 0.8.4-main.c1de068

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 (125) hide show
  1. package/dist/lib/browser/chunk-5XLSHLOG.mjs +1751 -0
  2. package/dist/lib/browser/chunk-5XLSHLOG.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-L2LSB6KV.mjs +18 -0
  4. package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +240 -1639
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/testing/index.mjs +121 -0
  9. package/dist/lib/browser/testing/index.mjs.map +7 -0
  10. package/dist/lib/browser/types/index.mjs +3 -5
  11. package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +20 -0
  12. package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +7 -0
  13. package/dist/lib/node-esm/chunk-Y66YLSTC.mjs +1752 -0
  14. package/dist/lib/node-esm/chunk-Y66YLSTC.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.mjs +240 -1639
  16. package/dist/lib/node-esm/index.mjs.map +4 -4
  17. package/dist/lib/node-esm/meta.json +1 -1
  18. package/dist/lib/node-esm/testing/index.mjs +122 -0
  19. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  20. package/dist/lib/node-esm/types/index.mjs +3 -5
  21. package/dist/types/src/components/Table/ColumnSettings.d.ts +3 -1
  22. package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
  23. package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +1 -1
  24. package/dist/types/src/components/Table/DynamicTable.d.ts +1 -1
  25. package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
  26. package/dist/types/src/components/Table/DynamicTable.stories.d.ts +1 -1
  27. package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
  28. package/dist/types/src/components/Table/Table.d.ts.map +1 -1
  29. package/dist/types/src/components/Table/Table.stories.d.ts +1 -1
  30. package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
  31. package/dist/types/src/components/Table/relations.stories.d.ts +1 -1
  32. package/dist/types/src/components/Table/relations.stories.d.ts.map +1 -1
  33. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +2 -1
  34. package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
  35. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +2 -1
  36. package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
  37. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +3 -2
  38. package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
  39. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +1 -1
  40. package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
  41. package/dist/types/src/components/testing.d.ts +3 -40
  42. package/dist/types/src/components/testing.d.ts.map +1 -1
  43. package/dist/types/src/hooks/index.d.ts +1 -0
  44. package/dist/types/src/hooks/index.d.ts.map +1 -1
  45. package/dist/types/src/hooks/useAddRow.d.ts +13 -0
  46. package/dist/types/src/hooks/useAddRow.d.ts.map +1 -0
  47. package/dist/types/src/hooks/useTableModel.d.ts +7 -6
  48. package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
  49. package/dist/types/src/index.d.ts +1 -2
  50. package/dist/types/src/index.d.ts.map +1 -1
  51. package/dist/types/src/model/selection-model.d.ts +2 -1
  52. package/dist/types/src/model/selection-model.d.ts.map +1 -1
  53. package/dist/types/src/model/table-model.d.ts +56 -20
  54. package/dist/types/src/model/table-model.d.ts.map +1 -1
  55. package/dist/types/src/model/table-presentation.d.ts +8 -0
  56. package/dist/types/src/model/table-presentation.d.ts.map +1 -1
  57. package/dist/types/src/model/table-sorting.d.ts +2 -2
  58. package/dist/types/src/model/table-sorting.d.ts.map +1 -1
  59. package/dist/types/src/playwright/playwright.config.d.ts +3 -0
  60. package/dist/types/src/playwright/playwright.config.d.ts.map +1 -0
  61. package/dist/types/src/testing/index.d.ts +2 -0
  62. package/dist/types/src/testing/index.d.ts.map +1 -0
  63. package/dist/types/src/testing/useTestTableModel.d.ts +41 -0
  64. package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -0
  65. package/dist/types/src/translations.d.ts +3 -4
  66. package/dist/types/src/translations.d.ts.map +1 -1
  67. package/dist/types/src/types/index.d.ts +1 -1
  68. package/dist/types/src/types/index.d.ts.map +1 -1
  69. package/dist/types/src/types/schema.d.ts +8 -0
  70. package/dist/types/src/types/schema.d.ts.map +1 -0
  71. package/dist/types/src/util/dynamic-table.d.ts +3 -4
  72. package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
  73. package/dist/types/src/util/table-buttons.d.ts +15 -1
  74. package/dist/types/src/util/table-buttons.d.ts.map +1 -1
  75. package/dist/types/src/util/table.d.ts +8 -11
  76. package/dist/types/src/util/table.d.ts.map +1 -1
  77. package/dist/types/tsconfig.tsbuildinfo +1 -1
  78. package/package.json +48 -40
  79. package/src/components/Table/ColumnSettings.tsx +14 -10
  80. package/src/components/Table/CreateRefPanel.tsx +5 -3
  81. package/src/components/Table/DynamicTable.stories.tsx +2 -2
  82. package/src/components/Table/DynamicTable.tsx +13 -7
  83. package/src/components/Table/Table.stories.tsx +104 -148
  84. package/src/components/Table/Table.tsx +50 -32
  85. package/src/components/Table/relations.stories.tsx +27 -35
  86. package/src/components/TableCellEditor/CellValidationMessage.tsx +6 -1
  87. package/src/components/TableCellEditor/FormCellEditor.tsx +30 -21
  88. package/src/components/TableCellEditor/TableCellEditor.stories.tsx +24 -28
  89. package/src/components/TableCellEditor/TableCellEditor.tsx +79 -21
  90. package/src/components/testing.ts +7 -24
  91. package/src/hooks/index.ts +1 -0
  92. package/src/hooks/useAddRow.ts +36 -0
  93. package/src/hooks/useTableModel.ts +20 -16
  94. package/src/index.ts +1 -2
  95. package/src/model/selection-model.ts +4 -2
  96. package/src/model/table-model.test.ts +7 -8
  97. package/src/model/table-model.ts +267 -78
  98. package/src/model/table-presentation.test.ts +6 -7
  99. package/src/model/table-presentation.ts +215 -132
  100. package/src/model/table-sorting.ts +9 -9
  101. package/src/playwright/playwright.config.ts +17 -0
  102. package/src/playwright/smoke.spec.ts +21 -20
  103. package/src/testing/index.ts +5 -0
  104. package/src/testing/useTestTableModel.ts +122 -0
  105. package/src/translations.ts +5 -3
  106. package/src/types/index.ts +2 -2
  107. package/src/types/schema.ts +16 -0
  108. package/src/util/dynamic-table.ts +19 -17
  109. package/src/util/table-buttons.ts +24 -1
  110. package/src/util/table.ts +33 -111
  111. package/dist/lib/browser/chunk-TL7CKQQV.mjs +0 -27
  112. package/dist/lib/browser/chunk-TL7CKQQV.mjs.map +0 -7
  113. package/dist/lib/node/chunk-O2VPBNS5.cjs +0 -50
  114. package/dist/lib/node/chunk-O2VPBNS5.cjs.map +0 -7
  115. package/dist/lib/node/index.cjs +0 -2739
  116. package/dist/lib/node/index.cjs.map +0 -7
  117. package/dist/lib/node/meta.json +0 -1
  118. package/dist/lib/node/types/index.cjs +0 -31
  119. package/dist/lib/node/types/index.cjs.map +0 -7
  120. package/dist/lib/node-esm/chunk-GBT6GD4G.mjs +0 -29
  121. package/dist/lib/node-esm/chunk-GBT6GD4G.mjs.map +0 -7
  122. package/dist/types/src/types/table.d.ts +0 -56
  123. package/dist/types/src/types/table.d.ts.map +0 -1
  124. package/src/playwright/playwright.config.cts +0 -18
  125. package/src/types/table.ts +0 -27
@@ -1,2739 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var node_exports = {};
30
- __export(node_exports, {
31
- BUTTON_IDENTIFIERS: () => BUTTON_IDENTIFIERS,
32
- CONTROL_IDENTIFIERS: () => CONTROL_IDENTIFIERS,
33
- CheckboxStory: () => CheckboxStory,
34
- DynamicTable: () => DynamicTable,
35
- ModalController: () => ModalController,
36
- SwitchStory: () => SwitchStory,
37
- Table: () => Table,
38
- TableModel: () => TableModel,
39
- TablePresentation: () => TablePresentation,
40
- TableSchema: () => import_chunk_O2VPBNS5.TableSchema,
41
- TableToolbar: () => TableToolbar,
42
- TableType: () => import_chunk_O2VPBNS5.TableType,
43
- cellClassesForRowSelection: () => cellClassesForRowSelection,
44
- getBaseSchema: () => getBaseSchema,
45
- initializeTable: () => initializeTable,
46
- makeDynamicTable: () => makeDynamicTable,
47
- narrowSchema: () => narrowSchema,
48
- tableButtons: () => tableButtons,
49
- tableControls: () => tableControls,
50
- touch: () => touch,
51
- translations: () => translations_default,
52
- useTableModel: () => useTableModel
53
- });
54
- module.exports = __toCommonJS(node_exports);
55
- var import_chunk_O2VPBNS5 = require("./chunk-O2VPBNS5.cjs");
56
- var import_tracking = require("@preact-signals/safe-react/tracking");
57
- var import_react = __toESM(require("react"));
58
- var import_echo_schema = require("@dxos/echo-schema");
59
- var import_invariant = require("@dxos/invariant");
60
- var import_echo = require("@dxos/react-client/echo");
61
- var import_react_ui = require("@dxos/react-ui");
62
- var import_react_ui_attention = require("@dxos/react-ui-attention");
63
- var import_react_ui_grid = require("@dxos/react-ui-grid");
64
- var import_react_ui_theme = require("@dxos/react-ui-theme");
65
- var import_util = require("@dxos/util");
66
- var import_tracking2 = require("@preact-signals/safe-react/tracking");
67
- var import_react2 = __toESM(require("react"));
68
- var import_react_ui2 = require("@dxos/react-ui");
69
- var import_tracking3 = require("@preact-signals/safe-react/tracking");
70
- var import_react3 = __toESM(require("react"));
71
- var import_react_ui3 = require("@dxos/react-ui");
72
- var import_react_ui_form = require("@dxos/react-ui-form");
73
- var import_tracking4 = require("@preact-signals/safe-react/tracking");
74
- var import_effect = require("effect");
75
- var import_react4 = __toESM(require("react"));
76
- var import_echo2 = require("@dxos/react-client/echo");
77
- var import_react_ui4 = require("@dxos/react-ui");
78
- var import_react_ui_form2 = require("@dxos/react-ui-form");
79
- var import_react_ui_grid2 = require("@dxos/react-ui-grid");
80
- var import_tracking5 = require("@preact-signals/safe-react/tracking");
81
- var import_react5 = __toESM(require("react"));
82
- var import_react_ui5 = require("@dxos/react-ui");
83
- var import_signals_core = require("@preact/signals-core");
84
- var import_context = require("@dxos/context");
85
- var import_echo_schema2 = require("@dxos/echo-schema");
86
- var import_invariant2 = require("@dxos/invariant");
87
- var import_live_object = require("@dxos/live-object");
88
- var import_react_ui_form3 = require("@dxos/react-ui-form");
89
- var import_schema = require("@dxos/schema");
90
- var import_signals_core2 = require("@preact/signals-core");
91
- var import_context2 = require("@dxos/context");
92
- var import_echo3 = require("@dxos/echo");
93
- var import_echo_schema3 = require("@dxos/echo-schema");
94
- var import_schema2 = require("@dxos/schema");
95
- var import_effect2 = require("effect");
96
- var import_echo_schema4 = require("@dxos/echo-schema");
97
- var import_react_client = require("@dxos/react-client");
98
- var import_echo4 = require("@dxos/react-client/echo");
99
- var import_schema3 = require("@dxos/schema");
100
- var import_effect3 = require("effect");
101
- var import_SchemaAST = require("effect/SchemaAST");
102
- var import_signals_core3 = require("@preact/signals-core");
103
- var import_lodash = __toESM(require("lodash.orderby"));
104
- var import_echo_schema5 = require("@dxos/echo-schema");
105
- var import_react_ui_form4 = require("@dxos/react-ui-form");
106
- var import_signals_core4 = require("@preact/signals-core");
107
- var import_log = require("@dxos/log");
108
- var import_signals_core5 = require("@preact/signals-core");
109
- var import_Predicate = require("effect/Predicate");
110
- var import_echo_schema6 = require("@dxos/echo-schema");
111
- var import_react_ui_form5 = require("@dxos/react-ui-form");
112
- var import_react_ui_grid3 = require("@dxos/react-ui-grid");
113
- var import_react_ui_theme2 = require("@dxos/react-ui-theme");
114
- var import_schema4 = require("@dxos/schema");
115
- var import_tracking6 = require("@preact-signals/safe-react/tracking");
116
- var import_react6 = __toESM(require("react"));
117
- var import_echo_schema7 = require("@dxos/echo-schema");
118
- var import_invariant3 = require("@dxos/invariant");
119
- var import_react_ui6 = require("@dxos/react-ui");
120
- var import_react_ui_editor = require("@dxos/react-ui-editor");
121
- var import_react_ui_grid4 = require("@dxos/react-ui-grid");
122
- var import_react_ui_tag_picker = require("@dxos/react-ui-tag-picker");
123
- var import_tracking7 = require("@preact-signals/safe-react/tracking");
124
- var import_react7 = __toESM(require("react"));
125
- var import_react_ui_grid5 = require("@dxos/react-ui-grid");
126
- var import_tracking8 = require("@preact-signals/safe-react/tracking");
127
- var import_react8 = __toESM(require("react"));
128
- var import_echo_schema8 = require("@dxos/echo-schema");
129
- var import_invariant4 = require("@dxos/invariant");
130
- var import_react_ui7 = require("@dxos/react-ui");
131
- var import_react_ui_form6 = require("@dxos/react-ui-form");
132
- var import_react_ui_grid6 = require("@dxos/react-ui-grid");
133
- var import_util2 = require("@dxos/util");
134
- var import_autocomplete = require("@codemirror/autocomplete");
135
- var import_view = require("@codemirror/view");
136
- var import_tracking9 = require("@preact-signals/safe-react/tracking");
137
- var import_react9 = __toESM(require("react"));
138
- var import_react_ui8 = require("@dxos/react-ui");
139
- var import_react_ui_theme3 = require("@dxos/react-ui-theme");
140
- var import_tracking10 = require("@preact-signals/safe-react/tracking");
141
- var import_signals_core6 = require("@preact/signals-core");
142
- var import_lodash2 = __toESM(require("lodash.orderby"));
143
- var import_react10 = require("react");
144
- var import_echo5 = require("@dxos/react-client/echo");
145
- var import_react_ui_attention2 = require("@dxos/react-ui-attention");
146
- var import_util3 = require("@dxos/util");
147
- var import_tracking11 = require("@preact-signals/safe-react/tracking");
148
- var import_rx_react = require("@effect-rx/rx-react");
149
- var import_react11 = __toESM(require("react"));
150
- var import_live_object2 = require("@dxos/live-object");
151
- var import_react_ui_menu = require("@dxos/react-ui-menu");
152
- var import_react_ui_menu2 = require("@dxos/react-ui-menu");
153
- var translationKey = "table";
154
- var translations_default = [
155
- {
156
- "en-US": {
157
- [translationKey]: {
158
- "object placeholder": "New table",
159
- "create object label": "Create table",
160
- "table name placeholder": "Table name",
161
- "settings title": "Table settings",
162
- "table schema label": "Schema",
163
- "new schema": "New schema",
164
- "continue label": "Continue",
165
- "create stack section label": "Create table",
166
- "add row label": "Add row",
167
- "create comment": "Create thread",
168
- "column action sort descending": "Sort Descending",
169
- "column action sort ascending": "Sort Ascending",
170
- "column action clear sorting": "Clear Sorting",
171
- "column action settings": "Column Settings",
172
- "column action delete": "Delete Column",
173
- "delete row label": "Delete row",
174
- "bulk delete row label": "Delete selected rows",
175
- "column deleted label": "Column deleted",
176
- "new column button label": "Create column",
177
- "create new object label": "Create new object \u201C{{text}}\u201D",
178
- "save view label": "Save changes to view"
179
- }
180
- }
181
- }
182
- ];
183
- var ColumnActionsMenu = ({ model, modals }) => {
184
- var _effect = (0, import_tracking2.useSignals)();
185
- try {
186
- const { t } = (0, import_react_ui2.useTranslation)(translationKey);
187
- const state = modals.state.value;
188
- if (state?.type !== "column") {
189
- return null;
190
- }
191
- const currentSort = model.sorting?.sorting;
192
- const isCurrentColumnSorted = currentSort?.fieldId === state.fieldId;
193
- return /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Root, {
194
- modal: false,
195
- open: true,
196
- onOpenChange: modals.close
197
- }, /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.VirtualTrigger, {
198
- virtualRef: modals.trigger
199
- }), /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Portal, null, /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Content, null, /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Viewport, null, (!isCurrentColumnSorted || currentSort?.direction === "asc") && /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
200
- "data-testid": "column-sort-descending",
201
- onClick: () => model.sorting?.setSort(state.fieldId, "desc")
202
- }, t("column action sort descending")), (!isCurrentColumnSorted || currentSort?.direction === "desc") && /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
203
- "data-testid": "column-sort-ascending",
204
- onClick: () => model.sorting?.setSort(state.fieldId, "asc")
205
- }, t("column action sort ascending")), isCurrentColumnSorted && /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
206
- "data-testid": "column-clear-sort",
207
- onClick: () => model.sorting?.clearSort()
208
- }, t("column action clear sorting")), model.getColumnCount() > 1 && model.features.schemaEditable && /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
209
- "data-testid": "column-delete",
210
- onClick: () => model.deleteColumn(state.fieldId)
211
- }, t("column action delete")), model.features.schemaEditable && /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Item, {
212
- "data-testid": "column-settings",
213
- onClick: () => modals.openColumnSettings()
214
- }, t("column action settings"))), /* @__PURE__ */ import_react2.default.createElement(import_react_ui2.DropdownMenu.Arrow, null))));
215
- } finally {
216
- _effect.f();
217
- }
218
- };
219
- var ColumnSettings = ({ model, modals, onNewColumn }) => {
220
- var _effect = (0, import_tracking3.useSignals)();
221
- try {
222
- const [newField, setNewField] = (0, import_react3.useState)();
223
- const state = modals.state.value;
224
- const space = model?.space;
225
- (0, import_react3.useEffect)(() => {
226
- if (state?.type === "columnSettings" && state.mode.type === "create" && model?.projection) {
227
- setNewField(model.projection.createFieldProjection());
228
- requestAnimationFrame(() => {
229
- onNewColumn();
230
- });
231
- } else {
232
- setNewField(void 0);
233
- }
234
- }, [
235
- model?.projection,
236
- state
237
- ]);
238
- const existingField = (0, import_react3.useMemo)(() => {
239
- if (state?.type === "columnSettings") {
240
- const { mode } = state;
241
- if (mode.type === "edit") {
242
- return model?.view?.fields.find((f) => f.id === mode.fieldId);
243
- }
244
- }
245
- return void 0;
246
- }, [
247
- model?.view?.fields,
248
- state
249
- ]);
250
- const field = existingField ?? newField;
251
- const handleSave = (0, import_react3.useCallback)(() => {
252
- modals.close();
253
- }, [
254
- modals
255
- ]);
256
- const handleCancel = (0, import_react3.useCallback)(() => {
257
- if (state?.type === "columnSettings" && state.mode.type === "create" && newField) {
258
- model?.projection?.deleteFieldProjection(newField.id);
259
- }
260
- }, [
261
- model?.projection,
262
- state,
263
- newField
264
- ]);
265
- if (!model?.view || !model.projection || !field) {
266
- return null;
267
- }
268
- return /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Popover.Root, {
269
- modal: false,
270
- open: state?.type === "columnSettings"
271
- }, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Popover.VirtualTrigger, {
272
- virtualRef: modals.trigger
273
- }), /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Popover.Portal, null, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Popover.Content, {
274
- classNames: "md:is-64"
275
- }, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Popover.Viewport, null, /* @__PURE__ */ import_react3.default.createElement(import_react_ui_form.FieldEditor, {
276
- view: model.view,
277
- projection: model.projection,
278
- field,
279
- registry: space?.db.schemaRegistry,
280
- onSave: handleSave,
281
- onCancel: handleCancel
282
- })), /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Popover.Arrow, null))));
283
- } finally {
284
- _effect.f();
285
- }
286
- };
287
- var CreateRefPanel = ({ model, modals, __gridScope }) => {
288
- var _effect = (0, import_tracking4.useSignals)();
289
- try {
290
- const { id: gridId } = (0, import_react_ui_grid2.useGridContext)("TableCellEditor", __gridScope);
291
- const space = model?.space;
292
- const state = modals.state.value;
293
- const schema = (0, import_react4.useMemo)(() => {
294
- if (!space || state?.type !== "createRefPanel") {
295
- return;
296
- }
297
- const [schema2] = space.db.schemaRegistry.query({
298
- typename: state.typename
299
- }).runSync();
300
- if (schema2) {
301
- const omit = import_effect.Schema.omit("id");
302
- return omit(schema2);
303
- }
304
- }, [
305
- space,
306
- state
307
- ]);
308
- const handleSave = (0, import_react4.useCallback)((values) => {
309
- if (!model || !space || state?.type !== "createRefPanel") {
310
- return;
311
- }
312
- const [schema2] = space.db.schemaRegistry.query({
313
- typename: state.typename
314
- }).runSync();
315
- if (schema2) {
316
- const obj = space.db.add((0, import_echo2.live)(schema2, values));
317
- state.onCreate?.(obj);
318
- }
319
- void modals.close();
320
- }, [
321
- modals,
322
- space,
323
- state
324
- ]);
325
- const handleCancel = (0, import_react4.useCallback)(() => {
326
- if (model) {
327
- modals.close();
328
- }
329
- }, [
330
- modals
331
- ]);
332
- if (!model?.view || !model.projection) {
333
- return null;
334
- }
335
- return /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Popover.Root, {
336
- modal: false,
337
- open: state?.type === "createRefPanel" && !!schema,
338
- onOpenChange: (nextOpen) => {
339
- if (model && !nextOpen) {
340
- return modals.close();
341
- }
342
- }
343
- }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Popover.VirtualTrigger, {
344
- virtualRef: modals.trigger
345
- }), /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Popover.Portal, null, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Popover.Content, {
346
- classNames: "md:is-64",
347
- "data-grid": gridId
348
- }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Popover.Viewport, null, state?.type === "createRefPanel" && schema && /* @__PURE__ */ import_react4.default.createElement(import_react_ui_form2.Form, {
349
- schema,
350
- values: state.initialValues ?? {},
351
- onSave: handleSave,
352
- onCancel: handleCancel
353
- })), /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Popover.Arrow, null))));
354
- } finally {
355
- _effect.f();
356
- }
357
- };
358
- var RowActionsMenu = ({ model, modals }) => {
359
- var _effect = (0, import_tracking5.useSignals)();
360
- try {
361
- const { t } = (0, import_react_ui5.useTranslation)(translationKey);
362
- const hasSelection = model.selection.hasSelection.value;
363
- const state = modals.state.value;
364
- if (state?.type !== "row") {
365
- return null;
366
- }
367
- return /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.DropdownMenu.Root, {
368
- modal: false,
369
- open: true,
370
- onOpenChange: modals.close
371
- }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.DropdownMenu.VirtualTrigger, {
372
- virtualRef: modals.trigger
373
- }), /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.DropdownMenu.Content, null, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.DropdownMenu.Viewport, null, model.features.dataEditable !== false && /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.DropdownMenu.Item, {
374
- "data-testid": "row-menu-delete",
375
- onClick: () => model.deleteRow(state.rowIndex)
376
- }, t(hasSelection ? "bulk delete row label" : "delete row label")), model.rowActions?.map((action) => /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.DropdownMenu.Item, {
377
- key: action.id,
378
- "data-testid": `row-action-${action.id}`,
379
- onClick: () => {
380
- modals.close();
381
- model.handleRowAction(action.id, state.rowIndex);
382
- }
383
- }, t(action.translationKey)))), /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.DropdownMenu.Arrow, null)));
384
- } finally {
385
- _effect.f();
386
- }
387
- };
388
- var getBaseSchema = ({ typename, properties, jsonSchema, schema }) => {
389
- if (typename && properties) {
390
- const schema2 = (0, import_schema2.getSchemaFromPropertyDefinitions)(typename, properties);
391
- return {
392
- typename: schema2.typename,
393
- jsonSchema: schema2.jsonSchema
394
- };
395
- } else if (schema) {
396
- return {
397
- typename: (0, import_echo_schema3.getTypename)(schema),
398
- jsonSchema: (0, import_echo_schema3.toJsonSchema)(schema)
399
- };
400
- } else if (typename && jsonSchema) {
401
- return {
402
- typename,
403
- jsonSchema
404
- };
405
- } else {
406
- throw new Error("invalid properties");
407
- }
408
- };
409
- var makeDynamicTable = ({ typename, jsonSchema, properties }) => {
410
- const view = (0, import_schema2.createView)({
411
- name: "dynamic-table",
412
- typename,
413
- jsonSchema,
414
- ...properties && {
415
- fields: properties.map((property) => property.name)
416
- }
417
- });
418
- const table = import_echo3.Obj.make(import_chunk_O2VPBNS5.TableType, {
419
- name: "dynamic-table",
420
- view: import_echo3.Ref.make(view)
421
- });
422
- const projection = new import_schema2.ViewProjection(jsonSchema, view);
423
- if (properties && view.fields) {
424
- setProperties(view, projection, properties);
425
- }
426
- return {
427
- table,
428
- projection
429
- };
430
- };
431
- var setProperties = (view, projection, properties) => {
432
- for (const property of properties) {
433
- const field = view.fields.find((field2) => field2.path === property.name);
434
- if (field) {
435
- if (property.size !== void 0) {
436
- field.size = property.size;
437
- }
438
- if (property.title !== void 0) {
439
- const fieldProjection = projection.getFieldProjection(field.id);
440
- projection.setFieldProjection({
441
- ...fieldProjection,
442
- props: {
443
- ...fieldProjection.props,
444
- title: property.title
445
- }
446
- });
447
- }
448
- if (property.sort) {
449
- const fieldId = field.id;
450
- view.query.sort = [
451
- {
452
- fieldId,
453
- direction: property.sort
454
- }
455
- ];
456
- }
457
- }
458
- }
459
- };
460
- var touch = (value) => value;
461
- var initializeTable = async ({ client, space, table, typename, initialRow = true }) => {
462
- if (typename) {
463
- const schema = await space.db.graph.getSchemaByTypename(typename, space.db);
464
- if (!schema) {
465
- throw new Error(`Schema not found: ${typename}`);
466
- }
467
- const fields = (0, import_schema3.getSchemaProperties)(schema.ast).map((prop) => prop.name);
468
- table.view = import_echo_schema4.Ref.make((0, import_schema3.createView)({
469
- // TODO(ZaymonFC): Don't hardcode name?
470
- name: "View",
471
- typename: schema.typename,
472
- jsonSchema: schema.jsonSchema,
473
- fields
474
- }));
475
- return schema;
476
- } else {
477
- const [schema] = await space.db.schemaRegistry.register([
478
- createContactSchema()
479
- ]);
480
- const fields = ContactFields;
481
- table.view = import_echo_schema4.Ref.make((0, import_schema3.createView)({
482
- name: "View",
483
- typename: schema.typename,
484
- jsonSchema: schema.jsonSchema,
485
- fields
486
- }));
487
- createProjection(schema, table.view.target);
488
- if (initialRow) {
489
- space.db.add((0, import_echo4.live)(schema, {}));
490
- }
491
- return schema;
492
- }
493
- };
494
- var createContactSchema = () => (0, import_echo_schema4.TypedObject)({
495
- typename: `example.com/type/${import_react_client.PublicKey.random().truncate()}`,
496
- version: "0.1.0"
497
- })({
498
- name: import_effect2.Schema.optional(import_effect2.Schema.String).annotations({
499
- title: "Name"
500
- }),
501
- active: import_effect2.Schema.optional(import_effect2.Schema.Boolean).annotations({
502
- title: "Active"
503
- }),
504
- email: import_effect2.Schema.optional(import_echo_schema4.Format.Email),
505
- salary: import_effect2.Schema.optional(import_echo_schema4.Format.Currency()).annotations({
506
- title: "Salary"
507
- })
508
- });
509
- var ContactFields = [
510
- "name",
511
- "email",
512
- "salary",
513
- "active"
514
- ];
515
- var createProjection = (schema, view) => {
516
- const projection = new import_schema3.ViewProjection(schema.jsonSchema, view);
517
- projection.setFieldProjection({
518
- field: {
519
- id: view.fields.find((f) => f.path === "salary").id,
520
- path: "salary",
521
- size: 150
522
- }
523
- });
524
- projection.setFieldProjection({
525
- field: {
526
- id: view.fields.find((f) => f.path === "active").id,
527
- path: "active",
528
- size: 100
529
- }
530
- });
531
- projection.setFieldProjection({
532
- field: {
533
- id: (0, import_schema3.createFieldId)(),
534
- path: "manager",
535
- referencePath: "name"
536
- },
537
- props: {
538
- property: "manager",
539
- type: import_echo_schema4.TypeEnum.Ref,
540
- format: import_echo_schema4.FormatEnum.Ref,
541
- referenceSchema: schema.typename,
542
- title: "Manager"
543
- }
544
- });
545
- return projection;
546
- };
547
- var BUTTON_IDENTIFIERS = {
548
- columnSettings: "data-table-column-settings-button",
549
- newColumn: "data-table-new-column-button",
550
- referencedCell: "data-table-ref-cell-button",
551
- rowMenu: "data-table-row-menu-button",
552
- sort: "data-table-sort-button"
553
- };
554
- var createButton = ({ attr, data, disabled = false, icon, testId, type = "primary" }) => {
555
- const dataAttrs = Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
556
- const positionClass = type === "primary" ? "inline-end-2" : "inline-end-9";
557
- return `<button ${attr} data-testid="${testId}" class="dx-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 ${positionClass}" ${dataAttrs} ${disabled ? "disabled" : ""}><svg data-size="4"><use href="/icons.svg#${icon}"/></svg></button>`;
558
- };
559
- var addColumnButton = {
560
- attr: BUTTON_IDENTIFIERS.newColumn,
561
- icon: "ph--plus--regular",
562
- render: ({ disabled }) => {
563
- return createButton({
564
- attr: BUTTON_IDENTIFIERS.newColumn,
565
- icon: addColumnButton.icon,
566
- disabled,
567
- data: {},
568
- testId: "table-new-column-button"
569
- });
570
- },
571
- getData: (_el) => ({
572
- type: "newColumn"
573
- })
574
- };
575
- var columnSettingsButton = {
576
- attr: BUTTON_IDENTIFIERS.columnSettings,
577
- icon: "ph--caret-down--regular",
578
- render: ({ fieldId }) => {
579
- return createButton({
580
- attr: BUTTON_IDENTIFIERS.columnSettings,
581
- icon: columnSettingsButton.icon,
582
- data: {
583
- "data-field-id": fieldId
584
- },
585
- testId: "table-column-settings-button"
586
- });
587
- },
588
- getData: (el) => ({
589
- type: "columnSettings",
590
- fieldId: el.getAttribute("data-field-id")
591
- })
592
- };
593
- var rowMenuButton = {
594
- attr: BUTTON_IDENTIFIERS.rowMenu,
595
- icon: "ph--dots-three--regular",
596
- render: ({ rowIndex }) => {
597
- return createButton({
598
- attr: BUTTON_IDENTIFIERS.rowMenu,
599
- icon: rowMenuButton.icon,
600
- data: {
601
- "data-row-index": rowIndex.toString()
602
- },
603
- testId: "table-row-menu-button"
604
- });
605
- },
606
- getData: (el) => ({
607
- type: "rowMenu",
608
- rowIndex: Number(el.getAttribute("data-row-index"))
609
- })
610
- };
611
- var sortButton = {
612
- attr: BUTTON_IDENTIFIERS.sort,
613
- icon: "ph--sort-ascending--regular",
614
- render: ({ fieldId, direction }) => {
615
- return createButton({
616
- attr: BUTTON_IDENTIFIERS.sort,
617
- icon: direction === "desc" ? "ph--sort-descending--regular" : "ph--sort-ascending--regular",
618
- data: {
619
- "data-field-id": fieldId,
620
- "data-direction": direction ?? ""
621
- },
622
- testId: "table-sort-button",
623
- // TODO(ZaymonFC): All buttons should be rendered into an absolutely positioned flex container.
624
- // This is a bit hacky.
625
- type: "secondary"
626
- });
627
- },
628
- getData: (el) => ({
629
- type: "sort",
630
- fieldId: el.getAttribute("data-field-id"),
631
- direction: el.getAttribute("data-direction")
632
- })
633
- };
634
- var tableButtons = {
635
- addColumn: addColumnButton,
636
- columnSettings: columnSettingsButton,
637
- rowMenu: rowMenuButton,
638
- sort: sortButton
639
- };
640
- var CONTROL_IDENTIFIERS = {
641
- checkbox: "data-table-checkbox",
642
- switch: "data-table-switch"
643
- };
644
- var BASE_CLASSES = {
645
- checkbox: "absolute inset-block-[.375rem] inline-end-[.375rem] dx-checkbox",
646
- switch: "absolute inset-block-[.25rem] inline-end-[.25rem] dx-checkbox--switch"
647
- };
648
- var renderAttributes = (data) => {
649
- return Object.entries(data).map(([k, v]) => `${k}="${v}"`).join(" ");
650
- };
651
- var renderInput = (baseClass, attrs, checked = false, disabled = false, preventToggle = false, testId) => {
652
- return `<input type="checkbox" class="${baseClass}" ${renderAttributes(attrs)} ${checked ? "checked" : ""} ${preventToggle ? 'onclick="return false"' : ""} ${disabled ? "disabled" : ""} data-testid="${testId}"/>`;
653
- };
654
- var CheckboxStory = ({ rowIndex, header = false, checked = false, disabled = false }) => {
655
- const attrs = {
656
- [CONTROL_IDENTIFIERS.checkbox]: "",
657
- "data-row-index": rowIndex.toString(),
658
- ...header && {
659
- "data-header": ""
660
- }
661
- };
662
- return renderInput(BASE_CLASSES.checkbox, attrs, checked, disabled, true, "table-selection");
663
- };
664
- var SwitchStory = ({ colIndex, rowIndex, checked = false, disabled = false }) => {
665
- const attrs = {
666
- [CONTROL_IDENTIFIERS.switch]: "",
667
- "data-row-index": rowIndex.toString(),
668
- "data-col-index": colIndex.toString()
669
- };
670
- return renderInput(BASE_CLASSES.switch, attrs, checked, disabled, true, "table-switch");
671
- };
672
- var tableControls = {
673
- checkbox: {
674
- attr: CONTROL_IDENTIFIERS.checkbox,
675
- render: CheckboxStory,
676
- getData: (el) => ({
677
- type: "checkbox",
678
- rowIndex: Number(el.getAttribute("data-row-index")),
679
- header: el.hasAttribute("data-header")
680
- })
681
- },
682
- switch: {
683
- attr: CONTROL_IDENTIFIERS.switch,
684
- render: SwitchStory,
685
- getData: (el) => ({
686
- type: "switch",
687
- rowIndex: Number(el.getAttribute("data-row-index")),
688
- colIndex: Number(el.getAttribute("data-col-index"))
689
- })
690
- }
691
- };
692
- var narrowSchema = (schema, paths) => {
693
- const ast = schema?.ast;
694
- if ((0, import_SchemaAST.isTypeLiteral)(ast)) {
695
- const propertySignatures = ast.propertySignatures.filter((signature) => paths.includes(signature.name.toString()));
696
- if (propertySignatures.length > 0) {
697
- const narrowType = new import_SchemaAST.TypeLiteral(propertySignatures, []);
698
- return import_effect3.Schema.make(narrowType);
699
- }
700
- }
701
- return void 0;
702
- };
703
- var SelectionModel = class extends import_context2.Resource {
704
- constructor(_rows, _selectionMode, _onSelectionChanged) {
705
- super(), this._rows = _rows, this._selectionMode = _selectionMode, this._onSelectionChanged = _onSelectionChanged, this._selection = (0, import_signals_core2.signal)(/* @__PURE__ */ new Set()), this._validSelectedIds = (0, import_signals_core2.computed)(() => {
706
- const rows = this._rows.value;
707
- if (!rows) {
708
- return /* @__PURE__ */ new Set();
709
- }
710
- const validIds = new Set(rows.map((row) => row.id));
711
- return new Set([
712
- ...this._selection.value
713
- ].filter((id) => validIds.has(id)));
714
- }), this._hasSelection = (0, import_signals_core2.computed)(() => this._validSelectedIds.value.size > 0), this._allSelected = (0, import_signals_core2.computed)(() => {
715
- const rows = this._rows.value;
716
- if (rows.length === 0) {
717
- return false;
718
- }
719
- return rows.every((row) => this._selection.value.has(row.id));
720
- }), this.getSelectedRows = () => {
721
- const selectedIds = this._validSelectedIds.value;
722
- return this._rows.value.filter((row) => selectedIds.has(row.id));
723
- }, this.isRowIndexSelected = (rowIndex) => {
724
- const row = this._rows.value[rowIndex];
725
- return this._selection.value.has(row.id);
726
- }, this.isObjectSelected = (object) => {
727
- return this._selection.value.has(object.id);
728
- }, this.toggleSelectionForRowIndex = (rowIndex) => {
729
- const row = this._rows.value[rowIndex];
730
- const newSelection = new Set(this._selection.value);
731
- if (newSelection.has(row.id)) {
732
- newSelection.delete(row.id);
733
- } else {
734
- if (this._selectionMode === "single") {
735
- newSelection.clear();
736
- }
737
- newSelection.add(row.id);
738
- }
739
- this._selection.value = newSelection;
740
- }, this.setSelection = (mode) => {
741
- switch (mode) {
742
- case "all": {
743
- this._selection.value = new Set(this._rows.value.map((row) => row.id));
744
- break;
745
- }
746
- case "none": {
747
- this._selection.value = /* @__PURE__ */ new Set();
748
- break;
749
- }
750
- }
751
- };
752
- }
753
- async _open() {
754
- const selectionWatcher = (0, import_signals_core2.effect)(() => {
755
- touch(this._selection.value);
756
- this._onSelectionChanged?.();
757
- });
758
- this._ctx.onDispose(selectionWatcher);
759
- }
760
- //
761
- // Getters
762
- //
763
- get selection() {
764
- return this._selection;
765
- }
766
- get hasSelection() {
767
- return this._hasSelection;
768
- }
769
- get allRowsSeleted() {
770
- return this._allSelected;
771
- }
772
- get selectionMode() {
773
- return this._selectionMode;
774
- }
775
- };
776
- var TableSorting = class {
777
- constructor(rows, _view, _projection) {
778
- this._view = _view;
779
- this._projection = _projection;
780
- this._displayToDataIndex = /* @__PURE__ */ new Map();
781
- this._localSort = (0, import_signals_core3.signal)(void 0);
782
- this._rows = rows;
783
- this._isDirty = (0, import_signals_core3.computed)(() => {
784
- const local = this._localSort.value;
785
- const viewSort = this._view?.query.sort?.[0];
786
- if (local?.type === "cleared") {
787
- return viewSort !== void 0;
788
- }
789
- if (local?.type === "active") {
790
- if (!viewSort) {
791
- return true;
792
- }
793
- return local.sort.fieldId !== viewSort.fieldId || local.sort.direction !== viewSort.direction;
794
- }
795
- return false;
796
- });
797
- this.sortedRows = this.initialiseSortedRows();
798
- }
799
- /**
800
- * @reactive
801
- * @returns Local sort if present, falls back to view sort.
802
- */
803
- get sorting() {
804
- const local = this._localSort.value;
805
- if (local?.type === "cleared") {
806
- return void 0;
807
- }
808
- if (local?.type === "active") {
809
- return local.sort;
810
- }
811
- return this._view?.query.sort?.[0];
812
- }
813
- /**
814
- * @reactive
815
- * @returns Whether local sort differs from view sort.
816
- */
817
- get isDirty() {
818
- return this._isDirty.value;
819
- }
820
- getDataIndex(displayIndex) {
821
- return this._displayToDataIndex.get(displayIndex) ?? displayIndex;
822
- }
823
- setSort(fieldId, direction) {
824
- this._localSort.value = {
825
- type: "active",
826
- sort: {
827
- fieldId,
828
- direction
829
- }
830
- };
831
- }
832
- toggleSort(fieldId) {
833
- if (!this._view || !this.sorting || this.sorting.fieldId !== fieldId) {
834
- return;
835
- }
836
- switch (this.sorting.direction) {
837
- case "asc": {
838
- this.setSort(fieldId, "desc");
839
- break;
840
- }
841
- case "desc": {
842
- this.setSort(fieldId, "asc");
843
- break;
844
- }
845
- }
846
- }
847
- clearSort() {
848
- this._localSort.value = {
849
- type: "cleared"
850
- };
851
- }
852
- save() {
853
- if (this._view && this._localSort.value !== void 0) {
854
- if (this._localSort.value.type === "active") {
855
- this._view.query.sort = [
856
- this._localSort.value.sort
857
- ];
858
- } else {
859
- this._view.query.sort = [];
860
- }
861
- this._localSort.value = void 0;
862
- }
863
- }
864
- //
865
- // Initialisation.
866
- //
867
- initialiseSortedRows() {
868
- return (0, import_signals_core3.computed)(() => {
869
- this._displayToDataIndex.clear();
870
- const sort = this.sorting;
871
- if (!sort || !this._view) {
872
- return this._rows.value;
873
- }
874
- const field = this._view.fields.find((f) => f.id === sort.fieldId);
875
- if (!field) {
876
- return this._rows.value;
877
- }
878
- const { props } = this._projection.getFieldProjection(field.id);
879
- const dataWithIndices = this._rows.value.map((item, index) => {
880
- const sortValue = this.getSortValue(props, field, item);
881
- const isEmpty = !(props.type === import_echo_schema5.TypeEnum.Boolean) && (sortValue == null || sortValue === "");
882
- return {
883
- item,
884
- index,
885
- value: sortValue,
886
- isEmpty
887
- };
888
- });
889
- const ordered = (0, import_lodash.default)(dataWithIndices, [
890
- "isEmpty",
891
- "value"
892
- ], [
893
- "asc",
894
- sort.direction
895
- ]);
896
- ordered.forEach(({ index: dataIndex }, displayIndex) => {
897
- if (displayIndex !== dataIndex) {
898
- this._displayToDataIndex.set(displayIndex, dataIndex);
899
- }
900
- });
901
- return ordered.map(({ item }) => item);
902
- });
903
- }
904
- getSortValue(props, field, item) {
905
- const { type, format } = props;
906
- const value = (0, import_echo_schema5.getValue)(item, field.path);
907
- if (type === import_echo_schema5.TypeEnum.Boolean) {
908
- return !!value;
909
- }
910
- if (type === import_echo_schema5.TypeEnum.Number) {
911
- return value;
912
- }
913
- if (value == null) {
914
- return value;
915
- }
916
- if (format === import_echo_schema5.FormatEnum.SingleSelect) {
917
- const options = props.options;
918
- if (!options) {
919
- return void 0;
920
- }
921
- const option = options.find((option2) => option2.id === value);
922
- return option ? options.indexOf(option) : void 0;
923
- }
924
- if (format === import_echo_schema5.FormatEnum.Ref && field.referencePath) {
925
- const refValue = (0, import_echo_schema5.getValue)(value.target, field.referencePath);
926
- return refValue;
927
- }
928
- return (0, import_react_ui_form4.formatForDisplay)({
929
- type,
930
- format,
931
- value
932
- });
933
- }
934
- };
935
- var TAG_PATTERN_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
936
- var extractTagIds = (value) => {
937
- if (typeof value !== "string") {
938
- return void 0;
939
- }
940
- const ids = [];
941
- let match;
942
- while ((match = TAG_PATTERN_REGEX.exec(value)) !== null) {
943
- if (match[2]) {
944
- ids.push(match[2]);
945
- }
946
- }
947
- return ids.length > 0 ? ids : void 0;
948
- };
949
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/table-model.ts";
950
- var defaultFeatures = {
951
- selection: {
952
- enabled: true,
953
- mode: "multiple"
954
- },
955
- dataEditable: false,
956
- schemaEditable: false
957
- };
958
- var TableModel = class extends import_context.Resource {
959
- constructor({ id, space, view, projection, features = {}, sorting = [], pinnedRows = {
960
- top: [],
961
- bottom: []
962
- }, rowActions = [], onCellUpdate, onDeleteColumn, onDeleteRows, onInsertRow, onRowOrderChange, onRowAction }) {
963
- super();
964
- this._visibleRange = (0, import_signals_core.signal)({
965
- start: {
966
- row: 0,
967
- col: 0
968
- },
969
- end: {
970
- row: 0,
971
- col: 0
972
- }
973
- });
974
- this._rows = (0, import_signals_core.signal)([]);
975
- this.setRows = (obj) => {
976
- this._rows.value = obj;
977
- };
978
- this.getRowCount = () => this._rows.value.length;
979
- this.getColumnCount = () => this._view?.fields.length ?? 0;
980
- this.insertRow = (rowIndex) => {
981
- const row = rowIndex !== void 0 ? this._sorting.getDataIndex(rowIndex) : this._rows.value.length;
982
- this._onInsertRow?.(row);
983
- };
984
- this.deleteRow = (rowIndex) => {
985
- const row = this._sorting.getDataIndex(rowIndex);
986
- const obj = this._rows.value[row];
987
- const objectsToDelete = [];
988
- if (this.features.selection.enabled && this._selection.hasSelection.value) {
989
- const selectedRows = this._selection.getSelectedRows();
990
- objectsToDelete.push(...selectedRows);
991
- } else {
992
- objectsToDelete.push(obj);
993
- }
994
- this._onDeleteRows?.(row, objectsToDelete);
995
- };
996
- this.handleRowAction = (actionId, rowIndex) => {
997
- if (!this._onRowAction) {
998
- return;
999
- }
1000
- const row = this._sorting.getDataIndex(rowIndex);
1001
- const data = this._rows.value[row];
1002
- if (data) {
1003
- this._onRowAction(actionId, data);
1004
- }
1005
- };
1006
- this.getCellData = ({ col, row }) => {
1007
- const fields = this._view?.fields ?? [];
1008
- if (col < 0 || col >= fields.length) {
1009
- return void 0;
1010
- }
1011
- const field = fields[col];
1012
- const dataIndex = this._sorting.getDataIndex(row);
1013
- const value = (0, import_echo_schema2.getValue)(this._rows.value[dataIndex], field.path);
1014
- if (value == null) {
1015
- return "";
1016
- }
1017
- const { props } = this._projection.getFieldProjection(field.id);
1018
- switch (props.format) {
1019
- case import_echo_schema2.FormatEnum.Ref: {
1020
- if (!field.referencePath) {
1021
- return "";
1022
- }
1023
- return (0, import_echo_schema2.getValue)(value.target, field.referencePath);
1024
- }
1025
- default: {
1026
- return (0, import_react_ui_form3.formatForEditing)({
1027
- type: props.type,
1028
- format: props.format,
1029
- value
1030
- });
1031
- }
1032
- }
1033
- };
1034
- this.validateCellData = async ({ col, row }, value) => {
1035
- const rowIdx = this._sorting.getDataIndex(row);
1036
- const fields = this._view?.fields ?? [];
1037
- if (col < 0 || col >= fields.length) {
1038
- return {
1039
- valid: false,
1040
- error: "Invalid column index"
1041
- };
1042
- }
1043
- const field = fields[col];
1044
- const { props } = this._projection.getFieldProjection(field.id);
1045
- const currentRow = this._rows.value[rowIdx];
1046
- (0, import_invariant2.invariant)(currentRow, "Invalid row index", {
1047
- F: __dxlog_file,
1048
- L: 355,
1049
- S: this,
1050
- A: [
1051
- "currentRow",
1052
- "'Invalid row index'"
1053
- ]
1054
- });
1055
- const snapshot = (0, import_echo_schema2.getSnapshot)(currentRow);
1056
- const transformedValue = editorTextToCellValue(props, value);
1057
- (0, import_echo_schema2.setValue)(snapshot, field.path, transformedValue);
1058
- const schema = (0, import_echo_schema2.getSchema)(currentRow);
1059
- (0, import_invariant2.invariant)(schema, void 0, {
1060
- F: __dxlog_file,
1061
- L: 365,
1062
- S: this,
1063
- A: [
1064
- "schema",
1065
- ""
1066
- ]
1067
- });
1068
- const validationResult = (0, import_schema.validateSchema)(schema, snapshot);
1069
- if (validationResult && validationResult.length > 0) {
1070
- const error = validationResult[0];
1071
- (0, import_invariant2.invariant)(error.path === field.path, void 0, {
1072
- F: __dxlog_file,
1073
- L: 370,
1074
- S: this,
1075
- A: [
1076
- "error.path === field.path",
1077
- ""
1078
- ]
1079
- });
1080
- return {
1081
- valid: false,
1082
- error: error.message
1083
- };
1084
- }
1085
- return {
1086
- valid: true
1087
- };
1088
- };
1089
- this.setCellData = ({ col, row }, value) => {
1090
- const rowIdx = this._sorting.getDataIndex(row);
1091
- const fields = this._view?.fields ?? [];
1092
- if (col < 0 || col >= fields.length) {
1093
- return;
1094
- }
1095
- const field = fields[col];
1096
- const { props } = this._projection.getFieldProjection(field.id);
1097
- const transformedValue = editorTextToCellValue(props, value);
1098
- if (props.format === import_echo_schema2.FormatEnum.Ref && !(0, import_live_object.isLiveObject)(value)) {
1099
- return;
1100
- }
1101
- (0, import_echo_schema2.setValue)(this._rows.value[rowIdx], field.path, transformedValue);
1102
- };
1103
- this._id = id;
1104
- this._space = space;
1105
- this._view = view;
1106
- this._projection = projection;
1107
- this._features = {
1108
- ...defaultFeatures,
1109
- ...features
1110
- };
1111
- (0, import_invariant2.invariant)(!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === "single"), "Single selection is not compatible with editable tables.", {
1112
- F: __dxlog_file,
1113
- L: 126,
1114
- S: this,
1115
- A: [
1116
- "!(this._features.dataEditable && this._features.selection.enabled && this._features.selection.mode === 'single')",
1117
- "'Single selection is not compatible with editable tables.'"
1118
- ]
1119
- });
1120
- this._sorting = new TableSorting(this._rows, this._view, projection);
1121
- if (sorting.length > 0) {
1122
- const [sort] = sorting;
1123
- this._sorting.setSort(sort.fieldId, sort.direction);
1124
- }
1125
- this._pinnedRows = pinnedRows;
1126
- this._rowActions = rowActions;
1127
- this._onInsertRow = onInsertRow;
1128
- this._onDeleteRows = onDeleteRows;
1129
- this._onDeleteColumn = onDeleteColumn;
1130
- this._onCellUpdate = onCellUpdate;
1131
- this._onRowOrderChange = onRowOrderChange;
1132
- this._onRowAction = onRowAction;
1133
- }
1134
- get id() {
1135
- return this._id;
1136
- }
1137
- get space() {
1138
- return this._space;
1139
- }
1140
- get view() {
1141
- return this._view;
1142
- }
1143
- get projection() {
1144
- return this._projection;
1145
- }
1146
- get rows() {
1147
- return this._sorting.sortedRows;
1148
- }
1149
- get features() {
1150
- return this._features;
1151
- }
1152
- /**
1153
- * @reactive
1154
- */
1155
- get sorting() {
1156
- return this._sorting;
1157
- }
1158
- /**
1159
- * Gets the row data at the specified display index.
1160
- */
1161
- getRowAt(displayIndex) {
1162
- if (displayIndex < 0 || displayIndex >= this._sorting.sortedRows.value.length) {
1163
- return void 0;
1164
- }
1165
- return this._sorting.sortedRows.value[displayIndex];
1166
- }
1167
- get pinnedRows() {
1168
- return this._pinnedRows;
1169
- }
1170
- get columnMeta() {
1171
- (0, import_invariant2.invariant)(this._columnMeta, void 0, {
1172
- F: __dxlog_file,
1173
- L: 195,
1174
- S: this,
1175
- A: [
1176
- "this._columnMeta",
1177
- ""
1178
- ]
1179
- });
1180
- return this._columnMeta;
1181
- }
1182
- get selection() {
1183
- return this._selection;
1184
- }
1185
- /** @reactive */
1186
- get isViewDirty() {
1187
- return this._sorting.isDirty;
1188
- }
1189
- get rowActions() {
1190
- return this._rowActions;
1191
- }
1192
- //
1193
- // Initialisation
1194
- //
1195
- async _open() {
1196
- this.initializeColumnMeta();
1197
- this.initializeEffects();
1198
- this._selection = new SelectionModel(this._sorting.sortedRows, this._features.selection.mode ?? "multiple", () => this._onRowOrderChange?.());
1199
- await this._selection.open(this._ctx);
1200
- }
1201
- initializeColumnMeta() {
1202
- this._columnMeta = (0, import_signals_core.computed)(() => {
1203
- const fields = this._view?.fields ?? [];
1204
- const meta = Object.fromEntries(fields.map((field, index) => [
1205
- index,
1206
- {
1207
- size: field?.size ?? 256,
1208
- resizeable: true
1209
- }
1210
- ]));
1211
- return {
1212
- grid: meta,
1213
- frozenColsStart: {
1214
- 0: {
1215
- size: 30,
1216
- resizeable: false
1217
- }
1218
- },
1219
- frozenColsEnd: {
1220
- 0: {
1221
- size: 40,
1222
- resizeable: false
1223
- }
1224
- }
1225
- };
1226
- });
1227
- }
1228
- initializeEffects() {
1229
- const rowOrderWatcher = (0, import_signals_core.effect)(() => {
1230
- touch(this._sorting.sortedRows.value);
1231
- this._onRowOrderChange?.();
1232
- });
1233
- this._ctx.onDispose(rowOrderWatcher);
1234
- const rowEffectManager = (0, import_signals_core.effect)(() => {
1235
- const { start, end } = touch(this._visibleRange.value);
1236
- const rowEffects = [];
1237
- for (let row = start.row; row <= end.row; row++) {
1238
- rowEffects.push((0, import_signals_core.effect)(() => {
1239
- const obj = this._sorting.sortedRows.value[row];
1240
- this._view?.fields.forEach((field) => touch((0, import_echo_schema2.getValue)(obj, field.path)));
1241
- this._onCellUpdate?.({
1242
- row,
1243
- col: start.col,
1244
- plane: "grid"
1245
- });
1246
- }));
1247
- }
1248
- return () => rowEffects.forEach((cleanup) => cleanup());
1249
- });
1250
- this._ctx.onDispose(rowEffectManager);
1251
- }
1252
- /**
1253
- * Updates a cell's value using a transform function.
1254
- * @param {DxGridPlanePosition} position - The position of the cell to update.
1255
- * @param {(value: any) => any} update - A function that takes the current value and returns the updated value.
1256
- */
1257
- updateCellData({ col, row }, update) {
1258
- const dataRow = this._sorting.getDataIndex(row);
1259
- const fields = this._view?.fields ?? [];
1260
- const field = fields[col];
1261
- const value = (0, import_echo_schema2.getValue)(this._rows.value[dataRow], field.path);
1262
- const updatedValue = update(value);
1263
- (0, import_echo_schema2.setValue)(this._rows.value[dataRow], field.path, updatedValue);
1264
- }
1265
- //
1266
- // Column Operations
1267
- //
1268
- deleteColumn(fieldId) {
1269
- if (!this._view) {
1270
- return;
1271
- }
1272
- const field = this._view?.fields.find((field2) => field2.id === fieldId);
1273
- if (field && this._onDeleteColumn) {
1274
- this._onDeleteColumn(field.id);
1275
- }
1276
- }
1277
- //
1278
- // Resize
1279
- //
1280
- setColumnWidth(columnIndex, width) {
1281
- const fields = this._view?.fields ?? [];
1282
- if (columnIndex < fields.length) {
1283
- const newWidth = Math.max(0, width);
1284
- const field = fields[columnIndex];
1285
- if (field) {
1286
- field.size = newWidth;
1287
- }
1288
- }
1289
- }
1290
- //
1291
- // Pinning
1292
- //
1293
- // TODO(burdon): Change to setPinned(on/off).
1294
- pinRow(rowIndex, side) {
1295
- this._pinnedRows[side].push(rowIndex);
1296
- }
1297
- unpinRow(rowIndex) {
1298
- this._pinnedRows.top = this._pinnedRows.top.filter((index) => index !== rowIndex);
1299
- this._pinnedRows.bottom = this._pinnedRows.bottom.filter((index) => index !== rowIndex);
1300
- }
1301
- //
1302
- // View operations
1303
- //
1304
- saveView() {
1305
- this._sorting.save();
1306
- }
1307
- };
1308
- var editorTextToCellValue = (props, value) => {
1309
- switch (props.format) {
1310
- case import_echo_schema2.FormatEnum.Ref: {
1311
- if ((0, import_live_object.isLiveObject)(value)) {
1312
- return (0, import_live_object.makeRef)(value);
1313
- } else {
1314
- return value;
1315
- }
1316
- }
1317
- case import_echo_schema2.FormatEnum.SingleSelect: {
1318
- const ids = extractTagIds(value);
1319
- if (ids && ids.length > 0) {
1320
- return ids[0];
1321
- } else {
1322
- return value;
1323
- }
1324
- }
1325
- case import_echo_schema2.FormatEnum.MultiSelect: {
1326
- const ids = extractTagIds(value);
1327
- return ids || value;
1328
- }
1329
- default: {
1330
- return (0, import_react_ui_form3.parseValue)({
1331
- type: props.type,
1332
- format: props.format,
1333
- value
1334
- });
1335
- }
1336
- }
1337
- };
1338
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/model/modal-controller.ts";
1339
- var ModalController = class {
1340
- constructor() {
1341
- this._state = (0, import_signals_core4.signal)({
1342
- type: "closed"
1343
- });
1344
- this._triggerRef = {
1345
- current: null
1346
- };
1347
- this.setTrigger = (trigger) => {
1348
- this._triggerRef.current = trigger;
1349
- };
1350
- this.showRowMenu = (rowIndex) => {
1351
- this._state.value = {
1352
- type: "row",
1353
- rowIndex
1354
- };
1355
- };
1356
- this.showColumnMenu = (fieldId) => {
1357
- this._state.value = {
1358
- type: "column",
1359
- fieldId
1360
- };
1361
- };
1362
- this.showColumnCreator = () => {
1363
- this._state.value = {
1364
- type: "columnSettings",
1365
- mode: {
1366
- type: "create"
1367
- }
1368
- };
1369
- };
1370
- this.showReferencePanel = (targetId, schemaId) => {
1371
- this._state.value = {
1372
- type: "refPanel",
1373
- targetId,
1374
- typename: schemaId
1375
- };
1376
- };
1377
- this.openColumnSettings = () => {
1378
- if (this._state.value.type === "column") {
1379
- const fieldId = this._state.value.fieldId;
1380
- requestAnimationFrame(() => {
1381
- this._state.value = {
1382
- type: "columnSettings",
1383
- mode: {
1384
- type: "edit",
1385
- fieldId
1386
- }
1387
- };
1388
- });
1389
- }
1390
- };
1391
- this.openCreateRef = (typename, anchorCell, initialValues, onCreate) => {
1392
- if (anchorCell) {
1393
- this._triggerRef.current = anchorCell;
1394
- this._state.value = {
1395
- type: "createRefPanel",
1396
- typename,
1397
- initialValues,
1398
- onCreate
1399
- };
1400
- } else {
1401
- import_log.log.warn("anchor cell not found while creating new ref", void 0, {
1402
- F: __dxlog_file2,
1403
- L: 86,
1404
- S: this,
1405
- C: (f, a) => f(...a)
1406
- });
1407
- }
1408
- };
1409
- this.close = () => {
1410
- this._state.value = {
1411
- type: "closed"
1412
- };
1413
- };
1414
- }
1415
- get state() {
1416
- return this._state;
1417
- }
1418
- get trigger() {
1419
- return this._triggerRef;
1420
- }
1421
- };
1422
- var TablePresentation = class {
1423
- constructor(model, _visibleRange = (0, import_signals_core5.signal)({
1424
- start: {
1425
- row: 0,
1426
- col: 0
1427
- },
1428
- end: {
1429
- row: 0,
1430
- col: 0
1431
- }
1432
- })) {
1433
- this.model = model;
1434
- this._visibleRange = _visibleRange;
1435
- }
1436
- getCells(range, plane) {
1437
- let cells;
1438
- switch (plane) {
1439
- case "grid":
1440
- this._visibleRange.value = range;
1441
- cells = this.getMainGridCells(range);
1442
- break;
1443
- case "frozenRowsStart":
1444
- cells = this.getHeaderCells(range);
1445
- break;
1446
- case "frozenColsStart":
1447
- cells = this.getSelectionColumnCells(range);
1448
- break;
1449
- case "frozenColsEnd":
1450
- cells = this.getActionColumnCells(range);
1451
- break;
1452
- case "fixedStartStart":
1453
- cells = this.getSelectAllCell();
1454
- break;
1455
- case "fixedStartEnd":
1456
- cells = this.getNewColumnCell();
1457
- break;
1458
- default:
1459
- cells = {};
1460
- }
1461
- if (plane === "grid" && this.model.features.dataEditable === false) {
1462
- Object.values(cells).forEach((cell) => {
1463
- cell.readonly = "text-select";
1464
- });
1465
- }
1466
- return cells;
1467
- }
1468
- getMainGridCells(range) {
1469
- const cells = {};
1470
- const fields = this.model.view?.fields ?? [];
1471
- const addCell = (obj, field, colIndex, displayIndex) => {
1472
- const { props } = this.model.projection.getFieldProjection(field.id);
1473
- const cell = {
1474
- get value() {
1475
- const value = (0, import_echo_schema6.getValue)(obj, field.path);
1476
- if (value == null) {
1477
- return "";
1478
- }
1479
- if (props.type === "array") {
1480
- return "";
1481
- }
1482
- switch (props.format) {
1483
- case import_echo_schema6.FormatEnum.Boolean:
1484
- case import_echo_schema6.FormatEnum.SingleSelect:
1485
- case import_echo_schema6.FormatEnum.MultiSelect: {
1486
- return "";
1487
- }
1488
- case import_echo_schema6.FormatEnum.Ref: {
1489
- if (!field.referencePath) {
1490
- return "";
1491
- }
1492
- return (0, import_echo_schema6.getValue)(value.target, field.referencePath);
1493
- }
1494
- default: {
1495
- return (0, import_react_ui_form5.formatForDisplay)({
1496
- type: props.type,
1497
- format: props.format,
1498
- value
1499
- });
1500
- }
1501
- }
1502
- }
1503
- };
1504
- const classes = [];
1505
- const formatClasses = (0, import_react_ui_form5.cellClassesForFieldType)({
1506
- type: props.type,
1507
- format: props.format
1508
- });
1509
- if (formatClasses) {
1510
- classes.push(formatClasses);
1511
- }
1512
- const rowSelectionClasses = cellClassesForRowSelection(this.model.selection.isObjectSelected(obj), this.model.selection.selectionMode);
1513
- if (rowSelectionClasses) {
1514
- classes.push(rowSelectionClasses);
1515
- }
1516
- if (classes.length > 0) {
1517
- cell.className = (0, import_react_ui_theme2.mx)(classes.flat());
1518
- }
1519
- if (props.type === import_echo_schema6.TypeEnum.Array) {
1520
- const targetArray = (0, import_echo_schema6.getValue)(obj, field.path);
1521
- if (targetArray && Array.isArray(targetArray)) {
1522
- const getLabel = (value) => {
1523
- if (!value) {
1524
- return void 0;
1525
- }
1526
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1527
- return String(value);
1528
- }
1529
- if (Array.isArray(value)) {
1530
- return "Array";
1531
- }
1532
- if (typeof value === "object" && value.name) {
1533
- return value.name;
1534
- }
1535
- if (typeof value === "object" && value.value) {
1536
- return `${value.value}`;
1537
- }
1538
- return "Object";
1539
- };
1540
- const tags = targetArray.map(getLabel).filter(import_Predicate.isNotNullable).map((title) => {
1541
- return `<span class="dx-tag rounded-xl" data-hue="neutral">${title}</span>`;
1542
- }).join("");
1543
- cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1 overflow-x-auto">${tags}</div>`;
1544
- }
1545
- }
1546
- if (props.format === import_echo_schema6.FormatEnum.Ref && props.referenceSchema) {
1547
- const targetObj = (0, import_echo_schema6.getValue)(obj, field.path)?.target;
1548
- if (targetObj) {
1549
- const dxn = (0, import_echo_schema6.getObjectDXN)(targetObj)?.toString();
1550
- cell.accessoryHtml = `<dx-ref-tag refId=${dxn} class="dx-button is-6 pli-[3px] pbe-[2px] min-bs-0 absolute inline-end-1"><dx-icon icon="ph--link-simple--regular"/></dx-ref-tag>`;
1551
- }
1552
- }
1553
- if (props.format === import_echo_schema6.FormatEnum.Boolean) {
1554
- const value = (0, import_echo_schema6.getValue)(obj, field.path);
1555
- cell.accessoryHtml = tableControls.switch.render({
1556
- colIndex,
1557
- rowIndex: displayIndex,
1558
- checked: value ?? false
1559
- });
1560
- cell.readonly = "no-text-select";
1561
- }
1562
- if (props.format === import_echo_schema6.FormatEnum.SingleSelect) {
1563
- const value = (0, import_echo_schema6.getValue)(obj, field.path);
1564
- const options = this.model.projection.getFieldProjection(field.id).props.options;
1565
- if (options) {
1566
- const option = options.find((o) => o.id === value);
1567
- if (option) {
1568
- cell.accessoryHtml = `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
1569
- }
1570
- }
1571
- }
1572
- if (props.format === import_echo_schema6.FormatEnum.MultiSelect) {
1573
- const values = (0, import_echo_schema6.getValue)(obj, field.path);
1574
- const options = this.model.projection.getFieldProjection(field.id).props.options;
1575
- if (options && values && values.length > 0) {
1576
- const tags = values.map((value) => {
1577
- const option = options.find((o) => o.id === value);
1578
- if (option) {
1579
- return `<span class="dx-tag" data-hue="${option.color}">${option.title}</span>`;
1580
- }
1581
- return null;
1582
- }).filter(Boolean).join(" ");
1583
- if (tags) {
1584
- cell.accessoryHtml = `<div role='none' class="flex flex-row gap-1">${tags}</div>`;
1585
- }
1586
- }
1587
- }
1588
- const idx = (0, import_react_ui_grid3.toPlaneCellIndex)({
1589
- col: colIndex,
1590
- row: displayIndex
1591
- });
1592
- cells[idx] = cell;
1593
- };
1594
- for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
1595
- for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1596
- const field = fields[col];
1597
- if (!field) {
1598
- continue;
1599
- }
1600
- addCell(this.model.rows.value[row], field, col, row);
1601
- }
1602
- }
1603
- return cells;
1604
- }
1605
- getHeaderCells(range) {
1606
- const cells = {};
1607
- const fields = this.model.view?.fields ?? [];
1608
- for (let col = range.start.col; col <= range.end.col && col < fields.length; col++) {
1609
- const { field, props } = this.model.projection.getFieldProjection(fields[col].id);
1610
- const sorting = this.model.sorting?.sorting;
1611
- const direction = sorting?.fieldId === field.id ? sorting.direction : void 0;
1612
- cells[(0, import_react_ui_grid3.toPlaneCellIndex)({
1613
- col,
1614
- row: 0
1615
- })] = {
1616
- // TODO(burdon): Use same logic as form for fallback title.
1617
- value: props.title ?? field.path,
1618
- readonly: true,
1619
- resizeHandle: "col",
1620
- accessoryHtml: `
1621
- ${direction !== void 0 ? tableButtons.sort.render({
1622
- fieldId: field.id,
1623
- direction
1624
- }) : ""}
1625
- ${tableButtons.columnSettings.render({
1626
- fieldId: field.id
1627
- })}
1628
- `,
1629
- className: "!bg-toolbarSurface"
1630
- };
1631
- }
1632
- return cells;
1633
- }
1634
- getSelectionColumnCells(range) {
1635
- const cells = {};
1636
- for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
1637
- const isSelected = this.model.selection.isRowIndexSelected(row);
1638
- const classes = cellClassesForRowSelection(isSelected, this.model.selection.selectionMode);
1639
- cells[(0, import_react_ui_grid3.toPlaneCellIndex)({
1640
- col: 0,
1641
- row
1642
- })] = {
1643
- value: "",
1644
- readonly: "no-text-select",
1645
- className: classes ? (0, import_react_ui_theme2.mx)(classes) : void 0,
1646
- accessoryHtml: tableControls.checkbox.render({
1647
- rowIndex: row,
1648
- checked: isSelected
1649
- })
1650
- };
1651
- }
1652
- return cells;
1653
- }
1654
- getActionColumnCells(range) {
1655
- const cells = {};
1656
- for (let row = range.start.row; row <= range.end.row && row < this.model.getRowCount(); row++) {
1657
- const isSelected = this.model.selection.isRowIndexSelected(row);
1658
- const classes = cellClassesForRowSelection(isSelected, this.model.selection.selectionMode);
1659
- cells[(0, import_react_ui_grid3.toPlaneCellIndex)({
1660
- col: 0,
1661
- row
1662
- })] = {
1663
- value: "",
1664
- readonly: true,
1665
- className: classes ? (0, import_react_ui_theme2.mx)(classes) : void 0,
1666
- accessoryHtml: tableButtons.rowMenu.render({
1667
- rowIndex: row
1668
- })
1669
- };
1670
- }
1671
- return cells;
1672
- }
1673
- getSelectAllCell() {
1674
- if (!this.model.features.selection.enabled || this.model.selection.selectionMode === "single") {
1675
- return {
1676
- [(0, import_react_ui_grid3.toPlaneCellIndex)({
1677
- col: 0,
1678
- row: 0
1679
- })]: {
1680
- className: "!bg-toolbarSurface",
1681
- readonly: true,
1682
- value: ""
1683
- }
1684
- };
1685
- }
1686
- return {
1687
- [(0, import_react_ui_grid3.toPlaneCellIndex)({
1688
- col: 0,
1689
- row: 0
1690
- })]: {
1691
- accessoryHtml: tableControls.checkbox.render({
1692
- rowIndex: 0,
1693
- header: true,
1694
- checked: this.model.selection.allRowsSeleted.value
1695
- }),
1696
- className: "!bg-toolbarSurface",
1697
- readonly: true,
1698
- value: ""
1699
- }
1700
- };
1701
- }
1702
- getNewColumnCell() {
1703
- return {
1704
- [(0, import_react_ui_grid3.toPlaneCellIndex)({
1705
- col: 0,
1706
- row: 0
1707
- })]: {
1708
- accessoryHtml: this.model.features.schemaEditable ? tableButtons.addColumn.render({
1709
- disabled: (this.model.view?.fields?.length ?? 0) >= import_schema4.VIEW_FIELD_LIMIT
1710
- }) : void 0,
1711
- className: "!bg-toolbarSurface",
1712
- readonly: true,
1713
- value: ""
1714
- }
1715
- };
1716
- }
1717
- };
1718
- var cellClassesForRowSelection = (selected, selectionMode) => {
1719
- if (!selected) {
1720
- if (selectionMode === "single") {
1721
- return [
1722
- "!cursor-pointer"
1723
- ];
1724
- } else {
1725
- return void 0;
1726
- }
1727
- }
1728
- switch (selectionMode) {
1729
- case "single":
1730
- return [
1731
- "!bg-currentRelated hover:bg-hoverSurface",
1732
- "!cursor-pointer"
1733
- ];
1734
- case "multiple":
1735
- return [
1736
- "!bg-gridCellSelected"
1737
- ];
1738
- }
1739
- };
1740
- var CellValidationMessage = ({ validationError, __gridScope }) => {
1741
- var _effect = (0, import_tracking7.useSignals)();
1742
- try {
1743
- const { editing, editBox: box } = (0, import_react_ui_grid5.useGridContext)("GridSheetCellEditor", __gridScope);
1744
- if (!editing || !validationError) {
1745
- return null;
1746
- }
1747
- return /* @__PURE__ */ import_react7.default.createElement("div", {
1748
- role: "none",
1749
- className: "absolute bg-errorSurface text-errorSurfaceText rounded-bs-sm text-xs p-1",
1750
- style: {
1751
- ...{
1752
- "--dx-gridCellWidth": `${box?.inlineSize ?? 200}px`
1753
- },
1754
- zIndex: 10,
1755
- insetBlockEnd: `calc(100% - ${box.insetBlockStart}px)`,
1756
- insetInlineStart: box.insetInlineStart,
1757
- inlineSize: box.inlineSize
1758
- }
1759
- }, validationError);
1760
- } finally {
1761
- _effect.f();
1762
- }
1763
- };
1764
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/FormCellEditor.tsx";
1765
- var FormCellEditor = ({ fieldProjection, model, schema, __gridScope }) => {
1766
- var _effect = (0, import_tracking8.useSignals)();
1767
- try {
1768
- const { editing, setEditing } = (0, import_react_ui_grid6.useGridContext)("ArrayEditor", __gridScope);
1769
- const cellRef = (0, import_react8.useRef)(null);
1770
- (0, import_react8.useEffect)(() => {
1771
- if (editing && editing.cellElement) {
1772
- cellRef.current = editing.cellElement;
1773
- }
1774
- }, [
1775
- editing?.cellElement
1776
- ]);
1777
- const narrowedSchema = (0, import_react8.useMemo)(() => {
1778
- if (!schema) {
1779
- return void 0;
1780
- }
1781
- return narrowSchema(schema, [
1782
- fieldProjection.field.path
1783
- ]);
1784
- }, [
1785
- JSON.stringify(schema),
1786
- fieldProjection.field.path
1787
- ]);
1788
- const originalRow = (0, import_react8.useMemo)(() => {
1789
- if (model && editing) {
1790
- const cell = (0, import_react_ui_grid6.parseCellIndex)(editing.index);
1791
- const row = model.getRowAt(cell.row);
1792
- (0, import_invariant4.invariant)(row, void 0, {
1793
- F: __dxlog_file3,
1794
- L: 47,
1795
- S: void 0,
1796
- A: [
1797
- "row",
1798
- ""
1799
- ]
1800
- });
1801
- return row;
1802
- }
1803
- return void 0;
1804
- }, [
1805
- model,
1806
- editing
1807
- ]);
1808
- const formValues = (0, import_react8.useMemo)(() => {
1809
- if (originalRow) {
1810
- return (0, import_echo_schema8.getSnapshot)(originalRow);
1811
- }
1812
- }, [
1813
- originalRow
1814
- ]);
1815
- const handleSave = (0, import_react8.useCallback)((values) => {
1816
- const path = fieldProjection.field.path;
1817
- const value = (0, import_util2.getDeep)(values, [
1818
- path
1819
- ]);
1820
- (0, import_util2.setDeep)(originalRow, [
1821
- path
1822
- ], value);
1823
- setEditing(null);
1824
- }, [
1825
- fieldProjection.field.path,
1826
- originalRow
1827
- ]);
1828
- const handleOpenChange = (0, import_react8.useCallback)((nextOpen) => {
1829
- if (nextOpen === false) {
1830
- setEditing(null);
1831
- }
1832
- }, [
1833
- setEditing
1834
- ]);
1835
- if (!editing) {
1836
- return null;
1837
- }
1838
- return /* @__PURE__ */ import_react8.default.createElement(import_react_ui7.Popover.Root, {
1839
- open: editing !== null,
1840
- onOpenChange: handleOpenChange
1841
- }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui7.Popover.VirtualTrigger, {
1842
- virtualRef: cellRef
1843
- }), /* @__PURE__ */ import_react8.default.createElement(import_react_ui7.Popover.Content, {
1844
- tabIndex: -1,
1845
- classNames: "popover-card-width"
1846
- }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui7.Popover.Arrow, null), /* @__PURE__ */ import_react8.default.createElement(import_react_ui7.Popover.Viewport, null, /* @__PURE__ */ import_react8.default.createElement(import_react_ui_form6.Form, {
1847
- values: formValues,
1848
- schema: narrowedSchema,
1849
- onSave: handleSave
1850
- }))));
1851
- } finally {
1852
- _effect.f();
1853
- }
1854
- };
1855
- var completion = ({ debug, onQuery, onMatch }) => {
1856
- return [
1857
- import_view.EditorView.theme({
1858
- ".cm-completionDialog": {
1859
- width: "var(--dx-gridCellWidth)"
1860
- }
1861
- }),
1862
- (0, import_autocomplete.autocompletion)({
1863
- icons: false,
1864
- activateOnTyping: true,
1865
- closeOnBlur: !debug,
1866
- override: [
1867
- async (context) => {
1868
- const text = context.state.doc.toString();
1869
- return {
1870
- from: 0,
1871
- options: await onQuery(text)
1872
- };
1873
- }
1874
- ],
1875
- // TODO(burdon): Consts from grid (to line-up with grid).
1876
- tooltipClass: () => "cm-completionDialog !mt-[8px] !-ml-[4px] [&>ul]:!max-h-[264px]",
1877
- optionClass: () => "flex h-[33px] items-center"
1878
- }),
1879
- // Check for accepted completion metadata in the transaction.
1880
- import_view.EditorView.updateListener.of((update) => {
1881
- update.transactions.forEach((tr) => {
1882
- const completion2 = tr.annotation(import_autocomplete.pickedCompletion);
1883
- if (completion2) {
1884
- onMatch(completion2.data);
1885
- }
1886
- });
1887
- })
1888
- ];
1889
- };
1890
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/TableCellEditor/TableCellEditor.tsx";
1891
- var newValue = Symbol.for("newValue");
1892
- var createOption = (text) => ({
1893
- [newValue]: true,
1894
- text
1895
- });
1896
- var isCreateOption = (data) => typeof data === "object" && data[newValue];
1897
- var TableValueEditor = ({ model, modals, schema, onEnter, onFocus, onQuery, __gridScope }) => {
1898
- var _effect = (0, import_tracking6.useSignals)();
1899
- try {
1900
- const { editing } = (0, import_react_ui_grid4.useGridContext)("TableValueEditor", __gridScope);
1901
- const fieldProjection = (0, import_react6.useMemo)(() => {
1902
- if (!model || !editing) {
1903
- return;
1904
- }
1905
- const { col } = (0, import_react_ui_grid4.parseCellIndex)(editing.index);
1906
- const field = model.projection.view.fields[col];
1907
- const fieldProjection2 = model.projection.getFieldProjection(field.id);
1908
- (0, import_invariant3.invariant)(fieldProjection2, void 0, {
1909
- F: __dxlog_file4,
1910
- L: 74,
1911
- S: void 0,
1912
- A: [
1913
- "fieldProjection",
1914
- ""
1915
- ]
1916
- });
1917
- return fieldProjection2;
1918
- }, [
1919
- model,
1920
- editing
1921
- ]);
1922
- if (fieldProjection?.props.type === import_echo_schema7.TypeEnum.Array) {
1923
- return /* @__PURE__ */ import_react6.default.createElement(FormCellEditor, {
1924
- fieldProjection,
1925
- model,
1926
- schema,
1927
- __gridScope
1928
- });
1929
- }
1930
- return /* @__PURE__ */ import_react6.default.createElement(TableCellEditor, {
1931
- model,
1932
- modals,
1933
- onEnter,
1934
- onFocus,
1935
- onQuery,
1936
- __gridScope
1937
- });
1938
- } finally {
1939
- _effect.f();
1940
- }
1941
- };
1942
- var TableCellEditor = ({ model, modals, onEnter, onFocus, onQuery, __gridScope }) => {
1943
- var _effect = (0, import_tracking6.useSignals)();
1944
- try {
1945
- const { id: gridId, editing, setEditing } = (0, import_react_ui_grid4.useGridContext)("TableCellEditor", __gridScope);
1946
- const suppressNextBlur = (0, import_react6.useRef)(false);
1947
- const { themeMode } = (0, import_react_ui6.useThemeContext)();
1948
- const [_validationError, setValidationError] = (0, import_react6.useState)(null);
1949
- const fieldProjection = (0, import_react6.useMemo)(() => {
1950
- if (!model || !editing) {
1951
- return;
1952
- }
1953
- const { col } = (0, import_react_ui_grid4.parseCellIndex)(editing.index);
1954
- const field = model.projection.view.fields[col];
1955
- const fieldProjection2 = model.projection.getFieldProjection(field.id);
1956
- (0, import_invariant3.invariant)(fieldProjection2, void 0, {
1957
- F: __dxlog_file4,
1958
- L: 116,
1959
- S: void 0,
1960
- A: [
1961
- "fieldProjection",
1962
- ""
1963
- ]
1964
- });
1965
- return fieldProjection2;
1966
- }, [
1967
- model,
1968
- editing
1969
- ]);
1970
- const handleEnter = (0, import_react6.useCallback)(async (value) => {
1971
- if (!model || !editing) {
1972
- return;
1973
- }
1974
- const cell = (0, import_react_ui_grid4.parseCellIndex)(editing.index);
1975
- const result = await model.validateCellData(cell, value);
1976
- if (result.valid) {
1977
- setValidationError(null);
1978
- model.setCellData(cell, value);
1979
- onEnter?.(cell);
1980
- onFocus?.();
1981
- setEditing(null);
1982
- } else {
1983
- setValidationError(result.error);
1984
- }
1985
- }, [
1986
- model,
1987
- editing,
1988
- onEnter,
1989
- onFocus,
1990
- setEditing
1991
- ]);
1992
- const handleBlur = (0, import_react6.useCallback)(async (value) => {
1993
- if (!model || !editing) {
1994
- return;
1995
- }
1996
- if (suppressNextBlur.current) {
1997
- suppressNextBlur.current = false;
1998
- }
1999
- }, [
2000
- model,
2001
- editing
2002
- ]);
2003
- const handleClose = (0, import_react6.useCallback)(async (value, event) => {
2004
- if (!model || !editing || !fieldProjection) {
2005
- return;
2006
- }
2007
- const cell = (0, import_react_ui_grid4.parseCellIndex)(editing.index);
2008
- if (value !== void 0) {
2009
- const result = await model.validateCellData(cell, value);
2010
- if (result.valid) {
2011
- setValidationError(null);
2012
- model.setCellData(cell, value);
2013
- setEditing(null);
2014
- onEnter?.(cell);
2015
- if (event && onFocus) {
2016
- onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
2017
- }
2018
- } else {
2019
- setValidationError(result.error);
2020
- }
2021
- } else {
2022
- setValidationError(null);
2023
- setEditing(null);
2024
- if (event && onFocus) {
2025
- onFocus(determineNavigationAxis(event), determineNavigationDelta(event));
2026
- }
2027
- }
2028
- }, [
2029
- model,
2030
- editing,
2031
- onFocus,
2032
- onEnter,
2033
- fieldProjection,
2034
- setEditing
2035
- ]);
2036
- const extension = (0, import_react6.useMemo)(() => {
2037
- if (!fieldProjection) {
2038
- return [];
2039
- }
2040
- const extension2 = [
2041
- (0, import_react_ui_grid4.editorKeys)({
2042
- onClose: handleClose,
2043
- ...editing?.initialContent && {
2044
- onNav: handleClose
2045
- }
2046
- })
2047
- ];
2048
- const format = fieldProjection.props.format;
2049
- if (format === import_echo_schema7.FormatEnum.SingleSelect || format === import_echo_schema7.FormatEnum.MultiSelect) {
2050
- extension2.push((0, import_react_ui_editor.createMarkdownExtensions)({
2051
- themeMode
2052
- }));
2053
- const options = fieldProjection.props.options || [];
2054
- const mode = format === import_echo_schema7.FormatEnum.SingleSelect ? "single-select" : "multi-select";
2055
- extension2.push((0, import_react_ui_tag_picker.tagPickerExtension)({
2056
- mode,
2057
- inGrid: true,
2058
- onSearch: (text, selectedIds) => {
2059
- return options.filter((option) => selectedIds.indexOf(option.id) === -1 && (text.length === 0 || option.title.toLowerCase().includes(text.toLowerCase()))).map((option) => ({
2060
- id: option.id,
2061
- label: option.title,
2062
- hue: option.color
2063
- }));
2064
- },
2065
- onUpdate: (ids) => {
2066
- if (model && editing) {
2067
- if (ids.length === 0) {
2068
- return;
2069
- }
2070
- if (mode === "single-select") {
2071
- void handleEnter(ids[0]);
2072
- } else {
2073
- void handleEnter(ids);
2074
- }
2075
- }
2076
- }
2077
- }));
2078
- }
2079
- if (onQuery) {
2080
- switch (fieldProjection.props.format) {
2081
- case import_echo_schema7.FormatEnum.Ref: {
2082
- extension2.push([
2083
- completion({
2084
- onQuery: (text) => onQuery(fieldProjection, text),
2085
- onMatch: (data) => {
2086
- if (model && editing && modals) {
2087
- if (isCreateOption(data)) {
2088
- const { field, props } = fieldProjection;
2089
- if (props.referenceSchema) {
2090
- suppressNextBlur.current = true;
2091
- modals.openCreateRef(props.referenceSchema, document.querySelector((0, import_react_ui_grid4.cellQuery)(editing.index, gridId)), {
2092
- [field.referencePath]: data.text
2093
- }, (data2) => {
2094
- void handleEnter(data2);
2095
- });
2096
- }
2097
- } else {
2098
- void handleEnter(data);
2099
- }
2100
- }
2101
- }
2102
- })
2103
- ]);
2104
- break;
2105
- }
2106
- }
2107
- }
2108
- return extension2;
2109
- }, [
2110
- model,
2111
- modals,
2112
- editing,
2113
- fieldProjection,
2114
- handleClose,
2115
- themeMode
2116
- ]);
2117
- const getCellContent = (0, import_react6.useCallback)(() => {
2118
- if (model && editing) {
2119
- const cell = (0, import_react_ui_grid4.parseCellIndex)(editing.index);
2120
- const { col } = cell;
2121
- const field = model.projection.view.fields[col];
2122
- const fieldProjection2 = model.projection.getFieldProjection(field.id);
2123
- if (fieldProjection2?.props.format === import_echo_schema7.FormatEnum.SingleSelect || fieldProjection2?.props.format === import_echo_schema7.FormatEnum.MultiSelect) {
2124
- const value2 = model.getCellData(cell);
2125
- if (value2 !== void 0) {
2126
- const options = fieldProjection2.props.options || [];
2127
- if (fieldProjection2.props.format === import_echo_schema7.FormatEnum.MultiSelect && Array.isArray(value2)) {
2128
- const tagItems = value2.map((id) => {
2129
- const option = options.find((o) => o.id === id);
2130
- if (option) {
2131
- return {
2132
- id,
2133
- label: option.title,
2134
- hue: option.color
2135
- };
2136
- }
2137
- return void 0;
2138
- }).filter((item) => item !== void 0);
2139
- return (0, import_react_ui_tag_picker.createLinks)(tagItems);
2140
- } else {
2141
- const option = options.find((o) => o.id === value2);
2142
- if (option) {
2143
- const tagItem = {
2144
- id: value2,
2145
- label: option.title,
2146
- hue: option.color
2147
- };
2148
- return (0, import_react_ui_tag_picker.createLinks)([
2149
- tagItem
2150
- ]);
2151
- }
2152
- }
2153
- }
2154
- return "";
2155
- }
2156
- const value = model.getCellData(cell);
2157
- return value !== void 0 ? String(value) : "";
2158
- }
2159
- }, [
2160
- model,
2161
- editing
2162
- ]);
2163
- return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement(CellValidationMessage, {
2164
- validationError: _validationError,
2165
- __gridScope
2166
- }), /* @__PURE__ */ import_react6.default.createElement(import_react_ui_grid4.GridCellEditor, {
2167
- extension,
2168
- getCellContent,
2169
- onBlur: handleBlur
2170
- }));
2171
- } finally {
2172
- _effect.f();
2173
- }
2174
- };
2175
- var determineNavigationAxis = ({ key }) => {
2176
- switch (key) {
2177
- case "ArrowUp":
2178
- case "ArrowDown":
2179
- case "Enter": {
2180
- return "row";
2181
- }
2182
- case "ArrowLeft":
2183
- case "ArrowRight":
2184
- case "Tab":
2185
- return "col";
2186
- }
2187
- };
2188
- var determineNavigationDelta = ({ key, shift }) => {
2189
- switch (key) {
2190
- case "ArrowUp":
2191
- case "ArrowLeft":
2192
- return -1;
2193
- case "ArrowDown":
2194
- case "ArrowRight":
2195
- return 1;
2196
- }
2197
- return shift ? -1 : 1;
2198
- };
2199
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-table/src/components/Table/Table.tsx";
2200
- var TableRoot = ({ children, role }) => {
2201
- var _effect = (0, import_tracking.useSignals)();
2202
- try {
2203
- return /* @__PURE__ */ import_react.default.createElement("div", {
2204
- role: "none",
2205
- className: (0, import_react_ui_theme.mx)("relative !border-separator", role === "section" ? "attention-surface overflow-hidden [&_.dx-grid]:max-is-[--dx-grid-content-inline-size]" : "flex flex-col [&_.dx-grid]:grow [&_.dx-grid]:max-is-[--dx-grid-content-inline-size] [&_.dx-grid]:bs-0 [&_.dx-grid]:max-bs-[--dx-grid-content-block-size]")
2206
- }, children);
2207
- } finally {
2208
- _effect.f();
2209
- }
2210
- };
2211
- var TableMain = /* @__PURE__ */ (0, import_react.forwardRef)(({ model, presentation, ignoreAttention, schema, client, onRowClick }, forwardedRef) => {
2212
- var _effect = (0, import_tracking.useSignals)();
2213
- try {
2214
- const [dxGrid, setDxGrid] = (0, import_react.useState)(null);
2215
- const { hasAttention } = (0, import_react_ui_attention.useAttention)(model?.id ?? "table");
2216
- const { t } = (0, import_react_ui.useTranslation)(translationKey);
2217
- const modals = (0, import_react.useMemo)(() => new ModalController(), []);
2218
- const frozen = (0, import_react.useMemo)(() => {
2219
- const noActionColumn = model?.features.dataEditable === false && model?.features.schemaEditable === false && model.rowActions.length === 0;
2220
- return {
2221
- frozenRowsStart: 1,
2222
- frozenColsStart: model?.features.selection.enabled ? 1 : 0,
2223
- frozenColsEnd: noActionColumn ? 0 : 1
2224
- };
2225
- }, [
2226
- model
2227
- ]);
2228
- const getCells = (0, import_react.useCallback)((range, plane) => presentation?.getCells(range, plane) ?? {}, [
2229
- presentation
2230
- ]);
2231
- (0, import_react.useEffect)(() => {
2232
- if (!presentation || !dxGrid) {
2233
- return;
2234
- }
2235
- dxGrid.getCells = getCells;
2236
- }, [
2237
- presentation,
2238
- dxGrid,
2239
- getCells
2240
- ]);
2241
- (0, import_react.useImperativeHandle)(forwardedRef, () => {
2242
- if (!presentation || !dxGrid) {
2243
- return {};
2244
- }
2245
- return {
2246
- update: (cell) => {
2247
- if (cell) {
2248
- dxGrid.updateIfWithinBounds(cell);
2249
- } else {
2250
- dxGrid.updateCells(true);
2251
- dxGrid.requestUpdate();
2252
- }
2253
- }
2254
- };
2255
- }, [
2256
- presentation,
2257
- dxGrid
2258
- ]);
2259
- const handleGridClick = (0, import_react.useCallback)((event) => {
2260
- const rowIndex = (0, import_util.safeParseInt)(event.target.ariaRowIndex ?? "");
2261
- if (rowIndex != null) {
2262
- if (onRowClick) {
2263
- const row = model?.getRowAt(rowIndex);
2264
- row && onRowClick(row);
2265
- }
2266
- if (model?.features.selection.enabled && model?.selection.selectionMode === "single") {
2267
- model.selection.toggleSelectionForRowIndex(rowIndex);
2268
- }
2269
- }
2270
- if (!modals) {
2271
- return;
2272
- }
2273
- const buttonSelector = Object.values(tableButtons).map((button) => `button[${button.attr}]`).join(",");
2274
- const tableButtonElement = event.target.closest(buttonSelector);
2275
- if (tableButtonElement) {
2276
- const button = Object.values(tableButtons).find((btn) => tableButtonElement.hasAttribute(btn.attr));
2277
- if (!button) {
2278
- return;
2279
- }
2280
- modals.setTrigger(tableButtonElement);
2281
- const data = button.getData(tableButtonElement);
2282
- switch (data.type) {
2283
- case "rowMenu": {
2284
- modals.showRowMenu(data.rowIndex);
2285
- break;
2286
- }
2287
- case "columnSettings": {
2288
- modals.showColumnMenu(data.fieldId);
2289
- break;
2290
- }
2291
- case "newColumn": {
2292
- modals.showColumnCreator();
2293
- break;
2294
- }
2295
- case "sort": {
2296
- model?.sorting?.toggleSort(data.fieldId);
2297
- break;
2298
- }
2299
- }
2300
- return;
2301
- }
2302
- const controlSelector = Object.values(tableControls).map((control) => `input[${control.attr}]`).join(",");
2303
- const controlElement = event.target.closest(controlSelector);
2304
- if (controlElement) {
2305
- const control = Object.values(tableControls).find((ctrl) => controlElement.hasAttribute(ctrl.attr));
2306
- if (!control) {
2307
- return;
2308
- }
2309
- const data = control.getData(controlElement);
2310
- switch (data.type) {
2311
- case "checkbox": {
2312
- if (data.header) {
2313
- model?.selection.setSelection(model.selection.allRowsSeleted.value ? "none" : "all");
2314
- } else {
2315
- model?.selection.toggleSelectionForRowIndex(data.rowIndex);
2316
- }
2317
- break;
2318
- }
2319
- case "switch": {
2320
- if (model) {
2321
- model.updateCellData({
2322
- row: data.rowIndex,
2323
- col: data.colIndex
2324
- }, (value) => !value);
2325
- }
2326
- break;
2327
- }
2328
- }
2329
- }
2330
- }, [
2331
- model,
2332
- modals
2333
- ]);
2334
- const handleFocus = (0, import_react.useCallback)((increment, delta) => {
2335
- if (dxGrid) {
2336
- dxGrid.refocus(increment, delta);
2337
- }
2338
- }, [
2339
- dxGrid
2340
- ]);
2341
- const handleEnter = (0, import_react.useCallback)((cell) => {
2342
- if (!model?.features.dataEditable) {
2343
- return;
2344
- }
2345
- if (model && cell.row === model.getRowCount() - 1) {
2346
- model.insertRow(cell.row);
2347
- if (dxGrid) {
2348
- requestAnimationFrame(() => {
2349
- dxGrid?.scrollToRow(cell.row + 1);
2350
- dxGrid?.refocus("row", 1);
2351
- });
2352
- }
2353
- }
2354
- }, [
2355
- model,
2356
- dxGrid
2357
- ]);
2358
- const handleKeyDown = (0, import_react.useCallback)((event) => {
2359
- if (!model?.features.dataEditable) {
2360
- return;
2361
- }
2362
- const cell = (0, import_react_ui_grid.closestCell)(event.target);
2363
- if (!model || !cell) {
2364
- return;
2365
- }
2366
- switch (event.key) {
2367
- case "Backspace":
2368
- case "Delete": {
2369
- model.setCellData(cell, void 0);
2370
- break;
2371
- }
2372
- }
2373
- }, [
2374
- model
2375
- ]);
2376
- const handleAxisResize = (0, import_react.useCallback)((event) => {
2377
- if (event.axis === "col") {
2378
- const columnIndex = parseInt(event.index, 10);
2379
- model?.setColumnWidth(columnIndex, event.size);
2380
- }
2381
- }, [
2382
- model
2383
- ]);
2384
- const handleWheel = (0, import_react.useCallback)((event) => {
2385
- if (!ignoreAttention && !hasAttention) {
2386
- event.stopPropagation();
2387
- }
2388
- }, [
2389
- hasAttention,
2390
- ignoreAttention
2391
- ]);
2392
- const handleNewColumn = (0, import_react.useCallback)(() => {
2393
- const columns = model?.getColumnCount();
2394
- if (dxGrid && columns) {
2395
- dxGrid.scrollToColumn(columns - 1);
2396
- }
2397
- }, [
2398
- model,
2399
- dxGrid
2400
- ]);
2401
- const handleQuery = (0, import_react.useCallback)(async ({ field, props }, text) => {
2402
- if (model && props.referenceSchema && field.referencePath) {
2403
- const space = model.space;
2404
- (0, import_invariant.invariant)(space, void 0, {
2405
- F: __dxlog_file5,
2406
- L: 311,
2407
- S: void 0,
2408
- A: [
2409
- "space",
2410
- ""
2411
- ]
2412
- });
2413
- let schema2;
2414
- if (client) {
2415
- schema2 = client.graph.schemaRegistry.getSchema(props.referenceSchema);
2416
- }
2417
- if (!schema2) {
2418
- schema2 = space.db.schemaRegistry.getSchema(props.referenceSchema);
2419
- }
2420
- if (schema2) {
2421
- const { objects } = await space.db.query(import_echo.Filter.type(schema2)).run();
2422
- const options = objects.map((obj) => {
2423
- const value = (0, import_echo_schema.getValue)(obj, field.referencePath);
2424
- if (!value || typeof value !== "string") {
2425
- return void 0;
2426
- }
2427
- return {
2428
- label: value,
2429
- data: obj
2430
- };
2431
- }).filter(import_util.isNotFalsy);
2432
- return [
2433
- ...options,
2434
- {
2435
- label: t("create new object label", {
2436
- text
2437
- }),
2438
- data: createOption(text)
2439
- }
2440
- ];
2441
- }
2442
- }
2443
- return [];
2444
- }, [
2445
- model,
2446
- client,
2447
- t
2448
- ]);
2449
- if (!model || !modals) {
2450
- return /* @__PURE__ */ import_react.default.createElement("span", {
2451
- role: "none",
2452
- className: "attention-surface"
2453
- });
2454
- }
2455
- return /* @__PURE__ */ import_react.default.createElement(import_react_ui_grid.Grid.Root, {
2456
- id: model.id ?? "table-grid"
2457
- }, /* @__PURE__ */ import_react.default.createElement(TableValueEditor, {
2458
- model,
2459
- modals,
2460
- schema,
2461
- onEnter: handleEnter,
2462
- onFocus: handleFocus,
2463
- onQuery: handleQuery
2464
- }), /* @__PURE__ */ import_react.default.createElement(import_react_ui_grid.Grid.Content, {
2465
- className: (0, import_react_ui_theme.mx)("[--dx-grid-base:var(--baseSurface)]", import_react_ui_grid.gridSeparatorInlineEnd, import_react_ui_grid.gridSeparatorBlockEnd),
2466
- frozen,
2467
- // getCells={getCells}
2468
- columns: model.columnMeta.value,
2469
- limitRows: model.getRowCount() ?? 0,
2470
- limitColumns: model.view?.fields?.length ?? 0,
2471
- overscroll: "trap",
2472
- onAxisResize: handleAxisResize,
2473
- onClick: handleGridClick,
2474
- onKeyDown: handleKeyDown,
2475
- onWheelCapture: handleWheel,
2476
- ref: setDxGrid
2477
- }), /* @__PURE__ */ import_react.default.createElement(RowActionsMenu, {
2478
- model,
2479
- modals
2480
- }), /* @__PURE__ */ import_react.default.createElement(ColumnActionsMenu, {
2481
- model,
2482
- modals
2483
- }), /* @__PURE__ */ import_react.default.createElement(ColumnSettings, {
2484
- model,
2485
- modals,
2486
- onNewColumn: handleNewColumn
2487
- }), /* @__PURE__ */ import_react.default.createElement(CreateRefPanel, {
2488
- model,
2489
- modals
2490
- }));
2491
- } finally {
2492
- _effect.f();
2493
- }
2494
- });
2495
- var Table = {
2496
- Root: TableRoot,
2497
- Main: TableMain
2498
- };
2499
- var useTableModel = ({ table, projection, rows, rowActions, features, onSelectionChanged, onRowAction, ...props }) => {
2500
- var _effect = (0, import_tracking10.useSignals)();
2501
- try {
2502
- const [model, setModel] = (0, import_react10.useState)();
2503
- (0, import_react10.useEffect)(() => {
2504
- if (!table || !projection) {
2505
- return;
2506
- }
2507
- let model2;
2508
- const t = setTimeout(async () => {
2509
- model2 = new TableModel({
2510
- id: (0, import_echo5.fullyQualifiedId)(table),
2511
- space: (0, import_echo5.getSpace)(table),
2512
- view: table.view?.target,
2513
- projection,
2514
- features,
2515
- rowActions,
2516
- onRowAction,
2517
- ...props
2518
- });
2519
- await model2.open();
2520
- setModel(model2);
2521
- });
2522
- return () => {
2523
- clearTimeout(t);
2524
- void model2?.close();
2525
- };
2526
- }, [
2527
- table,
2528
- projection,
2529
- table?.view?.target,
2530
- features,
2531
- rowActions
2532
- ]);
2533
- (0, import_react10.useEffect)(() => {
2534
- if (rows) {
2535
- const sortedRows = (0, import_lodash2.default)(rows, [
2536
- (row) => String(row.id)
2537
- ], [
2538
- "asc"
2539
- ]);
2540
- model?.setRows(sortedRows);
2541
- }
2542
- }, [
2543
- model,
2544
- rows
2545
- ]);
2546
- const { multiSelect, clear } = (0, import_react_ui_attention2.useSelectionActions)([
2547
- table?.id,
2548
- table?.view?.target?.query.typename
2549
- ].filter(import_util3.isNonNullable));
2550
- (0, import_react10.useEffect)(() => {
2551
- if (!model) {
2552
- return;
2553
- }
2554
- const unsubscribe = (0, import_signals_core6.effect)(() => {
2555
- const selectedItems = [
2556
- ...model.selection.selection.value
2557
- ];
2558
- multiSelect(selectedItems);
2559
- onSelectionChanged?.(selectedItems);
2560
- });
2561
- return () => {
2562
- clear();
2563
- unsubscribe();
2564
- };
2565
- }, [
2566
- model,
2567
- onSelectionChanged
2568
- ]);
2569
- return model;
2570
- } finally {
2571
- _effect.f();
2572
- }
2573
- };
2574
- var DynamicTable = ({ classNames, name = "example.com/dynamic-table", rows, properties, jsonSchema, schema, rowActions, onRowClick, onRowAction, ...props }) => {
2575
- var _effect = (0, import_tracking9.useSignals)();
2576
- try {
2577
- const { table, projection } = (0, import_react9.useMemo)(() => {
2578
- const props2 = getBaseSchema({
2579
- typename: name,
2580
- properties,
2581
- jsonSchema,
2582
- schema
2583
- });
2584
- return makeDynamicTable({
2585
- ...props2,
2586
- properties
2587
- });
2588
- }, [
2589
- name,
2590
- properties,
2591
- schema,
2592
- jsonSchema
2593
- ]);
2594
- const tableRef = (0, import_react9.useRef)(null);
2595
- const handleCellUpdate = (0, import_react9.useCallback)((cell) => {
2596
- tableRef.current?.update?.(cell);
2597
- }, []);
2598
- const handleRowOrderChange = (0, import_react9.useCallback)(() => {
2599
- tableRef.current?.update?.();
2600
- }, []);
2601
- const features = (0, import_react_ui8.useDefaultValue)(props.features, () => ({
2602
- selection: {
2603
- enabled: false
2604
- },
2605
- dataEditable: false
2606
- }));
2607
- const model = useTableModel({
2608
- table,
2609
- rows,
2610
- projection,
2611
- features,
2612
- rowActions,
2613
- onCellUpdate: handleCellUpdate,
2614
- onRowOrderChange: handleRowOrderChange,
2615
- onRowAction
2616
- });
2617
- const presentation = (0, import_react9.useMemo)(() => {
2618
- if (model) {
2619
- return new TablePresentation(model);
2620
- }
2621
- }, [
2622
- model
2623
- ]);
2624
- return /* @__PURE__ */ import_react9.default.createElement("div", {
2625
- role: "none",
2626
- className: (0, import_react_ui_theme3.mx)("is-full bs-full grow grid", classNames)
2627
- }, /* @__PURE__ */ import_react9.default.createElement("div", {
2628
- role: "none",
2629
- className: "grid min-bs-0 overflow-hidden"
2630
- }, /* @__PURE__ */ import_react9.default.createElement(Table.Root, null, /* @__PURE__ */ import_react9.default.createElement(Table.Main, {
2631
- ref: tableRef,
2632
- model,
2633
- presentation,
2634
- ignoreAttention: true,
2635
- onRowClick
2636
- }))));
2637
- } finally {
2638
- _effect.f();
2639
- }
2640
- };
2641
- var createTableToolbarActions = ({ state, onAdd, onSave, customActions }) => import_rx_react.Rx.make((get) => {
2642
- const add = (0, import_react_ui_menu.createMenuAction)("add-row", onAdd, {
2643
- type: "add-row",
2644
- icon: "ph--plus--regular",
2645
- label: [
2646
- "add row",
2647
- {
2648
- ns: translationKey
2649
- }
2650
- ],
2651
- testId: "table.toolbar.add-row"
2652
- });
2653
- const save = (0, import_react_ui_menu.createMenuAction)("save-view", onSave, {
2654
- type: "save-view",
2655
- icon: "ph--floppy-disk--regular",
2656
- label: [
2657
- "save view label",
2658
- {
2659
- ns: translationKey
2660
- }
2661
- ],
2662
- testId: "table.toolbar.save-view",
2663
- iconOnly: false,
2664
- hidden: get((0, import_react_ui_menu2.rxFromSignal)(() => !state.viewDirty))
2665
- });
2666
- const gap = (0, import_react_ui_menu.createGapSeparator)();
2667
- const nodes = [
2668
- add,
2669
- save,
2670
- ...gap.nodes
2671
- ];
2672
- const edges = nodes.map(({ id: target }) => ({
2673
- source: "root",
2674
- target
2675
- }));
2676
- if (customActions) {
2677
- const custom = get(customActions);
2678
- nodes.push(...custom.nodes);
2679
- edges.push(...custom.edges);
2680
- }
2681
- return {
2682
- nodes,
2683
- edges
2684
- };
2685
- });
2686
- var TableToolbar = ({ classNames, viewDirty, attendableId, onAdd, onSave, customActions }) => {
2687
- var _effect = (0, import_tracking11.useSignals)();
2688
- try {
2689
- const state = (0, import_react11.useMemo)(() => (0, import_live_object2.live)({
2690
- viewDirty
2691
- }), []);
2692
- const actionsCreator = (0, import_react11.useMemo)(() => createTableToolbarActions({
2693
- state,
2694
- onAdd,
2695
- onSave,
2696
- customActions
2697
- }), [
2698
- state,
2699
- onAdd,
2700
- onSave,
2701
- customActions
2702
- ]);
2703
- const menu = (0, import_react_ui_menu.useMenuActions)(actionsCreator);
2704
- return /* @__PURE__ */ import_react11.default.createElement(import_react_ui_menu.MenuProvider, {
2705
- ...menu,
2706
- attendableId
2707
- }, /* @__PURE__ */ import_react11.default.createElement(import_react_ui_menu.ToolbarMenu, {
2708
- classNames
2709
- }));
2710
- } finally {
2711
- _effect.f();
2712
- }
2713
- };
2714
- // Annotate the CommonJS export names for ESM import in node:
2715
- 0 && (module.exports = {
2716
- BUTTON_IDENTIFIERS,
2717
- CONTROL_IDENTIFIERS,
2718
- CheckboxStory,
2719
- DynamicTable,
2720
- ModalController,
2721
- SwitchStory,
2722
- Table,
2723
- TableModel,
2724
- TablePresentation,
2725
- TableSchema,
2726
- TableToolbar,
2727
- TableType,
2728
- cellClassesForRowSelection,
2729
- getBaseSchema,
2730
- initializeTable,
2731
- makeDynamicTable,
2732
- narrowSchema,
2733
- tableButtons,
2734
- tableControls,
2735
- touch,
2736
- translations,
2737
- useTableModel
2738
- });
2739
- //# sourceMappingURL=index.cjs.map