@dxos/plugin-sheet 0.6.8-main.3be982f → 0.6.8-staging.63bcb81

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 (76) hide show
  1. package/dist/lib/browser/SheetContainer-6K3XOBZ7.mjs +1765 -0
  2. package/dist/lib/browser/SheetContainer-6K3XOBZ7.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-6VPEAUG6.mjs → chunk-D3PUKBH6.mjs} +1 -1
  4. package/dist/lib/browser/{chunk-6VPEAUG6.mjs.map → chunk-D3PUKBH6.mjs.map} +1 -1
  5. package/dist/lib/browser/chunk-MJOFSXLS.mjs +3251 -0
  6. package/dist/lib/browser/chunk-MJOFSXLS.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +82 -6
  8. package/dist/lib/browser/index.mjs.map +4 -4
  9. package/dist/lib/browser/meta.json +1 -1
  10. package/dist/lib/browser/types.mjs +1 -1
  11. package/dist/lib/node/SheetContainer-QWNOHX7P.cjs +1759 -0
  12. package/dist/lib/node/SheetContainer-QWNOHX7P.cjs.map +7 -0
  13. package/dist/lib/node/chunk-3AINF7RX.cjs +3275 -0
  14. package/dist/lib/node/chunk-3AINF7RX.cjs.map +7 -0
  15. package/dist/lib/node/{chunk-4CE6FK5Z.cjs → chunk-3R3J7IZR.cjs} +4 -4
  16. package/dist/lib/node/{chunk-4CE6FK5Z.cjs.map → chunk-3R3J7IZR.cjs.map} +1 -1
  17. package/dist/lib/node/index.cjs +84 -15
  18. package/dist/lib/node/index.cjs.map +4 -4
  19. package/dist/lib/node/meta.json +1 -1
  20. package/dist/lib/node/types.cjs +9 -9
  21. package/dist/lib/node/types.cjs.map +1 -1
  22. package/dist/types/src/SheetPlugin.d.ts.map +1 -1
  23. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts.map +1 -1
  24. package/dist/types/src/components/CellEditor/extension.d.ts +2 -1
  25. package/dist/types/src/components/CellEditor/extension.d.ts.map +1 -1
  26. package/dist/types/src/components/ComputeGraph/async-function.d.ts +4 -2
  27. package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +1 -1
  28. package/dist/types/src/components/ComputeGraph/edge-function.d.ts.map +1 -1
  29. package/dist/types/src/components/ComputeGraph/graph-context.d.ts +2 -1
  30. package/dist/types/src/components/ComputeGraph/graph-context.d.ts.map +1 -1
  31. package/dist/types/src/components/ComputeGraph/graph.d.ts +9 -4
  32. package/dist/types/src/components/ComputeGraph/graph.d.ts.map +1 -1
  33. package/dist/types/src/components/ComputeGraph/index.d.ts +1 -1
  34. package/dist/types/src/components/ComputeGraph/index.d.ts.map +1 -1
  35. package/dist/types/src/components/Sheet/Sheet.d.ts.map +1 -1
  36. package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/Sheet/sheet-context.d.ts +3 -2
  38. package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -1
  39. package/dist/types/src/model/functions.d.ts +11 -0
  40. package/dist/types/src/model/functions.d.ts.map +1 -0
  41. package/dist/types/src/model/index.d.ts +1 -0
  42. package/dist/types/src/model/index.d.ts.map +1 -1
  43. package/dist/types/src/model/model.d.ts +25 -2
  44. package/dist/types/src/model/model.d.ts.map +1 -1
  45. package/dist/types/src/types.d.ts +1 -1
  46. package/dist/types/src/types.d.ts.map +1 -1
  47. package/package.json +28 -30
  48. package/src/SheetPlugin.tsx +26 -3
  49. package/src/components/CellEditor/CellEditor.stories.tsx +5 -2
  50. package/src/components/CellEditor/extension.test.ts +3 -1
  51. package/src/components/CellEditor/extension.ts +6 -13
  52. package/src/components/ComputeGraph/async-function.ts +10 -1
  53. package/src/components/ComputeGraph/edge-function.ts +8 -9
  54. package/src/components/ComputeGraph/graph-context.tsx +6 -2
  55. package/src/components/ComputeGraph/graph.browser.test.ts +3 -2
  56. package/src/components/ComputeGraph/graph.ts +22 -12
  57. package/src/components/ComputeGraph/index.ts +1 -1
  58. package/src/components/Sheet/Sheet.stories.tsx +3 -7
  59. package/src/components/Sheet/Sheet.tsx +7 -5
  60. package/src/components/Sheet/sheet-context.tsx +55 -6
  61. package/src/model/functions.ts +2427 -0
  62. package/src/model/index.ts +1 -0
  63. package/src/model/model.browser.test.ts +1 -1
  64. package/src/model/model.ts +77 -6
  65. package/src/types.ts +1 -1
  66. package/dist/lib/browser/SheetContainer-H22IDJ43.mjs +0 -3740
  67. package/dist/lib/browser/SheetContainer-H22IDJ43.mjs.map +0 -7
  68. package/dist/lib/browser/chunk-AT2FJXQX.mjs +0 -861
  69. package/dist/lib/browser/chunk-AT2FJXQX.mjs.map +0 -7
  70. package/dist/lib/node/SheetContainer-S32KTNZ6.cjs +0 -3731
  71. package/dist/lib/node/SheetContainer-S32KTNZ6.cjs.map +0 -7
  72. package/dist/lib/node/chunk-FCKJ4QRM.cjs +0 -881
  73. package/dist/lib/node/chunk-FCKJ4QRM.cjs.map +0 -7
  74. package/dist/types/src/components/CellEditor/functions.d.ts +0 -66
  75. package/dist/types/src/components/CellEditor/functions.d.ts.map +0 -1
  76. package/src/components/CellEditor/functions.ts +0 -2017
