@dxos/plugin-sheet 0.6.11 → 0.6.12-main.5cc132e

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 (106) hide show
  1. package/dist/lib/browser/{SheetContainer-U4H5D34A.mjs → SheetContainer-Y7ZMFBAP.mjs} +568 -109
  2. package/dist/lib/browser/SheetContainer-Y7ZMFBAP.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-D5AGLXJP.mjs → chunk-GNNVBNCX.mjs} +55 -47
  4. package/dist/lib/browser/chunk-GNNVBNCX.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-APHOLYUB.mjs → chunk-PGKZPKUD.mjs} +2 -2
  6. package/dist/lib/browser/chunk-VBF7YENS.mjs +8 -0
  7. package/dist/lib/browser/{chunk-FUAGSXA4.mjs → chunk-WUPTZUTX.mjs} +6 -3
  8. package/dist/lib/browser/chunk-WUPTZUTX.mjs.map +7 -0
  9. package/dist/lib/browser/index.mjs +15 -6
  10. package/dist/lib/browser/index.mjs.map +3 -3
  11. package/dist/lib/browser/meta.json +1 -1
  12. package/dist/lib/browser/testing.mjs +3 -3
  13. package/dist/lib/browser/types.mjs +1 -1
  14. package/dist/lib/node/{SheetContainer-AXQV3ZT5.cjs → SheetContainer-KEOKUKAQ.cjs} +509 -62
  15. package/dist/lib/node/SheetContainer-KEOKUKAQ.cjs.map +7 -0
  16. package/dist/lib/node/{chunk-PYXHNAAK.cjs → chunk-57PB2HPY.cjs} +5 -5
  17. package/dist/lib/node/{chunk-CN3RPESU.cjs → chunk-6LWBQAQZ.cjs} +9 -9
  18. package/dist/lib/node/{chunk-DSYKOI4E.cjs → chunk-VJU3NPUJ.cjs} +8 -5
  19. package/dist/lib/node/chunk-VJU3NPUJ.cjs.map +7 -0
  20. package/dist/lib/node/{chunk-5KKJ4NPP.cjs → chunk-ZRQZFV5T.cjs} +70 -57
  21. package/dist/lib/node/chunk-ZRQZFV5T.cjs.map +7 -0
  22. package/dist/lib/node/index.cjs +31 -23
  23. package/dist/lib/node/index.cjs.map +3 -3
  24. package/dist/lib/node/meta.json +1 -1
  25. package/dist/lib/node/testing.cjs +6 -6
  26. package/dist/lib/node/types.cjs +9 -9
  27. package/dist/lib/node/types.cjs.map +1 -1
  28. package/dist/lib/node-esm/SheetContainer-Y7ZMFBAP.mjs +2231 -0
  29. package/dist/lib/node-esm/SheetContainer-Y7ZMFBAP.mjs.map +7 -0
  30. package/dist/lib/node-esm/chunk-GNNVBNCX.mjs +3243 -0
  31. package/dist/lib/node-esm/chunk-GNNVBNCX.mjs.map +7 -0
  32. package/dist/lib/node-esm/chunk-JRL5LGCE.mjs +18 -0
  33. package/dist/lib/node-esm/chunk-JRL5LGCE.mjs.map +7 -0
  34. package/dist/lib/node-esm/chunk-PGKZPKUD.mjs +175 -0
  35. package/dist/lib/node-esm/chunk-PGKZPKUD.mjs.map +7 -0
  36. package/dist/lib/node-esm/chunk-VBF7YENS.mjs +8 -0
  37. package/dist/lib/node-esm/chunk-VBF7YENS.mjs.map +7 -0
  38. package/dist/lib/node-esm/chunk-WUPTZUTX.mjs +85 -0
  39. package/dist/lib/node-esm/chunk-WUPTZUTX.mjs.map +7 -0
  40. package/dist/lib/node-esm/index.mjs +257 -0
  41. package/dist/lib/node-esm/index.mjs.map +7 -0
  42. package/dist/lib/node-esm/meta.json +1 -0
  43. package/dist/lib/node-esm/meta.mjs +9 -0
  44. package/dist/lib/node-esm/meta.mjs.map +7 -0
  45. package/dist/lib/node-esm/testing.mjs +92 -0
  46. package/dist/lib/node-esm/testing.mjs.map +7 -0
  47. package/dist/lib/node-esm/types.mjs +22 -0
  48. package/dist/lib/node-esm/types.mjs.map +7 -0
  49. package/dist/types/src/SheetPlugin.d.ts.map +1 -1
  50. package/dist/types/src/components/Sheet/Sheet.d.ts.map +1 -1
  51. package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +1 -1
  52. package/dist/types/src/components/Sheet/decorations.d.ts +24 -0
  53. package/dist/types/src/components/Sheet/decorations.d.ts.map +1 -0
  54. package/dist/types/src/components/Sheet/formatting.d.ts.map +1 -1
  55. package/dist/types/src/components/Sheet/sheet-context.d.ts +2 -0
  56. package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -1
  57. package/dist/types/src/components/Sheet/threads.d.ts +2 -0
  58. package/dist/types/src/components/Sheet/threads.d.ts.map +1 -0
  59. package/dist/types/src/components/SheetContainer.d.ts +2 -3
  60. package/dist/types/src/components/SheetContainer.d.ts.map +1 -1
  61. package/dist/types/src/components/Toolbar/Toolbar.d.ts +19 -3
  62. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
  63. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +17 -12
  64. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  65. package/dist/types/src/components/index.d.ts +1 -2
  66. package/dist/types/src/components/index.d.ts.map +1 -1
  67. package/dist/types/src/model/index.d.ts +1 -0
  68. package/dist/types/src/model/index.d.ts.map +1 -1
  69. package/dist/types/src/model/model.d.ts +0 -16
  70. package/dist/types/src/model/model.d.ts.map +1 -1
  71. package/dist/types/src/model/util.d.ts +24 -0
  72. package/dist/types/src/model/util.d.ts.map +1 -1
  73. package/dist/types/src/translations.d.ts +17 -12
  74. package/dist/types/src/translations.d.ts.map +1 -1
  75. package/dist/types/src/types.d.ts +72 -2
  76. package/dist/types/src/types.d.ts.map +1 -1
  77. package/package.json +36 -32
  78. package/src/SheetPlugin.tsx +8 -15
  79. package/src/components/CellEditor/extension.test.ts +1 -2
  80. package/src/components/ComputeGraph/graph.browser.test.ts +1 -2
  81. package/src/components/Sheet/Sheet.stories.tsx +5 -1
  82. package/src/components/Sheet/Sheet.tsx +45 -8
  83. package/src/components/Sheet/decorations.ts +62 -0
  84. package/src/components/Sheet/formatting.ts +3 -3
  85. package/src/components/Sheet/sheet-context.tsx +9 -1
  86. package/src/components/Sheet/threads.tsx +201 -0
  87. package/src/components/SheetContainer.tsx +72 -18
  88. package/src/components/Toolbar/Toolbar.tsx +54 -12
  89. package/src/model/index.ts +1 -0
  90. package/src/model/model.browser.test.ts +1 -2
  91. package/src/model/model.ts +9 -43
  92. package/src/model/types.test.ts +1 -2
  93. package/src/model/util.ts +67 -0
  94. package/src/translations.ts +6 -1
  95. package/src/types.ts +26 -3
  96. package/dist/lib/browser/SheetContainer-U4H5D34A.mjs.map +0 -7
  97. package/dist/lib/browser/chunk-D5AGLXJP.mjs.map +0 -7
  98. package/dist/lib/browser/chunk-FUAGSXA4.mjs.map +0 -7
  99. package/dist/lib/browser/chunk-NU4PBN33.mjs +0 -8
  100. package/dist/lib/node/SheetContainer-AXQV3ZT5.cjs.map +0 -7
  101. package/dist/lib/node/chunk-5KKJ4NPP.cjs.map +0 -7
  102. package/dist/lib/node/chunk-DSYKOI4E.cjs.map +0 -7
  103. /package/dist/lib/browser/{chunk-APHOLYUB.mjs.map → chunk-PGKZPKUD.mjs.map} +0 -0
  104. /package/dist/lib/browser/{chunk-NU4PBN33.mjs.map → chunk-VBF7YENS.mjs.map} +0 -0
  105. /package/dist/lib/node/{chunk-PYXHNAAK.cjs.map → chunk-57PB2HPY.cjs.map} +0 -0
  106. /package/dist/lib/node/{chunk-CN3RPESU.cjs.map → chunk-6LWBQAQZ.cjs.map} +0 -0
