@pixldocs/canvas-renderer 0.5.491 → 0.5.493

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.
@@ -12079,7 +12079,29 @@ const PageCanvas = react.forwardRef(
12079
12079
  const [rotationLabel, setRotationLabel] = react.useState(null);
12080
12080
  const [sizeLabel, setSizeLabel] = react.useState(null);
12081
12081
  const [ready, setReady] = react.useState(false);
12082
+ const onReadyRef = react.useRef(onReady);
12083
+ const pendingInitialImageLoadsRef = react.useRef(0);
12082
12084
  const [unlockRequestId, setUnlockRequestId] = react.useState(0);
12085
+ react.useEffect(() => {
12086
+ onReadyRef.current = onReady;
12087
+ }, [onReady]);
12088
+ const trackInitialImageLoad = react.useCallback((promise) => {
12089
+ if (hasNotifiedReadyForPageRef.current === pageId) {
12090
+ return;
12091
+ }
12092
+ pendingInitialImageLoadsRef.current += 1;
12093
+ let settled = false;
12094
+ const finish = () => {
12095
+ if (settled) return;
12096
+ settled = true;
12097
+ pendingInitialImageLoadsRef.current = Math.max(0, pendingInitialImageLoadsRef.current - 1);
12098
+ };
12099
+ const timeout = window.setTimeout(finish, 12e3);
12100
+ void promise.finally(() => {
12101
+ window.clearTimeout(timeout);
12102
+ finish();
12103
+ });
12104
+ }, [pageId]);
12083
12105
  const applyLogicalGroupSelectionVisualState = react.useCallback((selection, groupId) => {
12084
12106
  var _a2;
12085
12107
  selection.__pixldocsGroupSelection = groupId;
@@ -12290,7 +12312,23 @@ const PageCanvas = react.forwardRef(
12290
12312
  }, [selectedIds]);
12291
12313
  react.useEffect(() => {
12292
12314
  const fc = fabricRef.current;
12293
- if (!fc || !isActive || !currentPage) return;
12315
+ if (!fc || !currentPage) return;
12316
+ if (!isActive) {
12317
+ try {
12318
+ fc.__activeEditingGroupId = null;
12319
+ drilledGroupIdRef.current = null;
12320
+ setDrilledGroupBounds(null);
12321
+ preserveActiveSelectionAfterTransformRef.current = null;
12322
+ recentGroupSelectionRestoreRef.current = null;
12323
+ if (fc.getActiveObject()) {
12324
+ fc.discardActiveObject();
12325
+ }
12326
+ clearCanvasActiveVisuals(fc);
12327
+ fc.requestRenderAll();
12328
+ } catch {
12329
+ }
12330
+ return;
12331
+ }
12294
12332
  const pageChildren2 = currentPage.children ?? [];
12295
12333
  const hasMissingSelection = selectedIds.some((id) => !findNodeById(pageChildren2, id));
12296
12334
  const activeEditingGroupId = fc.__activeEditingGroupId ?? null;
@@ -17116,6 +17154,10 @@ const PageCanvas = react.forwardRef(
17116
17154
  const innerImg = ct == null ? void 0 : ct._img;
17117
17155
  const innerSrc = ((_a2 = innerImg == null ? void 0 : innerImg.getSrc) == null ? void 0 : _a2.call(innerImg)) || ((_b2 = innerImg == null ? void 0 : innerImg._originalElement) == null ? void 0 : _b2.src) || (innerImg == null ? void 0 : innerImg.src) || "";
17118
17156
  const isPlaceholder = !innerSrc || innerSrc === EMPTY_IMAGE_PLACEHOLDER_DATA_URL;
17157
+ const activatedAt = cropGroupActivatedAtRef.current.get(target) ?? 0;
17158
+ if (Date.now() - activatedAt < 400) {
17159
+ return;
17160
+ }
17119
17161
  const targetId = getObjectId(target);
17120
17162
  const pageChildrenForCrop = ((_c2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c2.children) ?? [];
17121
17163
  const parentForCrop = targetId ? findParentGroup(pageChildrenForCrop, targetId) : null;
@@ -17132,10 +17174,6 @@ const PageCanvas = react.forwardRef(
17132
17174
  }
17133
17175
  return;
17134
17176
  }
17135
- const activatedAt = cropGroupActivatedAtRef.current.get(target) ?? 0;
17136
- if (Date.now() - activatedAt < 400) {
17137
- return;
17138
- }
17139
17177
  }
17140
17178
  if (innerImg && !isPlaceholder && !isCropGroupInCropMode(target)) {
17141
17179
  enterCropMode(target);
@@ -18099,7 +18137,7 @@ const PageCanvas = react.forwardRef(
18099
18137
  placeholder.dirty = true;
18100
18138
  fc.requestRenderAll();
18101
18139
  if (imageUrl) {
18102
- loadImageAsync2(elementForImage, placeholder, fc);
18140
+ trackInitialImageLoad(loadImageAsync2(elementForImage, placeholder, fc));
18103
18141
  }
18104
18142
  } else {
18105
18143
  const resolvedSizeCreate = pageTree.length > 0 ? getNodeBounds(element, pageTree) : { width: typeof element.width === "number" ? element.width : 200, height: typeof element.height === "number" ? element.height : 50 };
@@ -18362,12 +18400,35 @@ const PageCanvas = react.forwardRef(
18362
18400
  }, [allowEditing, isActive, pageId]);
18363
18401
  react.useEffect(() => {
18364
18402
  if (!ready || hasRunPostReadyReflowForPageRef.current === pageId) return;
18365
- hasRunPostReadyReflowForPageRef.current = pageId;
18366
18403
  let cancelled = false;
18404
+ let retryTimer = null;
18405
+ const readyWaitStartedAt = performance.now();
18406
+ const maxAssetWaitMs = 2500;
18407
+ let notifyRaf1 = null;
18408
+ let notifyRaf2 = null;
18367
18409
  const notifyReady = () => {
18368
18410
  if (cancelled || hasNotifiedReadyForPageRef.current === pageId) return;
18369
- hasNotifiedReadyForPageRef.current = pageId;
18370
- onReady == null ? void 0 : onReady();
18411
+ const finishWhenAssetsSettle = () => {
18412
+ if (cancelled || hasNotifiedReadyForPageRef.current === pageId) return;
18413
+ if (pendingInitialImageLoadsRef.current > 0 && performance.now() - readyWaitStartedAt < maxAssetWaitMs) {
18414
+ retryTimer = window.setTimeout(finishWhenAssetsSettle, 50);
18415
+ return;
18416
+ }
18417
+ notifyRaf1 = requestAnimationFrame(() => {
18418
+ notifyRaf2 = requestAnimationFrame(() => {
18419
+ var _a2;
18420
+ if (cancelled || hasNotifiedReadyForPageRef.current === pageId) return;
18421
+ if (pendingInitialImageLoadsRef.current > 0 && performance.now() - readyWaitStartedAt < maxAssetWaitMs) {
18422
+ retryTimer = window.setTimeout(finishWhenAssetsSettle, 50);
18423
+ return;
18424
+ }
18425
+ hasRunPostReadyReflowForPageRef.current = pageId;
18426
+ hasNotifiedReadyForPageRef.current = pageId;
18427
+ (_a2 = onReadyRef.current) == null ? void 0 : _a2.call(onReadyRef);
18428
+ });
18429
+ });
18430
+ };
18431
+ finishWhenAssetsSettle();
18371
18432
  };
18372
18433
  const runReflowAndPersist = () => {
18373
18434
  var _a2;
@@ -18375,37 +18436,42 @@ const PageCanvas = react.forwardRef(
18375
18436
  if (!fc || cancelled) return;
18376
18437
  const state = useEditorStore.getState();
18377
18438
  const repositionTree = isPreviewMode && (pageChildren == null ? void 0 : pageChildren.length) ? pageChildren ?? [] : ((_a2 = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
18378
- runFontReloadAndReflow({
18379
- canvas: fc,
18380
- pageTree: repositionTree,
18381
- pageBoundsOptions,
18382
- preserveGlobalFontCache,
18383
- // Persist measured Textbox sizes back to the editor store. The
18384
- // headless path passes no callback (it has no store to persist into).
18385
- persistTextboxSize: (id, measured, el) => {
18386
- const storeW = el.width ?? 0;
18387
- const storeH = el.height ?? 0;
18388
- const shouldKeepFixedSize = el.overflowPolicy === "auto-shrink";
18389
- const updates = {};
18390
- if (!shouldKeepFixedSize && measured.width > 0 && typeof storeW === "number" && Math.abs(measured.width - storeW) > 0.1) {
18391
- updates.width = measured.width;
18392
- }
18393
- if (shouldKeepFixedSize) {
18394
- if (measured.height > 0 && typeof storeH === "number" && measured.height < storeH - 0.5) updates.height = measured.height;
18395
- } else {
18396
- if (measured.height > 0 && (typeof storeH !== "number" || Math.abs(measured.height - storeH) > 0.1)) updates.height = measured.height;
18397
- }
18398
- if (Object.keys(updates).length > 0) {
18399
- state.updateElement(id, updates, { recordHistory: false, skipLayoutRecalc: true });
18400
- }
18401
- },
18402
- // Rebuild section/background groups before resnapping top-level objects.
18403
- preResnapSync: (isPreviewMode || isExportMode) && doSyncRef.current ? () => {
18404
- var _a3;
18405
- return (_a3 = doSyncRef.current) == null ? void 0 : _a3.call(doSyncRef);
18406
- } : void 0
18407
- });
18439
+ try {
18440
+ runFontReloadAndReflow({
18441
+ canvas: fc,
18442
+ pageTree: repositionTree,
18443
+ pageBoundsOptions,
18444
+ preserveGlobalFontCache,
18445
+ // Persist measured Textbox sizes back to the editor store. The
18446
+ // headless path passes no callback (it has no store to persist into).
18447
+ persistTextboxSize: (id, measured, el) => {
18448
+ const storeW = el.width ?? 0;
18449
+ const storeH = el.height ?? 0;
18450
+ const shouldKeepFixedSize = el.overflowPolicy === "auto-shrink";
18451
+ const updates = {};
18452
+ if (!shouldKeepFixedSize && measured.width > 0 && typeof storeW === "number" && Math.abs(measured.width - storeW) > 0.1) {
18453
+ updates.width = measured.width;
18454
+ }
18455
+ if (shouldKeepFixedSize) {
18456
+ if (measured.height > 0 && typeof storeH === "number" && measured.height < storeH - 0.5) updates.height = measured.height;
18457
+ } else {
18458
+ if (measured.height > 0 && (typeof storeH !== "number" || Math.abs(measured.height - storeH) > 0.1)) updates.height = measured.height;
18459
+ }
18460
+ if (Object.keys(updates).length > 0) {
18461
+ state.updateElement(id, updates, { recordHistory: false, skipLayoutRecalc: true });
18462
+ }
18463
+ },
18464
+ // Rebuild section/background groups before resnapping top-level objects.
18465
+ preResnapSync: (isPreviewMode || isExportMode) && doSyncRef.current ? () => {
18466
+ var _a3;
18467
+ return (_a3 = doSyncRef.current) == null ? void 0 : _a3.call(doSyncRef);
18468
+ } : void 0
18469
+ });
18470
+ } catch (err) {
18471
+ console.warn("[PageCanvas] post-ready reflow failed; continuing canvas ready state", err);
18472
+ }
18408
18473
  };
18474
+ const fallbackTimer = window.setTimeout(notifyReady, 3500);
18409
18475
  const raf1 = requestAnimationFrame(() => {
18410
18476
  requestAnimationFrame(() => {
18411
18477
  if (cancelled) return;
@@ -18421,9 +18487,13 @@ const PageCanvas = react.forwardRef(
18421
18487
  });
18422
18488
  return () => {
18423
18489
  cancelled = true;
18490
+ window.clearTimeout(fallbackTimer);
18424
18491
  cancelAnimationFrame(raf1);
18492
+ if (retryTimer !== null) window.clearTimeout(retryTimer);
18493
+ if (notifyRaf1 !== null) cancelAnimationFrame(notifyRaf1);
18494
+ if (notifyRaf2 !== null) cancelAnimationFrame(notifyRaf2);
18425
18495
  };
18426
- }, [ready, pageId, onReady]);
18496
+ }, [ready, pageId]);
18427
18497
  react.useEffect(() => {
18428
18498
  var _a2;
18429
18499
  const fc = fabricRef.current;
@@ -22006,7 +22076,6 @@ function applyFormDataToConfig(config, mappings, formValues, repeatableSectionsF
22006
22076
  return void 0;
22007
22077
  }
22008
22078
  const applyValue = (elementId, targetProperty, value, fieldKey, svgColorKey) => {
22009
- var _a3;
22010
22079
  const isTextLike = targetProperty === "text" || targetProperty === "content";
22011
22080
  const isImageLike = targetProperty === "src" || targetProperty === "imageUrl";
22012
22081
  if (value === void 0 || value === null) {
@@ -22032,19 +22101,32 @@ function applyFormDataToConfig(config, mappings, formValues, repeatableSectionsF
22032
22101
  }
22033
22102
  }
22034
22103
  if (elementId === PAGE_BACKGROUND_ELEMENT_ID && targetProperty === "backgroundColor") {
22035
- if ((_a3 = pages[0]) == null ? void 0 : _a3.settings) {
22036
- const settings = pages[0].settings;
22104
+ let applied = false;
22105
+ const hasExplicitBg = (settings) => {
22106
+ const raw = settings.backgroundColor;
22107
+ if (typeof raw !== "string") return false;
22108
+ const trimmed = raw.trim().toLowerCase();
22109
+ if (!trimmed) return false;
22110
+ if (trimmed === "transparent" || trimmed === "none") return false;
22111
+ return true;
22112
+ };
22113
+ for (const page of pages) {
22114
+ if (!page.settings) continue;
22115
+ const settings = page.settings;
22116
+ if (hasExplicitBg(settings) && !("backgroundGradient" in settings)) continue;
22037
22117
  if (isGradientConfig(effectiveValue)) {
22038
22118
  settings.backgroundGradient = effectiveValue;
22039
22119
  settings.backgroundColor = "";
22040
- return true;
22120
+ applied = true;
22121
+ continue;
22041
22122
  }
22042
22123
  if (typeof effectiveValue === "string") {
22043
22124
  if ("backgroundGradient" in settings) delete settings.backgroundGradient;
22044
22125
  settings.backgroundColor = effectiveValue;
22045
- return true;
22126
+ applied = true;
22046
22127
  }
22047
22128
  }
22129
+ if (applied) return true;
22048
22130
  }
22049
22131
  for (const page of pages) {
22050
22132
  if (page.children && setInTree(page.children, elementId, targetProperty, effectiveValue, svgColorKey)) return true;
@@ -25759,7 +25841,19 @@ function PixldocsPreview(props) {
25759
25841
  isResolveMode ? props.themeId : void 0
25760
25842
  ]);
25761
25843
  const config = isResolveMode ? resolvedConfig : props.config;
25762
- const previewKey = react.useMemo(() => `${pageIndex}`, [pageIndex]);
25844
+ const previewKey = react.useMemo(() => {
25845
+ var _a3, _b3;
25846
+ const page = (_a3 = config == null ? void 0 : config.pages) == null ? void 0 : _a3[pageIndex];
25847
+ const settings = (page == null ? void 0 : page.settings) ?? {};
25848
+ const gradientSignature = settings.backgroundGradient ? JSON.stringify(settings.backgroundGradient) : "";
25849
+ return [
25850
+ pageIndex,
25851
+ (page == null ? void 0 : page.id) ?? "page",
25852
+ settings.backgroundColor ?? "",
25853
+ gradientSignature,
25854
+ ((_b3 = page == null ? void 0 : page.children) == null ? void 0 : _b3.length) ?? 0
25855
+ ].join("|");
25856
+ }, [config, pageIndex]);
25763
25857
  const fontSignature = react.useMemo(() => computeFontSignature(config), [config]);
25764
25858
  const imageSignature = react.useMemo(() => computeImageSignature(config), [config]);
25765
25859
  const [imagesReady, setImagesReady] = react.useState(true);
@@ -26442,9 +26536,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
26442
26536
  }
26443
26537
  return svgString;
26444
26538
  }
26445
- const resolvedPackageVersion = "0.5.491";
26539
+ const resolvedPackageVersion = "0.5.493";
26446
26540
  const PACKAGE_VERSION = resolvedPackageVersion;
26447
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.491";
26541
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.493";
26448
26542
  const roundParityValue = (value) => {
26449
26543
  if (typeof value !== "number") return value;
26450
26544
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -27258,7 +27352,7 @@ class PixldocsRenderer {
27258
27352
  await this.waitForCanvasScene(container, cloned, i);
27259
27353
  }
27260
27354
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
27261
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BWUlBEaK.cjs"));
27355
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-obFAiUhx.cjs"));
27262
27356
  const prepared = preparePagesForExport(
27263
27357
  cloned.pages,
27264
27358
  canvasWidth,
@@ -29578,7 +29672,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
29578
29672
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
29579
29673
  sanitizeSvgTreeForPdf(svgToDraw);
29580
29674
  try {
29581
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BWUlBEaK.cjs"));
29675
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-obFAiUhx.cjs"));
29582
29676
  try {
29583
29677
  await logTextMeasurementDiagnostic(svgToDraw);
29584
29678
  } catch {
@@ -29892,4 +29986,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
29892
29986
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
29893
29987
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
29894
29988
  exports.warmTemplateFromForm = warmTemplateFromForm;
29895
- //# sourceMappingURL=index-sfUNqu61.cjs.map
29989
+ //# sourceMappingURL=index-CapZsm7x.cjs.map