@pixldocs/canvas-renderer 0.5.13 → 0.5.15

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.cjs CHANGED
@@ -2656,6 +2656,19 @@ const FONTS_TO_PRELOAD = [
2656
2656
  ];
2657
2657
  let fontsLoaded = false;
2658
2658
  let fontsLoadingPromise = null;
2659
+ const withFontTimeout = async (promise, timeoutMs = 4e3) => {
2660
+ let timeoutId;
2661
+ try {
2662
+ return await Promise.race([
2663
+ promise,
2664
+ new Promise((resolve) => {
2665
+ timeoutId = setTimeout(resolve, timeoutMs);
2666
+ })
2667
+ ]);
2668
+ } finally {
2669
+ if (timeoutId) clearTimeout(timeoutId);
2670
+ }
2671
+ };
2659
2672
  const preloadFont = async (fontFamily) => {
2660
2673
  try {
2661
2674
  if (document.fonts) {
@@ -2676,11 +2689,11 @@ const preloadAllFonts = async () => {
2676
2689
  }
2677
2690
  fontsLoadingPromise = (async () => {
2678
2691
  if (document.fonts) {
2679
- await document.fonts.ready;
2692
+ await withFontTimeout(document.fonts.ready, 2500);
2680
2693
  }
2681
- await Promise.all(FONTS_TO_PRELOAD.map((font) => preloadFont(font)));
2694
+ await withFontTimeout(Promise.all(FONTS_TO_PRELOAD.map((font) => preloadFont(font))).then(() => void 0), 5e3);
2682
2695
  if (document.fonts) {
2683
- await document.fonts.ready;
2696
+ await withFontTimeout(document.fonts.ready, 2500);
2684
2697
  }
2685
2698
  fontsLoaded = true;
2686
2699
  })();
@@ -2688,7 +2701,7 @@ const preloadAllFonts = async () => {
2688
2701
  };
2689
2702
  const waitForFontsReady = async () => {
2690
2703
  if (!document.fonts) return;
2691
- await document.fonts.ready;
2704
+ await withFontTimeout(document.fonts.ready, 2500);
2692
2705
  };
2693
2706
  const DEFAULT_FONT_CHECK_TIMEOUT_MS = 3500;
2694
2707
  const FONT_CHECK_POLL_MS = 60;
@@ -11694,6 +11707,19 @@ function normalizeFontFamily(fontStack) {
11694
11707
  }
11695
11708
  const loadedFonts = /* @__PURE__ */ new Set();
11696
11709
  const loadingPromises = /* @__PURE__ */ new Map();
11710
+ async function withTimeout(promise, timeoutMs = 4e3) {
11711
+ let timeoutId;
11712
+ try {
11713
+ return await Promise.race([
11714
+ promise,
11715
+ new Promise((resolve) => {
11716
+ timeoutId = setTimeout(resolve, timeoutMs);
11717
+ })
11718
+ ]);
11719
+ } finally {
11720
+ if (timeoutId) clearTimeout(timeoutId);
11721
+ }
11722
+ }
11697
11723
  async function loadGoogleFontCSS(rawFontFamily) {
11698
11724
  if (!rawFontFamily || typeof document === "undefined") return;
11699
11725
  const fontFamily = normalizeFontFamily(rawFontFamily);
@@ -11715,8 +11741,8 @@ async function loadGoogleFontCSS(rawFontFamily) {
11715
11741
  document.head.appendChild(link);
11716
11742
  });
11717
11743
  if (document.fonts) {
11718
- await document.fonts.load(`16px "${fontFamily}"`);
11719
- await document.fonts.ready;
11744
+ await withTimeout(document.fonts.load(`16px "${fontFamily}"`), 2500);
11745
+ await withTimeout(document.fonts.ready, 2500);
11720
11746
  }
11721
11747
  loadedFonts.add(fontFamily);
11722
11748
  } catch (e) {
@@ -11829,7 +11855,7 @@ async function ensureFontsForResolvedConfig(config) {
11829
11855
  if (typeof document === "undefined") return;
11830
11856
  const descriptors = collectFontDescriptorsFromConfig(config);
11831
11857
  const families = new Set(descriptors.map((d) => d.family));
11832
- await Promise.all([...families].map((f) => loadGoogleFontCSS(f)));
11858
+ await withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 8e3);
11833
11859
  if (document.fonts) {
11834
11860
  const loadPromises = descriptors.map((d) => {
11835
11861
  const stylePrefix = d.style === "italic" ? "italic " : "";
@@ -11838,8 +11864,8 @@ async function ensureFontsForResolvedConfig(config) {
11838
11864
  return document.fonts.load(spec).catch(() => {
11839
11865
  });
11840
11866
  });
11841
- await Promise.all(loadPromises);
11842
- await document.fonts.ready;
11867
+ await withTimeout(Promise.all(loadPromises), 8e3);
11868
+ await withTimeout(document.fonts.ready, 2500);
11843
11869
  }
11844
11870
  }
11845
11871
  function PixldocsPreview(props) {
@@ -11862,6 +11888,7 @@ function PixldocsPreview(props) {
11862
11888
  const [fontsReady, setFontsReady] = react.useState(false);
11863
11889
  const [fontsReadyVersion, setFontsReadyVersion] = react.useState(0);
11864
11890
  const [canvasSettled, setCanvasSettled] = react.useState(false);
11891
+ const [stabilizationPass, setStabilizationPass] = react.useState(0);
11865
11892
  const isResolveMode = !("config" in props && props.config);
11866
11893
  react.useEffect(() => {
11867
11894
  if (!isResolveMode) {
@@ -11920,6 +11947,7 @@ function PixldocsPreview(props) {
11920
11947
  if (!config) return;
11921
11948
  let cancelled = false;
11922
11949
  setCanvasSettled(false);
11950
+ setStabilizationPass(0);
11923
11951
  const bump = () => {
11924
11952
  if (cancelled) return;
11925
11953
  clearMeasurementCache();
@@ -11932,22 +11960,32 @@ function PixldocsPreview(props) {
11932
11960
  window.clearTimeout(timeoutId);
11933
11961
  };
11934
11962
  }, [config]);
11935
- const previewKey = react.useMemo(() => `${pageIndex}-${fontsReadyVersion}`, [pageIndex, fontsReadyVersion]);
11963
+ const previewKey = react.useMemo(
11964
+ () => `${pageIndex}-${fontsReadyVersion}-${stabilizationPass}`,
11965
+ [pageIndex, fontsReadyVersion, stabilizationPass]
11966
+ );
11936
11967
  react.useEffect(() => {
11937
11968
  if (isResolveMode) return;
11938
11969
  if (!config) {
11939
11970
  setFontsReady(false);
11940
11971
  setCanvasSettled(false);
11972
+ setStabilizationPass(0);
11941
11973
  return;
11942
11974
  }
11943
11975
  setFontsReady(false);
11944
11976
  setCanvasSettled(false);
11977
+ setStabilizationPass(0);
11945
11978
  ensureFontsForResolvedConfig(config).then(() => setFontsReady(true)).catch(() => setFontsReady(true));
11946
11979
  }, [isResolveMode, config]);
11947
11980
  const handleCanvasReady = react.useCallback(() => {
11981
+ if (stabilizationPass === 0) {
11982
+ setCanvasSettled(false);
11983
+ setStabilizationPass(1);
11984
+ return;
11985
+ }
11948
11986
  setCanvasSettled(true);
11949
11987
  onReady == null ? void 0 : onReady();
11950
- }, [onReady]);
11988
+ }, [onReady, stabilizationPass]);
11951
11989
  if (isLoading) {
11952
11990
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...style, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) });
11953
11991
  }
@@ -12361,6 +12399,7 @@ class PixldocsRenderer {
12361
12399
  cleanup();
12362
12400
  reject(new Error("Render timeout (30s)"));
12363
12401
  }, 3e4);
12402
+ let stabilizationPass = 0;
12364
12403
  const cleanup = () => {
12365
12404
  clearTimeout(timeout);
12366
12405
  try {
@@ -12370,6 +12409,19 @@ class PixldocsRenderer {
12370
12409
  container.remove();
12371
12410
  };
12372
12411
  const onReady = () => {
12412
+ if (stabilizationPass === 0) {
12413
+ stabilizationPass = 1;
12414
+ root.render(
12415
+ react.createElement(PreviewCanvas2, {
12416
+ config,
12417
+ pageIndex,
12418
+ zoom: pixelRatio,
12419
+ absoluteZoom: true,
12420
+ onReady
12421
+ })
12422
+ );
12423
+ return;
12424
+ }
12373
12425
  const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
12374
12426
  this.waitForCanvasImages(container, expectedImageCount).then(async () => {
12375
12427
  try {
@@ -12441,6 +12493,7 @@ class PixldocsRenderer {
12441
12493
  cleanup();
12442
12494
  reject(new Error("SVG render timeout (30s)"));
12443
12495
  }, 3e4);
12496
+ let stabilizationPass = 0;
12444
12497
  const cleanup = () => {
12445
12498
  clearTimeout(timeout);
12446
12499
  try {
@@ -12450,6 +12503,19 @@ class PixldocsRenderer {
12450
12503
  container.remove();
12451
12504
  };
12452
12505
  const onReady = () => {
12506
+ if (stabilizationPass === 0) {
12507
+ stabilizationPass = 1;
12508
+ root.render(
12509
+ react.createElement(PreviewCanvas2, {
12510
+ config,
12511
+ pageIndex,
12512
+ zoom: 1,
12513
+ absoluteZoom: true,
12514
+ onReady
12515
+ })
12516
+ );
12517
+ return;
12518
+ }
12453
12519
  const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
12454
12520
  this.waitForCanvasImages(container, expectedImageCount).then(async () => {
12455
12521
  var _a, _b;