@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.js CHANGED
@@ -2637,6 +2637,19 @@ const FONTS_TO_PRELOAD = [
2637
2637
  ];
2638
2638
  let fontsLoaded = false;
2639
2639
  let fontsLoadingPromise = null;
2640
+ const withFontTimeout = async (promise, timeoutMs = 4e3) => {
2641
+ let timeoutId;
2642
+ try {
2643
+ return await Promise.race([
2644
+ promise,
2645
+ new Promise((resolve) => {
2646
+ timeoutId = setTimeout(resolve, timeoutMs);
2647
+ })
2648
+ ]);
2649
+ } finally {
2650
+ if (timeoutId) clearTimeout(timeoutId);
2651
+ }
2652
+ };
2640
2653
  const preloadFont = async (fontFamily) => {
2641
2654
  try {
2642
2655
  if (document.fonts) {
@@ -2657,11 +2670,11 @@ const preloadAllFonts = async () => {
2657
2670
  }
2658
2671
  fontsLoadingPromise = (async () => {
2659
2672
  if (document.fonts) {
2660
- await document.fonts.ready;
2673
+ await withFontTimeout(document.fonts.ready, 2500);
2661
2674
  }
2662
- await Promise.all(FONTS_TO_PRELOAD.map((font) => preloadFont(font)));
2675
+ await withFontTimeout(Promise.all(FONTS_TO_PRELOAD.map((font) => preloadFont(font))).then(() => void 0), 5e3);
2663
2676
  if (document.fonts) {
2664
- await document.fonts.ready;
2677
+ await withFontTimeout(document.fonts.ready, 2500);
2665
2678
  }
2666
2679
  fontsLoaded = true;
2667
2680
  })();
@@ -2669,7 +2682,7 @@ const preloadAllFonts = async () => {
2669
2682
  };
2670
2683
  const waitForFontsReady = async () => {
2671
2684
  if (!document.fonts) return;
2672
- await document.fonts.ready;
2685
+ await withFontTimeout(document.fonts.ready, 2500);
2673
2686
  };
2674
2687
  const DEFAULT_FONT_CHECK_TIMEOUT_MS = 3500;
2675
2688
  const FONT_CHECK_POLL_MS = 60;
@@ -11675,6 +11688,19 @@ function normalizeFontFamily(fontStack) {
11675
11688
  }
11676
11689
  const loadedFonts = /* @__PURE__ */ new Set();
11677
11690
  const loadingPromises = /* @__PURE__ */ new Map();
11691
+ async function withTimeout(promise, timeoutMs = 4e3) {
11692
+ let timeoutId;
11693
+ try {
11694
+ return await Promise.race([
11695
+ promise,
11696
+ new Promise((resolve) => {
11697
+ timeoutId = setTimeout(resolve, timeoutMs);
11698
+ })
11699
+ ]);
11700
+ } finally {
11701
+ if (timeoutId) clearTimeout(timeoutId);
11702
+ }
11703
+ }
11678
11704
  async function loadGoogleFontCSS(rawFontFamily) {
11679
11705
  if (!rawFontFamily || typeof document === "undefined") return;
11680
11706
  const fontFamily = normalizeFontFamily(rawFontFamily);
@@ -11696,8 +11722,8 @@ async function loadGoogleFontCSS(rawFontFamily) {
11696
11722
  document.head.appendChild(link);
11697
11723
  });
11698
11724
  if (document.fonts) {
11699
- await document.fonts.load(`16px "${fontFamily}"`);
11700
- await document.fonts.ready;
11725
+ await withTimeout(document.fonts.load(`16px "${fontFamily}"`), 2500);
11726
+ await withTimeout(document.fonts.ready, 2500);
11701
11727
  }
11702
11728
  loadedFonts.add(fontFamily);
11703
11729
  } catch (e) {
@@ -11810,7 +11836,7 @@ async function ensureFontsForResolvedConfig(config) {
11810
11836
  if (typeof document === "undefined") return;
11811
11837
  const descriptors = collectFontDescriptorsFromConfig(config);
11812
11838
  const families = new Set(descriptors.map((d) => d.family));
11813
- await Promise.all([...families].map((f) => loadGoogleFontCSS(f)));
11839
+ await withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 8e3);
11814
11840
  if (document.fonts) {
11815
11841
  const loadPromises = descriptors.map((d) => {
11816
11842
  const stylePrefix = d.style === "italic" ? "italic " : "";
@@ -11819,8 +11845,8 @@ async function ensureFontsForResolvedConfig(config) {
11819
11845
  return document.fonts.load(spec).catch(() => {
11820
11846
  });
11821
11847
  });
11822
- await Promise.all(loadPromises);
11823
- await document.fonts.ready;
11848
+ await withTimeout(Promise.all(loadPromises), 8e3);
11849
+ await withTimeout(document.fonts.ready, 2500);
11824
11850
  }
11825
11851
  }
11826
11852
  function PixldocsPreview(props) {
@@ -11843,6 +11869,7 @@ function PixldocsPreview(props) {
11843
11869
  const [fontsReady, setFontsReady] = useState(false);
11844
11870
  const [fontsReadyVersion, setFontsReadyVersion] = useState(0);
11845
11871
  const [canvasSettled, setCanvasSettled] = useState(false);
11872
+ const [stabilizationPass, setStabilizationPass] = useState(0);
11846
11873
  const isResolveMode = !("config" in props && props.config);
11847
11874
  useEffect(() => {
11848
11875
  if (!isResolveMode) {
@@ -11901,6 +11928,7 @@ function PixldocsPreview(props) {
11901
11928
  if (!config) return;
11902
11929
  let cancelled = false;
11903
11930
  setCanvasSettled(false);
11931
+ setStabilizationPass(0);
11904
11932
  const bump = () => {
11905
11933
  if (cancelled) return;
11906
11934
  clearMeasurementCache();
@@ -11913,22 +11941,32 @@ function PixldocsPreview(props) {
11913
11941
  window.clearTimeout(timeoutId);
11914
11942
  };
11915
11943
  }, [config]);
11916
- const previewKey = useMemo(() => `${pageIndex}-${fontsReadyVersion}`, [pageIndex, fontsReadyVersion]);
11944
+ const previewKey = useMemo(
11945
+ () => `${pageIndex}-${fontsReadyVersion}-${stabilizationPass}`,
11946
+ [pageIndex, fontsReadyVersion, stabilizationPass]
11947
+ );
11917
11948
  useEffect(() => {
11918
11949
  if (isResolveMode) return;
11919
11950
  if (!config) {
11920
11951
  setFontsReady(false);
11921
11952
  setCanvasSettled(false);
11953
+ setStabilizationPass(0);
11922
11954
  return;
11923
11955
  }
11924
11956
  setFontsReady(false);
11925
11957
  setCanvasSettled(false);
11958
+ setStabilizationPass(0);
11926
11959
  ensureFontsForResolvedConfig(config).then(() => setFontsReady(true)).catch(() => setFontsReady(true));
11927
11960
  }, [isResolveMode, config]);
11928
11961
  const handleCanvasReady = useCallback(() => {
11962
+ if (stabilizationPass === 0) {
11963
+ setCanvasSettled(false);
11964
+ setStabilizationPass(1);
11965
+ return;
11966
+ }
11929
11967
  setCanvasSettled(true);
11930
11968
  onReady == null ? void 0 : onReady();
11931
- }, [onReady]);
11969
+ }, [onReady, stabilizationPass]);
11932
11970
  if (isLoading) {
11933
11971
  return /* @__PURE__ */ jsx("div", { className, style: { ...style, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) });
11934
11972
  }
@@ -12342,6 +12380,7 @@ class PixldocsRenderer {
12342
12380
  cleanup();
12343
12381
  reject(new Error("Render timeout (30s)"));
12344
12382
  }, 3e4);
12383
+ let stabilizationPass = 0;
12345
12384
  const cleanup = () => {
12346
12385
  clearTimeout(timeout);
12347
12386
  try {
@@ -12351,6 +12390,19 @@ class PixldocsRenderer {
12351
12390
  container.remove();
12352
12391
  };
12353
12392
  const onReady = () => {
12393
+ if (stabilizationPass === 0) {
12394
+ stabilizationPass = 1;
12395
+ root.render(
12396
+ createElement(PreviewCanvas2, {
12397
+ config,
12398
+ pageIndex,
12399
+ zoom: pixelRatio,
12400
+ absoluteZoom: true,
12401
+ onReady
12402
+ })
12403
+ );
12404
+ return;
12405
+ }
12354
12406
  const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
12355
12407
  this.waitForCanvasImages(container, expectedImageCount).then(async () => {
12356
12408
  try {
@@ -12422,6 +12474,7 @@ class PixldocsRenderer {
12422
12474
  cleanup();
12423
12475
  reject(new Error("SVG render timeout (30s)"));
12424
12476
  }, 3e4);
12477
+ let stabilizationPass = 0;
12425
12478
  const cleanup = () => {
12426
12479
  clearTimeout(timeout);
12427
12480
  try {
@@ -12431,6 +12484,19 @@ class PixldocsRenderer {
12431
12484
  container.remove();
12432
12485
  };
12433
12486
  const onReady = () => {
12487
+ if (stabilizationPass === 0) {
12488
+ stabilizationPass = 1;
12489
+ root.render(
12490
+ createElement(PreviewCanvas2, {
12491
+ config,
12492
+ pageIndex,
12493
+ zoom: 1,
12494
+ absoluteZoom: true,
12495
+ onReady
12496
+ })
12497
+ );
12498
+ return;
12499
+ }
12434
12500
  const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
12435
12501
  this.waitForCanvasImages(container, expectedImageCount).then(async () => {
12436
12502
  var _a, _b;