superdoc 2.0.0-next.45 → 2.0.0-next.47

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 (36) hide show
  1. package/AGENTS.md +15 -8
  2. package/dist/chunks/{create-super-doc-ui-BTOlZen9.es.js → create-super-doc-ui-CKyCKKdl.es.js} +244 -143
  3. package/dist/chunks/{create-super-doc-ui-DDxbK_M7.cjs → create-super-doc-ui-Dk6T01KE.cjs} +243 -142
  4. package/dist/collaboration-upgrade-engine.cjs +1 -1
  5. package/dist/collaboration-upgrade-engine.es.js +1 -1
  6. package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
  7. package/dist/document-api/src/contract/operation-definitions.d.ts +1 -1
  8. package/dist/public/ui-react.cjs +17 -14
  9. package/dist/public/ui-react.es.js +17 -14
  10. package/dist/public/ui.cjs +1 -1
  11. package/dist/public/ui.es.js +1 -1
  12. package/dist/style.css +23 -23
  13. package/dist/style.layered.css +23 -23
  14. package/dist/superdoc/src/components/surfaces/FindReplaceSurface.vue.d.ts +2 -2
  15. package/dist/superdoc/src/components/surfaces/PasswordPromptSurface.vue.d.ts +2 -2
  16. package/dist/superdoc/src/components/surfaces/SurfaceExternalMount.vue.d.ts +2 -2
  17. package/dist/superdoc/src/composables/replace-continuation.d.ts +37 -0
  18. package/dist/superdoc/src/composables/use-find-replace.d.ts +2 -2
  19. package/dist/superdoc/src/core/SuperDoc.d.ts +41 -0
  20. package/dist/superdoc/src/core/types/index.d.ts +2 -14
  21. package/dist/superdoc/src/internal/toolbar/built-in/default-items.d.ts +11 -0
  22. package/dist/superdoc/src/internal/toolbar/built-in-toolbar.d.ts +5 -5
  23. package/dist/superdoc/src/public/browser-document-api.d.ts +53 -0
  24. package/dist/superdoc/src/public/index.d.cts +4 -0
  25. package/dist/superdoc/src/public/index.d.ts +2 -0
  26. package/dist/superdoc/src/public/ui/react.d.ts +18 -7
  27. package/dist/superdoc/src/public/ui/types.d.ts +81 -12
  28. package/dist/superdoc/src/public/ui-react.d.ts +4 -3
  29. package/dist/superdoc/src/public/ui.d.cts +8 -0
  30. package/dist/superdoc/src/public/ui.d.ts +1 -1
  31. package/dist/superdoc.cjs +84 -59
  32. package/dist/superdoc.es.js +84 -59
  33. package/dist-cdn/style.layered.css +1 -1
  34. package/dist-cdn/superdoc.min.css +1 -1
  35. package/dist-cdn/superdoc.min.js +35 -35
  36. package/package.json +1 -1
@@ -1,27 +1,30 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("../chunks/rolldown-runtime-_dR15c8t.cjs");
3
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-DDxbK_M7.cjs");
3
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-Dk6T01KE.cjs");
4
4
  let react = require("react");
5
5
  var SuperDocUIContext = (0, react.createContext)(null);