@@ -1,24 +1,33 @@
1
1
  import {
2
2
  useComputeGraph
3
- } from "./chunk-APHOLYUB.mjs";
3
+ } from "./chunk-PGKZPKUD.mjs";
4
4
  import {
5
5
  SheetModel,
6
6
  addressFromA1Notation,
7
+ addressFromIndex,
7
8
  addressToA1Notation,
9
+ addressToIndex,
10
+ closest,
8
11
  columnLetter,
9
12
  defaultFunctions,
10
13
  inRange,
11
14
  posEquals,
15
+ rangeFromIndex,
12
16
  rangeToA1Notation
13
- } from "./chunk-D5AGLXJP.mjs";
17
+ } from "./chunk-GNNVBNCX.mjs";
14
18
  import {
15
19
  ValueTypeEnum
16
- } from "./chunk-FUAGSXA4.mjs";
17
- import "./chunk-JRL5LGCE.mjs";
20
+ } from "./chunk-WUPTZUTX.mjs";
21
+ import {
22
+ SHEET_PLUGIN
23
+ } from "./chunk-JRL5LGCE.mjs";
18
24
 
19
25
  // packages/plugins/plugin-sheet/src/components/SheetContainer.tsx
20
- import React4 from "react";
21
- import { mx as mx3 } from "@dxos/react-ui-theme";
26
+ import React7, { useCallback as useCallback2 } from "react";
27
+ import { useIntentDispatcher as useIntentDispatcher2 } from "@dxos/app-framework";
28
+ import { fullyQualifiedId as fullyQualifiedId4 } from "@dxos/react-client/echo";
29
+ import { useIsDirectlyAttended } from "@dxos/react-ui-attention";
30
+ import { focusRing, mx as mx4 } from "@dxos/react-ui-theme";
22
31
 
23
32
  // packages/plugins/plugin-sheet/src/components/Sheet/Sheet.tsx
24
33
  import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, TouchSensor, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
@@ -26,14 +35,14 @@ import { restrictToHorizontalAxis, restrictToVerticalAxis } from "@dnd-kit/modif
26
35
  import { getEventCoordinates, useCombinedRefs } from "@dnd-kit/utilities";
27
36
  import { Function as FunctionIcon } from "@phosphor-icons/react";
28
37
  import { Resizable } from "re-resizable";
29
- import React3, { forwardRef, useEffect as useEffect3, useImperativeHandle, useMemo, useRef, useState as useState4 } from "react";
38
+ import React4, { forwardRef, useEffect as useEffect4, useImperativeHandle, useMemo as useMemo3, useRef, useState as useState4 } from "react";
30
39
  import { createPortal } from "react-dom";
31
40
  import { useResizeDetector } from "react-resize-detector";
32
- import { debounce } from "@dxos/async";
33
- import { fullyQualifiedId as fullyQualifiedId2, createDocAccessor } from "@dxos/client/echo";
41
+ import { debounce as debounce2 } from "@dxos/async";
42
+ import { fullyQualifiedId as fullyQualifiedId3, createDocAccessor } from "@dxos/client/echo";
34
43
  import { log } from "@dxos/log";
35
44
  import { createAttendableAttributes, useHasAttention } from "@dxos/react-ui-attention";
36
- import { mx as mx2 } from "@dxos/react-ui-theme";
45
+ import { mx as mx3 } from "@dxos/react-ui-theme";
37
46
 
38
47
  // packages/plugins/plugin-sheet/src/components/Sheet/grid.ts
39
48
  import { useEffect, useState } from "react";
@@ -327,10 +336,49 @@ var useRangeSelect = (cb) => {
327
336
  };
328
337
 
329
338
  // packages/plugins/plugin-sheet/src/components/Sheet/sheet-context.tsx
330
- import React, { createContext, useContext, useState as useState3, useEffect as useEffect2 } from "react";
339
+ import React, { createContext, useContext, useState as useState3, useEffect as useEffect2, useMemo } from "react";
331
340
  import { invariant } from "@dxos/invariant";
332
341
  import { fullyQualifiedId } from "@dxos/react-client/echo";
333
342
 
343
+ // packages/plugins/plugin-sheet/src/components/Sheet/decorations.ts
344
+ import { create } from "@dxos/echo-schema";
345
+ var createDecorations = () => {
346
+ const { decorations } = create({
347
+ decorations: {}
348
+ });
349
+ const addDecoration = (cellIndex, decorator) => {
350
+ decorations[cellIndex] = [
351
+ ...decorations[cellIndex] || [],
352
+ decorator
353
+ ];
354
+ };
355
+ const removeDecoration = (cellIndex, type) => {
356
+ if (type) {
357
+ decorations[cellIndex] = (decorations[cellIndex] || []).filter((d) => d.type !== type);
358
+ } else {
359
+ delete decorations[cellIndex];
360
+ }
361
+ };
362
+ const getDecorationsForCell = (cellIndex) => {
363
+ return decorations[cellIndex];
364
+ };
365
+ const getAllDecorations = () => {
366
+ const result = [];
367
+ for (const decoratorArray of Object.values(decorations)) {
368
+ for (const decorator of decoratorArray) {
369
+ result.push(decorator);
370
+ }
371
+ }
372
+ return result;
373
+ };
374
+ return {
375
+ addDecoration,
376
+ removeDecoration,
377
+ getDecorationsForCell,
378
+ getAllDecorations
379
+ };
380
+ };
381
+
334
382
  // packages/plugins/plugin-sheet/src/components/Sheet/formatting.ts