@@ -0,0 +1,1765 @@
1
+ import {
2
+ SheetModel,
3
+ addressFromA1Notation,
4
+ addressToA1Notation,
5
+ columnLetter,
6
+ defaultFunctions,
7
+ inRange,
8
+ posEquals,
9
+ rangeToA1Notation,
10
+ useComputeGraph
11
+ } from "./chunk-MJOFSXLS.mjs";
12
+ import {
13
+ ValueTypeEnum
14
+ } from "./chunk-D3PUKBH6.mjs";
15
+ import "./chunk-JRL5LGCE.mjs";
16
+
17
+ // packages/plugins/plugin-sheet/src/components/SheetContainer.tsx
18
+ import React4 from "react";
19
+ import { mx as mx3 } from "@dxos/react-ui-theme";
20
+
21
+ // packages/plugins/plugin-sheet/src/components/Sheet/Sheet.tsx
22
+ import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, TouchSensor, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
23
+ import { restrictToHorizontalAxis, restrictToVerticalAxis } from "@dnd-kit/modifiers";
24
+ import { getEventCoordinates, useCombinedRefs } from "@dnd-kit/utilities";
25
+ import { Function as FunctionIcon } from "@phosphor-icons/react";
26
+ import { Resizable } from "re-resizable";
27
+ import React3, { forwardRef, useEffect as useEffect3, useImperativeHandle, useMemo, useRef, useState as useState4 } from "react";
28
+ import { createPortal } from "react-dom";
29
+ import { useResizeDetector } from "react-resize-detector";
30
+ import { debounce } from "@dxos/async";
31
+ import { fullyQualifiedId as fullyQualifiedId2, createDocAccessor } from "@dxos/client/echo";
32
+ import { log } from "@dxos/log";
33
+ import { createAttendableAttributes } from "@dxos/react-ui-attention";
34
+ import { mx as mx2 } from "@dxos/react-ui-theme";
35
+
36
+ // packages/plugins/plugin-sheet/src/components/Sheet/grid.ts
37
+ import { useEffect, useState } from "react";
38
+ var axisWidth = "calc(var(--rail-size)-2px)";
39
+ var axisHeight = 34;
40
+ var minWidth = 40;
41
+ var maxWidth = 800;
42
+ var minHeight = axisHeight;
43
+ var maxHeight = 400;
44
+ var defaultWidth = 200;
45
+ var defaultHeight = minHeight;
46
+ var CELL_DATA_KEY = "cell";
47
+ var useGridLayout = ({ scroller, size, rows, columns, rowSizes, columnSizes }) => {
48
+ const [rowPositions, setRowPositions] = useState([]);
49
+ useEffect(() => {
50
+ if (!rowSizes) {
51
+ return;
52
+ }
53
+ let y = 0;
54
+ setRowPositions(rows.map((idx, i) => {
55
+ const height2 = rowSizes?.[idx] ?? defaultHeight;
56
+ const top = y;
57
+ y += height2 - 1;
58
+ return {
59
+ row: i,
60
+ top,
61
+ height: height2
62
+ };
63
+ }));
64
+ }, [
65
+ rows,
66
+ rowSizes
67
+ ]);
68
+ const [columnPositions, setColumnPositions] = useState([]);
69
+ useEffect(() => {
70
+ if (!columns) {
71
+ return;
72
+ }
73
+ let x = 0;
74
+ setColumnPositions(columns.map((idx, i) => {
75
+ const width2 = columnSizes?.[idx] ?? defaultWidth;
76
+ const left = x;
77
+ x += width2 - 1;
78
+ return {
79
+ column: i,
80
+ left,
81
+ width: width2
82
+ };
83
+ }));
84
+ }, [
85
+ columns,
86
+ columnSizes
87
+ ]);
88
+ const height = rowPositions.length ? rowPositions[rowPositions.length - 1].top + rowPositions[rowPositions.length - 1].height : 0;
89
+ const width = columnPositions.length ? columnPositions[columnPositions.length - 1].left + columnPositions[columnPositions.length - 1].width : 0;
90
+ const [{ rowRange, columnRange }, setWindow] = useState({
91
+ rowRange: [],
92
+ columnRange: []
93
+ });
94
+ useEffect(() => {
95
+ const handleScroll = () => {
96
+ if (!scroller) {
97
+ return;
98
+ }
99
+ const { scrollLeft: left, scrollTop: top, clientWidth: width2, clientHeight: height2 } = scroller;
100
+ let rowStart = 0;
101
+ let rowEnd = 0;
102
+ for (let i = 0; i < rowPositions.length; i++) {
103
+ const row = rowPositions[i];
104
+ if (row.top <= top) {
105
+ rowStart = i;
106
+ }
107
+ if (row.top + row.height >= top + height2) {
108
+ rowEnd = i;
109
+ break;
110
+ }
111
+ }
112
+ let columnStart = 0;
113
+ let columnEnd = 0;
114
+ for (let i = 0; i < columnPositions.length; i++) {
115
+ const column = columnPositions[i];
116
+ if (column.left <= left) {
117
+ columnStart = i;
118
+ }
119
+ if (column.left + column.width >= left + width2) {
120
+ columnEnd = i;
121
+ break;
122
+ }
123
+ }
124
+ const overscan = 5;
125
+ setWindow({
126
+ rowRange: rowPositions.slice(Math.max(0, rowStart - overscan), Math.min(rowPositions.length, rowEnd + overscan)),
127
+ columnRange: columnPositions.slice(Math.max(0, columnStart - overscan), Math.min(columnPositions.length, columnEnd + overscan))
128
+ });
129
+ };
130
+ scroller?.addEventListener("scroll", handleScroll);
131
+ handleScroll();
132
+ return () => {
133
+ scroller?.removeEventListener("scroll", handleScroll);
134
+ };
135
+ }, [
136
+ size.width,
137
+ size.height,
138
+ rowPositions,
139
+ columnPositions
140
+ ]);
141
+ return {
142
+ width,
143
+ height,
144
+ rowRange,
145
+ columnRange
146
+ };
147
+ };
148
+ var getCellAtPointer = (event) => {
149
+ const element = document.elementFromPoint(event.clientX, event.clientY);
150
+ const root = element?.closest(`[data-${CELL_DATA_KEY}]`);
151
+ if (root) {
152
+ const value = root.dataset[CELL_DATA_KEY];
153
+ if (value) {
154
+ return addressFromA1Notation(value);
155
+ }
156
+ }
157
+ };
158
+ var getCellElement = (root, cell) => {
159
+ const pos = addressToA1Notation(cell);
160
+ return root.querySelector(`[data-${CELL_DATA_KEY}="${pos}"]`);
161
+ };
162
+
163
+ // packages/plugins/plugin-sheet/src/components/Sheet/nav.ts
164
+ import { useState as useState2 } from "react";
165
+ var handleNav = (ev, cursor, range, size) => {
166
+ if (cursor && ev.shiftKey) {
167
+ const opposite = range?.to ?? {
168
+ ...cursor
169
+ };
170
+ switch (ev.key) {
171
+ case "ArrowUp": {
172
+ if (opposite.row > 0) {
173
+ opposite.row -= 1;
174
+ }
175
+ break;
176
+ }
177
+ case "ArrowDown": {
178
+ if (opposite.row < size.numRows - 1) {
179
+ opposite.row += 1;
180
+ }
181
+ break;
182
+ }
183
+ case "ArrowLeft": {
184
+ if (opposite.column > 0) {
185
+ opposite.column -= 1;
186
+ }
187
+ break;
188
+ }
189
+ case "ArrowRight": {
190
+ if (opposite.column < size.numColumns - 1) {
191
+ opposite.column += 1;
192
+ }
193
+ break;
194
+ }
195
+ }
196
+ return {
197
+ cursor,
198
+ range: {
199
+ from: cursor,
200
+ to: opposite
201
+ }
202
+ };
203
+ }
204
+ const next = handleArrowNav(ev, cursor, size);
205
+ return {
206
+ cursor: next
207
+ };
208
+ };
209
+ var handleArrowNav = (ev, cursor, { numRows, numColumns }) => {
210
+ switch (ev.key) {
211
+ case "ArrowUp":
212
+ if (cursor === void 0) {
213
+ return {
214
+ row: 0,
215
+ column: 0
216
+ };
217
+ } else if (cursor.row > 0) {
218
+ return {
219
+ row: ev.metaKey ? 0 : cursor.row - 1,
220
+ column: cursor.column
221
+ };
222
+ }
223
+ break;
224
+ case "ArrowDown":
225
+ if (cursor === void 0) {
226
+ return {
227
+ row: 0,
228
+ column: 0
229
+ };
230
+ } else if (cursor.row < numRows - 1) {
231
+ return {
232
+ row: ev.metaKey ? numRows - 1 : cursor.row + 1,
233
+ column: cursor.column
234
+ };
235
+ }
236
+ break;
237
+ case "ArrowLeft":
238
+ if (cursor === void 0) {
239
+ return {
240
+ row: 0,
241
+ column: 0
242
+ };
243
+ } else if (cursor.column > 0) {
244
+ return {
245
+ row: cursor.row,
246
+ column: ev.metaKey ? 0 : cursor.column - 1
247
+ };
248
+ }
249
+ break;
250
+ case "ArrowRight":
251
+ if (cursor === void 0) {
252
+ return {
253
+ row: 0,
254
+ column: 0
255
+ };
256
+ } else if (cursor.column < numColumns - 1) {
257
+ return {
258
+ row: cursor.row,
259
+ column: ev.metaKey ? numColumns - 1 : cursor.column + 1
260
+ };
261
+ }
262
+ break;
263
+ case "Home":
264
+ return {
265
+ row: 0,
266
+ column: 0
267
+ };
268
+ case "End":
269
+ return {
270
+ row: numRows - 1,
271
+ column: numColumns - 1
272
+ };
273
+ }
274
+ };
275
+ var useRangeSelect = (cb) => {
276
+ const [from, setFrom] = useState2();
277
+ const [to, setTo] = useState2();
278
+ const onMouseDown = (ev) => {
279
+ const current = getCellAtPointer(ev);
280
+ setFrom(current);
281
+ if (current) {
282
+ setTimeout(() => cb("start", {
283
+ from: current
284
+ }));
285
+ }
286
+ };
287
+ const onMouseMove = (ev) => {
288
+ if (from) {
289
+ let current = getCellAtPointer(ev);
290
+ if (posEquals(current, from)) {
291
+ current = void 0;
292
+ }
293
+ setTo(current);
294
+ setTimeout(() => cb("move", {
295
+ from,
296
+ to: current
297
+ }));
298
+ }
299
+ };
300
+ const onMouseUp = (ev) => {
301
+ if (from) {
302
+ let current = getCellAtPointer(ev);
303
+ if (posEquals(current, from)) {
304
+ current = void 0;
305
+ }
306
+ setFrom(void 0);
307
+ setTo(void 0);
308
+ setTimeout(() => cb("end", current ? {
309
+ from,
310
+ to: current
311
+ } : void 0));
312
+ }
313
+ };
314
+ return {
315
+ range: from ? {
316
+ from,
317
+ to
318
+ } : void 0,
319
+ handlers: {
320
+ onMouseDown,
321
+ onMouseMove,
322
+ onMouseUp
323
+ }
324
+ };
325
+ };
326
+
327
+ // packages/plugins/plugin-sheet/src/components/Sheet/sheet-context.tsx
328
+ import React, { createContext, useContext, useState as useState3, useEffect as useEffect2 } from "react";
329
+ import { invariant } from "@dxos/invariant";
330
+ import { fullyQualifiedId } from "@dxos/react-client/echo";
331
+
332
+ // packages/plugins/plugin-sheet/src/components/Sheet/formatting.ts
333
+ var FormattingModel = class {
334
+ constructor(model) {
335
+ this.model = model;
336
+ }
337
+ /**
338
+ * Get formatted string value and className for cell.
339
+ */
340
+ getFormatting(cell) {
341
+ const value = this.model.getValue(cell);
342
+ if (value === void 0 || value === null) {
343
+ return {};
344
+ }
345
+ const locales = void 0;
346
+ const idx = this.model.addressToIndex(cell);
347
+ let formatting = this.model.sheet.formatting?.[idx] ?? {};
348
+ const classNames = [
349
+ ...formatting?.classNames ?? []
350
+ ];
351
+ for (const [idx2, _formatting] of Object.entries(this.model.sheet.formatting)) {
352
+ const range = this.model.rangeFromIndex(idx2);
353
+ if (inRange(range, cell)) {
354
+ if (_formatting.classNames) {
355
+ classNames.push(..._formatting.classNames);
356
+ }
357
+ if (_formatting.type) {
358
+ formatting = _formatting;
359
+ }
360
+ }
361
+ }
362
+ const defaultNumber = "justify-end font-mono";
363
+ const type = formatting?.type ?? this.model.getValueType(cell);
364
+ switch (type) {
365
+ case ValueTypeEnum.Boolean: {
366
+ return {
367
+ value: value.toLocaleString().toUpperCase(),
368
+ classNames: [
369
+ ...classNames,
370
+ value ? "!text-green-500" : "!text-orange-500"
371
+ ]
372
+ };
373
+ }
374
+ case ValueTypeEnum.Number: {
375
+ return {
376
+ value: value.toLocaleString(locales),
377
+ classNames: [
378
+ ...classNames,
379
+ defaultNumber
380
+ ]
381
+ };
382
+ }
383
+ case ValueTypeEnum.Percent: {
384
+ return {
385
+ value: value * 100 + "%",
386
+ classNames: [
387
+ ...classNames,
388
+ defaultNumber
389
+ ]
390
+ };
391
+ }
392
+ case ValueTypeEnum.Currency: {
393
+ return {
394
+ value: value.toLocaleString(locales, {
395
+ style: "currency",
396
+ currency: "USD",
397
+ minimumFractionDigits: 2,
398
+ maximumFractionDigits: 2
399
+ }),
400
+ classNames: [
401
+ ...classNames,
402
+ defaultNumber
403
+ ]
404
+ };
405
+ }
406
+ case ValueTypeEnum.DateTime: {
407
+ const date = this.model.toLocalDate(value);
408
+ return {
409
+ value: date.toLocaleString(locales),
410
+ classNames
411
+ };
412
+ }
413
+ case ValueTypeEnum.Date: {
414
+ const date = this.model.toLocalDate(value);
415
+ return {
416
+ value: date.toLocaleDateString(locales),
417
+ classNames
418
+ };
419
+ }
420
+ case ValueTypeEnum.Time: {
421
+ const date = this.model.toLocalDate(value);
422
+ return {
423
+ value: date.toLocaleTimeString(locales),
424
+ classNames
425
+ };
426
+ }
427
+ default: {
428
+ return {
429
+ value: String(value),
430
+ classNames
431
+ };
432
+ }
433
+ }
434
+ }
435
+ };
436
+
437
+ // packages/plugins/plugin-sheet/src/components/Sheet/sheet-context.tsx
438
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-sheet/src/components/Sheet/sheet-context.tsx";
439
+ var OBJECT_ID_LENGTH = 60;
440
+ var SheetContext = /* @__PURE__ */ createContext(null);
441
+ var useSheetContext = () => {
442
+ const context = useContext(SheetContext);
443
+ invariant(context, void 0, {
444
+ F: __dxlog_file,
445
+ L: 45,
446
+ S: void 0,
447
+ A: [
448
+ "context",
449
+ ""
450
+ ]
451
+ });
452
+ return context;
453
+ };
454
+ var mapFormulaBindingToId = (functions) => (formula) => {
455
+ return formula.replace(/([a-zA-Z0-9]+)\((.*)\)/g, (match, binding, args) => {
456
+ if (defaultFunctions.find((fn2) => fn2.name === binding) || binding === "EDGE") {
457
+ return match;
458
+ }
459
+ const fn = functions.find((fn2) => fn2.binding === binding);
460
+ if (fn) {
461
+ return `${fullyQualifiedId(fn)}(${args})`;
462
+ } else {
463
+ return match;
464
+ }
465
+ });
466
+ };
467
+ var mapFormulaBindingFromId = (functions) => (formula) => {
468
+ return formula.replace(/([a-zA-Z0-9]+):([a-zA-Z0-9]+)\((.*)\)/g, (match, spaceId, objectId, args) => {
469
+ const id = `${spaceId}:${objectId}`;
470
+ if (id.length !== OBJECT_ID_LENGTH) {
471
+ return match;
472
+ }
473
+ const fn = functions.find((fn2) => fullyQualifiedId(fn2) === id);
474
+ if (fn?.binding) {
475
+ return `${fn.binding}(${args})`;
476
+ } else {
477
+ return match;
478
+ }
479
+ });
480
+ };
481
+ var SheetContextProvider = ({ children, sheet, space, readonly, onInfo, ...options }) => {
482
+ const graph = useComputeGraph(space, options);
483
+ const [cursor, setCursor] = useState3();
484
+ const [range, setRange] = useState3();
485
+ const [editing, setEditing] = useState3(false);
486
+ const [[model, formatting] = [], setModels] = useState3(void 0);
487
+ useEffect2(() => {
488
+ let model2;
489
+ let formatting2;
490
+ const t = setTimeout(async () => {
491
+ model2 = new SheetModel(graph, sheet, space, {
492
+ readonly,
493
+ mapFormulaBindingToId,
494
+ mapFormulaBindingFromId
495
+ });
496
+ await model2.initialize();
497
+ formatting2 = new FormattingModel(model2);
498
+ setModels([
499
+ model2,
500
+ formatting2
501
+ ]);
502
+ });
503
+ return () => {
504
+ clearTimeout(t);
505
+ void model2?.destroy();
506
+ };
507
+ }, [
508
+ graph,
509
+ readonly
510
+ ]);
511
+ if (!model || !formatting) {
512
+ return null;
513
+ }
514
+ return /* @__PURE__ */ React.createElement(SheetContext.Provider, {
515
+ value: {
516
+ model,
517
+ formatting,
518
+ cursor,
519
+ setCursor,
520
+ range,
521
+ setRange,
522
+ editing,
523
+ setEditing,
524
+ // TODO(burdon): Change to event.
525
+ onInfo
526
+ }
527
+ }, children);
528
+ };
529
+
530
+ // packages/plugins/plugin-sheet/src/components/Sheet/util.ts
531
+ var getRelativeClientRect = (root, element) => {
532
+ const rootRect = root.getBoundingClientRect();
533
+ const elementRect = element.getBoundingClientRect();
534
+ return new DOMRect(elementRect.left - rootRect.left + root.scrollLeft, elementRect.top - rootRect.top + root.scrollTop, elementRect.width, elementRect.height);
535
+ };
536
+ var getRectUnion = (b1, b2) => {
537
+ return {
538
+ left: Math.min(b1.left, b2.left),
539
+ top: Math.min(b1.top, b2.top),
540
+ width: Math.abs(b1.left - b2.left) + (b1.left > b2.left ? b1.width : b2.width),
541
+ height: Math.abs(b1.top - b2.top) + (b1.height > b2.height ? b1.height : b2.height)
542
+ };
543
+ };
544
+ var scrollIntoView = (scrollContainer, el) => {
545
+ el.scrollIntoView({
546
+ block: "nearest",
547
+ inline: "nearest"
548
+ });
549
+ const cellBounds = el.getBoundingClientRect();
550
+ const scrollerBounds = scrollContainer.getBoundingClientRect();
551
+ if (cellBounds.top < scrollerBounds.top) {
552
+ scrollContainer.scrollTop -= scrollerBounds.top - cellBounds.top;
553
+ } else if (cellBounds.bottom >= scrollerBounds.bottom - 1) {
554
+ scrollContainer.scrollTop += 2 + scrollerBounds.bottom - cellBounds.bottom;
555
+ }
556
+ if (cellBounds.left < scrollerBounds.left) {
557
+ scrollContainer.scrollLeft -= scrollerBounds.left - cellBounds.left;
558
+ } else if (cellBounds.right >= scrollerBounds.right) {
559
+ scrollContainer.scrollLeft += 2 + scrollerBounds.right - cellBounds.right;
560
+ }
561
+ };
562
+
563
+ // packages/plugins/plugin-sheet/src/components/CellEditor/CellEditor.tsx
564
+ import { EditorView, keymap } from "@codemirror/view";
565
+ import React2 from "react";
566
+ import { useThemeContext } from "@dxos/react-ui";
567
+ import { createBasicExtensions, createThemeExtensions, preventNewline, useTextEditor } from "@dxos/react-ui-editor";
568
+ var editorKeys = ({ onNav, onClose }) => {
569
+ return keymap.of([
570
+ {
571
+ key: "ArrowUp",
572
+ run: (editor) => {
573
+ const value = editor.state.doc.toString();
574
+ onNav?.(value, {
575
+ key: "ArrowUp"
576
+ });
577
+ return !!onNav;
578
+ }
579
+ },
580
+ {
581
+ key: "ArrowDown",
582
+ run: (editor) => {
583
+ const value = editor.state.doc.toString();
584
+ onNav?.(value, {
585
+ key: "ArrowDown"
586
+ });
587
+ return !!onNav;
588
+ }
589
+ },
590
+ {
591
+ key: "ArrowLeft",
592
+ run: (editor) => {
593
+ const value = editor.state.doc.toString();
594
+ onNav?.(value, {
595
+ key: "ArrowLeft"
596
+ });
597
+ return !!onNav;
598
+ }
599
+ },
600
+ {
601
+ key: "ArrowRight",
602
+ run: (editor) => {
603
+ const value = editor.state.doc.toString();
604
+ onNav?.(value, {
605
+ key: "ArrowRight"
606
+ });
607
+ return !!onNav;
608
+ }
609
+ },
610
+ {
611
+ key: "Enter",
612
+ run: (editor) => {
613
+ onClose(editor.state.doc.toString());
614
+ return true;
615
+ }
616
+ },
617
+ {
618
+ key: "Escape",
619
+ run: () => {
620
+ onClose(void 0);
621
+ return true;
622
+ }
623
+ }
624
+ ]);
625
+ };
626
+ var CellEditor = ({ value, extension, autoFocus, onBlur }) => {
627
+ const { themeMode } = useThemeContext();
628
+ const { parentRef } = useTextEditor(() => {
629
+ return {
630
+ autoFocus,
631
+ initialValue: value,
632
+ selection: {
633
+ anchor: value?.length ?? 0
634
+ },
635
+ extensions: [
636
+ extension ?? [],
637
+ preventNewline,
638
+ EditorView.focusChangeEffect.of((_, focusing) => {
639
+ if (!focusing) {
640
+ onBlur?.({
641
+ type: "blur"
642
+ });
643
+ }
644
+ return null;
645
+ }),
646
+ createBasicExtensions({
647
+ lineWrapping: false
648
+ }),
649
+ createThemeExtensions({
650
+ themeMode,
651
+ slots: {
652
+ editor: {
653
+ className: "flex w-full [&>.cm-scroller]:scrollbar-none"
654
+ },
655
+ content: {
656
+ className: "!px-2 !py-1"
657
+ }
658
+ }
659
+ })
660
+ ]
661
+ };
662
+ }, [
663
+ extension
664
+ ]);
665
+ return /* @__PURE__ */ React2.createElement("div", {
666
+ ref: parentRef,
667
+ className: "flex w-full"
668
+ });
669
+ };
670
+
671
+ // packages/plugins/plugin-sheet/src/components/CellEditor/extension.ts
672
+ import { acceptCompletion, autocompletion, completionStatus, startCompletion } from "@codemirror/autocomplete";
673
+ import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
674
+ import { Facet } from "@codemirror/state";
675
+ import { ViewPlugin, keymap as keymap2 } from "@codemirror/view";
676
+ import { tags } from "@lezer/highlight";
677
+ import { spreadsheet } from "codemirror-lang-spreadsheet";
678
+ import { mx } from "@dxos/react-ui-theme";
679
+ var highlightStyles = HighlightStyle.define([
680
+ // Function.
681
+ {
682
+ tag: tags.name,
683
+ class: "text-primary-500"
684
+ },
685
+ // Range.
686
+ {
687
+ tag: tags.tagName,
688
+ class: "text-pink-500"
689
+ },
690
+ // Values.
691
+ {
692
+ tag: tags.number,
693
+ class: "text-teal-500"
694
+ },
695
+ {
696
+ tag: tags.bool,
697
+ class: "text-teal-500"
698
+ },
699
+ {
700
+ tag: tags.string,
701
+ class: "text-teal-500"
702
+ },
703
+ // Error.
704
+ {
705
+ tag: tags.invalid,
706
+ class: "text-neutral-500"
707
+ }
708
+ ]);
709
+ var languageFacet = Facet.define();
710
+ var sheetExtension = ({ functions = [] }) => {
711
+ const { extension, language } = spreadsheet({
712
+ idiom: "en-US",
713
+ decimalSeparator: "."
714
+ });
715
+ const createCompletion = (name) => {
716
+ const { section = "Custom", description, syntax } = functions.find((value) => value.name === name) ?? {};
717
+ return {
718
+ section,
719
+ label: name,
720
+ info: () => {
721
+ if (!description && !syntax) {
722
+ return null;
723
+ }
724
+ const root = document.createElement("div");
725
+ root.className = "flex flex-col gap-2 text-sm";
726
+ const title = document.createElement("h2");
727
+ title.innerText = name;
728
+ title.className = "text-lg font-mono text-primary-500";
729
+ root.appendChild(title);
730
+ if (description) {
731
+ const info = document.createElement("p");
732
+ info.innerText = description;
733
+ info.className = "fg-subdued";
734
+ root.appendChild(info);
735
+ }
736
+ if (syntax) {
737
+ const detail = document.createElement("pre");
738
+ detail.innerText = syntax;
739
+ detail.className = "whitespace-pre-wrap text-green-500";
740
+ root.appendChild(detail);
741
+ }
742
+ return root;
743
+ },
744
+ apply: (view, completion, from, to) => {
745
+ const insertParens = to === view.state.doc.toString().length;
746
+ view.dispatch(view.state.update({
747
+ changes: {
748
+ from,
749
+ to,
750
+ insert: completion.label + (insertParens ? "()" : "")
751
+ },
752
+ selection: {
753
+ anchor: from + completion.label.length + 1
754
+ }
755
+ }));
756
+ }
757
+ };
758
+ };
759
+ return [
760
+ extension,
761
+ languageFacet.of(language),
762
+ language.data.of({
763
+ autocomplete: (context) => {
764
+ if (context.state.doc.toString()[0] !== "=") {
765
+ return null;
766
+ }
767
+ const match = context.matchBefore(/\w*/);
768
+ if (!match || match.from === match.to) {
769
+ return null;
770
+ }
771
+ const text = match.text.toUpperCase();
772
+ if (!context.explicit && match.text.length < 2) {
773
+ return null;
774
+ }
775
+ return {
776
+ from: match.from,
777
+ options: functions?.filter(({ name }) => name.startsWith(text)).map(({ name }) => createCompletion(name)) ?? []
778
+ };
779
+ }
780
+ }),
781
+ syntaxHighlighting(highlightStyles),
782
+ autocompletion({
783
+ aboveCursor: false,
784
+ defaultKeymap: true,
785
+ activateOnTyping: true,
786
+ // NOTE: Useful for debugging.
787
+ closeOnBlur: false,
788
+ icons: false,
789
+ tooltipClass: () => mx(
790
+ // TODO(burdon): Factor out fragments.
791
+ // TODO(burdon): Size to make width same as column.
792
+ "!-left-[1px] !top-[33px] !-m-0 border !border-t-0 [&>ul]:!min-w-[198px]",
793
+ "[&>ul>li[aria-selected]]:!bg-primary-700",
794
+ "border-neutral-200 dark:border-neutral-700"
795
+ )
796
+ }),
797
+ keymap2.of([
798
+ {
799
+ key: "Tab",
800
+ run: (view) => {
801
+ return completionStatus(view.state) === "active" ? acceptCompletion(view) : startCompletion(view);
802
+ }
803
+ }
804
+ ])
805
+ ];
806
+ };
807
+ var rangeExtension = (onInit) => {
808
+ let view;
809
+ let activeRange;
810
+ const provider = (range) => {
811
+ if (activeRange) {
812
+ view.dispatch(view.state.update({
813
+ changes: {
814
+ ...activeRange,
815
+ insert: range.toString()
816
+ },
817
+ selection: {
818
+ anchor: activeRange.from + range.length
819
+ }
820
+ }));
821
+ }
822
+ view.focus();
823
+ };
824
+ return ViewPlugin.fromClass(class {
825
+ constructor(_view) {
826
+ view = _view;
827
+ onInit(provider);
828
+ }
829
+ update(view2) {
830
+ const { anchor } = view2.state.selection.ranges[0];
831
+ activeRange = void 0;
832
+ const [language] = view2.state.facet(languageFacet);
833
+ const { topNode } = language.parser.parse(view2.state.doc.toString());
834
+ visitTree(topNode, ({ type, from, to }) => {
835
+ if (from <= anchor && to >= anchor) {
836
+ switch (type.name) {
837
+ case "Function": {
838
+ activeRange = {
839
+ from: to,
840
+ to
841
+ };
842
+ break;
843
+ }
844
+ case "RangeToken":
845
+ case "CellToken":
846
+ activeRange = {
847
+ from,
848
+ to
849
+ };
850
+ return true;
851
+ }
852
+ }
853
+ return false;
854
+ });
855
+ if (!activeRange && view2.state.doc.toString()[0] === "=") {
856
+ activeRange = {
857
+ from: 1,
858
+ to: view2.state.doc.toString().length
859
+ };
860
+ }
861
+ }
862
+ });
863
+ };
864
+ var visitTree = (node, callback) => {
865
+ if (callback(node)) {
866
+ return true;
867
+ }
868
+ for (let child = node.firstChild; child !== null; child = child.nextSibling) {
869
+ if (visitTree(child, callback)) {
870
+ return true;
871
+ }
872
+ }
873
+ return false;
874
+ };
875
+
876
+ // packages/plugins/plugin-sheet/src/components/Sheet/Sheet.tsx
877
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-sheet/src/components/Sheet/Sheet.tsx";
878
+ var fragments = {
879
+ axis: "bg-neutral-50 text-neutral-800 dark:bg-neutral-800 dark:text-neutral-200 text-xs select-none",
880
+ axisSelected: "bg-neutral-100 dark:bg-neutral-900 text-black dark:text-white",
881
+ cell: "dark:bg-neutral-850",
882
+ cellSelected: "bg-neutral-50 dark:bg-neutral-900 text-black dark:text-white border !border-primary-500",
883
+ border: "border-neutral-200 dark:border-neutral-700"
884
+ };
885
+ var SheetRoot = ({ children, ...props }) => {
886
+ return /* @__PURE__ */ React3.createElement(SheetContextProvider, props, children);
887
+ };
888
+ var SheetMain = /* @__PURE__ */ forwardRef(({ classNames, numRows, numColumns }, forwardRef2) => {
889
+ const { model, cursor, setCursor, setRange, setEditing } = useSheetContext();
890
+ const { rowsRef, columnsRef, contentRef } = useScrollHandlers();
891
+ const [rows, setRows] = useState4([
892
+ ...model.sheet.rows
893
+ ]);
894
+ const [columns, setColumns] = useState4([
895
+ ...model.sheet.columns
896
+ ]);
897
+ useEffect3(() => {
898
+ const rowsAccessor = createDocAccessor(model.sheet, [
899
+ "rows"
900
+ ]);
901
+ const columnsAccessor = createDocAccessor(model.sheet, [
902
+ "columns"
903
+ ]);
904
+ const handleUpdate = debounce(() => {
905
+ setRows([
906
+ ...model.sheet.rows
907
+ ]);
908
+ setColumns([
909
+ ...model.sheet.columns
910
+ ]);
911
+ }, 100);
912
+ rowsAccessor.handle.addListener("change", handleUpdate);
913
+ columnsAccessor.handle.addListener("change", handleUpdate);
914
+ handleUpdate();
915
+ return () => {
916
+ rowsAccessor.handle.removeListener("change", handleUpdate);
917
+ columnsAccessor.handle.removeListener("change", handleUpdate);
918
+ };
919
+ }, [
920
+ model
921
+ ]);
922
+ useEffect3(() => {
923
+ model.reset();
924
+ }, [
925
+ rows,
926
+ columns
927
+ ]);
928
+ const handleMoveRows = (from, to, num = 1) => {
929
+ const cursorIdx = cursor ? model.addressToIndex(cursor) : void 0;
930
+ const [rows2] = model.sheet.rows.splice(from, num);
931
+ model.sheet.rows.splice(to, 0, rows2);
932
+ if (cursorIdx) {
933
+ setCursor(model.addressFromIndex(cursorIdx));
934
+ }
935
+ setRows([
936
+ ...model.sheet.rows
937
+ ]);
938
+ };
939
+ const handleMoveColumns = (from, to, num = 1) => {
940
+ const cursorIdx = cursor ? model.addressToIndex(cursor) : void 0;
941
+ const columns2 = model.sheet.columns.splice(from, num);
942
+ model.sheet.columns.splice(to, 0, ...columns2);
943
+ if (cursorIdx) {
944
+ setCursor(model.addressFromIndex(cursorIdx));
945
+ }
946
+ setColumns([
947
+ ...model.sheet.columns
948
+ ]);
949
+ };
950
+ const [rowSizes, setRowSizes] = useState4();
951
+ const [columnSizes, setColumnSizes] = useState4();
952
+ useEffect3(() => {
953
+ const rowAccessor = createDocAccessor(model.sheet, [
954
+ "rowMeta"
955
+ ]);
956
+ const columnAccessor = createDocAccessor(model.sheet, [
957
+ "columnMeta"
958
+ ]);
959
+ const handleUpdate = debounce(() => {
960
+ const mapSizes = (values) => values.reduce((map, [idx, meta]) => {
961
+ if (meta.size) {
962
+ map[idx] = meta.size;
963
+ }
964
+ return map;
965
+ }, {});
966
+ setRowSizes(mapSizes(Object.entries(model.sheet.rowMeta)));
967
+ setColumnSizes(mapSizes(Object.entries(model.sheet.columnMeta)));
968
+ }, 100);
969
+ rowAccessor.handle.addListener("change", handleUpdate);
970
+ columnAccessor.handle.addListener("change", handleUpdate);
971
+ handleUpdate();
972
+ return () => {
973
+ rowAccessor.handle.removeListener("change", handleUpdate);
974
+ columnAccessor.handle.removeListener("change", handleUpdate);
975
+ };
976
+ }, [
977
+ model
978
+ ]);
979
+ const handleResizeRow = (idx, size, save) => {
980
+ if (save) {
981
+ model.sheet.rowMeta[idx] ??= {};
982
+ model.sheet.rowMeta[idx].size = size;
983
+ } else {
984
+ setRowSizes((sizes) => ({
985
+ ...sizes,
986
+ [idx]: size
987
+ }));
988
+ }
989
+ };
990
+ const handleResizeColumn = (idx, size, save) => {
991
+ if (save) {
992
+ model.sheet.columnMeta[idx] ??= {};
993
+ model.sheet.columnMeta[idx].size = size;
994
+ } else {
995
+ setColumnSizes((sizes) => ({
996
+ ...sizes,
997
+ [idx]: size
998
+ }));
999
+ }
1000
+ };
1001
+ return /* @__PURE__ */ React3.createElement("div", {
1002
+ role: "none",
1003
+ className: mx2("grid grid-cols-[calc(var(--rail-size)-2px)_1fr] grid-rows-[32px_1fr_32px] bs-full is-full overflow-hidden", fragments.border, classNames)
1004
+ }, /* @__PURE__ */ React3.createElement(GridCorner, {
1005
+ onClick: () => {
1006
+ setCursor(void 0);
1007
+ setRange(void 0);
1008
+ setEditing(false);
1009
+ }
1010
+ }), /* @__PURE__ */ React3.createElement(SheetColumns, {
1011
+ ref: columnsRef,
1012
+ columns,
1013
+ sizes: columnSizes,
1014
+ selected: cursor?.column,
1015
+ onSelect: (column) => setCursor(cursor?.column === column ? void 0 : {
1016
+ row: -1,
1017
+ column
1018
+ }),
1019
+ onResize: handleResizeColumn,
1020
+ onMove: handleMoveColumns
1021
+ }), /* @__PURE__ */ React3.createElement(SheetRows, {
1022
+ ref: rowsRef,
1023
+ rows,
1024
+ sizes: rowSizes,
1025
+ selected: cursor?.row,
1026
+ onSelect: (row) => setCursor(cursor?.row === row ? void 0 : {
1027
+ row,
1028
+ column: -1
1029
+ }),
1030
+ onResize: handleResizeRow,
1031
+ onMove: handleMoveRows
1032
+ }), /* @__PURE__ */ React3.createElement(SheetGrid, {
1033
+ ref: contentRef,
1034
+ size: {
1035
+ numRows: numRows ?? rows.length,
1036
+ numColumns: numColumns ?? columns.length
1037
+ },
1038
+ rows,
1039
+ columns,
1040
+ rowSizes,
1041
+ columnSizes
1042
+ }), /* @__PURE__ */ React3.createElement(GridCorner, null), /* @__PURE__ */ React3.createElement(SheetStatusBar, null));
1043
+ });
1044
+ var useScrollHandlers = () => {
1045
+ const rowsRef = useRef(null);
1046
+ const columnsRef = useRef(null);
1047
+ const contentRef = useRef(null);
1048
+ useEffect3(() => {
1049
+ const handleRowsScroll = (ev) => {
1050
+ const { scrollTop } = ev.target;
1051
+ if (!rowsRef.current.dataset.locked) {
1052
+ contentRef.current.scrollTop = scrollTop;
1053
+ }
1054
+ };
1055
+ const handleColumnsScroll = (ev) => {
1056
+ const { scrollLeft } = ev.target;
1057
+ if (!columnsRef.current.dataset.locked) {
1058
+ contentRef.current.scrollLeft = scrollLeft;
1059
+ }
1060
+ };
1061
+ const handleContentScroll = (ev) => {
1062
+ const { scrollTop, scrollLeft } = ev.target;
1063
+ rowsRef.current.scrollTop = scrollTop;
1064
+ columnsRef.current.scrollLeft = scrollLeft;
1065
+ };
1066
+ const rows = rowsRef.current;
1067
+ const columns = columnsRef.current;
1068
+ const content = contentRef.current;
1069
+ rows.addEventListener("scroll", handleRowsScroll);
1070
+ columns.addEventListener("scroll", handleColumnsScroll);
1071
+ content.addEventListener("scroll", handleContentScroll);
1072
+ return () => {
1073
+ rows.removeEventListener("scroll", handleRowsScroll);
1074
+ columns.removeEventListener("scroll", handleColumnsScroll);
1075
+ content.removeEventListener("scroll", handleContentScroll);
1076
+ };
1077
+ }, []);
1078
+ return {
1079
+ rowsRef,
1080
+ columnsRef,
1081
+ contentRef
1082
+ };
1083
+ };
1084
+ var GridCorner = (props) => {
1085
+ return /* @__PURE__ */ React3.createElement("div", {
1086
+ className: fragments.axis,
1087
+ ...props
1088
+ });
1089
+ };
1090
+ var MovingOverlay = ({ label }) => {
1091
+ return /* @__PURE__ */ React3.createElement("div", {
1092
+ className: "flex w-full h-full justify-center items-center text-sm p-1 bg-primary-500/50 cursor-pointer"
1093
+ }, label);
1094
+ };
1095
+ var mouseConstraints = {
1096
+ distance: 10
1097
+ };
1098
+ var touchConstraints = {
1099
+ delay: 250,
1100
+ tolerance: 5
1101
+ };
1102
+ var SheetRows = /* @__PURE__ */ forwardRef(({ rows, sizes, selected, onSelect, onResize, onMove }, forwardRef2) => {
1103
+ const mouseSensor = useSensor(MouseSensor, {
1104
+ activationConstraint: mouseConstraints
1105
+ });
1106
+ const touchSensor = useSensor(TouchSensor, {
1107
+ activationConstraint: touchConstraints
1108
+ });
1109
+ const keyboardSensor = useSensor(KeyboardSensor, {});
1110
+ const sensors = useSensors(mouseSensor, touchSensor, keyboardSensor);
1111
+ const [active, setActive] = useState4(null);
1112
+ const handleDragStart = ({ active: active2 }) => {
1113
+ setActive(active2);
1114
+ };
1115
+ const handleDragEnd = ({ over, active: active2 }) => {
1116
+ if (over && over.id !== active2.id) {
1117
+ setActive(null);
1118
+ onMove?.(active2.data.current.index, over.data.current.index);
1119
+ }
1120
+ };
1121
+ const snapToCenter = ({ activatorEvent, draggingNodeRect, transform }) => {
1122
+ if (draggingNodeRect && activatorEvent) {
1123
+ const activatorCoordinates = getEventCoordinates(activatorEvent);
1124
+ if (!activatorCoordinates) {
1125
+ return transform;
1126
+ }
1127
+ const offset = activatorCoordinates.y - draggingNodeRect.top;
1128
+ return {
1129
+ ...transform,
1130
+ y: transform.y + offset - draggingNodeRect.height / 2
1131
+ };
1132
+ }
1133
+ return transform;
1134
+ };
1135
+ return /* @__PURE__ */ React3.createElement("div", {
1136
+ className: "relative flex grow overflow-hidden"
1137
+ }, /* @__PURE__ */ React3.createElement("div", {
1138
+ className: mx2("z-20 absolute inset-0 border-y pointer-events-none", fragments.border),
1139
+ style: {
1140
+ width: axisWidth
1141
+ }
1142
+ }), /* @__PURE__ */ React3.createElement("div", {
1143
+ ref: forwardRef2,
1144
+ role: "rowheader",
1145
+ className: "grow overflow-y-auto scrollbar-none"
1146
+ }, /* @__PURE__ */ React3.createElement(DndContext, {
1147
+ sensors,
1148
+ modifiers: [
1149
+ restrictToVerticalAxis,
1150
+ snapToCenter
1151
+ ],
1152
+ onDragStart: handleDragStart,
1153
+ onDragEnd: handleDragEnd
1154
+ }, /* @__PURE__ */ React3.createElement("div", {
1155
+ className: "flex flex-col",
1156
+ style: {
1157
+ width: axisWidth
1158
+ }
1159
+ }, rows.map((idx, index) => /* @__PURE__ */ React3.createElement(GridRowCell, {
1160
+ key: idx,
1161
+ idx,
1162
+ index,
1163
+ label: String(index + 1),
1164
+ size: sizes?.[idx] ?? defaultHeight,
1165
+ resize: index < rows.length - 1,
1166
+ selected: selected === index,
1167
+ onResize,
1168
+ onSelect
1169
+ }))), /* @__PURE__ */ createPortal(/* @__PURE__ */ React3.createElement(DragOverlay, null, active && /* @__PURE__ */ React3.createElement(MovingOverlay, {
1170
+ label: String(active.data.current.index + 1)
1171
+ })), document.body))));
1172
+ });
1173
+ var GridRowCell = ({ idx, index, label, size, resize, selected, onSelect, onResize }) => {
1174
+ const { setNodeRef: setDroppableNodeRef } = useDroppable({
1175
+ id: idx,
1176
+ data: {
1177
+ index
1178
+ }
1179
+ });
1180
+ const { setNodeRef: setDraggableNodeRef, attributes, listeners, isDragging, over } = useDraggable({
1181
+ id: idx,
1182
+ data: {
1183
+ index
1184
+ }
1185
+ });
1186
+ const setNodeRef = useCombinedRefs(setDroppableNodeRef, setDraggableNodeRef);
1187
+ const [initialSize, setInitialSize] = useState4(size);
1188
+ const [resizing, setResizing] = useState4(false);
1189
+ const scrollHandler = useRef();
1190
+ const handleResizeStart = (_ev, _dir, elementRef) => {
1191
+ const scrollContainer = elementRef.closest('[role="rowheader"]');
1192
+ const scrollTop = scrollContainer.scrollTop;
1193
+ scrollHandler.current = (ev) => ev.target.scrollTop = scrollTop;
1194
+ scrollContainer.addEventListener("scroll", scrollHandler.current);
1195
+ scrollContainer.dataset.locked = "true";
1196
+ setResizing(true);
1197
+ };
1198
+ const handleResize = (_ev, _dir, _elementRef, { height }) => {
1199
+ onResize?.(idx, initialSize + height);
1200
+ };
1201
+ const handleResizeStop = (_ev, _dir, elementRef, { height }) => {
1202
+ const scrollContainer = elementRef.closest('[role="rowheader"]');
1203
+ scrollContainer.removeEventListener("scroll", scrollHandler.current);
1204
+ delete scrollContainer.dataset.locked;
1205
+ scrollHandler.current = void 0;
1206
+ setInitialSize(initialSize + height);
1207
+ onResize?.(idx, initialSize + height, true);
1208
+ setResizing(false);
1209
+ };
1210
+ return /* @__PURE__ */ React3.createElement(Resizable, {
1211
+ enable: {
1212
+ bottom: resize
1213
+ },
1214
+ size: {
1215
+ height: size - 1
1216
+ },
1217
+ minHeight: minHeight - 1,
1218
+ maxHeight,
1219
+ onResizeStart: handleResizeStart,
1220
+ onResize: handleResize,
1221
+ onResizeStop: handleResizeStop
1222
+ }, /* @__PURE__ */ React3.createElement("div", {
1223
+ ref: setNodeRef,
1224
+ ...attributes,
1225
+ ...listeners,
1226
+ className: mx2("flex h-full items-center justify-center cursor-pointer", "border-t focus-visible:outline-none", fragments.border, fragments.axis, selected && fragments.axisSelected, isDragging && fragments.axisSelected),
1227
+ onClick: () => onSelect?.(index)
1228
+ }, /* @__PURE__ */ React3.createElement("span", {
1229
+ className: "flex w-full justify-center"
1230
+ }, label), over?.id === idx && !isDragging && /* @__PURE__ */ React3.createElement("div", {
1231
+ className: "z-20 absolute top-0 w-full min-h-[4px] border-b-4 border-primary-500"
1232
+ }), resizing && /* @__PURE__ */ React3.createElement("div", {
1233
+ className: "z-20 absolute bottom-0 w-full min-h-[4px] border-b-4 border-primary-500"
1234
+ })));
1235
+ };
1236
+ var SheetColumns = /* @__PURE__ */ forwardRef(({ columns, sizes, selected, onSelect, onResize, onMove }, forwardRef2) => {
1237
+ const mouseSensor = useSensor(MouseSensor, {
1238
+ activationConstraint: mouseConstraints
1239
+ });
1240
+ const touchSensor = useSensor(TouchSensor, {
1241
+ activationConstraint: touchConstraints
1242
+ });
1243
+ const keyboardSensor = useSensor(KeyboardSensor, {});
1244
+ const sensors = useSensors(mouseSensor, touchSensor, keyboardSensor);
1245
+ const [active, setActive] = useState4(null);
1246
+ const handleDragStart = ({ active: active2 }) => {
1247
+ setActive(active2);
1248
+ };
1249
+ const handleDragEnd = ({ active: active2, over }) => {
1250
+ if (over && over.id !== active2.id) {
1251
+ setActive(null);
1252
+ onMove?.(active2.data.current.index, over.data.current.index);
1253
+ }
1254
+ };
1255
+ const snapToCenter = ({ activatorEvent, draggingNodeRect, transform }) => {
1256
+ if (draggingNodeRect && activatorEvent) {
1257
+ const activatorCoordinates = getEventCoordinates(activatorEvent);
1258
+ if (!activatorCoordinates) {
1259
+ return transform;
1260
+ }
1261
+ const offset = activatorCoordinates.x - draggingNodeRect.left;
1262
+ return {
1263
+ ...transform,
1264
+ x: transform.x + offset - draggingNodeRect.width / 2
1265
+ };
1266
+ }
1267
+ return transform;
1268
+ };
1269
+ return /* @__PURE__ */ React3.createElement("div", {
1270
+ className: "relative flex grow overflow-hidden"
1271
+ }, /* @__PURE__ */ React3.createElement("div", {
1272
+ className: mx2("z-20 absolute inset-0 border-x pointer-events-none", fragments.border),
1273
+ style: {
1274
+ height: axisHeight
1275
+ }
1276
+ }), /* @__PURE__ */ React3.createElement("div", {
1277
+ ref: forwardRef2,
1278
+ role: "columnheader",
1279
+ className: "grow overflow-x-auto scrollbar-none"
1280
+ }, /* @__PURE__ */ React3.createElement(DndContext, {
1281
+ autoScroll: {
1282
+ enabled: true
1283
+ },
1284
+ sensors,
1285
+ modifiers: [
1286
+ restrictToHorizontalAxis,
1287
+ snapToCenter
1288
+ ],
1289
+ onDragStart: handleDragStart,
1290
+ onDragEnd: handleDragEnd
1291
+ }, /* @__PURE__ */ React3.createElement("div", {
1292
+ className: "flex h-full",
1293
+ style: {
1294
+ height: axisHeight
1295
+ }
1296
+ }, columns.map((idx, index) => /* @__PURE__ */ React3.createElement(GridColumnCell, {
1297
+ key: idx,
1298
+ idx,
1299
+ index,
1300
+ label: columnLetter(index),
1301
+ size: sizes?.[idx] ?? defaultWidth,
1302
+ resize: index < columns.length - 1,
1303
+ selected: selected === index,
1304
+ onResize,
1305
+ onSelect
1306
+ }))), /* @__PURE__ */ createPortal(/* @__PURE__ */ React3.createElement(DragOverlay, null, active && /* @__PURE__ */ React3.createElement(MovingOverlay, {
1307
+ label: columnLetter(active.data.current.index)
1308
+ })), document.body))));
1309
+ });
1310
+ var GridColumnCell = ({ idx, index, label, size, resize, selected, onSelect, onResize }) => {
1311
+ const { setNodeRef: setDroppableNodeRef } = useDroppable({
1312
+ id: idx,
1313
+ data: {
1314
+ index
1315
+ }
1316
+ });
1317
+ const { setNodeRef: setDraggableNodeRef, attributes, listeners, over, isDragging } = useDraggable({
1318
+ id: idx,
1319
+ data: {
1320
+ index
1321
+ }
1322
+ });
1323
+ const setNodeRef = useCombinedRefs(setDroppableNodeRef, setDraggableNodeRef);
1324
+ const [initialSize, setInitialSize] = useState4(size);
1325
+ const [resizing, setResizing] = useState4(false);
1326
+ const scrollHandler = useRef();
1327
+ const handleResizeStart = (_ev, _dir, elementRef) => {
1328
+ const scrollContainer = elementRef.closest('[role="columnheader"]');
1329
+ const scrollLeft = scrollContainer.scrollLeft;
1330
+ scrollHandler.current = (ev) => ev.target.scrollLeft = scrollLeft;
1331
+ scrollContainer.addEventListener("scroll", scrollHandler.current);
1332
+ scrollContainer.dataset.locked = "true";
1333
+ setResizing(true);
1334
+ };
1335
+ const handleResize = (_ev, _dir, _elementRef, { width }) => {
1336
+ onResize?.(idx, initialSize + width);
1337
+ };
1338
+ const handleResizeStop = (_ev, _dir, elementRef, { width }) => {
1339
+ const scrollContainer = elementRef.closest('[role="columnheader"]');
1340
+ scrollContainer.removeEventListener("scroll", scrollHandler.current);
1341
+ delete scrollContainer.dataset.locked;
1342
+ scrollHandler.current = void 0;
1343
+ setInitialSize(initialSize + width);
1344
+ onResize?.(idx, initialSize + width, true);
1345
+ setResizing(false);
1346
+ };
1347
+ return /* @__PURE__ */ React3.createElement(Resizable, {
1348
+ enable: {
1349
+ right: resize
1350
+ },
1351
+ size: {
1352
+ width: size - 1
1353
+ },
1354
+ minWidth: minWidth - 1,
1355
+ maxWidth,
1356
+ onResizeStart: handleResizeStart,
1357
+ onResize: handleResize,
1358
+ onResizeStop: handleResizeStop
1359
+ }, /* @__PURE__ */ React3.createElement("div", {
1360
+ ref: setNodeRef,
1361
+ ...attributes,
1362
+ ...listeners,
1363
+ className: mx2("flex h-full items-center justify-center cursor-pointer", "border-l focus-visible:outline-none", fragments.border, fragments.axis, selected && fragments.axisSelected, isDragging && fragments.axisSelected),
1364
+ onClick: () => onSelect?.(index)
1365
+ }, /* @__PURE__ */ React3.createElement("span", {
1366
+ className: "flex w-full justify-center"
1367
+ }, label), over?.id === idx && !isDragging && /* @__PURE__ */ React3.createElement("div", {
1368
+ className: "z-20 absolute left-0 h-full min-w-[4px] border-l-4 border-primary-500"
1369
+ }), resizing && /* @__PURE__ */ React3.createElement("div", {
1370
+ className: "z-20 absolute right-0 h-full min-h-[4px] border-l-4 border-primary-500"
1371
+ })));
1372
+ };
1373
+ var SheetGrid = /* @__PURE__ */ forwardRef(({ size, rows, columns, rowSizes, columnSizes }, forwardRef2) => {
1374
+ const { ref: containerRef, width: containerWidth = 0, height: containerHeight = 0 } = useResizeDetector({
1375
+ refreshRate: 200
1376
+ });
1377
+ const scrollerRef = useRef(null);
1378
+ useImperativeHandle(forwardRef2, () => scrollerRef.current);
1379
+ const { model, cursor, range, editing, setCursor, setRange, setEditing, onInfo } = useSheetContext();
1380
+ const initialText = useRef();
1381
+ const quickEdit = useRef(false);
1382
+ const [, forceUpdate] = useState4({});
1383
+ useEffect3(() => {
1384
+ const unsubscribe = model.update.on(() => {
1385
+ log("updated", {
1386
+ id: model.id
1387
+ }, {
1388
+ F: __dxlog_file2,
1389
+ L: 735,
1390
+ S: void 0,
1391
+ C: (f, a) => f(...a)
1392
+ });
1393
+ forceUpdate({});
1394
+ });
1395
+ return () => {
1396
+ unsubscribe();
1397
+ };
1398
+ }, [
1399
+ model
1400
+ ]);
1401
+ const inputRef = useRef(null);
1402
+ const handleKeyDown = (ev) => {
1403
+ const isMacOS = /Mac|iPhone|iPod|iPad/.test(navigator.userAgent);
1404
+ if (cursor && (isMacOS && ev.metaKey || ev.ctrlKey)) {
1405
+ switch (ev.key) {
1406
+ case "x": {
1407
+ model.cut(range ?? {
1408
+ from: cursor
1409
+ });
1410
+ return;
1411
+ }
1412
+ case "c": {
1413
+ model.copy(range ?? {
1414
+ from: cursor
1415
+ });
1416
+ return;
1417
+ }
1418
+ case "v": {
1419
+ model.paste(cursor);
1420
+ return;
1421
+ }
1422
+ case "z": {
1423
+ if (ev.shiftKey) {
1424
+ model.redo();
1425
+ } else {
1426
+ model.undo();
1427
+ }
1428
+ return;
1429
+ }
1430
+ }
1431
+ }
1432
+ switch (ev.key) {
1433
+ case "ArrowUp":
1434
+ case "ArrowDown":
1435
+ case "ArrowLeft":
1436
+ case "ArrowRight":
1437
+ case "Home":
1438
+ case "End": {
1439
+ const next = handleNav(ev, cursor, range, size);
1440
+ setRange(next.range);
1441
+ if (next.cursor) {
1442
+ setCursor(next.cursor);
1443
+ const element = getCellElement(scrollerRef.current, next.cursor);
1444
+ if (element) {
1445
+ scrollIntoView(scrollerRef.current, element);
1446
+ }
1447
+ }
1448
+ break;
1449
+ }
1450
+ case "Backspace": {
1451
+ if (cursor) {
1452
+ if (range) {
1453
+ model.clear(range);
1454
+ } else {
1455
+ model.setValue(cursor, null);
1456
+ }
1457
+ }
1458
+ break;
1459
+ }
1460
+ case "Escape": {
1461
+ setRange(void 0);
1462
+ break;
1463
+ }
1464
+ case "Enter": {
1465
+ ev.stopPropagation();
1466
+ if (cursor) {
1467
+ setEditing(true);
1468
+ }
1469
+ break;
1470
+ }
1471
+ case "?": {
1472
+ onInfo?.();
1473
+ break;
1474
+ }
1475
+ default: {
1476
+ if (ev.key.length === 1) {
1477
+ initialText.current = ev.key;
1478
+ quickEdit.current = true;
1479
+ setEditing(true);
1480
+ }
1481
+ }
1482
+ }
1483
+ };
1484
+ const { handlers } = useRangeSelect((event, range2) => {
1485
+ switch (event) {
1486
+ case "start": {
1487
+ setRange(void 0);
1488
+ break;
1489
+ }
1490
+ default: {
1491
+ setRange(range2);
1492
+ }
1493
+ }
1494
+ });
1495
+ const { width, height, rowRange, columnRange } = useGridLayout({
1496
+ scroller: scrollerRef.current,
1497
+ size: {
1498
+ width: containerWidth,
1499
+ height: containerHeight
1500
+ },
1501
+ rows,
1502
+ columns,
1503
+ rowSizes,
1504
+ columnSizes
1505
+ });
1506
+ const qualifiedSubjectId = fullyQualifiedId2(model.sheet);
1507
+ const attendableAttrs = createAttendableAttributes(qualifiedSubjectId);
1508
+ return /* @__PURE__ */ React3.createElement("div", {
1509
+ ref: containerRef,
1510
+ role: "grid",
1511
+ className: "relative flex grow overflow-hidden"
1512
+ }, /* @__PURE__ */ React3.createElement("div", {
1513
+ className: mx2("z-20 absolute inset-0 border pointer-events-none", fragments.border)
1514
+ }), /* @__PURE__ */ React3.createElement("div", {
1515
+ ref: scrollerRef,
1516
+ className: "grow overflow-auto scrollbar-thin"
1517
+ }, /* @__PURE__ */ React3.createElement("div", {
1518
+ className: "relative select-none",
1519
+ style: {
1520
+ width,
1521
+ height
1522
+ },
1523
+ onClick: () => inputRef.current?.focus(),
1524
+ ...handlers
1525
+ }, scrollerRef.current && /* @__PURE__ */ React3.createElement(SelectionOverlay, {
1526
+ root: scrollerRef.current
1527
+ }), rowRange.map(({ row, top, height: height2 }) => {
1528
+ return columnRange.map(({ column, left, width: width2 }) => {
1529
+ const style = {
1530
+ position: "absolute",
1531
+ top,
1532
+ left,
1533
+ width: width2,
1534
+ height: height2
1535
+ };
1536
+ const cell = {
1537
+ row,
1538
+ column
1539
+ };
1540
+ const id = addressToA1Notation(cell);
1541
+ const idx = model.addressToIndex(cell);
1542
+ const active = posEquals(cursor, cell);
1543
+ if (active && editing) {
1544
+ const value = initialText.current ?? model.getCellText(cell) ?? "";
1545
+ const handleClose = (value2) => {
1546
+ initialText.current = void 0;
1547
+ quickEdit.current = false;
1548
+ if (value2 !== void 0) {
1549
+ model.setValue(cell, value2);
1550
+ const next = handleArrowNav({
1551
+ key: "ArrowDown",
1552
+ metaKey: false
1553
+ }, cursor, size);
1554
+ if (next) {
1555
+ setCursor(next);
1556
+ }
1557
+ }
1558
+ inputRef.current?.focus();
1559
+ setEditing(false);
1560
+ };
1561
+ const handleNav2 = (value2, { key }) => {
1562
+ initialText.current = void 0;
1563
+ model.setValue(cell, value2 ?? null);
1564
+ const next = handleArrowNav({
1565
+ key,
1566
+ metaKey: false
1567
+ }, cursor, size);
1568
+ if (next) {
1569
+ setCursor(next);
1570
+ }
1571
+ inputRef.current?.focus();
1572
+ setEditing(false);
1573
+ };
1574
+ return /* @__PURE__ */ React3.createElement(GridCellEditor, {
1575
+ key: idx,
1576
+ value,
1577
+ style,
1578
+ onNav: quickEdit.current ? handleNav2 : void 0,
1579
+ onClose: handleClose
1580
+ });
1581
+ }
1582
+ return /* @__PURE__ */ React3.createElement(SheetCell, {
1583
+ key: id,
1584
+ id,
1585
+ cell,
1586
+ active,
1587
+ style,
1588
+ onSelect: (cell2, edit) => {
1589
+ setEditing(edit);
1590
+ setCursor(cell2);
1591
+ }
1592
+ });
1593
+ });
1594
+ }))), /* @__PURE__ */ createPortal(/* @__PURE__ */ React3.createElement("input", {
1595
+ ref: inputRef,
1596
+ autoFocus: true,
1597
+ className: "absolute w-[1px] h-[1px] bg-transparent outline-none border-none caret-transparent",
1598
+ onKeyDown: handleKeyDown,
1599
+ ...attendableAttrs
1600
+ }), document.body));
1601
+ });
1602
+ var SelectionOverlay = ({ root }) => {
1603
+ const { range } = useSheetContext();
1604
+ if (!range) {
1605
+ return null;
1606
+ }
1607
+ const c1 = getCellElement(root, range.from);
1608
+ const c2 = range.to ? getCellElement(root, range.to) : c1;
1609
+ if (!c1 || !c2) {
1610
+ return null;
1611
+ }
1612
+ const b1 = getRelativeClientRect(root, c1);
1613
+ const b2 = getRelativeClientRect(root, c2);
1614
+ const bounds = getRectUnion(b1, b2);
1615
+ return /* @__PURE__ */ React3.createElement("div", {
1616
+ role: "none",
1617
+ style: bounds,
1618
+ className: "z-10 absolute pointer-events-none bg-primary-500/20 border border-primary-500/50"
1619
+ });
1620
+ };
1621
+ var SheetCell = ({ id, cell, style, active, onSelect }) => {
1622
+ const { formatting, editing, setRange } = useSheetContext();
1623
+ const { value, classNames } = formatting.getFormatting(cell);
1624
+ return /* @__PURE__ */ React3.createElement("div", {
1625
+ [`data-${CELL_DATA_KEY}`]: id,
1626
+ role: "cell",
1627
+ style,
1628
+ className: mx2("flex w-full h-full truncate items-center border cursor-pointer", "px-2 py-1", fragments.cell, fragments.border, active && [
1629
+ "z-20",
1630
+ fragments.cellSelected
1631
+ ], classNames),
1632
+ onClick: () => {
1633
+ if (editing) {
1634
+ setRange?.({
1635
+ from: cell
1636
+ });
1637
+ } else {
1638
+ onSelect?.(cell, false);
1639
+ }
1640
+ },
1641
+ onDoubleClick: () => onSelect?.(cell, true)
1642
+ }, value);
1643
+ };
1644
+ var GridCellEditor = ({ style, value, onNav, onClose }) => {
1645
+ const { model, range } = useSheetContext();
1646
+ const notifier = useRef();
1647
+ useEffect3(() => {
1648
+ if (range) {
1649
+ notifier.current?.(rangeToA1Notation(range));
1650
+ }
1651
+ }, [
1652
+ range
1653
+ ]);
1654
+ const extension = useMemo(() => [
1655
+ editorKeys({
1656
+ onNav,
1657
+ onClose
1658
+ }),
1659
+ sheetExtension({
1660
+ functions: model.functions
1661
+ }),
1662
+ rangeExtension((fn) => notifier.current = fn)
1663
+ ], [
1664
+ model
1665
+ ]);
1666
+ return /* @__PURE__ */ React3.createElement("div", {
1667
+ role: "cell",
1668
+ style,
1669
+ className: mx2("z-20 flex", fragments.cellSelected),
1670
+ onClick: (ev) => ev.stopPropagation()
1671
+ }, /* @__PURE__ */ React3.createElement(CellEditor, {
1672
+ autoFocus: true,
1673
+ value,
1674
+ extension
1675
+ }));
1676
+ };
1677
+ var SheetStatusBar = () => {
1678
+ const { model, cursor, range } = useSheetContext();
1679
+ let value;
1680
+ let isFormula = false;
1681
+ if (cursor) {
1682
+ value = model.getCellValue(cursor);
1683
+ if (typeof value === "string" && value.charAt(0) === "=") {
1684
+ value = model.mapFormulaBindingFromId(model.mapFormulaIndicesToRefs(value));
1685
+ isFormula = true;
1686
+ } else if (value != null) {
1687
+ value = String(value);
1688
+ }
1689
+ }
1690
+ return /* @__PURE__ */ React3.createElement("div", {
1691
+ className: mx2("flex shrink-0 justify-between items-center px-4 py-1 text-sm border-x", fragments.border)
1692
+ }, /* @__PURE__ */ React3.createElement("div", {
1693
+ className: "flex gap-4 items-center"
1694
+ }, /* @__PURE__ */ React3.createElement("div", {
1695
+ className: "flex w-16 items-center font-mono"
1696
+ }, range && rangeToA1Notation(range) || cursor && addressToA1Notation(cursor)), /* @__PURE__ */ React3.createElement("div", {
1697
+ className: "flex gap-2 items-center"
1698
+ }, /* @__PURE__ */ React3.createElement(FunctionIcon, {
1699
+ className: mx2("text-green-500", isFormula ? "visible" : "invisible")
1700
+ }), /* @__PURE__ */ React3.createElement("span", {
1701
+ className: "font-mono"
1702
+ }, value))));
1703
+ };
1704
+ var SheetDebug = () => {
1705
+ const { model, cursor, range } = useSheetContext();
1706
+ const [, forceUpdate] = useState4({});
1707
+ useEffect3(() => {
1708
+ const accessor = createDocAccessor(model.sheet, []);
1709
+ const handleUpdate = () => forceUpdate({});
1710
+ accessor.handle.addListener("change", handleUpdate);
1711
+ handleUpdate();
1712
+ return () => {
1713
+ accessor.handle.removeListener("change", handleUpdate);
1714
+ };
1715
+ }, [
1716
+ model
1717
+ ]);
1718
+ return /* @__PURE__ */ React3.createElement("div", {
1719
+ className: mx2("z-20 absolute right-0 top-20 bottom-20 w-[30rem] overflow-auto scrollbar-thin", "border text-xs bg-neutral-50 dark:bg-black text-cyan-500 font-mono p-1 opacity-80", fragments.border)
1720
+ }, /* @__PURE__ */ React3.createElement("pre", {
1721
+ className: "whitespace-pre-wrap"
1722
+ }, JSON.stringify({
1723
+ cursor,
1724
+ range,
1725
+ cells: model.sheet.cells,
1726
+ rowMeta: model.sheet.rowMeta,
1727
+ columnMeta: model.sheet.columnMeta,
1728
+ formatting: model.sheet.formatting
1729
+ }, void 0, 2)));
1730
+ };
1731
+ var Sheet = {
1732
+ Root: SheetRoot,
1733
+ Main: SheetMain,
1734
+ Rows: SheetRows,
1735
+ Columns: SheetColumns,
1736
+ Grid: SheetGrid,
1737
+ Cell: SheetCell,
1738
+ StatusBar: SheetStatusBar,
1739
+ Debug: SheetDebug
1740
+ };
1741
+
1742
+ // packages/plugins/plugin-sheet/src/components/SheetContainer.tsx
1743
+ var SheetContainer = ({ sheet, space, role, coordinate = {
1744
+ part: "main",
1745
+ entryId: ""
1746
+ } }) => {
1747
+ return /* @__PURE__ */ React4.createElement("div", {
1748
+ role: "none",
1749
+ className: mx3(role === "section" && "aspect-square", role === "article" && "row-span-2")
1750
+ }, /* @__PURE__ */ React4.createElement(Sheet.Root, {
1751
+ sheet,
1752
+ space
1753
+ }, /* @__PURE__ */ React4.createElement(Sheet.Main, {
1754
+ // TODO(burdon): Standardize for other components (e.g., table).
1755
+ classNames: [
1756
+ coordinate.part !== "solo" && "border-is",
1757
+ role === "section" && "border-y border-is"
1758
+ ]
1759
+ })));
1760
+ };
1761
+ var SheetContainer_default = SheetContainer;
1762
+ export {
1763
+ SheetContainer_default as default
1764
+ };
1765
+ //# sourceMappingURL=SheetContainer-6K3XOBZ7.mjs.map