@pixldocs/canvas-renderer 0.5.169 → 0.5.171

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.
@@ -15752,6 +15752,20 @@ function paintRepeatableSections(config, repeatableSections) {
15752
15752
  }
15753
15753
  }
15754
15754
  const PREVIEW_DEBUG_PREFIX = "[canvas-renderer][preview-debug]";
15755
+ function computeFontSignature(config) {
15756
+ var _a;
15757
+ if (!((_a = config == null ? void 0 : config.pages) == null ? void 0 : _a.length)) return "";
15758
+ const fams = /* @__PURE__ */ new Set();
15759
+ const walk = (nodes) => {
15760
+ var _a2;
15761
+ for (const node of nodes || []) {
15762
+ if (node == null ? void 0 : node.fontFamily) fams.add(String(node.fontFamily));
15763
+ if ((_a2 = node == null ? void 0 : node.children) == null ? void 0 : _a2.length) walk(node.children);
15764
+ }
15765
+ };
15766
+ for (const page of config.pages) walk(page.children || []);
15767
+ return Array.from(fams).sort().join("|");
15768
+ }
15755
15769
  function countUnderlinedNodes(config) {
15756
15770
  var _a;
15757
15771
  if (!((_a = config == null ? void 0 : config.pages) == null ? void 0 : _a.length)) return 0;
@@ -15870,6 +15884,7 @@ function PixldocsPreview(props) {
15870
15884
  ]);
15871
15885
  const config = isResolveMode ? resolvedConfig : props.config;
15872
15886
  const previewKey = useMemo(() => `${pageIndex}`, [pageIndex]);
15887
+ const fontSignature = useMemo(() => computeFontSignature(config), [config]);
15873
15888
  useEffect(() => {
15874
15889
  if (isResolveMode) return;
15875
15890
  if (!config) {
@@ -15899,7 +15914,7 @@ function PixldocsPreview(props) {
15899
15914
  return () => {
15900
15915
  cancelled = true;
15901
15916
  };
15902
- }, [isResolveMode, config]);
15917
+ }, [isResolveMode, fontSignature]);
15903
15918
  const handleCanvasReady = useCallback(() => {
15904
15919
  console.log(PREVIEW_DEBUG_PREFIX, "canvas-ready", { pageIndex, action: "settled" });
15905
15920
  setCanvasSettled(true);
@@ -16102,9 +16117,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
16102
16117
  }
16103
16118
  return svgString;
16104
16119
  }
16105
- const resolvedPackageVersion = "0.5.169";
16120
+ const resolvedPackageVersion = "0.5.171";
16106
16121
  const PACKAGE_VERSION = resolvedPackageVersion;