335
383
  var FormattingModel = class {
336
384
  constructor(model) {
@@ -345,13 +393,13 @@ var FormattingModel = class {
345
393
  return {};
346
394
  }
347
395
  const locales = void 0;
348
- const idx = this.model.addressToIndex(cell);
396
+ const idx = addressToIndex(this.model.sheet, cell);
349
397
  let formatting = this.model.sheet.formatting?.[idx] ?? {};
350
398
  const classNames = [
351
399
  ...formatting?.classNames ?? []
352
400
  ];
353
401
  for (const [idx2, _formatting] of Object.entries(this.model.sheet.formatting)) {
354
- const range = this.model.rangeFromIndex(idx2);
402
+ const range = rangeFromIndex(this.model.sheet, idx2);
355
403
  if (inRange(range, cell)) {
356
404
  if (_formatting.classNames) {
357
405
  classNames.push(..._formatting.classNames);
@@ -450,7 +498,7 @@ var useSheetContext = () => {
450
498
  const context = useContext(SheetContext);
451
499
  invariant(context, void 0, {
452
500
  F: __dxlog_file,
453
- L: 45,
501
+ L: 49,
454
502
  S: void 0,
455
503
  A: [
456
504
  "context",
@@ -491,6 +539,7 @@ var SheetContextProvider = ({ children, sheet, space, readonly, onInfo, ...optio
491
539
  const [cursor, setCursor] = useState3();
492
540
  const [range, setRange] = useState3();
493
541
  const [editing, setEditing] = useState3(false);
542
+ const decorations = useMemo(() => createDecorations(), []);
494
543
  const [[model, formatting] = [], setModels] = useState3(void 0);
495
544
  useEffect2(() => {
496
545
  let model2;
@@ -530,11 +579,178 @@ var SheetContextProvider = ({ children, sheet, space, readonly, onInfo, ...optio
530
579
  editing,
531
580
  setEditing,
532
581
  // TODO(burdon): Change to event.
533
- onInfo
582
+ onInfo,
583
+ decorations
534
584
  }
535
585
  }, children);
536
586
  };
537
587
 
588
+ // packages/plugins/plugin-sheet/src/components/Sheet/threads.tsx
589
+ import { effect } from "@preact/signals-core";
590
+ import React2, { useCallback, useEffect as useEffect3, useMemo as useMemo2 } from "react";
591
+ import { LayoutAction, useIntentDispatcher, useIntentResolver } from "@dxos/app-framework";
592
+ import { debounce } from "@dxos/async";
593
+ import { fullyQualifiedId as fullyQualifiedId2 } from "@dxos/react-client/echo";
594
+ import { Icon, useTranslation } from "@dxos/react-ui";
595
+ import { mx } from "@dxos/react-ui-theme";
596
+ var CommentIndicator = () => {
597
+ return /* @__PURE__ */ React2.createElement("div", {
598
+ role: "none",
599
+ className: "absolute top-0 right-0 w-0 h-0 border-t-8 border-l-8 border-t-cmCommentSurface border-l-transparent"
600
+ });
601
+ };
602
+ var ThreadedCellWrapper = ({ children }) => {
603
+ const dispatch = useIntentDispatcher();
604
+ const [isHovered, setIsHovered] = React2.useState(true);
605
+ const { t } = useTranslation(SHEET_PLUGIN);
606
+ const handleClick = React2.useCallback((_event) => {
607
+ void dispatch({
608
+ action: LayoutAction.SET_LAYOUT,
609
+ data: {
610
+ element: "complementary",
611
+ state: true
612
+ }
613
+ });
614
+ }, [
615
+ dispatch
616
+ ]);
617
+ return /* @__PURE__ */ React2.createElement("div", {
618
+ role: "none",
619
+ className: mx("relative h-full is-full"),
620
+ onMouseEnter: () => {
621
+ setIsHovered(true);
622
+ },
623
+ onMouseLeave: () => {
624
+ setIsHovered(false);
625
+ }
626
+ }, /* @__PURE__ */ React2.createElement(CommentIndicator, null), isHovered && /* @__PURE__ */ React2.createElement("div", {
627
+ className: "absolute inset-0 flex items-center justify-end pr-1"
628
+ }, /* @__PURE__ */ React2.createElement("button", {
629
+ className: "ch-button text-xs min-bs-0 p-1",
630
+ onClick: handleClick,
631
+ "aria-label": t("open comment for sheet cell")
632
+ }, /* @__PURE__ */ React2.createElement(Icon, {
633
+ icon: "ph--chat--regular",
634
+ "aria-hidden": true
635
+ }))), children);
636
+ };
637
+ var createThreadDecoration = (cellIndex, threadId, sheetId) => {
638
+ return {
639
+ type: "comment",
640
+ cellIndex,
641
+ decorate: (props) => /* @__PURE__ */ React2.createElement(ThreadedCellWrapper, props)
642
+ };
643
+ };
644
+ var useUpdateCursorOnThreadSelection = () => {
645
+ const { setCursor, model } = useSheetContext();
646
+ const handleScrollIntoView = useCallback(({ action, data }) => {
647
+ switch (action) {
648
+ case LayoutAction.SCROLL_INTO_VIEW: {
649
+ if (!data?.id || data?.cursor === void 0 || data?.id !== fullyQualifiedId2(model.sheet)) {
650
+ return;
651
+ }
652
+ const cellAddress = addressFromIndex(model.sheet, data.cursor);
653
+ setCursor(cellAddress);
654
+ }
655
+ }
656
+ }, [
657
+ model.sheet,
658
+ setCursor
659
+ ]);
660
+ useIntentResolver(SHEET_PLUGIN, handleScrollIntoView);
661
+ };
662
+ var useSelectThreadOnCursorChange = () => {
663
+ const { cursor, model } = useSheetContext();
664
+ const dispatch = useIntentDispatcher();
665
+ const activeThreads = useMemo2(() => model.sheet.threads?.filter((thread) => !!thread && thread.status === "active") ?? [], [
666
+ JSON.stringify(model.sheet.threads)
667
+ ]);
668
+ const activeThreadAddresses = useMemo2(() => activeThreads.map((thread) => thread.anchor).filter((anchor) => anchor !== void 0).map((anchor) => addressFromIndex(model.sheet, anchor)), [
669
+ activeThreads,
670
+ model.sheet
671
+ ]);
672
+ const selectClosestThread = useCallback((cellAddress) => {
673
+ if (!cellAddress || !activeThreads) {
674
+ return;
675
+ }
676
+ const closestThreadAnchor = closest(cellAddress, activeThreadAddresses);
677
+ if (closestThreadAnchor) {
678
+ const closestThread = activeThreads.find((thread) => thread && thread.anchor === addressToIndex(model.sheet, closestThreadAnchor));
679
+ if (closestThread) {
680
+ void dispatch([
681
+ {
682
+ action: "dxos.org/plugin/thread/action/select",
683
+ data: {
684
+ current: fullyQualifiedId2(closestThread)
685
+ }
686
+ }
687
+ ]);
688
+ }
689
+ }
690
+ }, [
691
+ dispatch,
692
+ activeThreads,
693
+ activeThreadAddresses,
694
+ model.sheet
695
+ ]);
696
+ const debounced = useMemo2(() => {
697
+ return debounce((cursor2) => requestAnimationFrame(() => selectClosestThread(cursor2)), 50);
698
+ }, [
699
+ selectClosestThread
700
+ ]);
701
+ useEffect3(() => {
702
+ if (!cursor) {
703
+ return;
704
+ }
705
+ debounced(cursor);
706
+ }, [
707
+ cursor,
708
+ selectClosestThread
709
+ ]);
710
+ };
711
+ var useThreadDecorations = () => {
712
+ const { decorations, model } = useSheetContext();
713
+ const sheet = useMemo2(() => model.sheet, [
714
+ model.sheet
715
+ ]);
716
+ const sheetId = useMemo2(() => fullyQualifiedId2(sheet), [
717
+ sheet
718
+ ]);
719
+ useEffect3(() => {
720
+ const unsubscribe = effect(() => {
721
+ const activeThreadAnchors = /* @__PURE__ */ new Set();
722
+ if (!sheet.threads) {
723
+ return;
724
+ }
725
+ for (const thread of sheet.threads) {
726
+ if (!thread || thread.anchor === void 0 || thread.status === "resolved") {
727
+ continue;
728
+ }
729
+ activeThreadAnchors.add(thread.anchor);
730
+ const index = thread.anchor;
731
+ const existingDecorations = decorations.getDecorationsForCell(index);
732
+ if (!existingDecorations || !existingDecorations.some((d) => d.type === "comment")) {
733
+ decorations.addDecoration(index, createThreadDecoration(index, thread.id, sheetId));
734
+ }
735
+ }
736
+ for (const decoration of decorations.getAllDecorations()) {
737
+ if (decoration.type !== "comment") {
738
+ continue;
739
+ }
740
+ if (!activeThreadAnchors.has(decoration.cellIndex)) {
741
+ decorations.removeDecoration(decoration.cellIndex, "comment");
742
+ }
743
+ }
744
+ });
745
+ return () => unsubscribe();
746
+ });
747
+ };
748
+ var useThreads = () => {
749
+ useUpdateCursorOnThreadSelection();
750
+ useSelectThreadOnCursorChange();
751
+ useThreadDecorations();
752
+ };
753
+
538
754
  // packages/plugins/plugin-sheet/src/components/Sheet/util.ts
539
755
  var getRelativeClientRect = (root, element) => {
540
756
  const rootRect = root.getBoundingClientRect();
@@ -570,7 +786,7 @@ var scrollIntoView = (scrollContainer, el) => {
570
786
 
571
787
  // packages/plugins/plugin-sheet/src/components/CellEditor/CellEditor.tsx
572
788
  import { EditorView, keymap } from "@codemirror/view";
573
- import React2 from "react";
789
+ import React3 from "react";
574
790
  import { useThemeContext } from "@dxos/react-ui";
575
791
  import { createBasicExtensions, createThemeExtensions, preventNewline, useTextEditor } from "@dxos/react-ui-editor";
576
792
  var editorKeys = ({ onNav, onClose }) => {
@@ -670,7 +886,7 @@ var CellEditor = ({ value, extension, autoFocus, onBlur }) => {
670
886
  }, [
671
887
  extension
672
888
  ]);
673
- return /* @__PURE__ */ React2.createElement("div", {
889
+ return /* @__PURE__ */ React3.createElement("div", {
674
890
  ref: parentRef,
675
891
  className: "flex w-full"
676
892
  });
@@ -683,7 +899,7 @@ import { Facet } from "@codemirror/state";
683
899
  import { ViewPlugin, keymap as keymap2 } from "@codemirror/view";
684
900
  import { tags } from "@lezer/highlight";
685
901
  import { spreadsheet } from "codemirror-lang-spreadsheet";
686
- import { mx } from "@dxos/react-ui-theme";
902
+ import { mx as mx2 } from "@dxos/react-ui-theme";
687
903
  var highlightStyles = HighlightStyle.define([
688
904
  // Function.
689
905
  {
@@ -794,7 +1010,7 @@ var sheetExtension = ({ functions = [] }) => {
794
1010
  // NOTE: Useful for debugging.
795
1011
  closeOnBlur: false,
796
1012
  icons: false,
797
- tooltipClass: () => mx(
1013
+ tooltipClass: () => mx2(
798
1014
  // TODO(burdon): Factor out fragments.
799
1015
  // TODO(burdon): Size to make width same as column.
800
1016
  "!-left-[1px] !top-[33px] !-m-0 border !border-t-0 [&>ul]:!min-w-[198px]",
@@ -897,25 +1113,26 @@ var fragments = {
897
1113
  cellSelected: "bg-gridCellSelected text-baseText border !border-accentSurface"
898
1114
  };
899
1115
  var SheetRoot = ({ children, ...props }) => {
900
- return /* @__PURE__ */ React3.createElement(SheetContextProvider, props, children);
1116
+ return /* @__PURE__ */ React4.createElement(SheetContextProvider, props, children);
901
1117
  };
902
1118
  var SheetMain = /* @__PURE__ */ forwardRef(({ classNames, numRows, numColumns }, forwardRef2) => {
903
1119
  const { model, cursor, setCursor, setRange, setEditing } = useSheetContext();
904
1120
  const { rowsRef, columnsRef, contentRef } = useScrollHandlers();
1121
+ useThreads();
905
1122
  const [rows, setRows] = useState4([
906
1123
  ...model.sheet.rows
907
1124
  ]);
908
1125
  const [columns, setColumns] = useState4([
909
1126
  ...model.sheet.columns
910
1127
  ]);
911
- useEffect3(() => {
1128
+ useEffect4(() => {
912
1129
  const rowsAccessor = createDocAccessor(model.sheet, [
913
1130
  "rows"
914
1131
  ]);
915
1132
  const columnsAccessor = createDocAccessor(model.sheet, [
916
1133
  "columns"
917
1134
  ]);
918
- const handleUpdate = debounce(() => {
1135
+ const handleUpdate = debounce2(() => {
919
1136
  setRows([
920
1137
  ...model.sheet.rows
921
1138
  ]);
@@ -933,29 +1150,29 @@ var SheetMain = /* @__PURE__ */ forwardRef(({ classNames, numRows, numColumns },
933
1150
  }, [
934
1151
  model
935
1152
  ]);
936
- useEffect3(() => {
1153
+ useEffect4(() => {
937
1154
  model.reset();
938
1155
  }, [
939
1156
  rows,
940
1157
  columns
941
1158
  ]);
942
1159
  const handleMoveRows = (from, to, num = 1) => {
943
- const cursorIdx = cursor ? model.addressToIndex(cursor) : void 0;
1160
+ const cursorIdx = cursor ? addressToIndex(model.sheet, cursor) : void 0;
944
1161
  const [rows2] = model.sheet.rows.splice(from, num);
945
1162
  model.sheet.rows.splice(to, 0, rows2);
946
1163
  if (cursorIdx) {
947
- setCursor(model.addressFromIndex(cursorIdx));
1164
+ setCursor(addressFromIndex(model.sheet, cursorIdx));
948
1165
  }
949
1166
  setRows([
950
1167
  ...model.sheet.rows
951
1168
  ]);
952
1169
  };
953
1170
  const handleMoveColumns = (from, to, num = 1) => {
954
- const cursorIdx = cursor ? model.addressToIndex(cursor) : void 0;
1171
+ const cursorIdx = cursor ? addressToIndex(model.sheet, cursor) : void 0;
955
1172
  const columns2 = model.sheet.columns.splice(from, num);
956
1173
  model.sheet.columns.splice(to, 0, ...columns2);
957
1174
  if (cursorIdx) {
958
- setCursor(model.addressFromIndex(cursorIdx));
1175
+ setCursor(addressFromIndex(model.sheet, cursorIdx));
959
1176
  }
960
1177
  setColumns([
961
1178
  ...model.sheet.columns
@@ -963,14 +1180,14 @@ var SheetMain = /* @__PURE__ */ forwardRef(({ classNames, numRows, numColumns },
963
1180
  };
964
1181
  const [rowSizes, setRowSizes] = useState4();
965
1182
  const [columnSizes, setColumnSizes] = useState4();
966
- useEffect3(() => {
1183
+ useEffect4(() => {
967
1184
  const rowAccessor = createDocAccessor(model.sheet, [
968
1185
  "rowMeta"
969
1186
  ]);
970
1187
  const columnAccessor = createDocAccessor(model.sheet, [
971
1188
  "columnMeta"
972
1189
  ]);
973
- const handleUpdate = debounce(() => {
1190
+ const handleUpdate = debounce2(() => {
974
1191
  const mapSizes = (values) => values.reduce((map, [idx, meta]) => {
975
1192
  if (meta.size) {
976
1193
  map[idx] = meta.size;
@@ -1012,16 +1229,16 @@ var SheetMain = /* @__PURE__ */ forwardRef(({ classNames, numRows, numColumns },
1012
1229
  }));
1013
1230
  }
1014
1231
  };
1015
- return /* @__PURE__ */ React3.createElement("div", {
1232
+ return /* @__PURE__ */ React4.createElement("div", {
1016
1233
  role: "none",
1017
- className: mx2("grid grid-cols-[calc(var(--rail-size)-2px)_1fr] grid-rows-[32px_1fr_32px] bs-full is-full overflow-hidden", classNames)
1018
- }, /* @__PURE__ */ React3.createElement(GridCorner, {
1234
+ className: mx3("grid grid-cols-[calc(var(--rail-size)-2px)_1fr] grid-rows-[32px_1fr_32px] bs-full is-full overflow-hidden", classNames)
1235
+ }, /* @__PURE__ */ React4.createElement(GridCorner, {
1019
1236
  onClick: () => {
1020
1237
  setCursor(void 0);
1021
1238
  setRange(void 0);
1022
1239
  setEditing(false);
1023
1240
  }
1024
- }), /* @__PURE__ */ React3.createElement(SheetColumns, {
1241
+ }), /* @__PURE__ */ React4.createElement(SheetColumns, {
1025
1242
  ref: columnsRef,
1026
1243
  columns,
1027
1244
  sizes: columnSizes,
@@ -1032,7 +1249,7 @@ var SheetMain = /* @__PURE__ */ forwardRef(({ classNames, numRows, numColumns },
1032
1249
  }),
1033
1250
  onResize: handleResizeColumn,
1034
1251
  onMove: handleMoveColumns
1035
- }), /* @__PURE__ */ React3.createElement(SheetRows, {
1252
+ }), /* @__PURE__ */ React4.createElement(SheetRows, {
1036
1253
  ref: rowsRef,
1037
1254
  rows,
1038
1255
  sizes: rowSizes,
@@ -1043,7 +1260,7 @@ var SheetMain = /* @__PURE__ */ forwardRef(({ classNames, numRows, numColumns },
1043
1260
  }),
1044
1261
  onResize: handleResizeRow,
1045
1262
  onMove: handleMoveRows
1046
- }), /* @__PURE__ */ React3.createElement(SheetGrid, {
1263
+ }), /* @__PURE__ */ React4.createElement(SheetGrid, {
1047
1264
  ref: contentRef,
1048
1265
  size: {
1049
1266
  numRows: numRows ?? rows.length,
@@ -1053,13 +1270,13 @@ var SheetMain = /* @__PURE__ */ forwardRef(({ classNames, numRows, numColumns },
1053
1270
  columns,
1054
1271
  rowSizes,
1055
1272
  columnSizes
1056
- }), /* @__PURE__ */ React3.createElement(GridCorner, null), /* @__PURE__ */ React3.createElement(SheetStatusBar, null));
1273
+ }), /* @__PURE__ */ React4.createElement(GridCorner, null), /* @__PURE__ */ React4.createElement(SheetStatusBar, null));
1057
1274
  });
1058
1275
  var useScrollHandlers = () => {
1059
1276
  const rowsRef = useRef(null);
1060
1277
  const columnsRef = useRef(null);
1061
1278
  const contentRef = useRef(null);
1062
- useEffect3(() => {
1279
+ useEffect4(() => {
1063
1280
  const handleRowsScroll = (ev) => {
1064
1281
  const { scrollTop } = ev.target;
1065
1282
  if (!rowsRef.current.dataset.locked) {
@@ -1096,13 +1313,13 @@ var useScrollHandlers = () => {
1096
1313
  };
1097
1314
  };
1098
1315
  var GridCorner = (props) => {
1099
- return /* @__PURE__ */ React3.createElement("div", {
1316
+ return /* @__PURE__ */ React4.createElement("div", {
1100
1317
  className: fragments.axis,
1101
1318
  ...props
1102
1319
  });
1103
1320
  };
1104
1321
  var MovingOverlay = ({ label }) => {
1105
- return /* @__PURE__ */ React3.createElement("div", {
1322
+ return /* @__PURE__ */ React4.createElement("div", {
1106
1323
  className: "flex w-full h-full justify-center items-center text-sm p-1 bg-gridOverlay cursor-pointer"
1107
1324
  }, label);
1108
1325
  };
@@ -1146,18 +1363,18 @@ var SheetRows = /* @__PURE__ */ forwardRef(({ rows, sizes, selected, onSelect, o
1146
1363
  }
1147
1364
  return transform;
1148
1365
  };
1149
- return /* @__PURE__ */ React3.createElement("div", {
1366
+ return /* @__PURE__ */ React4.createElement("div", {
1150
1367
  className: "relative flex grow overflow-hidden"
1151
- }, /* @__PURE__ */ React3.createElement("div", {
1152
- className: mx2("z-20 absolute inset-0 border-y border-gridLine pointer-events-none"),
1368
+ }, /* @__PURE__ */ React4.createElement("div", {
1369
+ className: mx3("z-20 absolute inset-0 border-y border-gridLine pointer-events-none"),
1153
1370
  style: {
1154
1371
  width: axisWidth
1155
1372
  }
1156
- }), /* @__PURE__ */ React3.createElement("div", {
1373
+ }), /* @__PURE__ */ React4.createElement("div", {
1157
1374
  ref: forwardRef2,
1158
1375
  role: "rowheader",
1159
1376
  className: "grow overflow-y-auto scrollbar-none"
1160
- }, /* @__PURE__ */ React3.createElement(DndContext, {
1377
+ }, /* @__PURE__ */ React4.createElement(DndContext, {
1161
1378
  sensors,
1162
1379
  modifiers: [
1163
1380
  restrictToVerticalAxis,
@@ -1165,12 +1382,12 @@ var SheetRows = /* @__PURE__ */ forwardRef(({ rows, sizes, selected, onSelect, o
1165
1382
  ],
1166
1383
  onDragStart: handleDragStart,
1167
1384
  onDragEnd: handleDragEnd
1168
- }, /* @__PURE__ */ React3.createElement("div", {
1385
+ }, /* @__PURE__ */ React4.createElement("div", {
1169
1386
  className: "flex flex-col",
1170
1387
  style: {
1171
1388
  width: axisWidth
1172
1389
  }
1173
- }, rows.map((idx, index) => /* @__PURE__ */ React3.createElement(GridRowCell, {
1390
+ }, rows.map((idx, index) => /* @__PURE__ */ React4.createElement(GridRowCell, {
1174
1391
  key: idx,
1175
1392
  idx,
1176
1393
  index,
@@ -1180,7 +1397,7 @@ var SheetRows = /* @__PURE__ */ forwardRef(({ rows, sizes, selected, onSelect, o
1180
1397
  selected: selected === index,
1181
1398
  onResize,
1182
1399
  onSelect
1183
- }))), /* @__PURE__ */ createPortal(/* @__PURE__ */ React3.createElement(DragOverlay, null, active && /* @__PURE__ */ React3.createElement(MovingOverlay, {
1400
+ }))), /* @__PURE__ */ createPortal(/* @__PURE__ */ React4.createElement(DragOverlay, null, active && /* @__PURE__ */ React4.createElement(MovingOverlay, {
1184
1401
  label: String(active.data.current.index + 1)
1185
1402
  })), document.body))));
1186
1403
  });
@@ -1221,7 +1438,7 @@ var GridRowCell = ({ idx, index, label, size, resize, selected, onSelect, onResi
1221
1438
  onResize?.(idx, initialSize + height, true);
1222
1439
  setResizing(false);
1223
1440
  };
1224
- return /* @__PURE__ */ React3.createElement(Resizable, {
1441
+ return /* @__PURE__ */ React4.createElement(Resizable, {
1225
1442
  enable: {
1226
1443
  bottom: resize
1227
1444
  },
@@ -1233,17 +1450,17 @@ var GridRowCell = ({ idx, index, label, size, resize, selected, onSelect, onResi
1233
1450
  onResizeStart: handleResizeStart,
1234
1451
  onResize: handleResize,
1235
1452
  onResizeStop: handleResizeStop
1236
- }, /* @__PURE__ */ React3.createElement("div", {
1453
+ }, /* @__PURE__ */ React4.createElement("div", {
1237
1454
  ref: setNodeRef,
1238
1455
  ...attributes,
1239
1456
  ...listeners,
1240
- className: mx2("flex h-full items-center justify-center cursor-pointer", "border-t border-gridLine focus-visible:outline-none", fragments.axis, selected && fragments.axisSelected, isDragging && fragments.axisSelected),
1457
+ className: mx3("flex h-full items-center justify-center cursor-pointer", "border-t border-gridLine focus-visible:outline-none", fragments.axis, selected && fragments.axisSelected, isDragging && fragments.axisSelected),
1241
1458
  onClick: () => onSelect?.(index)
1242
- }, /* @__PURE__ */ React3.createElement("span", {
1459
+ }, /* @__PURE__ */ React4.createElement("span", {
1243
1460
  className: "flex w-full justify-center"
1244
- }, label), over?.id === idx && !isDragging && /* @__PURE__ */ React3.createElement("div", {
1461
+ }, label), over?.id === idx && !isDragging && /* @__PURE__ */ React4.createElement("div", {
1245
1462
  className: "z-20 absolute top-0 w-full min-h-[4px] border-b-4 border-accentSurface"
1246
- }), resizing && /* @__PURE__ */ React3.createElement("div", {
1463
+ }), resizing && /* @__PURE__ */ React4.createElement("div", {
1247
1464
  className: "z-20 absolute bottom-0 w-full min-h-[4px] border-b-4 border-accentSurface"
1248
1465
  })));
1249
1466
  };
@@ -1280,18 +1497,18 @@ var SheetColumns = /* @__PURE__ */ forwardRef(({ columns, sizes, selected, onSel
1280
1497
  }
1281
1498
  return transform;
1282
1499
  };
1283
- return /* @__PURE__ */ React3.createElement("div", {
1500
+ return /* @__PURE__ */ React4.createElement("div", {
1284
1501
  className: "relative flex grow overflow-hidden"
1285
- }, /* @__PURE__ */ React3.createElement("div", {
1286
- className: mx2("z-20 absolute inset-0 border-x border-gridLine pointer-events-none"),
1502
+ }, /* @__PURE__ */ React4.createElement("div", {
1503
+ className: mx3("z-20 absolute inset-0 border-x border-gridLine pointer-events-none"),
1287
1504
  style: {
1288
1505
  height: axisHeight
1289
1506
  }
1290
- }), /* @__PURE__ */ React3.createElement("div", {
1507
+ }), /* @__PURE__ */ React4.createElement("div", {
1291
1508
  ref: forwardRef2,
1292
1509
  role: "columnheader",
1293
1510
  className: "grow overflow-x-auto scrollbar-none"
1294
- }, /* @__PURE__ */ React3.createElement(DndContext, {
1511
+ }, /* @__PURE__ */ React4.createElement(DndContext, {
1295
1512
  autoScroll: {
1296
1513
  enabled: true
1297
1514
  },
@@ -1302,12 +1519,12 @@ var SheetColumns = /* @__PURE__ */ forwardRef(({ columns, sizes, selected, onSel
1302
1519
  ],
1303
1520
  onDragStart: handleDragStart,
1304
1521
  onDragEnd: handleDragEnd
1305
- }, /* @__PURE__ */ React3.createElement("div", {
1522
+ }, /* @__PURE__ */ React4.createElement("div", {
1306
1523
  className: "flex h-full",
1307
1524
  style: {
1308
1525
  height: axisHeight
1309
1526
  }
1310
- }, columns.map((idx, index) => /* @__PURE__ */ React3.createElement(GridColumnCell, {
1527
+ }, columns.map((idx, index) => /* @__PURE__ */ React4.createElement(GridColumnCell, {
1311
1528
  key: idx,
1312
1529
  idx,
1313
1530
  index,
@@ -1317,7 +1534,7 @@ var SheetColumns = /* @__PURE__ */ forwardRef(({ columns, sizes, selected, onSel
1317
1534
  selected: selected === index,
1318
1535
  onResize,
1319
1536
  onSelect
1320
- }))), /* @__PURE__ */ createPortal(/* @__PURE__ */ React3.createElement(DragOverlay, null, active && /* @__PURE__ */ React3.createElement(MovingOverlay, {
1537
+ }))), /* @__PURE__ */ createPortal(/* @__PURE__ */ React4.createElement(DragOverlay, null, active && /* @__PURE__ */ React4.createElement(MovingOverlay, {
1321
1538
  label: columnLetter(active.data.current.index)
1322
1539
  })), document.body))));
1323
1540
  });
@@ -1358,7 +1575,7 @@ var GridColumnCell = ({ idx, index, label, size, resize, selected, onSelect, onR
1358
1575
  onResize?.(idx, initialSize + width, true);
1359
1576
  setResizing(false);
1360
1577
  };
1361
- return /* @__PURE__ */ React3.createElement(Resizable, {
1578
+ return /* @__PURE__ */ React4.createElement(Resizable, {
1362
1579
  enable: {
1363
1580
  right: resize
1364
1581
  },
@@ -1370,17 +1587,17 @@ var GridColumnCell = ({ idx, index, label, size, resize, selected, onSelect, onR
1370
1587
  onResizeStart: handleResizeStart,
1371
1588
  onResize: handleResize,
1372
1589
  onResizeStop: handleResizeStop
1373
- }, /* @__PURE__ */ React3.createElement("div", {
1590
+ }, /* @__PURE__ */ React4.createElement("div", {
1374
1591
  ref: setNodeRef,
1375
1592
  ...attributes,
1376
1593
  ...listeners,
1377
- className: mx2("flex h-full items-center justify-center cursor-pointer", "border-l border-gridLine focus-visible:outline-none", fragments.axis, selected && fragments.axisSelected, isDragging && fragments.axisSelected),
1594
+ className: mx3("flex h-full items-center justify-center cursor-pointer", "border-l border-gridLine focus-visible:outline-none", fragments.axis, selected && fragments.axisSelected, isDragging && fragments.axisSelected),
1378
1595
  onClick: () => onSelect?.(index)
1379
- }, /* @__PURE__ */ React3.createElement("span", {
1596
+ }, /* @__PURE__ */ React4.createElement("span", {
1380
1597
  className: "flex w-full justify-center"
1381
- }, label), over?.id === idx && !isDragging && /* @__PURE__ */ React3.createElement("div", {
1598
+ }, label), over?.id === idx && !isDragging && /* @__PURE__ */ React4.createElement("div", {
1382
1599
  className: "z-20 absolute left-0 h-full min-w-[4px] border-l-4 border-accentSurface"
1383
- }), resizing && /* @__PURE__ */ React3.createElement("div", {
1600
+ }), resizing && /* @__PURE__ */ React4.createElement("div", {
1384
1601
  className: "z-20 absolute right-0 h-full min-h-[4px] border-l-4 border-accentSurface"
1385
1602
  })));
1386
1603
  };
@@ -1394,13 +1611,13 @@ var SheetGrid = /* @__PURE__ */ forwardRef(({ size, rows, columns, rowSizes, col
1394
1611
  const initialText = useRef();
1395
1612
  const quickEdit = useRef(false);
1396
1613
  const [, forceUpdate] = useState4({});
1397
- useEffect3(() => {
1614
+ useEffect4(() => {
1398
1615
  const unsubscribe = model.update.on(() => {
1399
1616
  log("updated", {
1400
1617
  id: model.id
1401
1618
  }, {
1402
1619
  F: __dxlog_file2,
1403
- L: 730,
1620
+ L: 737,
1404
1621
  S: void 0,
1405
1622
  C: (f, a) => f(...a)
1406
1623
  });
@@ -1517,19 +1734,19 @@ var SheetGrid = /* @__PURE__ */ forwardRef(({ size, rows, columns, rowSizes, col
1517
1734
  rowSizes,
1518
1735
  columnSizes
1519
1736
  });
1520
- const id = fullyQualifiedId2(model.sheet);
1737
+ const id = fullyQualifiedId3(model.sheet);
1521
1738
  const attendableAttrs = createAttendableAttributes(id);
1522
1739
  const hasAttention = useHasAttention(id);
1523
- return /* @__PURE__ */ React3.createElement("div", {
1740
+ return /* @__PURE__ */ React4.createElement("div", {
1524
1741
  ref: containerRef,
1525
1742
  role: "grid",
1526
1743
  className: "relative flex grow overflow-hidden"
1527
- }, /* @__PURE__ */ React3.createElement("div", {
1528
- className: mx2("z-20 absolute inset-0 border border-gridLine pointer-events-none")
1529
- }), /* @__PURE__ */ React3.createElement("div", {
1744
+ }, /* @__PURE__ */ React4.createElement("div", {
1745
+ className: mx3("z-20 absolute inset-0 border border-gridLine pointer-events-none")
1746
+ }), /* @__PURE__ */ React4.createElement("div", {
1530
1747
  ref: scrollerRef,
1531
- className: mx2("grow", hasAttention && "overflow-auto scrollbar-thin")
1532
- }, /* @__PURE__ */ React3.createElement("div", {
1748
+ className: mx3("grow", hasAttention && "overflow-auto scrollbar-thin")
1749
+ }, /* @__PURE__ */ React4.createElement("div", {
1533
1750
  className: "relative select-none",
1534
1751
  style: {
1535
1752
  width,
@@ -1537,7 +1754,7 @@ var SheetGrid = /* @__PURE__ */ forwardRef(({ size, rows, columns, rowSizes, col
1537
1754
  },
1538
1755
  onClick: () => inputRef.current?.focus(),
1539
1756
  ...handlers
1540
- }, scrollerRef.current && /* @__PURE__ */ React3.createElement(SelectionOverlay, {
1757
+ }, scrollerRef.current && /* @__PURE__ */ React4.createElement(SelectionOverlay, {
1541
1758
  root: scrollerRef.current
1542
1759
  }), rowRange.map(({ row, top, height: height2 }) => {
1543
1760
  return columnRange.map(({ column, left, width: width2 }) => {
@@ -1553,7 +1770,7 @@ var SheetGrid = /* @__PURE__ */ forwardRef(({ size, rows, columns, rowSizes, col
1553
1770
  column
1554
1771
  };
1555
1772
  const id2 = addressToA1Notation(cell);
1556
- const idx = model.addressToIndex(cell);
1773
+ const idx = addressToIndex(model.sheet, cell);
1557
1774
  const active = posEquals(cursor, cell);
1558
1775
  if (active && editing) {
1559
1776
  const value = initialText.current ?? model.getCellText(cell) ?? "";
@@ -1586,7 +1803,7 @@ var SheetGrid = /* @__PURE__ */ forwardRef(({ size, rows, columns, rowSizes, col
1586
1803
  inputRef.current?.focus();
1587
1804
  setEditing(false);
1588
1805
  };
1589
- return /* @__PURE__ */ React3.createElement(GridCellEditor, {
1806
+ return /* @__PURE__ */ React4.createElement(GridCellEditor, {
1590
1807
  key: idx,
1591
1808
  value,
1592
1809
  style,
@@ -1594,7 +1811,7 @@ var SheetGrid = /* @__PURE__ */ forwardRef(({ size, rows, columns, rowSizes, col
1594
1811
  onClose: handleClose
1595
1812
  });
1596
1813
  }
1597
- return /* @__PURE__ */ React3.createElement(SheetCell, {
1814
+ return /* @__PURE__ */ React4.createElement(SheetCell, {
1598
1815
  key: id2,
1599
1816
  id: id2,
1600
1817
  cell,
@@ -1606,7 +1823,7 @@ var SheetGrid = /* @__PURE__ */ forwardRef(({ size, rows, columns, rowSizes, col
1606
1823
  }
1607
1824
  });
1608
1825
  });
1609
- }))), /* @__PURE__ */ createPortal(/* @__PURE__ */ React3.createElement("input", {
1826
+ }))), /* @__PURE__ */ createPortal(/* @__PURE__ */ React4.createElement("input", {
1610
1827
  ref: inputRef,
1611
1828
  autoFocus: true,
1612
1829
  className: "absolute w-[1px] h-[1px] bg-transparent outline-none border-none caret-transparent",
@@ -1627,20 +1844,34 @@ var SelectionOverlay = ({ root }) => {
1627
1844
  const b1 = getRelativeClientRect(root, c1);
1628
1845
  const b2 = getRelativeClientRect(root, c2);
1629
1846
  const bounds = getRectUnion(b1, b2);
1630
- return /* @__PURE__ */ React3.createElement("div", {
1847
+ return /* @__PURE__ */ React4.createElement("div", {
1631
1848
  role: "none",
1632
1849
  style: bounds,
1633
1850
  className: "z-10 absolute pointer-events-none bg-gridSelectionOverlay border border-gridOverlay"
1634
1851
  });
1635
1852
  };
1636
1853
  var SheetCell = ({ id, cell, style, active, onSelect }) => {
1637
- const { formatting, editing, setRange } = useSheetContext();
1854
+ const { formatting, editing, setRange, decorations, model: { sheet } } = useSheetContext();
1638
1855
  const { value, classNames } = formatting.getFormatting(cell);
1639
- return /* @__PURE__ */ React3.createElement("div", {
1856
+ const decorationsForCell = decorations.getDecorationsForCell(addressToIndex(sheet, cell)) ?? [];
1857
+ const decorationAddedClasses = useMemo3(() => decorationsForCell.flatMap((d) => d.classNames ?? []), [
1858
+ decorationsForCell
1859
+ ]);
1860
+ const decoratedContent = decorationsForCell.reduce((children, { decorate }) => {
1861
+ if (!decorate) {
1862
+ return children;
1863
+ }
1864
+ const DecoratorComponent = decorate;
1865
+ return /* @__PURE__ */ React4.createElement(DecoratorComponent, null, children);
1866
+ }, /* @__PURE__ */ React4.createElement("div", {
1867
+ role: "none",
1868
+ className: mx3("flex flex-grow bs-full is-full px-2 items-center truncate cursor-pointer", ...decorationAddedClasses)
1869
+ }, value));
1870
+ return /* @__PURE__ */ React4.createElement("div", {
1640
1871
  [`data-${CELL_DATA_KEY}`]: id,
1641
1872
  role: "cell",
1642
1873
  style,
1643
- className: mx2("flex w-full h-full px-2 py-1 truncate items-center border border-gridLine cursor-pointer", fragments.cell, active && [
1874
+ className: mx3("border border-gridLine cursor-pointer", fragments.cell, active && [
1644
1875
  "z-20",
1645
1876
  fragments.cellSelected
1646
1877
  ], classNames),
@@ -1654,19 +1885,19 @@ var SheetCell = ({ id, cell, style, active, onSelect }) => {
1654
1885
  }
1655
1886
  },
1656
1887
  onDoubleClick: () => onSelect?.(cell, true)
1657
- }, value);
1888
+ }, decoratedContent);
1658
1889
  };
1659
1890
  var GridCellEditor = ({ style, value, onNav, onClose }) => {
1660
1891
  const { model, range } = useSheetContext();
1661
1892
  const notifier = useRef();
1662
- useEffect3(() => {
1893
+ useEffect4(() => {
1663
1894
  if (range) {
1664
1895
  notifier.current?.(rangeToA1Notation(range));
1665
1896
  }
1666
1897
  }, [
1667
1898
  range
1668
1899
  ]);
1669
- const extension = useMemo(() => [
1900
+ const extension = useMemo3(() => [
1670
1901
  editorKeys({
1671
1902
  onNav,
1672
1903
  onClose
@@ -1678,12 +1909,12 @@ var GridCellEditor = ({ style, value, onNav, onClose }) => {
1678
1909
  ], [
1679
1910
  model
1680
1911
  ]);
1681
- return /* @__PURE__ */ React3.createElement("div", {
1912
+ return /* @__PURE__ */ React4.createElement("div", {
1682
1913
  role: "cell",
1683
1914
  style,
1684
- className: mx2("z-20 flex", fragments.cellSelected),
1915
+ className: mx3("z-20 flex", fragments.cellSelected),
1685
1916
  onClick: (ev) => ev.stopPropagation()
1686
- }, /* @__PURE__ */ React3.createElement(CellEditor, {
1917
+ }, /* @__PURE__ */ React4.createElement(CellEditor, {
1687
1918
  autoFocus: true,
1688
1919
  value,
1689
1920
  extension
@@ -1702,24 +1933,24 @@ var SheetStatusBar = () => {
1702
1933
  value = String(value);
1703
1934
  }
1704
1935
  }
1705
- return /* @__PURE__ */ React3.createElement("div", {
1706
- className: mx2("flex shrink-0 justify-between items-center px-4 py-1 text-sm border-x border-gridLine")
1707
- }, /* @__PURE__ */ React3.createElement("div", {
1936
+ return /* @__PURE__ */ React4.createElement("div", {
1937
+ className: mx3("flex shrink-0 justify-between items-center px-4 py-1 text-sm border-x border-gridLine")
1938
+ }, /* @__PURE__ */ React4.createElement("div", {
1708
1939
  className: "flex gap-4 items-center"
1709
- }, /* @__PURE__ */ React3.createElement("div", {
1940
+ }, /* @__PURE__ */ React4.createElement("div", {
1710
1941
  className: "flex w-16 items-center font-mono"
1711
- }, range && rangeToA1Notation(range) || cursor && addressToA1Notation(cursor)), /* @__PURE__ */ React3.createElement("div", {
1942
+ }, range && rangeToA1Notation(range) || cursor && addressToA1Notation(cursor)), /* @__PURE__ */ React4.createElement("div", {
1712
1943
  className: "flex gap-2 items-center"
1713
- }, /* @__PURE__ */ React3.createElement(FunctionIcon, {
1714
- className: mx2("text-greenText", isFormula ? "visible" : "invisible")
1715
- }), /* @__PURE__ */ React3.createElement("span", {
1944
+ }, /* @__PURE__ */ React4.createElement(FunctionIcon, {
1945
+ className: mx3("text-greenText", isFormula ? "visible" : "invisible")
1946
+ }), /* @__PURE__ */ React4.createElement("span", {
1716
1947
  className: "font-mono"
1717
1948
  }, value))));
1718
1949
  };
1719
1950
  var SheetDebug = () => {
1720
1951
  const { model, cursor, range } = useSheetContext();
1721
1952
  const [, forceUpdate] = useState4({});
1722
- useEffect3(() => {
1953
+ useEffect4(() => {
1723
1954
  const accessor = createDocAccessor(model.sheet, []);
1724
1955
  const handleUpdate = () => forceUpdate({});
1725
1956
  accessor.handle.addListener("change", handleUpdate);
@@ -1730,9 +1961,9 @@ var SheetDebug = () => {
1730
1961
  }, [
1731
1962
  model
1732
1963
  ]);
1733
- return /* @__PURE__ */ React3.createElement("div", {
1734
- className: mx2("z-20 absolute right-0 top-20 bottom-20 w-[30rem] overflow-auto scrollbar-thin", "border border-gridLine text-xs bg-neutral-50 dark:bg-black text-cyan-500 font-mono p-1 opacity-80")
1735
- }, /* @__PURE__ */ React3.createElement("pre", {
1964
+ return /* @__PURE__ */ React4.createElement("div", {
1965
+ className: mx3("z-20 absolute right-0 top-20 bottom-20 w-[30rem] overflow-auto scrollbar-thin", "border border-gridLine text-xs bg-neutral-50 dark:bg-black text-cyan-500 font-mono p-1 opacity-80")
1966
+ }, /* @__PURE__ */ React4.createElement("pre", {
1736
1967
  className: "whitespace-pre-wrap"
1737
1968
  }, JSON.stringify({
1738
1969
  cursor,
@@ -1754,19 +1985,247 @@ var Sheet = {
1754
1985
  Debug: SheetDebug
1755
1986
  };
1756
1987
 
1988
+ // packages/plugins/plugin-sheet/src/components/Toolbar/Toolbar.tsx
1989
+ import { Calendar, ChatText, CurrencyDollar, Eraser, HighlighterCircle, TextAlignCenter, TextAlignLeft, TextAlignRight } from "@phosphor-icons/react";
1990
+ import { createContext as createContext2 } from "@radix-ui/react-context";
1991
+ import React6 from "react";
1992
+ import { DensityProvider, ElevationProvider, Toolbar as NaturalToolbar2, useTranslation as useTranslation2 } from "@dxos/react-ui";
1993
+ import { nonNullable } from "@dxos/util";
1994
+
1995
+ // packages/plugins/plugin-sheet/src/components/Toolbar/common.tsx
1996
+ import React5 from "react";
1997
+ import { Toolbar as NaturalToolbar, Tooltip } from "@dxos/react-ui";
1998
+ import { getSize } from "@dxos/react-ui-theme";
1999
+ var iconStyles = getSize(5);
2000
+ var buttonStyles = "min-bs-0 p-2";
2001
+ var tooltipProps = {
2002
+ side: "top",
2003
+ classNames: "z-10"
2004
+ };
2005
+ var ToolbarSeparator = () => /* @__PURE__ */ React5.createElement("div", {
2006
+ role: "separator",
2007
+ className: "grow"
2008
+ });
2009
+ var ToolbarButton = ({ Icon: Icon2, children, ...props }) => {
2010
+ return /* @__PURE__ */ React5.createElement(Tooltip.Root, null, /* @__PURE__ */ React5.createElement(Tooltip.Trigger, {
2011
+ asChild: true
2012
+ }, /* @__PURE__ */ React5.createElement(NaturalToolbar.Button, {
2013
+ variant: "ghost",
2014
+ ...props,
2015
+ classNames: buttonStyles
2016
+ }, /* @__PURE__ */ React5.createElement(Icon2, {
2017
+ className: iconStyles
2018
+ }), /* @__PURE__ */ React5.createElement("span", {
2019
+ className: "sr-only"
2020
+ }, children))), /* @__PURE__ */ React5.createElement(Tooltip.Portal, null, /* @__PURE__ */ React5.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React5.createElement(Tooltip.Arrow, null))));
2021
+ };
2022
+ var ToolbarToggleButton = ({ Icon: Icon2, children, ...props }) => {
2023
+ return /* @__PURE__ */ React5.createElement(Tooltip.Root, null, /* @__PURE__ */ React5.createElement(Tooltip.Trigger, {
2024
+ asChild: true
2025
+ }, /* @__PURE__ */ React5.createElement(NaturalToolbar.ToggleGroupItem, {
2026
+ variant: "ghost",
2027
+ ...props,
2028
+ classNames: buttonStyles
2029
+ }, /* @__PURE__ */ React5.createElement(Icon2, {
2030
+ className: iconStyles
2031
+ }), /* @__PURE__ */ React5.createElement("span", {
2032
+ className: "sr-only"
2033
+ }, children))), /* @__PURE__ */ React5.createElement(Tooltip.Portal, null, /* @__PURE__ */ React5.createElement(Tooltip.Content, tooltipProps, children, /* @__PURE__ */ React5.createElement(Tooltip.Arrow, null))));
2034
+ };
2035
+
2036
+ // packages/plugins/plugin-sheet/src/components/Toolbar/Toolbar.tsx
2037
+ var [ToolbarContextProvider, useToolbarContext] = createContext2("Toolbar");
2038
+ var ToolbarRoot = ({ children, onAction, classNames }) => {
2039
+ return /* @__PURE__ */ React6.createElement(ToolbarContextProvider, {
2040
+ onAction
2041
+ }, /* @__PURE__ */ React6.createElement(DensityProvider, {
2042
+ density: "fine"
2043
+ }, /* @__PURE__ */ React6.createElement(ElevationProvider, {
2044
+ elevation: "chrome"
2045
+ }, /* @__PURE__ */ React6.createElement(NaturalToolbar2.Root, {
2046
+ classNames: [
2047
+ "is-full shrink-0 overflow-x-auto overflow-y-hidden p-1",
2048
+ classNames
2049
+ ]
2050
+ }, children))));
2051
+ };
2052
+ var formatOptions = [
2053
+ {
2054
+ type: "date",
2055
+ Icon: Calendar,
2056
+ getState: (state) => false
2057
+ },
2058
+ {
2059
+ type: "currency",
2060
+ Icon: CurrencyDollar,
2061
+ getState: (state) => false
2062
+ }
2063
+ ];
2064
+ var Format = () => {
2065
+ const { onAction } = useToolbarContext("Format");
2066
+ const { t } = useTranslation2(SHEET_PLUGIN);
2067
+ return /* @__PURE__ */ React6.createElement(NaturalToolbar2.ToggleGroup, {
2068
+ type: "single"
2069
+ }, formatOptions.map(({ type, getState, Icon: Icon2 }) => /* @__PURE__ */ React6.createElement(ToolbarToggleButton, {
2070
+ key: type,
2071
+ value: type,
2072
+ Icon: Icon2,
2073
+ // disabled={state?.blockType === 'codeblock'}
2074
+ // onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
2075
+ onClick: () => onAction?.({
2076
+ type
2077
+ })
2078
+ }, t(`toolbar ${type} label`))));
2079
+ };
2080
+ var alignmentOptions = [
2081
+ {
2082
+ type: "left",
2083
+ Icon: TextAlignLeft,
2084
+ getState: (state) => false
2085
+ },
2086
+ {
2087
+ type: "center",
2088
+ Icon: TextAlignCenter,
2089
+ getState: (state) => false
2090
+ },
2091
+ {
2092
+ type: "right",
2093
+ Icon: TextAlignRight,
2094
+ getState: (state) => false
2095
+ }
2096
+ ];
2097
+ var Alignment = () => {
2098
+ const { onAction } = useToolbarContext("Alignment");
2099
+ const { t } = useTranslation2(SHEET_PLUGIN);
2100
+ return /* @__PURE__ */ React6.createElement(NaturalToolbar2.ToggleGroup, {
2101
+ type: "single"
2102
+ }, alignmentOptions.map(({ type, getState, Icon: Icon2 }) => /* @__PURE__ */ React6.createElement(ToolbarToggleButton, {
2103
+ key: type,
2104
+ value: type,
2105
+ Icon: Icon2,
2106
+ // disabled={state?.blockType === 'codeblock'}
2107
+ // onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
2108
+ onClick: () => onAction?.({
2109
+ type
2110
+ })
2111
+ }, t(`toolbar ${type} label`))));
2112
+ };
2113
+ var styleOptions = [
2114
+ {
2115
+ type: "clear",
2116
+ Icon: Eraser,
2117
+ getState: (state) => false
2118
+ },
2119
+ {
2120
+ type: "highlight",
2121
+ Icon: HighlighterCircle,
2122
+ getState: (state) => false
2123
+ }
2124
+ ];
2125
+ var Styles = () => {
2126
+ const { onAction } = useToolbarContext("Alignment");
2127
+ const { t } = useTranslation2(SHEET_PLUGIN);
2128
+ return /* @__PURE__ */ React6.createElement(NaturalToolbar2.ToggleGroup, {
2129
+ type: "single"
2130
+ }, styleOptions.map(({ type, getState, Icon: Icon2 }) => /* @__PURE__ */ React6.createElement(ToolbarToggleButton, {
2131
+ key: type,
2132
+ value: type,
2133
+ Icon: Icon2,
2134
+ // disabled={state?.blockType === 'codeblock'}
2135
+ // onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
2136
+ onClick: () => onAction?.({
2137
+ type
2138
+ })
2139
+ }, t(`toolbar ${type} label`))));
2140
+ };
2141
+ var Actions = () => {
2142
+ const { onAction } = useToolbarContext("Actions");
2143
+ const { cursor, range, model } = useSheetContext();
2144
+ const { t } = useTranslation2(SHEET_PLUGIN);
2145
+ const overlapsCommentAnchor = (model.sheet.threads ?? []).filter(nonNullable).filter((thread) => thread.status !== "resolved").some((thread) => {
2146
+ if (!cursor) {
2147
+ return false;
2148
+ }
2149
+ return addressToIndex(model.sheet, cursor) === thread.anchor;
2150
+ });
2151
+ const hasCursor = !!cursor;
2152
+ const cursorOnly = hasCursor && !range && !overlapsCommentAnchor;
2153
+ const tooltipLabelKey = !hasCursor ? "no cursor label" : overlapsCommentAnchor ? "selection overlaps existing comment label" : range ? "comment ranges not supported label" : "comment label";
2154
+ return /* @__PURE__ */ React6.createElement(ToolbarButton, {
2155
+ value: "comment",
2156
+ Icon: ChatText,
2157
+ "data-testid": "editor.toolbar.comment",
2158
+ onClick: () => {
2159
+ if (!cursor) {
2160
+ return;
2161
+ }
2162
+ return onAction?.({
2163
+ type: "comment",
2164
+ anchor: addressToIndex(model.sheet, cursor),
2165
+ cellContent: model.getCellText(cursor)
2166
+ });
2167
+ },
2168
+ disabled: !cursorOnly || overlapsCommentAnchor
2169
+ }, t(tooltipLabelKey));
2170
+ };
2171
+ var Toolbar = {
2172
+ Root: ToolbarRoot,
2173
+ Separator: ToolbarSeparator,
2174
+ Alignment,
2175
+ Format,
2176
+ Styles,
2177
+ Actions
2178
+ };
2179
+
1757
2180
  // packages/plugins/plugin-sheet/src/components/SheetContainer.tsx
2181
+ var attentionFragment = mx4("group-focus-within/editor:attention-surface group-[[aria-current]]/editor:attention-surface", "group-focus-within/editor:border-separator");
2182
+ var sectionToolbarLayout = "bs-[--rail-action] bg-[--sticky-bg] sticky block-start-0 __-block-start-px transition-opacity";
1758
2183
  var SheetContainer = ({ sheet, space, role, remoteFunctionUrl }) => {
1759
- return /* @__PURE__ */ React4.createElement("div", {
2184
+ const dispatch = useIntentDispatcher2();
2185
+ const id = fullyQualifiedId4(sheet);
2186
+ const isDirectlyAttended = useIsDirectlyAttended(id);
2187
+ const handleAction = useCallback2((action) => {
2188
+ switch (action.type) {
2189
+ case "comment": {
2190
+ void dispatch({
2191
+ action: "dxos.org/plugin/thread/action/create",
2192
+ data: {
2193
+ cursor: action.anchor,
2194
+ name: action.cellContent,
2195
+ subject: sheet
2196
+ }
2197
+ });
2198
+ }
2199
+ }
2200
+ }, [
2201
+ sheet,
2202
+ dispatch
2203
+ ]);
2204
+ return /* @__PURE__ */ React7.createElement("div", {
1760
2205
  role: "none",
1761
- className: mx3("flex", role === "article" && "row-span-2", role === "section" && "aspect-square border-y border-is border-separator")
1762
- }, /* @__PURE__ */ React4.createElement(Sheet.Root, {
2206
+ className: role === "article" ? "row-span-2 grid grid-rows-subgrid" : void 0
2207
+ }, /* @__PURE__ */ React7.createElement(Sheet.Root, {
1763
2208
  sheet,
1764
2209
  space,
1765
2210
  remoteFunctionUrl
1766
- }, /* @__PURE__ */ React4.createElement(Sheet.Main, null)));
2211
+ }, /* @__PURE__ */ React7.createElement("div", {
2212
+ role: "none",
2213
+ className: mx4("flex flex-0 justify-center overflow-x-auto")
2214
+ }, /* @__PURE__ */ React7.createElement(Toolbar.Root, {
2215
+ onAction: handleAction,
2216
+ classNames: mx4(role === "section" ? [
2217
+ "z-[2] group-focus-within/section:visible",
2218
+ !isDirectlyAttended && "invisible",
2219
+ sectionToolbarLayout
2220
+ ] : "group-focus-within/editor:border-separator group-[[aria-current]]/editor:border-separator")
2221
+ }, /* @__PURE__ */ React7.createElement(Toolbar.Separator, null), /* @__PURE__ */ React7.createElement(Toolbar.Actions, null))), /* @__PURE__ */ React7.createElement("div", {
2222
+ role: "none",
2223
+ className: mx4(role === "section" && "aspect-square border-is border-bs border-be border-separator", role === "article" && "flex is-full overflow-hidden focus-visible:ring-inset row-span-1 data-[toolbar=disabled]:pbs-2 data-[toolbar=disabled]:row-span-2 border-bs border-separator", focusRing, attentionFragment)
2224
+ }, /* @__PURE__ */ React7.createElement(Sheet.Main, null))));
1767
2225
  };
1768
2226
  var SheetContainer_default = SheetContainer;
1769
2227
  export {
1770
- SheetContainer_default as default
2228
+ SheetContainer_default as default,
2229
+ sectionToolbarLayout
1771
2230
  };
1772
- //# sourceMappingURL=SheetContainer-U4H5D34A.mjs.map
2231
+ //# sourceMappingURL=SheetContainer-Y7ZMFBAP.mjs.map