@extend-ai/react-docx 0.7.0-alpha.6 → 0.7.0-alpha.7

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.
package/dist/index.js CHANGED
@@ -22439,13 +22439,14 @@ function ensureDocxViewerPageSurfaceRegistry(editor) {
22439
22439
  registry = {
22440
22440
  pageElements: /* @__PURE__ */ new Map(),
22441
22441
  pageContentKeys: /* @__PURE__ */ new Map(),
22442
+ pageSizes: /* @__PURE__ */ new Map(),
22442
22443
  listeners: /* @__PURE__ */ new Set()
22443
22444
  };
22444
22445
  docxViewerPageSurfaceRegistryByEditor.set(owner, registry);
22445
22446
  }
22446
22447
  return registry;
22447
22448
  }
22448
- function syncDocxViewerPageSurfaceContentKeys(editor, contentKeysByPage) {
22449
+ function syncDocxViewerPageSurfaceContentKeys(editor, contentKeysByPage, pageSizesByPage = []) {
22449
22450
  const registry = ensureDocxViewerPageSurfaceRegistry(editor);
22450
22451
  let changed = false;
22451
22452
  contentKeysByPage.forEach((contentKey, pageIndex) => {
@@ -22454,12 +22455,27 @@ function syncDocxViewerPageSurfaceContentKeys(editor, contentKeysByPage) {
22454
22455
  changed = true;
22455
22456
  }
22456
22457
  });
22458
+ pageSizesByPage.forEach((pageSize, pageIndex) => {
22459
+ const widthPx = Math.max(1, Math.round(pageSize.widthPx));
22460
+ const heightPx = Math.max(1, Math.round(pageSize.heightPx));
22461
+ const previous = registry.pageSizes.get(pageIndex);
22462
+ if (previous?.widthPx !== widthPx || previous?.heightPx !== heightPx) {
22463
+ registry.pageSizes.set(pageIndex, { widthPx, heightPx });
22464
+ changed = true;
22465
+ }
22466
+ });
22457
22467
  registry.pageContentKeys.forEach((_, pageIndex) => {
22458
22468
  if (pageIndex >= contentKeysByPage.length) {
22459
22469
  registry.pageContentKeys.delete(pageIndex);
22460
22470
  changed = true;
22461
22471
  }
22462
22472
  });
22473
+ registry.pageSizes.forEach((_, pageIndex) => {
22474
+ if (pageIndex >= pageSizesByPage.length) {
22475
+ registry.pageSizes.delete(pageIndex);
22476
+ changed = true;
22477
+ }
22478
+ });
22463
22479
  if (changed) {
22464
22480
  notifyDocxViewerPageSurfaceSubscribers(registry);
22465
22481
  }
@@ -22476,7 +22492,7 @@ function notifyDocxViewerPageSurfaceSubscribers(registry) {
22476
22492
  listener();
22477
22493
  });
22478
22494
  }
