@dxos/react-ui-table 0.9.1-staging.ee54ba693a → 0.11.0

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