@dxos/plugin-sheet 0.6.8-staging.77f93a3 → 0.6.8-staging.c55b37f

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