22479
- function registerDocxViewerPageSurface(editor, pageIndex, element) {
22495
+ function registerDocxViewerPageSurface(editor, pageIndex, element, previousElement) {
22480
22496
  const registry = ensureDocxViewerPageSurfaceRegistry(editor);
22481
22497
  const normalizedPageIndex = Math.max(0, Math.round(pageIndex));
22482
22498
  const currentElement = registry.pageElements.get(normalizedPageIndex);
@@ -22491,9 +22507,22 @@ function registerDocxViewerPageSurface(editor, pageIndex, element) {
22491
22507
  if (!currentElement) {
22492
22508
  return;
22493
22509
  }
22510
+ if (previousElement && currentElement !== previousElement) {
22511
+ return;
22512
+ }
22494
22513
  registry.pageElements.delete(normalizedPageIndex);
22495
22514
  notifyDocxViewerPageSurfaceSubscribers(registry);
22496
22515
  }
22516
+ function resolveDocxViewerRegisteredPageSurfaceSize(registry, pageIndex, fallbackWidthPx, fallbackHeightPx) {
22517
+ const registeredSize = registry.pageSizes.get(pageIndex);
22518
+ if (registeredSize) {
22519
+ return registeredSize;
22520
+ }
22521
+ return {
22522
+ widthPx: Math.max(1, Math.round(fallbackWidthPx)),
22523
+ heightPx: Math.max(1, Math.round(fallbackHeightPx))
22524
+ };
22525
+ }
22497
22526
  function resolveDocxViewerPageSurfaceSize(element, fallbackWidthPx, fallbackHeightPx) {
22498
22527
  if (element) {
22499
22528
  const rect = element.getBoundingClientRect();
@@ -22527,6 +22556,104 @@ function resolveDocxViewerPageSurfaceSize(element, fallbackWidthPx, fallbackHeig
22527
22556
  heightPx: Math.max(1, Math.round(fallbackHeightPx))
22528
22557
  };
22529
22558
  }
22559
+ function DocxDetachedThumbnailPageSurface({
22560
+ editor,
22561
+ pageIndex
22562
+ }) {
22563
+ return /* @__PURE__ */ jsx(
22564
+ DocxEditorViewer,
22565
+ {
22566
+ editor,
22567
+ mode: "read-only",
22568
+ visiblePageRange: { startPageIndex: pageIndex, endPageIndex: pageIndex },
22569
+ pageVirtualization: { enabled: false },
22570
+ showTrackedChanges: editor.showTrackedChanges,
22571
+ showComments: editor.showComments,
22572
+ style: {
22573
+ background: "transparent",
22574
+ padding: 0,
22575
+ margin: 0
22576
+ }
22577
+ }
22578
+ );
22579
+ }
22580
+ var DocxDetachedThumbnailSurfaceRenderer = class {
22581
+ host;
22582
+ root;
22583
+ activePageIndex;
22584
+ async renderPageSurface(params) {
22585
+ if (typeof document === "undefined" || typeof window === "undefined") {
22586
+ return void 0;
22587
+ }
22588
+ const { editor, registry, pageIndex } = params;
22589
+ await this.ensureRoot();
22590
+ if (!this.root) {
22591
+ return void 0;
22592
+ }
22593
+ if (this.activePageIndex !== pageIndex) {
22594
+ this.activePageIndex = pageIndex;
22595
+ this.root.render(
22596
+ /* @__PURE__ */ jsx(
22597
+ DocxDetachedThumbnailPageSurface,
22598
+ {
22599
+ editor,
22600
+ pageIndex
22601
+ }
22602
+ )
22603
+ );
22604
+ }
22605
+ return this.waitForPageSurface(registry, pageIndex);
22606
+ }
22607
+ clear() {
22608
+ if (this.root) {
22609
+ this.root.unmount();
22610
+ this.root = void 0;
22611
+ }
22612
+ if (this.host?.parentNode) {
22613
+ this.host.parentNode.removeChild(this.host);
22614
+ }
22615
+ this.host = void 0;
22616
+ this.activePageIndex = void 0;
22617
+ }
22618
+ async ensureRoot() {
22619
+ if (this.root) {
22620
+ return;
22621
+ }
22622
+ if (typeof document === "undefined") {
22623
+ return;
22624
+ }
22625
+ const host = document.createElement("div");
22626
+ host.setAttribute("data-docx-thumbnail-detached-renderer", "true");
22627
+ Object.assign(host.style, {
22628
+ position: "fixed",
22629
+ left: "-100000px",
22630
+ top: "0",
22631
+ width: "1px",
22632
+ height: "1px",
22633
+ overflow: "visible",
22634
+ opacity: "0",
22635
+ pointerEvents: "none",
22636
+ zIndex: "-1"
22637
+ });
22638
+ document.body.appendChild(host);
22639
+ this.host = host;
22640
+ const { createRoot } = await import("react-dom/client");
22641
+ this.root = createRoot(host);
22642
+ }
22643
+ async waitForPageSurface(registry, pageIndex) {
22644
+ for (let attempt = 0; attempt < 8; attempt += 1) {
22645
+ const pageElement2 = registry.pageElements.get(pageIndex);
22646
+ if (pageElement2?.isConnected) {
22647
+ return pageElement2;
22648
+ }
22649
+ await new Promise((resolve) => {
22650
+ window.requestAnimationFrame(() => resolve());
22651
+ });
22652
+ }
22653
+ const pageElement = registry.pageElements.get(pageIndex);
22654
+ return pageElement?.isConnected ? pageElement : void 0;
22655
+ }
22656
+ };
22530
22657
  var DOCX_THUMBNAIL_SURFACE_CACHE_MAX_ENTRIES = 32;
22531
22658
  var DOCX_THUMBNAIL_MIN_RASTER_INTERVAL_MS = 200;
22532
22659
  function resolveDocxPageThumbnailResolution(options) {
@@ -22604,6 +22731,7 @@ function useDocxPageThumbnails(editor, options = {}) {
22604
22731
  );
22605
22732
  const thumbnailSurfaceCacheRef = React.useRef(void 0);
22606
22733
  const thumbnailRasterQueueRef = React.useRef(void 0);
22734
+ const detachedThumbnailSurfaceRendererRef = React.useRef(void 0);
22607
22735
  const lastPaintedThumbnailKeyByCanvasRef = React.useRef(
22608
22736
  /* @__PURE__ */ new WeakMap()
22609
22737
  );
@@ -22626,8 +22754,17 @@ function useDocxPageThumbnails(editor, options = {}) {
22626
22754
  React.useEffect(() => {
22627
22755
  thumbnailSurfaceCacheRef.current?.clear();
22628
22756
  thumbnailRasterQueueRef.current?.clear();
22757
+ detachedThumbnailSurfaceRendererRef.current?.clear();
22758
+ detachedThumbnailSurfaceRendererRef.current = void 0;
22629
22759
  lastPaintedThumbnailKeyByCanvasRef.current = /* @__PURE__ */ new WeakMap();
22630
22760
  }, [editor.documentLoadNonce, pageSurfaceRegistryOwner]);
22761
+ React.useEffect(
22762
+ () => () => {
22763
+ detachedThumbnailSurfaceRendererRef.current?.clear();
22764
+ detachedThumbnailSurfaceRendererRef.current = void 0;
22765
+ },
22766
+ []
22767
+ );
22631
22768
  const thumbnailResolutionOptionsKey = React.useMemo(() => {
22632
22769
  const bounds = options.resolution;
22633
22770
  const boundsKey = typeof bounds === "number" ? `n${bounds}` : bounds ? `b${bounds.maxWidth ?? ""}x${bounds.maxHeight ?? ""}` : "";
@@ -22655,11 +22792,6 @@ function useDocxPageThumbnails(editor, options = {}) {
22655
22792
  return;
22656
22793
  }
22657
22794
  const requiresAttachedTarget = canvas === void 0;
22658
- const pageElement = pageSurfaceRegistry.pageElements.get(pageIndex);
22659
- if (!pageElement || !pageElement.isConnected) {
22660
- updatePageThumbnailState(pageIndex, "unavailable");
22661
- return;
22662
- }
22663
22795
  const force = renderOptions?.force === true;
22664
22796
  const lastPaintedKey = lastPaintedThumbnailKeyByCanvasRef.current.get(targetCanvas);
22665
22797
  if (!force && lastPaintedKey !== void 0 && lastPaintedKey === thumbnailSkipKeyForPage(pageIndex)) {
@@ -22671,41 +22803,67 @@ function useDocxPageThumbnails(editor, options = {}) {
22671
22803
  if (requiresAttachedTarget && attachedCanvasByPageRef.current.get(pageIndex) !== targetCanvas) {
22672
22804
  return;
22673
22805
  }
22674
- const livePageElement = pageSurfaceRegistry.pageElements.get(pageIndex);
22675
- if (!livePageElement || !livePageElement.isConnected) {
22676
- updatePageThumbnailState(pageIndex, "unavailable");
22677
- return;
22678
- }
22679
22806
  const runSkipKey = thumbnailSkipKeyForPage(pageIndex);
22680
- const sourceSize = resolveDocxViewerPageSurfaceSize(
22681
- livePageElement,
22807
+ const fallbackSourceSize = resolveDocxViewerRegisteredPageSurfaceSize(
22808
+ pageSurfaceRegistry,
22809
+ pageIndex,
22682
22810
  fallbackLayout.pageWidthPx,
22683
22811
  fallbackLayout.pageHeightPx
22684
22812
  );
22685
22813
  const resolution = resolveDocxPageThumbnailResolution({
22686
- sourceWidthPx: sourceSize.widthPx,
22687
- sourceHeightPx: sourceSize.heightPx,
22814
+ sourceWidthPx: fallbackSourceSize.widthPx,
22815
+ sourceHeightPx: fallbackSourceSize.heightPx,
22688
22816
  resolution: options.resolution,
22689
22817
  maxWidthPx: options.maxWidthPx,
22690
22818
  maxHeightPx: options.maxHeightPx,
22691
22819
  pixelRatio: options.pixelRatio
22692
22820
  });
22693
- const surfaceKey = runSkipKey === void 0 ? void 0 : `${runSkipKey}|${sourceSize.widthPx}x${sourceSize.heightPx}|${resolution.pixelWidthPx}x${resolution.pixelHeightPx}`;
22821
+ const surfaceKey = runSkipKey === void 0 ? void 0 : `${runSkipKey}|${fallbackSourceSize.widthPx}x${fallbackSourceSize.heightPx}|${resolution.pixelWidthPx}x${resolution.pixelHeightPx}`;
22694
22822
  const surfaceCache = ensureThumbnailSurfaceCache();
22695
22823
  try {
22696
22824
  let surface = !force && surfaceKey !== void 0 ? surfaceCache.get(surfaceKey) : void 0;
22697
22825
  if (!surface) {
22698
- surface = await rasterizeDocxThumbnailSurface({
22699
- pageElement: livePageElement,
22700
- sourceWidthPx: sourceSize.widthPx,
22701
- sourceHeightPx: sourceSize.heightPx,
22702
- widthPx: resolution.widthPx,
22703
- heightPx: resolution.heightPx,
22704
- pixelWidthPx: resolution.pixelWidthPx,
22705
- pixelHeightPx: resolution.pixelHeightPx
22706
- });
22707
- if (surfaceKey !== void 0) {
22708
- surfaceCache.set(surfaceKey, surface);
22826
+ let livePageElement = pageSurfaceRegistry.pageElements.get(pageIndex);
22827
+ let renderedDetachedSurface = false;
22828
+ try {
22829
+ if (!livePageElement || !livePageElement.isConnected) {
22830
+ if (!detachedThumbnailSurfaceRendererRef.current) {
22831
+ detachedThumbnailSurfaceRendererRef.current = new DocxDetachedThumbnailSurfaceRenderer();
22832
+ }
22833
+ livePageElement = await detachedThumbnailSurfaceRendererRef.current.renderPageSurface(
22834
+ {
22835
+ editor,
22836
+ registry: pageSurfaceRegistry,
22837
+ pageIndex
22838
+ }
22839
+ );
22840
+ renderedDetachedSurface = true;
22841
+ }
22842
+ if (!livePageElement || !livePageElement.isConnected) {
22843
+ updatePageThumbnailState(pageIndex, "unavailable");
22844
+ return;
22845
+ }
22846
+ const sourceSize = resolveDocxViewerPageSurfaceSize(
22847
+ livePageElement,
22848
+ fallbackSourceSize.widthPx,
22849
+ fallbackSourceSize.heightPx
22850
+ );
22851
+ surface = await rasterizeDocxThumbnailSurface({
22852
+ pageElement: livePageElement,
22853
+ sourceWidthPx: sourceSize.widthPx,
22854
+ sourceHeightPx: sourceSize.heightPx,
22855
+ widthPx: resolution.widthPx,
22856
+ heightPx: resolution.heightPx,
22857
+ pixelWidthPx: resolution.pixelWidthPx,
22858
+ pixelHeightPx: resolution.pixelHeightPx
22859
+ });
22860
+ if (surfaceKey !== void 0) {
22861
+ surfaceCache.set(surfaceKey, surface);
22862
+ }
22863
+ } finally {
22864
+ if (renderedDetachedSurface) {
22865
+ detachedThumbnailSurfaceRendererRef.current?.clear();
22866
+ }
22709
22867
  }
22710
22868
  }
22711
22869
  blitDocxThumbnailSurface(surface, targetCanvas, resolution);
@@ -22737,7 +22895,8 @@ function useDocxPageThumbnails(editor, options = {}) {
22737
22895
  options.pixelRatio,
22738
22896
  pageSurfaceRegistry,
22739
22897
  thumbnailSkipKeyForPage,
22740
- updatePageThumbnailState
22898
+ updatePageThumbnailState,
22899
+ editor
22741
22900
  ]
22742
22901
  );
22743
22902
  const requestAttachedThumbnailRenders = React.useCallback(
@@ -22781,10 +22940,15 @@ function useDocxPageThumbnails(editor, options = {}) {
22781
22940
  const totalPages = Math.max(1, editor.totalPages);
22782
22941
  return Array.from({ length: totalPages }, (_, pageIndex) => {
22783
22942
  const pageElement = mountedPageElements.get(pageIndex);
22784
- const sourceSize = resolveDocxViewerPageSurfaceSize(
22943
+ const sourceSize = pageElement && pageElement.isConnected ? resolveDocxViewerPageSurfaceSize(
22785
22944
  pageElement,
22786
22945
  fallbackLayout.pageWidthPx,
22787
22946
  fallbackLayout.pageHeightPx
22947
+ ) : resolveDocxViewerRegisteredPageSurfaceSize(
22948
+ pageSurfaceRegistry,
22949
+ pageIndex,
22950
+ fallbackLayout.pageWidthPx,
22951
+ fallbackLayout.pageHeightPx
22788
22952
  );
22789
22953
  const resolution = resolveDocxPageThumbnailResolution({
22790
22954
  sourceWidthPx: sourceSize.widthPx,
@@ -22854,6 +23018,7 @@ function useDocxPageThumbnails(editor, options = {}) {
22854
23018
  options.maxHeightPx,
22855
23019
  options.maxWidthPx,
22856
23020
  options.pixelRatio,
23021
+ pageSurfaceRegistry,
22857
23022
  pageThumbnailStates
22858
23023
  ]);
22859
23024
  const paintThumbnail = React.useCallback(
@@ -24150,13 +24315,23 @@ function DocxEditorViewer({
24150
24315
  if (cached) {
24151
24316
  return cached;
24152
24317
  }
24318
+ let registeredElement = null;
24153
24319
  const nextRef = (element) => {
24154
24320
  if (element) {
24321
+ registeredElement = element;
24155
24322
  pageElementsRef.current.set(normalizedPageIndex, element);
24156
24323
  } else {
24157
24324
  pageElementsRef.current.delete(normalizedPageIndex);
24158
24325
  }
24159
- registerDocxViewerPageSurface(editor, normalizedPageIndex, element);
24326
+ registerDocxViewerPageSurface(
24327
+ editor,
24328
+ normalizedPageIndex,
24329
+ element,
24330
+ registeredElement
24331
+ );
24332
+ if (!element) {
24333
+ registeredElement = null;
24334
+ }
24160
24335
  };
24161
24336
  pageSurfaceRefCallbacksRef.current.set(normalizedPageIndex, nextRef);
24162
24337
  return nextRef;
@@ -25219,12 +25394,27 @@ function DocxEditorViewer({
25219
25394
  pageSectionInfoByIndex,
25220
25395
  trackedChangesEnabled
25221
25396
  ]);
25397
+ const pageThumbnailSurfaceSizesByPage = React.useMemo(
25398
+ () => pageNodeSegmentsByPage.map((_, pageIndex) => {
25399
+ const pageLayout = pageSectionInfoByIndex[pageIndex]?.layout ?? documentLayout;
25400
+ return {
25401
+ widthPx: pageLayout.pageWidthPx,
25402
+ heightPx: pageLayout.pageHeightPx
25403
+ };
25404
+ }),
25405
+ [documentLayout, pageNodeSegmentsByPage, pageSectionInfoByIndex]
25406
+ );
25222
25407
  React.useEffect(() => {
25223
25408
  syncDocxViewerPageSurfaceContentKeys(
25224
25409
  editor,
25225
- pageThumbnailContentKeysByPage
25410
+ pageThumbnailContentKeysByPage,
25411
+ pageThumbnailSurfaceSizesByPage
25226
25412
  );
25227
- }, [pageSurfaceRegistryOwner, pageThumbnailContentKeysByPage]);
25413
+ }, [
25414
+ pageSurfaceRegistryOwner,
25415
+ pageThumbnailContentKeysByPage,
25416
+ pageThumbnailSurfaceSizesByPage
25417
+ ]);
25228
25418
  const resolveStyleRefFieldValueForPage = React.useMemo(() => {
25229
25419
  const valueCache = /* @__PURE__ */ new Map();
25230
25420
  const nodes = editor.model.nodes;