@dxos/react-ui-table 0.10.0 → 0.11.1

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