@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.
@@ -15770,6 +15770,20 @@ function paintRepeatableSections(config, repeatableSections) {
15770
15770
  }
15771
15771
  }
15772
15772
  const PREVIEW_DEBUG_PREFIX = "[canvas-renderer][preview-debug]";
15773
+ function computeFontSignature(config) {
15774
+ var _a;
15775
+ if (!((_a = config == null ? void 0 : config.pages) == null ? void 0 : _a.length)) return "";
15776
+ const fams = /* @__PURE__ */ new Set();
15777
+ const walk = (nodes) => {
15778
+ var _a2;
15779
+ for (const node of nodes || []) {
15780
+ if (node == null ? void 0 : node.fontFamily) fams.add(String(node.fontFamily));
15781
+ if ((_a2 = node == null ? void 0 : node.children) == null ? void 0 : _a2.length) walk(node.children);
15782
+ }
15783
+ };
15784
+ for (const page of config.pages) walk(page.children || []);
15785
+ return Array.from(fams).sort().join("|");
15786
+ }
15773
15787
  function countUnderlinedNodes(config) {
15774
15788
  var _a;
15775
15789
  if (!((_a = config == null ? void 0 : config.pages) == null ? void 0 : _a.length)) return 0;
@@ -15888,6 +15902,7 @@ function PixldocsPreview(props) {
15888
15902
  ]);
15889
15903
  const config = isResolveMode ? resolvedConfig : props.config;
15890
15904
  const previewKey = react.useMemo(() => `${pageIndex}`, [pageIndex]);
15905
+ const fontSignature = react.useMemo(() => computeFontSignature(config), [config]);
15891
15906
  react.useEffect(() => {
15892
15907
  if (isResolveMode) return;
15893
15908
  if (!config) {
@@ -15917,7 +15932,7 @@ function PixldocsPreview(props) {
15917
15932
  return () => {
15918
15933
  cancelled = true;
15919
15934
  };
15920
- }, [isResolveMode, config]);
15935
+ }, [isResolveMode, fontSignature]);
15921
15936
  const handleCanvasReady = react.useCallback(() => {
15922
15937
  console.log(PREVIEW_DEBUG_PREFIX, "canvas-ready", { pageIndex, action: "settled" });
15923
15938
  setCanvasSettled(true);
@@ -16120,9 +16135,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
16120
16135
  }
16121
16136
  return svgString;
16122
16137
  }
16123
- const resolvedPackageVersion = "0.5.169";
16138
+ const resolvedPackageVersion = "0.5.171";
16124
16139
  const PACKAGE_VERSION = resolvedPackageVersion;
