@pixldocs/canvas-renderer 0.5.490 → 0.5.492

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.
@@ -3,7 +3,7 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  var _a, _b, _c;
5
5
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
6
- import { forwardRef, useRef, useState, useCallback, useMemo, useEffect, useImperativeHandle, createElement } from "react";
6
+ import { forwardRef, useRef, useState, useEffect, useCallback, useMemo, useImperativeHandle, createElement } from "react";
7
7
  import { flushSync } from "react-dom";
8
8
  import { toast } from "sonner";
9
9
  import { create } from "zustand";
@@ -12061,7 +12061,29 @@ const PageCanvas = forwardRef(
12061
12061
  const [rotationLabel, setRotationLabel] = useState(null);
12062
12062
  const [sizeLabel, setSizeLabel] = useState(null);
12063
12063
  const [ready, setReady] = useState(false);
12064
+ const onReadyRef = useRef(onReady);
12065
+ const pendingInitialImageLoadsRef = useRef(0);
12064
12066
  const [unlockRequestId, setUnlockRequestId] = useState(0);
12067
+ useEffect(() => {
12068
+ onReadyRef.current = onReady;
12069
+ }, [onReady]);
12070
+ const trackInitialImageLoad = useCallback((promise) => {
12071
+ if (hasNotifiedReadyForPageRef.current === pageId) {
12072
+ return;
12073
+ }
12074
+ pendingInitialImageLoadsRef.current += 1;
12075
+ let settled = false;
12076
+ const finish = () => {
12077
+ if (settled) return;
12078
+ settled = true;
12079
+ pendingInitialImageLoadsRef.current = Math.max(0, pendingInitialImageLoadsRef.current - 1);
12080
+ };
12081
+ const timeout = window.setTimeout(finish, 12e3);
12082
+ void promise.finally(() => {
12083
+ window.clearTimeout(timeout);
12084
+ finish();
12085
+ });
12086
+ }, [pageId]);
12065
12087
  const applyLogicalGroupSelectionVisualState = useCallback((selection, groupId) => {
12066
12088
  var _a2;
12067
12089
  selection.__pixldocsGroupSelection = groupId;
@@ -17233,15 +17255,13 @@ const PageCanvas = forwardRef(
17233
17255
  }
17234
17256
  updateElement(elementId, {
17235
17257
  text: newText,
17236
- ...typeof nextHeight === "number" && nextHeight > 0 && { height: nextHeight },
17237
- ...target.styles && Object.keys(target.styles).length > 0 ? { styles: JSON.parse(JSON.stringify(target.styles)) } : {}
17258
+ ...typeof nextHeight === "number" && nextHeight > 0 && { height: nextHeight }
17238
17259
  });
17239
17260
  } else {
17240
17261
  updateElement(elementId, {
17241
17262
  text: newText,
17242
17263
  ...fabricHeight > 0 && { height: fabricHeight },
17243
- ...fabricWidth > 0 && { width: fabricWidth },
17244
- ...target.styles && Object.keys(target.styles).length > 0 ? { styles: JSON.parse(JSON.stringify(target.styles)) } : {}
17264
+ ...fabricWidth > 0 && { width: fabricWidth }
17245
17265
  });
17246
17266
  }
17247
17267
  commitHistory2();
@@ -18083,7 +18103,7 @@ const PageCanvas = forwardRef(
18083
18103
  placeholder.dirty = true;
18084
18104
  fc.requestRenderAll();
18085
18105
  if (imageUrl) {
18086
- loadImageAsync2(elementForImage, placeholder, fc);
18106
+ trackInitialImageLoad(loadImageAsync2(elementForImage, placeholder, fc));
18087
18107
  }
18088
18108
  } else {
18089
18109
  const resolvedSizeCreate = pageTree.length > 0 ? getNodeBounds(element, pageTree) : { width: typeof element.width === "number" ? element.width : 200, height: typeof element.height === "number" ? element.height : 50 };
@@ -18346,12 +18366,35 @@ const PageCanvas = forwardRef(
18346
18366
  }, [allowEditing, isActive, pageId]);
18347
18367
  useEffect(() => {
18348
18368
  if (!ready || hasRunPostReadyReflowForPageRef.current === pageId) return;
18349
- hasRunPostReadyReflowForPageRef.current = pageId;
18350
18369
  let cancelled = false;
18370
+ let retryTimer = null;
18371
+ const readyWaitStartedAt = performance.now();
18372
+ const maxAssetWaitMs = 2500;
18373
+ let notifyRaf1 = null;
18374
+ let notifyRaf2 = null;
18351
18375
  const notifyReady = () => {
18352
18376
  if (cancelled || hasNotifiedReadyForPageRef.current === pageId) return;
18353
- hasNotifiedReadyForPageRef.current = pageId;
18354
- onReady == null ? void 0 : onReady();
18377
+ const finishWhenAssetsSettle = () => {
18378
+ if (cancelled || hasNotifiedReadyForPageRef.current === pageId) return;
18379
+ if (pendingInitialImageLoadsRef.current > 0 && performance.now() - readyWaitStartedAt < maxAssetWaitMs) {
18380
+ retryTimer = window.setTimeout(finishWhenAssetsSettle, 50);
18381
+ return;
18382
+ }
18383
+ notifyRaf1 = requestAnimationFrame(() => {
18384
+ notifyRaf2 = requestAnimationFrame(() => {
18385
+ var _a2;
18386
+ if (cancelled || hasNotifiedReadyForPageRef.current === pageId) return;
18387
+ if (pendingInitialImageLoadsRef.current > 0 && performance.now() - readyWaitStartedAt < maxAssetWaitMs) {
18388
+ retryTimer = window.setTimeout(finishWhenAssetsSettle, 50);
18389
+ return;
18390
+ }
18391
+ hasRunPostReadyReflowForPageRef.current = pageId;
18392
+ hasNotifiedReadyForPageRef.current = pageId;
18393
+ (_a2 = onReadyRef.current) == null ? void 0 : _a2.call(onReadyRef);
18394
+ });
18395
+ });
18396
+ };
18397
+ finishWhenAssetsSettle();
18355
18398
  };
18356
18399
  const runReflowAndPersist = () => {
18357
18400
  var _a2;
@@ -18359,37 +18402,42 @@ const PageCanvas = forwardRef(
18359
18402
  if (!fc || cancelled) return;
18360
18403
  const state = useEditorStore.getState();
18361
18404
  const repositionTree = isPreviewMode && (pageChildren == null ? void 0 : pageChildren.length) ? pageChildren ?? [] : ((_a2 = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
18362
- runFontReloadAndReflow({
18363
- canvas: fc,
18364
- pageTree: repositionTree,
18365
- pageBoundsOptions,
18366
- preserveGlobalFontCache,
18367
- // Persist measured Textbox sizes back to the editor store. The
18368
- // headless path passes no callback (it has no store to persist into).
18369
- persistTextboxSize: (id, measured, el) => {
18370
- const storeW = el.width ?? 0;
18371
- const storeH = el.height ?? 0;
18372
- const shouldKeepFixedSize = el.overflowPolicy === "auto-shrink";
18373
- const updates = {};
18374
- if (!shouldKeepFixedSize && measured.width > 0 && typeof storeW === "number" && Math.abs(measured.width - storeW) > 0.1) {
18375
- updates.width = measured.width;
18376
- }
18377
- if (shouldKeepFixedSize) {
18378
- if (measured.height > 0 && typeof storeH === "number" && measured.height < storeH - 0.5) updates.height = measured.height;
18379
- } else {
18380
- if (measured.height > 0 && (typeof storeH !== "number" || Math.abs(measured.height - storeH) > 0.1)) updates.height = measured.height;
18381
- }
18382
- if (Object.keys(updates).length > 0) {
18383
- state.updateElement(id, updates, { recordHistory: false, skipLayoutRecalc: true });
18384
- }
18385
- },
18386
- // Rebuild section/background groups before resnapping top-level objects.
18387
- preResnapSync: (isPreviewMode || isExportMode) && doSyncRef.current ? () => {
18388
- var _a3;
18389
- return (_a3 = doSyncRef.current) == null ? void 0 : _a3.call(doSyncRef);
18390
- } : void 0
18391
- });
18405
+ try {
18406
+ runFontReloadAndReflow({
18407
+ canvas: fc,
18408
+ pageTree: repositionTree,
18409
+ pageBoundsOptions,
18410
+ preserveGlobalFontCache,
18411
+ // Persist measured Textbox sizes back to the editor store. The
18412
+ // headless path passes no callback (it has no store to persist into).
18413
+ persistTextboxSize: (id, measured, el) => {
18414
+ const storeW = el.width ?? 0;
18415
+ const storeH = el.height ?? 0;
18416
+ const shouldKeepFixedSize = el.overflowPolicy === "auto-shrink";
18417
+ const updates = {};
18418
+ if (!shouldKeepFixedSize && measured.width > 0 && typeof storeW === "number" && Math.abs(measured.width - storeW) > 0.1) {
18419
+ updates.width = measured.width;
18420
+ }
18421
+ if (shouldKeepFixedSize) {
18422
+ if (measured.height > 0 && typeof storeH === "number" && measured.height < storeH - 0.5) updates.height = measured.height;
18423
+ } else {
18424
+ if (measured.height > 0 && (typeof storeH !== "number" || Math.abs(measured.height - storeH) > 0.1)) updates.height = measured.height;
18425
+ }
18426
+ if (Object.keys(updates).length > 0) {
18427
+ state.updateElement(id, updates, { recordHistory: false, skipLayoutRecalc: true });
18428
+ }
18429
+ },
18430
+ // Rebuild section/background groups before resnapping top-level objects.
18431
+ preResnapSync: (isPreviewMode || isExportMode) && doSyncRef.current ? () => {
18432
+ var _a3;
18433
+ return (_a3 = doSyncRef.current) == null ? void 0 : _a3.call(doSyncRef);
18434
+ } : void 0
18435
+ });
18436
+ } catch (err) {
18437
+ console.warn("[PageCanvas] post-ready reflow failed; continuing canvas ready state", err);
18438
+ }
18392
18439
  };
18440
+ const fallbackTimer = window.setTimeout(notifyReady, 3500);
18393
18441
  const raf1 = requestAnimationFrame(() => {
18394
18442
  requestAnimationFrame(() => {
18395
18443
  if (cancelled) return;
@@ -18405,9 +18453,13 @@ const PageCanvas = forwardRef(
18405
18453
  });
18406
18454
  return () => {
18407
18455
  cancelled = true;
18456
+ window.clearTimeout(fallbackTimer);
18408
18457
  cancelAnimationFrame(raf1);
18458
+ if (retryTimer !== null) window.clearTimeout(retryTimer);
18459
+ if (notifyRaf1 !== null) cancelAnimationFrame(notifyRaf1);
18460
+ if (notifyRaf2 !== null) cancelAnimationFrame(notifyRaf2);
18409
18461
  };
18410
- }, [ready, pageId, onReady]);
18462
+ }, [ready, pageId]);
18411
18463
  useEffect(() => {
18412
18464
  var _a2;
18413
18465
  const fc = fabricRef.current;
@@ -21990,7 +22042,6 @@ function applyFormDataToConfig(config, mappings, formValues, repeatableSectionsF
21990
22042
  return void 0;
21991
22043
  }
21992
22044
  const applyValue = (elementId, targetProperty, value, fieldKey, svgColorKey) => {
21993
- var _a3;
21994
22045
  const isTextLike = targetProperty === "text" || targetProperty === "content";
21995
22046
  const isImageLike = targetProperty === "src" || targetProperty === "imageUrl";
21996
22047
  if (value === void 0 || value === null) {
@@ -22016,19 +22067,32 @@ function applyFormDataToConfig(config, mappings, formValues, repeatableSectionsF
22016
22067
  }
22017
22068
  }
22018
22069
  if (elementId === PAGE_BACKGROUND_ELEMENT_ID && targetProperty === "backgroundColor") {
22019
- if ((_a3 = pages[0]) == null ? void 0 : _a3.settings) {
22020
- const settings = pages[0].settings;
22070
+ let applied = false;
22071
+ const hasExplicitBg = (settings) => {
22072
+ const raw = settings.backgroundColor;
22073
+ if (typeof raw !== "string") return false;
22074
+ const trimmed = raw.trim().toLowerCase();
22075
+ if (!trimmed) return false;
22076
+ if (trimmed === "transparent" || trimmed === "none") return false;
22077
+ return true;
22078
+ };
22079
+ for (const page of pages) {
22080
+ if (!page.settings) continue;
22081
+ const settings = page.settings;
22082
+ if (hasExplicitBg(settings) && !("backgroundGradient" in settings)) continue;
22021
22083
  if (isGradientConfig(effectiveValue)) {
22022
22084
  settings.backgroundGradient = effectiveValue;
22023
22085
  settings.backgroundColor = "";
22024
- return true;
22086
+ applied = true;
22087
+ continue;
22025
22088
  }
22026
22089
  if (typeof effectiveValue === "string") {
22027
22090
  if ("backgroundGradient" in settings) delete settings.backgroundGradient;
22028
22091
  settings.backgroundColor = effectiveValue;
22029
- return true;
22092
+ applied = true;
22030
22093
  }
22031
22094
  }
22095
+ if (applied) return true;
22032
22096
  }
22033
22097
  for (const page of pages) {
22034
22098
  if (page.children && setInTree(page.children, elementId, targetProperty, effectiveValue, svgColorKey)) return true;
@@ -25743,7 +25807,19 @@ function PixldocsPreview(props) {
25743
25807
  isResolveMode ? props.themeId : void 0
25744
25808
  ]);
25745
25809
  const config = isResolveMode ? resolvedConfig : props.config;
25746
- const previewKey = useMemo(() => `${pageIndex}`, [pageIndex]);
25810
+ const previewKey = useMemo(() => {
25811
+ var _a3, _b3;
25812
+ const page = (_a3 = config == null ? void 0 : config.pages) == null ? void 0 : _a3[pageIndex];
25813
+ const settings = (page == null ? void 0 : page.settings) ?? {};
25814
+ const gradientSignature = settings.backgroundGradient ? JSON.stringify(settings.backgroundGradient) : "";
25815
+ return [
25816
+ pageIndex,
25817
+ (page == null ? void 0 : page.id) ?? "page",
25818
+ settings.backgroundColor ?? "",
25819
+ gradientSignature,
25820
+ ((_b3 = page == null ? void 0 : page.children) == null ? void 0 : _b3.length) ?? 0
25821
+ ].join("|");
25822
+ }, [config, pageIndex]);
25747
25823
  const fontSignature = useMemo(() => computeFontSignature(config), [config]);
25748
25824
  const imageSignature = useMemo(() => computeImageSignature(config), [config]);
25749
25825
  const [imagesReady, setImagesReady] = useState(true);
@@ -26426,9 +26502,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
26426
26502
  }
26427
26503
  return svgString;
26428
26504
  }
26429
- const resolvedPackageVersion = "0.5.490";
26505
+ const resolvedPackageVersion = "0.5.492";
26430
26506
  const PACKAGE_VERSION = resolvedPackageVersion;
26431
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.490";
26507
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.492";
26432
26508
  const roundParityValue = (value) => {
26433
26509
  if (typeof value !== "number") return value;
26434
26510
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -27242,7 +27318,7 @@ class PixldocsRenderer {
27242
27318
  await this.waitForCanvasScene(container, cloned, i);
27243
27319
  }
27244
27320
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
27245
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-f828EcQ6.js");
27321
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-rz4LyyuM.js");
27246
27322
  const prepared = preparePagesForExport(
27247
27323
  cloned.pages,
27248
27324
  canvasWidth,
@@ -29562,7 +29638,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
29562
29638
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
29563
29639
  sanitizeSvgTreeForPdf(svgToDraw);
29564
29640
  try {
29565
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-f828EcQ6.js");
29641
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-rz4LyyuM.js");
29566
29642
  try {
29567
29643
  await logTextMeasurementDiagnostic(svgToDraw);
29568
29644
  } catch {
@@ -29879,4 +29955,4 @@ export {
29879
29955
  buildTeaserBlurFlatKeys as y,
29880
29956
  collectFontDescriptorsFromConfig as z
29881
29957
  };
29882
- //# sourceMappingURL=index-xazc-CdA.js.map
29958
+ //# sourceMappingURL=index-DHzIvJSN.js.map