@pixldocs/canvas-renderer 0.5.396 → 0.5.398

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.
@@ -10592,6 +10592,56 @@ const collectFabricObjectWorldPoints = (objects) => {
10592
10592
  }
10593
10593
  return points;
10594
10594
  };
10595
+ const collectFabricObjectWorldCenters = (objects) => {
10596
+ var _a2;
10597
+ const centers = [];
10598
+ for (const obj of objects) {
10599
+ try {
10600
+ obj.setCoords();
10601
+ } catch {
10602
+ }
10603
+ const coords = typeof obj.getCoords === "function" ? obj.getCoords() : null;
10604
+ if (Array.isArray(coords) && coords.length >= 4) {
10605
+ const pts = coords.slice(0, 4).map((p) => ({ x: Number(p.x), y: Number(p.y) })).filter((p) => Number.isFinite(p.x) && Number.isFinite(p.y));
10606
+ if (pts.length) centers.push({ x: pts.reduce((sum, p) => sum + p.x, 0) / pts.length, y: pts.reduce((sum, p) => sum + p.y, 0) / pts.length });
10607
+ continue;
10608
+ }
10609
+ try {
10610
+ const center = (_a2 = obj.getCenterPoint) == null ? void 0 : _a2.call(obj);
10611
+ if (center && Number.isFinite(center.x) && Number.isFinite(center.y)) centers.push({ x: center.x, y: center.y });
10612
+ } catch {
10613
+ }
10614
+ }
10615
+ return centers;
10616
+ };
10617
+ const logicalFrameContainsWorldCenters = (frame, angle, centers) => {
10618
+ if (!isValidLogicalGroupFrame(frame) || centers.length === 0) return true;
10619
+ const a = typeof angle === "number" && Number.isFinite(angle) ? normalizeAngle180(angle) : 0;
10620
+ const cx = frame.left + frame.width / 2;
10621
+ const cy = frame.top + frame.height / 2;
10622
+ const rad = -a * Math.PI / 180;
10623
+ const c = Math.cos(rad);
10624
+ const s = Math.sin(rad);
10625
+ const tolerance = Math.max(8, Math.min(frame.width, frame.height) * 0.08);
10626
+ return centers.every((p) => {
10627
+ const dx = p.x - cx;
10628
+ const dy = p.y - cy;
10629
+ const localX = cx + dx * c - dy * s;
10630
+ const localY = cy + dx * s + dy * c;
10631
+ return localX >= frame.left - tolerance && localX <= frame.left + frame.width + tolerance && localY >= frame.top - tolerance && localY <= frame.top + frame.height + tolerance;
10632
+ });
10633
+ };
10634
+ const shouldRepairUnrotatedLogicalGroupFrame = (storedFrame, contentFrame, angle) => {
10635
+ if (!isValidLogicalGroupFrame(storedFrame) || !isValidLogicalGroupFrame(contentFrame)) return false;
10636
+ if (Math.abs(normalizeAngle180(typeof angle === "number" && Number.isFinite(angle) ? angle : 0)) > 0.5) return false;
10637
+ const storedArea = storedFrame.width * storedFrame.height;
10638
+ const contentArea = contentFrame.width * contentFrame.height;
10639
+ const areaRatio = storedArea / Math.max(1, contentArea);
10640
+ const dx = Math.abs(storedFrame.left + storedFrame.width / 2 - (contentFrame.left + contentFrame.width / 2));
10641
+ const dy = Math.abs(storedFrame.top + storedFrame.height / 2 - (contentFrame.top + contentFrame.height / 2));
10642
+ const driftTolerance = Math.max(12, Math.min(storedFrame.width, storedFrame.height) * 0.08);
10643
+ return areaRatio > 1.35 || dx > driftTolerance || dy > driftTolerance;
10644
+ };
10595
10645
  let ensureCanvaControlRenders = () => {
10596
10646
  };