16125
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.169";
16140
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.171";
16126
16141
  const roundParityValue = (value) => {
16127
16142
  if (typeof value !== "number") return value;
16128
16143
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -16620,7 +16635,7 @@ class PixldocsRenderer {
16620
16635
  await this.waitForCanvasScene(container, cloned, i);
16621
16636
  }
16622
16637
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
16623
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BU855BbG.cjs"));
16638
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BrwXcGkA.cjs"));
16624
16639
  const prepared = preparePagesForExport(
16625
16640
  cloned.pages,
16626
16641
  canvasWidth,
@@ -16640,28 +16655,46 @@ class PixldocsRenderer {
16640
16655
  }
16641
16656
  }
16642
16657
  getExpectedImageCount(config, pageIndex) {
16658
+ return this.getExpectedImageIds(config, pageIndex).length;
16659
+ }
16660
+ /**
16661
+ * Collects ids of nodes that the renderer expects to produce a renderable
16662
+ * fabric image. Excludes SVG sources because those are loaded as Groups,
16663
+ * not HTMLImageElement-backed Images, and would otherwise inflate the
16664
+ * `expected` counter forever.
16665
+ */
16666
+ getExpectedImageIds(config, pageIndex) {
16643
16667
  const page = config.pages[pageIndex];
16644
- if (!(page == null ? void 0 : page.children)) return 0;
16645
- let count = 0;
16668
+ if (!(page == null ? void 0 : page.children)) return [];
16669
+ const ids = [];
16670
+ const isSvgUrl = (u) => /\.svg(\?|#|$)/i.test(u) || u.startsWith("data:image/svg");
16646
16671
  const walk = (nodes) => {
16647
16672
  for (const node of nodes) {
16648
16673
  if (!node || node.visible === false) continue;
16649
16674
  const src = typeof node.src === "string" ? node.src.trim() : "";
16650
16675
  const imageUrl = typeof node.imageUrl === "string" ? node.imageUrl.trim() : "";
16651
- if (node.type === "image" && (src || imageUrl)) count += 1;
16676
+ const url = src || imageUrl;
16677
+ if (node.type === "image" && url && !isSvgUrl(url) && node.id) {
16678
+ ids.push(String(node.id));
16679
+ }
16652
16680
  if (Array.isArray(node.children) && node.children.length > 0) {
16653
16681
  walk(node.children);
16654
16682
  }
16655
16683
  }
16656
16684
  };
16657
16685
  walk(page.children);
16658
- return count;
16686
+ return ids;
16659
16687
  }
16660
- waitForCanvasImages(container, expectedImageCount, maxWaitMs = 15e3, pollMs = 120) {
16688
+ waitForCanvasImages(container, expectedImageCount, maxWaitMs, pollMs = 120) {
16689
+ const timeout = Math.max(500, maxWaitMs ?? this.config.assetWaitTimeoutMs ?? 15e3);
16690
+ const earlyExitMs = Math.max(250, this.config.assetWaitEarlyExitMs ?? 1500);
16691
+ const debug = !!this.config.debug;
16661
16692
  return new Promise((resolve) => {
16662
16693
  const start = Date.now();
16663
16694
  let stableFrames = 0;
16664
16695
  let lastSummary = "";
16696
+ let lastActual = -1;
16697
+ let lastProgressAt = Date.now();
16665
16698
  const isRenderableImage = (value) => value instanceof HTMLImageElement && value.complete && value.naturalWidth > 0 && value.naturalHeight > 0;
16666
16699
  const collectRenderableImages = (obj, seen) => {
16667
16700
  if (!obj || typeof obj !== "object") return;
@@ -16725,19 +16758,34 @@ class PixldocsRenderer {
16725
16758
  const summary = `expected=${expectedImageCount} actual=${actualImageCount} dom=${domImages.length} fabricReady=${fabricReady} domReady=${allDomLoaded} canvasReady=${canvasReady}`;
16726
16759
  if (summary !== lastSummary) {
16727
16760
  lastSummary = summary;
16728
- console.log(`[canvas-renderer][asset-wait] ${summary}`);
16761
+ if (debug) console.log(`[canvas-renderer][asset-wait] ${summary}`);
16762
+ }
16763
+ if (actualImageCount !== lastActual) {
16764
+ lastActual = actualImageCount;
16765
+ lastProgressAt = Date.now();
16729
16766
  }
16730
16767
  if (ready) {
16731
16768
  stableFrames += 1;
16732
16769
  if (stableFrames >= 2) {
16733
- console.log(`[canvas-renderer][asset-wait] ready after ${elapsed}ms (${summary})`);
16770
+ if (debug) console.log(`[canvas-renderer][asset-wait] ready after ${elapsed}ms (${summary})`);
16734
16771
  settle();
16735
16772
  return;
16736
16773
  }
16737
16774
  } else {
16738
16775
  stableFrames = 0;
16739
16776
  }
16740
- if (elapsed >= maxWaitMs) {
16777
+ const sceneSettled = fabricReady && allDomLoaded && canvasReady && fabricObjects.length > 0;
16778
+ const idleFor = Date.now() - lastProgressAt;
16779
+ if (sceneSettled && actualImageCount < expectedImageCount && idleFor >= earlyExitMs) {
16780
+ if (debug) {
16781
+ console.log(
16782
+ `[canvas-renderer][asset-wait] early-exit after ${elapsed}ms (idle=${idleFor}ms, ${summary})`
16783
+ );
16784
+ }
16785
+ settle();
16786
+ return;
16787
+ }
16788
+ if (elapsed >= timeout) {
16741
16789
  const fabricImageDebug = [];
16742
16790
  for (const obj of fabricObjects) {
16743
16791
  getImageDebugInfo(obj, fabricImageDebug);
@@ -18722,7 +18770,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18722
18770
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18723
18771
  sanitizeSvgTreeForPdf(svgToDraw);
18724
18772
  try {
18725
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BU855BbG.cjs"));
18773
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BrwXcGkA.cjs"));
18726
18774
  try {
18727
18775
  await logTextMeasurementDiagnostic(svgToDraw);
18728
18776
  } catch {
@@ -19121,4 +19169,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
19121
19169
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
19122
19170
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
19123
19171
  exports.warmTemplateFromForm = warmTemplateFromForm;
19124
- //# sourceMappingURL=index-Bg1FRZ3d.cjs.map
19172
+ //# sourceMappingURL=index-BgOzEKmN.cjs.map