16107
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.169";
16122
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.171";
16108
16123
  const roundParityValue = (value) => {
16109
16124
  if (typeof value !== "number") return value;
16110
16125
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -16602,7 +16617,7 @@ class PixldocsRenderer {
16602
16617
  await this.waitForCanvasScene(container, cloned, i);
16603
16618
  }
16604
16619
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
16605
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-C2jE125-.js");
16620
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport--EtCdnlG.js");
16606
16621
  const prepared = preparePagesForExport(
16607
16622
  cloned.pages,
16608
16623
  canvasWidth,
@@ -16622,28 +16637,46 @@ class PixldocsRenderer {
16622
16637
  }
16623
16638
  }
16624
16639
  getExpectedImageCount(config, pageIndex) {
16640
+ return this.getExpectedImageIds(config, pageIndex).length;
16641
+ }
16642
+ /**
16643
+ * Collects ids of nodes that the renderer expects to produce a renderable
16644
+ * fabric image. Excludes SVG sources because those are loaded as Groups,
16645
+ * not HTMLImageElement-backed Images, and would otherwise inflate the
16646
+ * `expected` counter forever.
16647
+ */
16648
+ getExpectedImageIds(config, pageIndex) {
16625
16649
  const page = config.pages[pageIndex];
16626
- if (!(page == null ? void 0 : page.children)) return 0;
16627
- let count = 0;
16650
+ if (!(page == null ? void 0 : page.children)) return [];
16651
+ const ids = [];
16652
+ const isSvgUrl = (u) => /\.svg(\?|#|$)/i.test(u) || u.startsWith("data:image/svg");
16628
16653
  const walk = (nodes) => {
16629
16654
  for (const node of nodes) {
16630
16655
  if (!node || node.visible === false) continue;
16631
16656
  const src = typeof node.src === "string" ? node.src.trim() : "";
16632
16657
  const imageUrl = typeof node.imageUrl === "string" ? node.imageUrl.trim() : "";
16633
- if (node.type === "image" && (src || imageUrl)) count += 1;
16658
+ const url = src || imageUrl;
16659
+ if (node.type === "image" && url && !isSvgUrl(url) && node.id) {
16660
+ ids.push(String(node.id));
16661
+ }
16634
16662
  if (Array.isArray(node.children) && node.children.length > 0) {
16635
16663
  walk(node.children);
16636
16664
  }
16637
16665
  }
16638
16666
  };
16639
16667
  walk(page.children);
16640
- return count;
16668
+ return ids;
16641
16669
  }
16642
- waitForCanvasImages(container, expectedImageCount, maxWaitMs = 15e3, pollMs = 120) {
16670
+ waitForCanvasImages(container, expectedImageCount, maxWaitMs, pollMs = 120) {
16671
+ const timeout = Math.max(500, maxWaitMs ?? this.config.assetWaitTimeoutMs ?? 15e3);
16672
+ const earlyExitMs = Math.max(250, this.config.assetWaitEarlyExitMs ?? 1500);
16673
+ const debug = !!this.config.debug;
16643
16674
  return new Promise((resolve) => {
16644
16675
  const start = Date.now();
16645
16676
  let stableFrames = 0;
16646
16677
  let lastSummary = "";
16678
+ let lastActual = -1;
16679
+ let lastProgressAt = Date.now();
16647
16680
  const isRenderableImage = (value) => value instanceof HTMLImageElement && value.complete && value.naturalWidth > 0 && value.naturalHeight > 0;
16648
16681
  const collectRenderableImages = (obj, seen) => {
16649
16682
  if (!obj || typeof obj !== "object") return;
@@ -16707,19 +16740,34 @@ class PixldocsRenderer {
16707
16740
  const summary = `expected=${expectedImageCount} actual=${actualImageCount} dom=${domImages.length} fabricReady=${fabricReady} domReady=${allDomLoaded} canvasReady=${canvasReady}`;
16708
16741
  if (summary !== lastSummary) {
16709
16742
  lastSummary = summary;
16710
- console.log(`[canvas-renderer][asset-wait] ${summary}`);
16743
+ if (debug) console.log(`[canvas-renderer][asset-wait] ${summary}`);
16744
+ }
16745
+ if (actualImageCount !== lastActual) {
16746
+ lastActual = actualImageCount;
16747
+ lastProgressAt = Date.now();
16711
16748
  }
16712
16749
  if (ready) {
16713
16750
  stableFrames += 1;
16714
16751
  if (stableFrames >= 2) {
16715
- console.log(`[canvas-renderer][asset-wait] ready after ${elapsed}ms (${summary})`);
16752
+ if (debug) console.log(`[canvas-renderer][asset-wait] ready after ${elapsed}ms (${summary})`);
16716
16753
  settle();
16717
16754
  return;
16718
16755
  }
16719
16756
  } else {
16720
16757
  stableFrames = 0;
16721
16758
  }
16722
- if (elapsed >= maxWaitMs) {
16759
+ const sceneSettled = fabricReady && allDomLoaded && canvasReady && fabricObjects.length > 0;
16760
+ const idleFor = Date.now() - lastProgressAt;
16761
+ if (sceneSettled && actualImageCount < expectedImageCount && idleFor >= earlyExitMs) {
16762
+ if (debug) {
16763
+ console.log(
16764
+ `[canvas-renderer][asset-wait] early-exit after ${elapsed}ms (idle=${idleFor}ms, ${summary})`
16765
+ );
16766
+ }
16767
+ settle();
16768
+ return;
16769
+ }
16770
+ if (elapsed >= timeout) {
16723
16771
  const fabricImageDebug = [];
16724
16772
  for (const obj of fabricObjects) {
16725
16773
  getImageDebugInfo(obj, fabricImageDebug);
@@ -18704,7 +18752,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18704
18752
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18705
18753
  sanitizeSvgTreeForPdf(svgToDraw);
18706
18754
  try {
18707
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-C2jE125-.js");
18755
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport--EtCdnlG.js");
18708
18756
  try {
18709
18757
  await logTextMeasurementDiagnostic(svgToDraw);
18710
18758
  } catch {
@@ -19106,4 +19154,4 @@ export {
19106
19154
  collectFontDescriptorsFromConfig as y,
19107
19155
  collectFontsFromConfig as z
19108
19156
  };
19109
- //# sourceMappingURL=index-qJRuErt-.js.map
19157
+ //# sourceMappingURL=index-Cq9sQGri.js.map