10597
10647
  try {
@@ -11585,13 +11635,40 @@ function applyWarpAwareSelectionBorders(selection, preferredGroupAngle, preferre
11585
11635
  for (const b of buckets) b.area = orientedAreaForAngle(b.angle);
11586
11636
  buckets.sort((a, b) => b.count - a.count || a.area - b.area || Math.abs(b.angle) - Math.abs(a.angle));
11587
11637
  const dominant = buckets[0];
11588
- const rawPreferredGroupAngle = typeof preferredGroupAngle === "number" && Number.isFinite(preferredGroupAngle) ? preferredGroupAngle : typeof selection.__pixldocsGroupAngle === "number" && Number.isFinite(selection.__pixldocsGroupAngle) ? selection.__pixldocsGroupAngle : null;
11638
+ let effectivePreferredGroupAngle = preferredGroupAngle;
11639
+ let effectivePreferredGroupFrame = preferredGroupFrame;
11640
+ const logicalGroupId = selection.__pixldocsGroupSelection;
11641
+ if (logicalGroupId && (!(typeof effectivePreferredGroupAngle === "number" && Number.isFinite(effectivePreferredGroupAngle)) || !isValidLogicalGroupFrame(effectivePreferredGroupFrame))) {
11642
+ try {
11643
+ const stateNow = useEditorStore.getState();
11644
+ const pageNow = stateNow.canvas.pages.find((p) => p.id === stateNow.canvas.currentPageId);
11645
+ const groupNode = pageNow ? findNodeById(pageNow.children ?? [], logicalGroupId) : null;
11646
+ if (groupNode && isGroup(groupNode)) {
11647
+ if (!(typeof effectivePreferredGroupAngle === "number" && Number.isFinite(effectivePreferredGroupAngle)) && typeof groupNode.angle === "number") {
11648
+ effectivePreferredGroupAngle = groupNode.angle;
11649
+ }
11650
+ if (!isValidLogicalGroupFrame(effectivePreferredGroupFrame)) {
11651
+ effectivePreferredGroupFrame = frameFromStoredGroupNode(groupNode, (pageNow == null ? void 0 : pageNow.children) ?? []);
11652
+ }
11653
+ }
11654
+ } catch {
11655
+ }
11656
+ }
11657
+ const rawPreferredGroupAngle = typeof effectivePreferredGroupAngle === "number" && Number.isFinite(effectivePreferredGroupAngle) ? effectivePreferredGroupAngle : typeof selection.__pixldocsGroupAngle === "number" && Number.isFinite(selection.__pixldocsGroupAngle) ? selection.__pixldocsGroupAngle : null;
11589
11658
  const preferredAngle = rawPreferredGroupAngle != null ? normalizeAngle180(rawPreferredGroupAngle) : null;
11590
11659
  let targetAngle = preferredAngle;
11591
- const isLogicalGroupSelection = !!selection.__pixldocsGroupSelection;
11660
+ const isLogicalGroupSelection = !!logicalGroupId;
11592
11661
  if (targetAngle == null && dominant && Math.abs(dominant.angle) > 0.5 && (isLogicalGroupSelection || kids.length === 1 || dominant.count >= 2 || dominant.count === kids.length)) {
11593
11662
  targetAngle = dominant.angle;
11594
11663
  }
11664
+ if (isLogicalGroupSelection && isValidLogicalGroupFrame(effectivePreferredGroupFrame) && targetAngle != null) {
11665
+ const contentFrame = orientedFrameFromWorldPoints(worldPoints, targetAngle);
11666
+ if (shouldRepairUnrotatedLogicalGroupFrame(effectivePreferredGroupFrame, contentFrame, targetAngle)) {
11667
+ effectivePreferredGroupFrame = contentFrame;
11668
+ } else if (!logicalFrameContainsWorldCenters(effectivePreferredGroupFrame, targetAngle, collectFabricObjectWorldCenters(kids))) {
11669
+ effectivePreferredGroupFrame = null;
11670
+ }
11671
+ }
11595
11672
  if (targetAngle != null) {
11596
11673
  const restoreKidsFromWorld = () => {
11597
11674
  const invSelection = fabric__namespace.util.invertTransform(
@@ -11630,7 +11707,7 @@ function applyWarpAwareSelectionBorders(selection, preferredGroupAngle, preferre
11630
11707
  targetAngle,
11631
11708
  worldAngles
11632
11709
  });
11633
- const fixedFrame = preferredGroupFrame && Number.isFinite(preferredGroupFrame.left) && Number.isFinite(preferredGroupFrame.top) && Number.isFinite(preferredGroupFrame.width) && preferredGroupFrame.width > 0 && Number.isFinite(preferredGroupFrame.height) && preferredGroupFrame.height > 0 ? preferredGroupFrame : null;
11710
+ const fixedFrame = effectivePreferredGroupFrame && Number.isFinite(effectivePreferredGroupFrame.left) && Number.isFinite(effectivePreferredGroupFrame.top) && Number.isFinite(effectivePreferredGroupFrame.width) && effectivePreferredGroupFrame.width > 0 && Number.isFinite(effectivePreferredGroupFrame.height) && effectivePreferredGroupFrame.height > 0 ? effectivePreferredGroupFrame : null;
11634
11711
  selection.set({ angle: targetAngle, scaleX: 1, scaleY: 1, skewX: 0, skewY: 0 });
11635
11712
  if (fixedFrame) {
11636
11713
  selection.set({ width: fixedFrame.width, height: fixedFrame.height, originX: "center", originY: "center" });
@@ -11780,35 +11857,17 @@ const PageCanvas = react.forwardRef(
11780
11857
  }
11781
11858
  }
11782
11859
  let groupFrame = groupNode && isGroup(groupNode) ? frameFromStoredGroupNode(groupNode, (pageNow == null ? void 0 : pageNow.children) ?? []) : null;
11783
- let groupFrameWasInferred = false;
11784
- if (!groupFrame && groupNode && isGroup(groupNode) && typeof groupAngle === "number" && Number.isFinite(groupAngle)) {
11785
- groupFrame = orientedFrameFromWorldPoints(collectFabricObjectWorldPoints(members), normalizeAngle180(groupAngle));
11786
- groupFrameWasInferred = isValidLogicalGroupFrame(groupFrame);
11860
+ const memberWorldPoints = collectFabricObjectWorldPoints(members);
11861
+ const memberWorldCenters = collectFabricObjectWorldCenters(members);
11862
+ const contentFrame = typeof groupAngle === "number" && Number.isFinite(groupAngle) ? orientedFrameFromWorldPoints(memberWorldPoints, normalizeAngle180(groupAngle)) : null;
11863
+ if (shouldRepairUnrotatedLogicalGroupFrame(groupFrame, contentFrame, groupAngle)) {
11864
+ groupFrame = contentFrame;
11865
+ } else if (groupFrame && !logicalFrameContainsWorldCenters(groupFrame, groupAngle, memberWorldCenters)) {
11866
+ groupFrame = null;
11787
11867
  }
11788
- if (groupNode && isGroup(groupNode)) {
11789
- const updates = {};
11790
- if (typeof groupAngle === "number" && Number.isFinite(groupAngle)) {
11791
- const prevAngle = typeof groupNode.angle === "number" ? groupNode.angle : void 0;
11792
- if (prevAngle === void 0 || Math.abs(normalizeAngle180(prevAngle - groupAngle)) > 0.01) {
11793
- updates.angle = normalizeAngle180(groupAngle);
11794
- }
11795
- }
11796
- if (isValidLogicalGroupFrame(groupFrame)) {
11797
- const prevW = Number(groupNode.width);
11798
- const prevH = Number(groupNode.height);
11799
- if (!Number.isFinite(prevW) || Math.abs(prevW - groupFrame.width) > 0.5) updates.width = groupFrame.width;
11800
- if (!Number.isFinite(prevH) || Math.abs(prevH - groupFrame.height) > 0.5) updates.height = groupFrame.height;
11801
- if (groupFrameWasInferred) {
11802
- const storePos = absoluteToStorePosition(groupFrame.left, groupFrame.top, groupId, (pageNow == null ? void 0 : pageNow.children) ?? []);
11803
- const prevLeft = Number(groupNode.left ?? 0);
11804
- const prevTop = Number(groupNode.top ?? 0);
11805
- if (!Number.isFinite(prevLeft) || Math.abs(prevLeft - storePos.left) > 0.5) updates.left = storePos.left;
11806
- if (!Number.isFinite(prevTop) || Math.abs(prevTop - storePos.top) > 0.5) updates.top = storePos.top;
11807
- }
11808
- }
11809
- if (Object.keys(updates).length > 0) {
11810
- useEditorStore.getState().updateNode(groupId, updates, { recordHistory: false, skipLayoutRecalc: true });
11811
- }
11868
+ if (!groupFrame && groupNode && isGroup(groupNode) && typeof groupAngle === "number" && Number.isFinite(groupAngle)) {
11869
+ groupFrame = contentFrame ?? orientedFrameFromWorldPoints(memberWorldPoints, normalizeAngle180(groupAngle));
11870
+ isValidLogicalGroupFrame(groupFrame);
11812
11871
  }
11813
11872
  if (groupAngle !== void 0) {
11814
11873
  selection.__pixldocsGroupAngle = groupAngle;
@@ -25351,9 +25410,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
25351
25410
  }
25352
25411
  return svgString;
25353
25412
  }
25354
- const resolvedPackageVersion = "0.5.396";
25413
+ const resolvedPackageVersion = "0.5.398";
25355
25414
  const PACKAGE_VERSION = resolvedPackageVersion;
25356
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.396";
25415
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.398";
25357
25416
  const roundParityValue = (value) => {
25358
25417
  if (typeof value !== "number") return value;
25359
25418
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -26167,7 +26226,7 @@ class PixldocsRenderer {
26167
26226
  await this.waitForCanvasScene(container, cloned, i);
26168
26227
  }
26169
26228
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
26170
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-oL70Zv8c.cjs"));
26229
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-nSxpHANQ.cjs"));
26171
26230
  const prepared = preparePagesForExport(
26172
26231
  cloned.pages,
26173
26232
  canvasWidth,
@@ -28487,7 +28546,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
28487
28546
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
28488
28547
  sanitizeSvgTreeForPdf(svgToDraw);
28489
28548
  try {
28490
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-oL70Zv8c.cjs"));
28549
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-nSxpHANQ.cjs"));
28491
28550
  try {
28492
28551
  await logTextMeasurementDiagnostic(svgToDraw);
28493
28552
  } catch {
@@ -28884,4 +28943,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
28884
28943
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
28885
28944
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
28886
28945
  exports.warmTemplateFromForm = warmTemplateFromForm;
28887
- //# sourceMappingURL=index-DQYnrYMM.cjs.map
28946
+ //# sourceMappingURL=index-YhKOXBPt.cjs.map