6
+ function disposeOwnedUi(ref) {
7
+ const ui = ref.current;
8
+ if (!ui) return;
9
+ ui.destroy();
10
+ ref.current = null;
11
+ }
6
12
  function SuperDocUIProvider(props) {
7
13
  const [ui, setUi] = (0, react.useState)(null);
8
14
  const [host, setHost] = (0, react.useState)(null);
9
- const uiRef = (0, react.useRef)(null);
15
+ const ownedUiRef = (0, react.useRef)(null);
10
16
  const setSuperDoc = (0, react.useCallback)((superdoc) => {
11
- if (uiRef.current) uiRef.current.destroy();
12
- const next = require_create_super_doc_ui.createSuperDocUI({ superdoc });
13
- uiRef.current = next;
14
- setUi(next);
17
+ const hostUi = superdoc.ui;
18
+ disposeOwnedUi(ownedUiRef);
19
+ if (hostUi) setUi(hostUi);
20
+ else {
21
+ const created = require_create_super_doc_ui.createSuperDocUI({ superdoc });
22
+ ownedUiRef.current = created;
23
+ setUi(created);
24
+ }
15
25
  setHost(superdoc);
16
26
  }, []);
17
- (0, react.useEffect)(() => {
18
- return () => {
19
- if (uiRef.current) {
20
- uiRef.current.destroy();
21
- uiRef.current = null;
22
- }
23
- };
24
- }, []);
27
+ (0, react.useEffect)(() => () => disposeOwnedUi(ownedUiRef), []);
25
28
  const value = {
26
29
  ui,
27
30
  host,
@@ -1,25 +1,28 @@
1
- import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BTOlZen9.es.js";
1
+ import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-CKyCKKdl.es.js";
2
2
  import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
3
3
  var SuperDocUIContext = createContext(null);
4
+ function disposeOwnedUi(ref) {
5
+ const ui = ref.current;
6
+ if (!ui) return;
7
+ ui.destroy();
8
+ ref.current = null;
9
+ }
4
10
  function SuperDocUIProvider(props) {
5
11
  const [ui, setUi] = useState(null);
6
12
  const [host, setHost] = useState(null);
7
- const uiRef = useRef(null);
13
+ const ownedUiRef = useRef(null);
8
14
  const setSuperDoc = useCallback((superdoc) => {
9
- if (uiRef.current) uiRef.current.destroy();
10
- const next = createSuperDocUI({ superdoc });
11
- uiRef.current = next;
12
- setUi(next);
15
+ const hostUi = superdoc.ui;
16
+ disposeOwnedUi(ownedUiRef);
17
+ if (hostUi) setUi(hostUi);
18
+ else {
19
+ const created = createSuperDocUI({ superdoc });
20
+ ownedUiRef.current = created;
21
+ setUi(created);
22
+ }
13
23
  setHost(superdoc);
14
24
  }, []);
15
- useEffect(() => {
16
- return () => {
17
- if (uiRef.current) {
18
- uiRef.current.destroy();
19
- uiRef.current = null;
20
- }
21
- };
22
- }, []);
25
+ useEffect(() => () => disposeOwnedUi(ownedUiRef), []);
23
26
  const value = {
24
27
  ui,
25
28
  host,
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-DDxbK_M7.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-Dk6T01KE.cjs");
3
3
  exports.BUILT_IN_COMMAND_IDS = require_create_super_doc_ui.BUILT_IN_COMMAND_IDS;
4
4
  exports.createSuperDocUI = require_create_super_doc_ui.createSuperDocUI;
5
5
  exports.shallowEqual = require_create_super_doc_ui.shallowEqual;
@@ -1,2 +1,2 @@
1
- import { n as BUILT_IN_COMMAND_IDS, r as shallowEqual, t as createSuperDocUI } from "../chunks/create-super-doc-ui-BTOlZen9.es.js";
1
+ import { n as shallowEqual, r as BUILT_IN_COMMAND_IDS, t as createSuperDocUI } from "../chunks/create-super-doc-ui-CKyCKKdl.es.js";
2
2
  export { BUILT_IN_COMMAND_IDS, createSuperDocUI, shallowEqual };
package/dist/style.css CHANGED
@@ -1727,11 +1727,11 @@ img[data-v-c95b2073] {
1727
1727
  pointer-events: auto;
1728
1728
  }
1729
1729
 
1730
- .superdoc[data-v-91c4cd11] {
1730
+ .superdoc[data-v-41f40a40] {
1731
1731
  display: flex;
1732
1732
  position: relative;
1733
1733
  }
1734
- .sd-visually-hidden[data-v-91c4cd11] {
1734
+ .sd-visually-hidden[data-v-41f40a40] {
1735
1735
  position: absolute;
1736
1736
  width: 1px;
1737
1737
  height: 1px;
@@ -1742,30 +1742,30 @@ img[data-v-c95b2073] {
1742
1742
  white-space: nowrap;
1743
1743
  border: 0;
1744
1744
  }
1745
- .right-sidebar[data-v-91c4cd11] {
1745
+ .right-sidebar[data-v-41f40a40] {
1746
1746
  min-width: 320px;
1747
1747
  height: 100%;
1748
1748
  }
1749
- .floating-comments[data-v-91c4cd11] {
1749
+ .floating-comments[data-v-41f40a40] {
1750
1750
  min-width: 300px;
1751
1751
  width: 300px;
1752
1752
  height: 100%;
1753
1753
  overflow: visible;
1754
1754
  }
1755
- .superdoc__layers[data-v-91c4cd11] {
1755
+ .superdoc__layers[data-v-41f40a40] {
1756
1756
  height: 100%;
1757
1757
  position: relative;
1758
1758
  box-sizing: border-box;
1759
1759
  }
1760
- .superdoc__document[data-v-91c4cd11] {
1760
+ .superdoc__document[data-v-41f40a40] {
1761
1761
  width: 100%;
1762
1762
  position: relative;
1763
1763
  }
1764
- .superdoc__sub-document[data-v-91c4cd11] {
1764
+ .superdoc__sub-document[data-v-41f40a40] {
1765
1765
  width: 100%;
1766
1766
  position: relative;
1767
1767
  }
1768
- .superdoc__selection-layer[data-v-91c4cd11] {
1768
+ .superdoc__selection-layer[data-v-41f40a40] {
1769
1769
  position: absolute;
1770
1770
  min-width: 100%;
1771
1771
  min-height: 100%;
@@ -1776,13 +1776,13 @@ img[data-v-c95b2073] {
1776
1776
  /* SD-3497: PDF whiteboard overlay sits above the rendered PDF canvas but below
1777
1777
  the PDF comment anchors (z-index 6 in PdfCommentsLayer) so anchors stay
1778
1778
  clickable, and below the selection layer (z-index 10). */
1779
- .superdoc__whiteboard-layer[data-v-91c4cd11] {
1779
+ .superdoc__whiteboard-layer[data-v-41f40a40] {
1780
1780
  z-index: 4;
1781
1781
  }
1782
- .superdoc__temp-selection[data-v-91c4cd11] {
1782
+ .superdoc__temp-selection[data-v-41f40a40] {
1783
1783
  position: absolute;
1784
1784
  }
1785
- .superdoc__right-sidebar[data-v-91c4cd11] {
1785
+ .superdoc__right-sidebar[data-v-41f40a40] {
1786
1786
  width: 320px;
1787
1787
  min-width: 320px;
1788
1788
  padding: 0 10px;
@@ -1790,7 +1790,7 @@ img[data-v-c95b2073] {
1790
1790
  position: relative;
1791
1791
  z-index: 2;
1792
1792
  }
1793
- .superdoc__compact-comment-popover[data-v-91c4cd11] {
1793
+ .superdoc__compact-comment-popover[data-v-41f40a40] {
1794
1794
  position: absolute;
1795
1795
  top: 12px;
1796
1796
  right: 12px;
@@ -1799,14 +1799,14 @@ img[data-v-c95b2073] {
1799
1799
  }
1800
1800
 
1801
1801
  /* Tools styles */
1802
- .tools[data-v-91c4cd11] {
1802
+ .tools[data-v-41f40a40] {
1803
1803
  position: absolute;
1804
1804
  z-index: 3;
1805
1805
  display: flex;
1806
1806
  flex-direction: column;
1807
1807
  gap: var(--sd-ui-tools-gap, 6px);
1808
1808
  }
1809
- .tools-item[data-v-91c4cd11] {
1809
+ .tools-item[data-v-41f40a40] {
1810
1810
  display: flex;
1811
1811
  align-items: center;
1812
1812
  justify-content: center;
@@ -1817,10 +1817,10 @@ img[data-v-c95b2073] {
1817
1817
  cursor: pointer;
1818
1818
  position: relative;
1819
1819
  }
1820
- .tools-item i[data-v-91c4cd11] {
1820
+ .tools-item i[data-v-41f40a40] {
1821
1821
  cursor: pointer;
1822
1822
  }
1823
- .superdoc__tools-icon[data-v-91c4cd11] {
1823
+ .superdoc__tools-icon[data-v-41f40a40] {
1824
1824
  width: var(--sd-ui-tools-icon-size, 20px);
1825
1825
  height: var(--sd-ui-tools-icon-size, 20px);
1826
1826
  flex-shrink: 0;
@@ -1835,22 +1835,22 @@ img[data-v-c95b2073] {
1835
1835
 
1836
1836
  /* 834px is iPad screen size in portrait orientation */
1837
1837
  @media (max-width: 834px) {
1838
- .superdoc .superdoc__layers[data-v-91c4cd11] {
1838
+ .superdoc .superdoc__layers[data-v-41f40a40] {
1839
1839
  margin: 0;
1840
1840
  border: 0 !important;
1841
1841
  box-shadow: none;
1842
1842
  }
1843
- .superdoc__sub-document[data-v-91c4cd11] {
1843
+ .superdoc__sub-document[data-v-41f40a40] {
1844
1844
  max-width: 100%;
1845
1845
  }
1846
- .superdoc__right-sidebar[data-v-91c4cd11] {
1846
+ .superdoc__right-sidebar[data-v-41f40a40] {
1847
1847
  padding: 10px;
1848
1848
  position: relative;
1849
1849
  }
1850
1850
  }
1851
1851
 
1852
1852
  /* AI Writer styles */
1853
- .ai-writer-container[data-v-91c4cd11] {
1853
+ .ai-writer-container[data-v-41f40a40] {
1854
1854
  position: fixed;
1855
1855
  z-index: 1000;
1856
1856
  background: white;
@@ -1866,10 +1866,10 @@ img[data-v-c95b2073] {
1866
1866
  transform: translateY(-50%);
1867
1867
  z-index: 50;
1868
1868
  } */
1869
- .ai-tool > svg[data-v-91c4cd11] {
1869
+ .ai-tool > svg[data-v-41f40a40] {
1870
1870
  fill: transparent;
1871
1871
  }
1872
- .ai-tool[data-v-91c4cd11]::before {
1872
+ .ai-tool[data-v-41f40a40]::before {
1873
1873
  content: '';
1874
1874
  position: absolute;
1875
1875
  width: 20px;
@@ -1890,7 +1890,7 @@ img[data-v-c95b2073] {
1890
1890
  filter: brightness(1.2);
1891
1891
  transition: filter 0.2s ease;
1892
1892
  }
1893
- .ai-tool[data-v-91c4cd11]:hover::before {
1893
+ .ai-tool[data-v-41f40a40]:hover::before {
1894
1894
  filter: brightness(1.3);
1895
1895
  }
1896
1896
 
@@ -1727,11 +1727,11 @@ img[data-v-c95b2073] {
1727
1727
  pointer-events: auto;
1728
1728
  }
1729
1729
 
1730
- .superdoc[data-v-91c4cd11] {
1730
+ .superdoc[data-v-41f40a40] {
1731
1731
  display: flex;
1732
1732
  position: relative;
1733
1733
  }
1734
- .sd-visually-hidden[data-v-91c4cd11] {
1734
+ .sd-visually-hidden[data-v-41f40a40] {
1735
1735
  position: absolute;
1736
1736
  width: 1px;
1737
1737
  height: 1px;
@@ -1742,30 +1742,30 @@ img[data-v-c95b2073] {
1742
1742
  white-space: nowrap;
1743
1743
  border: 0;
1744
1744
  }
1745
- .right-sidebar[data-v-91c4cd11] {
1745
+ .right-sidebar[data-v-41f40a40] {
1746
1746
  min-width: 320px;
1747
1747
  height: 100%;
1748
1748
  }
1749
- .floating-comments[data-v-91c4cd11] {
1749
+ .floating-comments[data-v-41f40a40] {
1750
1750
  min-width: 300px;
1751
1751
  width: 300px;
1752
1752
  height: 100%;
1753
1753
  overflow: visible;
1754
1754
  }
1755
- .superdoc__layers[data-v-91c4cd11] {
1755
+ .superdoc__layers[data-v-41f40a40] {
1756
1756
  height: 100%;
1757
1757
  position: relative;
1758
1758
  box-sizing: border-box;
1759
1759
  }
1760
- .superdoc__document[data-v-91c4cd11] {
1760
+ .superdoc__document[data-v-41f40a40] {
1761
1761
  width: 100%;
1762
1762
  position: relative;
1763
1763
  }
1764
- .superdoc__sub-document[data-v-91c4cd11] {
1764
+ .superdoc__sub-document[data-v-41f40a40] {
1765
1765
  width: 100%;
1766
1766
  position: relative;
1767
1767
  }
1768
- .superdoc__selection-layer[data-v-91c4cd11] {
1768
+ .superdoc__selection-layer[data-v-41f40a40] {
1769
1769
  position: absolute;
1770
1770
  min-width: 100%;
1771
1771
  min-height: 100%;
@@ -1776,13 +1776,13 @@ img[data-v-c95b2073] {
1776
1776
  /* SD-3497: PDF whiteboard overlay sits above the rendered PDF canvas but below
1777
1777
  the PDF comment anchors (z-index 6 in PdfCommentsLayer) so anchors stay
1778
1778
  clickable, and below the selection layer (z-index 10). */
1779
- .superdoc__whiteboard-layer[data-v-91c4cd11] {
1779
+ .superdoc__whiteboard-layer[data-v-41f40a40] {
1780
1780
  z-index: 4;
1781
1781
  }
1782
- .superdoc__temp-selection[data-v-91c4cd11] {
1782
+ .superdoc__temp-selection[data-v-41f40a40] {
1783
1783
  position: absolute;
1784
1784
  }
1785
- .superdoc__right-sidebar[data-v-91c4cd11] {
1785
+ .superdoc__right-sidebar[data-v-41f40a40] {
1786
1786
  width: 320px;
1787
1787
  min-width: 320px;
1788
1788
  padding: 0 10px;
@@ -1790,7 +1790,7 @@ img[data-v-c95b2073] {
1790
1790
  position: relative;
1791
1791
  z-index: 2;
1792
1792
  }
1793
- .superdoc__compact-comment-popover[data-v-91c4cd11] {
1793
+ .superdoc__compact-comment-popover[data-v-41f40a40] {
1794
1794
  position: absolute;
1795
1795
  top: 12px;
1796
1796
  right: 12px;
@@ -1799,14 +1799,14 @@ img[data-v-c95b2073] {
1799
1799
  }
1800
1800
 
1801
1801
  /* Tools styles */
1802
- .tools[data-v-91c4cd11] {
1802
+ .tools[data-v-41f40a40] {
1803
1803
  position: absolute;
1804
1804
  z-index: 3;
1805
1805
  display: flex;
1806
1806
  flex-direction: column;
1807
1807
  gap: var(--sd-ui-tools-gap, 6px);
1808
1808
  }
1809
- .tools-item[data-v-91c4cd11] {
1809
+ .tools-item[data-v-41f40a40] {
1810
1810
  display: flex;
1811
1811
  align-items: center;
1812
1812
  justify-content: center;
@@ -1817,10 +1817,10 @@ img[data-v-c95b2073] {
1817
1817
  cursor: pointer;
1818
1818
  position: relative;
1819
1819
  }
1820
- .tools-item i[data-v-91c4cd11] {
1820
+ .tools-item i[data-v-41f40a40] {
1821
1821
  cursor: pointer;
1822
1822
  }
1823
- .superdoc__tools-icon[data-v-91c4cd11] {
1823
+ .superdoc__tools-icon[data-v-41f40a40] {
1824
1824
  width: var(--sd-ui-tools-icon-size, 20px);
1825
1825
  height: var(--sd-ui-tools-icon-size, 20px);
1826
1826
  flex-shrink: 0;
@@ -1835,22 +1835,22 @@ img[data-v-c95b2073] {
1835
1835
 
1836
1836
  /* 834px is iPad screen size in portrait orientation */
1837
1837
  @media (max-width: 834px) {
1838
- .superdoc .superdoc__layers[data-v-91c4cd11] {
1838
+ .superdoc .superdoc__layers[data-v-41f40a40] {
1839
1839
  margin: 0;
1840
1840
  border: 0 !important;
1841
1841
  box-shadow: none;
1842
1842
  }
1843
- .superdoc__sub-document[data-v-91c4cd11] {
1843
+ .superdoc__sub-document[data-v-41f40a40] {
1844
1844
  max-width: 100%;
1845
1845
  }
1846
- .superdoc__right-sidebar[data-v-91c4cd11] {
1846
+ .superdoc__right-sidebar[data-v-41f40a40] {
1847
1847
  padding: 10px;
1848
1848
  position: relative;
1849
1849
  }
1850
1850
  }
1851
1851
 
1852
1852
  /* AI Writer styles */
1853
- .ai-writer-container[data-v-91c4cd11] {
1853
+ .ai-writer-container[data-v-41f40a40] {
1854
1854
  position: fixed;
1855
1855
  z-index: 1000;
1856
1856
  background: white;
@@ -1866,10 +1866,10 @@ img[data-v-c95b2073] {
1866
1866
  transform: translateY(-50%);
1867
1867
  z-index: 50;
1868
1868
  } */
1869
- .ai-tool > svg[data-v-91c4cd11] {
1869
+ .ai-tool > svg[data-v-41f40a40] {
1870
1870
  fill: transparent;
1871
1871
  }
1872
- .ai-tool[data-v-91c4cd11]::before {
1872
+ .ai-tool[data-v-41f40a40]::before {
1873
1873
  content: '';
1874
1874
  position: absolute;
1875
1875
  width: 20px;
@@ -1890,7 +1890,7 @@ img[data-v-c95b2073] {
1890
1890
  filter: brightness(1.2);
1891
1891
  transition: filter 0.2s ease;
1892
1892
  }
1893
- .ai-tool[data-v-91c4cd11]:hover::before {
1893
+ .ai-tool[data-v-41f40a40]:hover::before {
1894
1894
  filter: brightness(1.3);
1895
1895
  }
1896
1896
 
@@ -1,15 +1,15 @@
1
1
  declare const _default: import('vue').DefineComponent<{}, {
2
2
  close: Function;
3
3
  resolve: Function;
4
- mode: string;
5
4
  request: Record<string, any>;
5
+ mode: string;
6
6
  surfaceId: string;
7
7
  findReplace: Record<string, any>;
8
8
  $props: {
9
9
  readonly close?: Function | undefined;
10
10
  readonly resolve?: Function | undefined;
11
- readonly mode?: string | undefined;
12
11
  readonly request?: Record<string, any> | undefined;
12
+ readonly mode?: string | undefined;
13
13
  readonly surfaceId?: string | undefined;
14
14
  readonly findReplace?: Record<string, any> | undefined;
15
15
  };
@@ -1,15 +1,15 @@
1
1
  declare const _default: import('vue').DefineComponent<{}, {
2
2
  close: Function;
3
3
  resolve: Function;
4
- mode: string;
5
4
  request: Record<string, any>;
5
+ mode: string;
6
6
  surfaceId: string;
7
7
  passwordPrompt: Record<string, any>;
8
8
  $props: {
9
9
  readonly close?: Function | undefined;
10
10
  readonly resolve?: Function | undefined;
11
- readonly mode?: string | undefined;
12
11
  readonly request?: Record<string, any> | undefined;
12
+ readonly mode?: string | undefined;
13
13
  readonly surfaceId?: string | undefined;
14
14
  readonly passwordPrompt?: Record<string, any> | undefined;
15
15
  };
@@ -1,15 +1,15 @@
1
1
  declare const _default: import('vue').DefineComponent<{}, {
2
2
  close: Function;
3
3
  resolve: Function;
4
- mode: string;
5
4
  request: Record<string, any>;
5
+ mode: string;
6
6
  render: Function;
7
7
  surfaceId: string;
8
8
  $props: {
9
9
  readonly close?: Function | undefined;
10
10
  readonly resolve?: Function | undefined;
11
- readonly mode?: string | undefined;
12
11
  readonly request?: Record<string, any> | undefined;
12
+ readonly mode?: string | undefined;
13
13
  readonly render?: Function | undefined;
14
14
  readonly surfaceId?: string | undefined;
15
15
  };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The find/replace panel's settled-replace continuation.
3
+ *
4
+ * A worker-backed replace resolves asynchronously, and the session it belongs to
5
+ * can be gone by the time it does: the search handle is reassigned when the
6
+ * active editor changes and nulled on teardown. Publishing the resolved snapshot
7
+ * anyway would repopulate the panel with matches from a document the user is no
8
+ * longer looking at.
9
+ *
10
+ * A leaf module rather than a closure inside `useFindReplace`, following
11
+ * `find-shortcut-owner.js`. The guard previously lived in two byte-identical
12
+ * inline closures, each of which needed a full composable driving a
13
+ * worker-backed host caught mid-swap to reach one branch. Nothing could, so it
14
+ * shipped with a comment admitting it was verified by inspection only. The
15
+ * duplication was the tell: logic worth stating twice is worth naming once.
16
+ */
17
+ /**
18
+ * Build the continuation that publishes a settled replace back into the panel.
19
+ *
20
+ * The session handle itself is the identity. `onSettled` always runs, including
21
+ * when the write is skipped: it clears the pending flag that gates the replace
22
+ * controls, and leaving it set would disable them with nothing left to settle.
23
+ *
24
+ * @param {{ getSnapshot: () => unknown }} session The handle captured when the replace was issued.
25
+ * @param {object} deps
26
+ * @param {() => unknown} deps.getCurrentSession Reads the live session identity.
27
+ * @param {(snapshot: unknown) => void} deps.applySlice Publishes a snapshot into the panel.
28
+ * @param {() => void} deps.onSettled Runs whether or not the write was skipped.
29
+ * @returns {() => void}
30
+ */
31
+ export function createReplaceContinuation(session: {
32
+ getSnapshot: () => unknown;
33
+ }, { getCurrentSession, applySlice, onSettled }: {
34
+ getCurrentSession: () => unknown;
35
+ applySlice: (snapshot: unknown) => void;
36
+ onSettled: () => void;
37
+ }): () => void;
@@ -10,8 +10,8 @@
10
10
  * @param {() => SearchEditor | null} options.getActiveEditor
11
11
  * @param {import('vue').Ref} [options.activeEditorRef] - Reactive ref to the active editor (for watching switches)
12
12
  * @param {() => boolean | FindReplaceConfig | undefined} [options.getFindReplaceConfig] - Config getter
13
- * @param {() => { search?: any } | null | undefined} [options.getSuperDocUI] - V2 UI controller getter
14
- * (`createSuperDocUI({ superdoc })`). Its `.search` slice is the single V2
13
+ * @param {() => { search?: any } | null | undefined} [options.getSuperDocUI] - Getter for the
14
+ * SuperDoc-owned UI controller (`superdoc.ui`). Its `.search` slice is the single V2
15
15
  * find/replace session authority; the V2 driver never touches `editor.commands`.
16
16
  */
17
17
  export function useFindReplace({ getSurfaceManager, getActiveEditor, activeEditorRef, getFindReplaceConfig, getSuperDocUI, }: {
@@ -3,6 +3,7 @@ import { HocuspocusProviderWebsocket } from '@hocuspocus/provider';
3
3
  import { createSuperdocVueApp } from './create-app.js';
4
4
  import { Whiteboard } from './whiteboard/Whiteboard.js';
5
5
  import { EditorRuntimeFocusOptions } from './editor-runtime/types.js';
6
+ import { BorrowedSuperDocUI } from '../public/ui/types.js';
6
7
  import { AwarenessUser, CanPerformPermissionParams, CollaborationProvider, Config, ContentControlActiveChangePayload, ContentControlClickPayload, DocumentMode, Editor, EditorUpdateEvent, ExportParams, FontsChangedPayload, FontsResolvedPayload, InternalConfig, ListDefinitionsPayload, NavigableAddress, DocumentRendererRuntime, SearchMatch, SuperDocAwarenessUpdatePayload, SuperDocCommentsUpdatePayload, SuperDocEditorPayload, SuperDocExceptionPayload, SuperDocFontsApi, SuperDocLockedPayload, SuperDocMeasurementUnit, SuperDocMeasurementUnitChangePayload, SuperDocReadyPayload, SuperDocState, SuperDocViewportChangePayload, SuperDocViewportMetrics, SuperDocZoomMode, SuperDocZoomPayload, SuperDocZoomState, SurfaceHandle, SurfaceRequest, UpgradeToCollaborationOptions, User } from './types/index.js';
7
8
  import { WhiteboardData } from './whiteboard/Whiteboard.js';
8
9
  type ToolbarLike = {
@@ -53,6 +54,13 @@ interface SuperDocEventMap {
53
54
  'measurement-unit-change': [SuperDocMeasurementUnitChangePayload];
54
55
  'formatting-marks-change': [SuperDocFormattingMarksPayload];
55
56
  'document-mode-change': [SuperDocDocumentModeChangePayload];
57
+ /**
58
+ * The active editor was assigned or cleared. Internal: the UI controller
59
+ * listens so its snapshot follows the live editor. `editorCreate` only
60
+ * covers assignment, and it is emitted after `broadcastReady()`, so
61
+ * neither a pre-ready read nor a clear would refresh without this.
62
+ */
63
+ 'active-editor-change': [];
56
64
  'editor-update': [EditorUpdateEvent];
57
65
  'content-error': [SuperDocContentErrorPayload];
58
66
  'fonts-resolved': [FontsResolvedPayload];
@@ -231,6 +239,39 @@ export declare class SuperDoc extends EventEmitter<SuperDocEventMap> {
231
239
  * @returns The number of required editors
232
240
  */
233
241
  get requiredNumberOfEditors(): number;
242
+ /**
243
+ * The UI controller for this instance: the single place to read command
244
+ * state and drive comments, track changes, selection, zoom, and the other
245
+ * UI surfaces from application code.
246
+ *
247
+ * SuperDoc owns exactly one controller per instance. Every internal
248
+ * consumer — the built-in toolbar, the link popover, keyboard command
249
+ * routing, and the React bindings — reads this same object, so command
250
+ * state never diverges between built-in and custom UI. The controller is
251
+ * created by the first read and its identity never changes afterwards:
252
+ * replacing the document, remounting an editor, or switching the active
253
+ * editor in a multi-document instance all keep the same controller.
254
+ *
255
+ * Reading it is safe before the document is ready. Slices report a `pending`
256
+ * status and commands report themselves disabled instead of throwing, so a
257
+ * custom UI can subscribe in the same tick as the constructor and will start
258
+ * receiving real values once an editor mounts.
259
+ *
260
+ * `SuperDoc.destroy()` destroys the controller. The returned type is
261
+ * {@link BorrowedSuperDocUI}, which omits `destroy()`, so a consumer tearing
262
+ * down state that other readers of this instance still observe is a compile
263
+ * error rather than a rule in a comment. The instance keeps the owning
264
+ * reference privately.
265
+ *
266
+ * This is an observation and command surface, not a permission boundary.
267
+ * Anything it exposes is reachable by the page that hosts SuperDoc.
268
+ *
269
+ * @example
270
+ * const superdoc = new SuperDoc({ selector: '#editor', document: file });
271
+ * const stop = superdoc.ui.comments.observe((comments) => render(comments));
272
+ * superdoc.ui.commands.get('bold').getState(); // { enabled, active, ... }
273
+ */
274
+ get ui(): BorrowedSuperDocUI;
234
275
  /**
235
276
  * Snapshot of the current SuperDoc state. Always reflects the most
236
277
  * recent values from the Pinia store; consumers must re-read on
@@ -1,25 +1,13 @@
1
1
  import { Doc as YDoc } from 'yjs';
2
2
  import { HocuspocusProviderWebsocket } from '@hocuspocus/provider';
3
3
  import { Ref, ComputedRef } from 'vue';
4
- import { DocumentApi } from '../../../../document-api/src/index.js';
5
4
  import { DocumentFontOption, FontAssetUrlResolver, FontFamilyOption, FontLoadSummary, FontResolutionRecord } from '../../../../shared/font-system/src/index.js';
6
5
  import { SuperDoc as SuperDocClass } from '../SuperDoc.js';
7
6
  import { SuperDocActiveEditorExtensions, SuperDocExtension } from '../extensions/index.js';
7
+ import { BrowserDocumentApi } from '../../public/browser-document-api.js';
8
8
  export type { DocumentFontOption, FontAssetUrlContext, FontAssetUrlResolver, FontFaceSlot, FontFamilyOption, FontLoadResult, FontLoadStatus, FontLoadSummary, FontResolutionReason, FontResolutionRecord, GlyphException, ResolvedFontEvidence, SubstitutePolicyAction, SubstituteVerdict, } from '../../../../shared/font-system/src/index.js';
9
9
  export type SuperDoc = SuperDocClass;
10
- type MaybePromise<T> = T | Promise<T>;
11
- type BrowserDocumentApiObject<T> = {
12
- [K in keyof T]: BrowserDocumentApiValue<T[K]>;
13
- };
14
- type BrowserDocumentApiValue<T> = T extends (...args: infer Args) => infer Return ? ((...args: Args) => MaybePromise<Awaited<Return>>) & BrowserDocumentApiObject<T> : T extends object ? BrowserDocumentApiObject<T> : T;
15
- /**
16
- * Browser V2 active-editor Document API facade (`superdoc.activeEditor.doc`).
17
- * In the browser this surface is intentionally async-capable: callers must
18
- * tolerate promise-returning reads/writes, including the default
19
- * worker-backed runtime. SDK/headless callers should continue using the
20
- * synchronous `@superdoc/document-api` surface directly.
21
- */
22
- export type BrowserDocumentApi = BrowserDocumentApiObject<DocumentApi>;
10
+ export type { BrowserDocumentApi } from '../../public/browser-document-api.js';
23
11
  export type V2AuthoringSelectionCollapse = 'start' | 'end' | null;
24
12
  export type V2AuthoringResult = {
25
13
  ok: true;
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Set or clear the link item's `href` without disturbing the rest of its
3
+ * attributes. The static configuration (`ariaLabel`, and anything added later)
4
+ * lives in the same object as the transient href, so rebuilding that object
5
+ * from the keys a caller knows about silently drops the others.
6
+ *
7
+ * Exported because the built-in toolbar's `updateToolbarState()` writes the
8
+ * href on its own path, without going through this item's handlers. Both
9
+ * callers share this one rule so the two cannot drift apart.
10
+ */
11
+ export function withLinkHref(attributes: any, href: any): any;
1
12
  export function makeDefaultItems({ superToolbar, toolbarIcons, toolbarTexts, toolbarFonts, hideButtons, availableWidth, role, isDev, }?: {
2
13
  isDev?: boolean | undefined;
3
14
  }): {
@@ -177,14 +177,14 @@ export class BuiltInToolbar extends EventEmitter<string | symbol, any> {
177
177
  _detachFontsChanged: null;
178
178
  /** Active editor compatibility reference (set by `SuperDoc.setActiveEditor`). */
179
179
  activeEditor: any;
180
- /** Live shared command controller (single command-state truth). */
181
- ui: import('../../public/ui.js').SuperDocUI | null;
180
+ /** SuperDoc-owned command controller (single command-state truth). */
181
+ ui: any;
182
182
  /** Latest controller toolbar snapshot. */
183
- snapshot: import('../../public/ui.js').ToolbarSnapshotSlice | null;
183
+ snapshot: any;
184
184
  /** Controller subscription unsubscribe handle. */
185
- _unsubscribeController: (() => void) | null;
185
+ _unsubscribeController: any;
186
186
  /** Format-painter mode subscription unsubscribe handle. */
187
- _detachFormatPainterModeChange: (() => void) | null;
187
+ _detachFormatPainterModeChange: any;
188
188
  /** Registered custom-button command unregister handles. */
189
189
  _customCommandRegs: Map<any, any>;
190
190
  /** Signature of the last-built font options, to skip redundant rebuilds. */