@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.
@@ -10574,6 +10574,56 @@ const collectFabricObjectWorldPoints = (objects) => {
10574
10574
  }
10575
10575
  return points;
10576
10576
  };
10577
+ const collectFabricObjectWorldCenters = (objects) => {
10578
+ var _a2;
10579
+ const centers = [];
10580
+ for (const obj of objects) {
10581
+ try {
10582
+ obj.setCoords();
10583
+ } catch {
10584
+ }
10585
+ const coords = typeof obj.getCoords === "function" ? obj.getCoords() : null;
10586
+ if (Array.isArray(coords) && coords.length >= 4) {
10587
+ 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));
10588
+ 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 });
10589
+ continue;
10590
+ }
10591
+ try {
10592
+ const center = (_a2 = obj.getCenterPoint) == null ? void 0 : _a2.call(obj);
10593
+ if (center && Number.isFinite(center.x) && Number.isFinite(center.y)) centers.push({ x: center.x, y: center.y });
10594
+ } catch {
10595
+ }
10596
+ }
10597
+ return centers;
10598
+ };
10599
+ const logicalFrameContainsWorldCenters = (frame, angle, centers) => {
10600
+ if (!isValidLogicalGroupFrame(frame) || centers.length === 0) return true;
10601
+ const a = typeof angle === "number" && Number.isFinite(angle) ? normalizeAngle180(angle) : 0;
10602
+ const cx = frame.left + frame.width / 2;
10603
+ const cy = frame.top + frame.height / 2;
10604
+ const rad = -a * Math.PI / 180;
10605
+ const c = Math.cos(rad);
10606
+ const s = Math.sin(rad);
10607
+ const tolerance = Math.max(8, Math.min(frame.width, frame.height) * 0.08);
10608
+ return centers.every((p) => {
10609
+ const dx = p.x - cx;
10610
+ const dy = p.y - cy;
10611
+ const localX = cx + dx * c - dy * s;
10612
+ const localY = cy + dx * s + dy * c;
10613
+ return localX >= frame.left - tolerance && localX <= frame.left + frame.width + tolerance && localY >= frame.top - tolerance && localY <= frame.top + frame.height + tolerance;
10614
+ });
10615
+ };
10616
+ const shouldRepairUnrotatedLogicalGroupFrame = (storedFrame, contentFrame, angle) => {
10617
+ if (!isValidLogicalGroupFrame(storedFrame) || !isValidLogicalGroupFrame(contentFrame)) return false;
10618
+ if (Math.abs(normalizeAngle180(typeof angle === "number" && Number.isFinite(angle) ? angle : 0)) > 0.5) return false;
10619
+ const storedArea = storedFrame.width * storedFrame.height;
10620
+ const contentArea = contentFrame.width * contentFrame.height;
10621
+ const areaRatio = storedArea / Math.max(1, contentArea);
10622
+ const dx = Math.abs(storedFrame.left + storedFrame.width / 2 - (contentFrame.left + contentFrame.width / 2));
10623
+ const dy = Math.abs(storedFrame.top + storedFrame.height / 2 - (contentFrame.top + contentFrame.height / 2));
10624
+ const driftTolerance = Math.max(12, Math.min(storedFrame.width, storedFrame.height) * 0.08);
10625
+ return areaRatio > 1.35 || dx > driftTolerance || dy > driftTolerance;
10626
+ };
10577
10627
  let ensureCanvaControlRenders = () => {
10578
10628
  };
10579
10629
  try {
@@ -11567,13 +11617,40 @@ function applyWarpAwareSelectionBorders(selection, preferredGroupAngle, preferre
11567
11617
  for (const b of buckets) b.area = orientedAreaForAngle(b.angle);
11568
11618
  buckets.sort((a, b) => b.count - a.count || a.area - b.area || Math.abs(b.angle) - Math.abs(a.angle));
11569
11619
  const dominant = buckets[0];
11570
- const rawPreferredGroupAngle = typeof preferredGroupAngle === "number" && Number.isFinite(preferredGroupAngle) ? preferredGroupAngle : typeof selection.__pixldocsGroupAngle === "number" && Number.isFinite(selection.__pixldocsGroupAngle) ? selection.__pixldocsGroupAngle : null;
11620
+ let effectivePreferredGroupAngle = preferredGroupAngle;
11621
+ let effectivePreferredGroupFrame = preferredGroupFrame;
11622
+ const logicalGroupId = selection.__pixldocsGroupSelection;
11623
+ if (logicalGroupId && (!(typeof effectivePreferredGroupAngle === "number" && Number.isFinite(effectivePreferredGroupAngle)) || !isValidLogicalGroupFrame(effectivePreferredGroupFrame))) {
11624
+ try {
11625
+ const stateNow = useEditorStore.getState();
11626
+ const pageNow = stateNow.canvas.pages.find((p) => p.id === stateNow.canvas.currentPageId);
11627
+ const groupNode = pageNow ? findNodeById(pageNow.children ?? [], logicalGroupId) : null;
11628
+ if (groupNode && isGroup(groupNode)) {
11629
+ if (!(typeof effectivePreferredGroupAngle === "number" && Number.isFinite(effectivePreferredGroupAngle)) && typeof groupNode.angle === "number") {
11630
+ effectivePreferredGroupAngle = groupNode.angle;
11631
+ }
11632
+ if (!isValidLogicalGroupFrame(effectivePreferredGroupFrame)) {
11633
+ effectivePreferredGroupFrame = frameFromStoredGroupNode(groupNode, (pageNow == null ? void 0 : pageNow.children) ?? []);
11634
+ }
11635
+ }
11636
+ } catch {
11637
+ }
11638
+ }
11639
+ const rawPreferredGroupAngle = typeof effectivePreferredGroupAngle === "number" && Number.isFinite(effectivePreferredGroupAngle) ? effectivePreferredGroupAngle : typeof selection.__pixldocsGroupAngle === "number" && Number.isFinite(selection.__pixldocsGroupAngle) ? selection.__pixldocsGroupAngle : null;
11571
11640
  const preferredAngle = rawPreferredGroupAngle != null ? normalizeAngle180(rawPreferredGroupAngle) : null;
11572
11641
  let targetAngle = preferredAngle;
11573
- const isLogicalGroupSelection = !!selection.__pixldocsGroupSelection;
11642
+ const isLogicalGroupSelection = !!logicalGroupId;
11574
11643
  if (targetAngle == null && dominant && Math.abs(dominant.angle) > 0.5 && (isLogicalGroupSelection || kids.length === 1 || dominant.count >= 2 || dominant.count === kids.length)) {
11575
11644
  targetAngle = dominant.angle;
11576
11645
  }
11646
+ if (isLogicalGroupSelection && isValidLogicalGroupFrame(effectivePreferredGroupFrame) && targetAngle != null) {
11647
+ const contentFrame = orientedFrameFromWorldPoints(worldPoints, targetAngle);
11648
+ if (shouldRepairUnrotatedLogicalGroupFrame(effectivePreferredGroupFrame, contentFrame, targetAngle)) {
11649
+ effectivePreferredGroupFrame = contentFrame;
11650
+ } else if (!logicalFrameContainsWorldCenters(effectivePreferredGroupFrame, targetAngle, collectFabricObjectWorldCenters(kids))) {
11651
+ effectivePreferredGroupFrame = null;
11652
+ }
11653
+ }
11577
11654
  if (targetAngle != null) {
11578
11655
  const restoreKidsFromWorld = () => {
11579
11656
  const invSelection = fabric.util.invertTransform(
@@ -11612,7 +11689,7 @@ function applyWarpAwareSelectionBorders(selection, preferredGroupAngle, preferre
11612
11689
  targetAngle,
11613
11690
  worldAngles
11614
11691
  });
11615
- 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;
11692
+ 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;
11616
11693
  selection.set({ angle: targetAngle, scaleX: 1, scaleY: 1, skewX: 0, skewY: 0 });
11617
11694
  if (fixedFrame) {
11618
11695
  selection.set({ width: fixedFrame.width, height: fixedFrame.height, originX: "center", originY: "center" });
@@ -11762,35 +11839,17 @@ const PageCanvas = forwardRef(
11762
11839
  }
11763
11840
  }
11764
11841
  let groupFrame = groupNode && isGroup(groupNode) ? frameFromStoredGroupNode(groupNode, (pageNow == null ? void 0 : pageNow.children) ?? []) : null;
11765
- let groupFrameWasInferred = false;
11766
- if (!groupFrame && groupNode && isGroup(groupNode) && typeof groupAngle === "number" && Number.isFinite(groupAngle)) {
11767
- groupFrame = orientedFrameFromWorldPoints(collectFabricObjectWorldPoints(members), normalizeAngle180(groupAngle));
11768
- groupFrameWasInferred = isValidLogicalGroupFrame(groupFrame);
11842
+ const memberWorldPoints = collectFabricObjectWorldPoints(members);
11843
+ const memberWorldCenters = collectFabricObjectWorldCenters(members);
11844
+ const contentFrame = typeof groupAngle === "number" && Number.isFinite(groupAngle) ? orientedFrameFromWorldPoints(memberWorldPoints, normalizeAngle180(groupAngle)) : null;
11845
+ if (shouldRepairUnrotatedLogicalGroupFrame(groupFrame, contentFrame, groupAngle)) {
11846
+ groupFrame = contentFrame;
11847
+ } else if (groupFrame && !logicalFrameContainsWorldCenters(groupFrame, groupAngle, memberWorldCenters)) {
11848
+ groupFrame = null;
11769
11849
  }
11770
- if (groupNode && isGroup(groupNode)) {
11771
- const updates = {};
11772
- if (typeof groupAngle === "number" && Number.isFinite(groupAngle)) {
11773
- const prevAngle = typeof groupNode.angle === "number" ? groupNode.angle : void 0;
11774
- if (prevAngle === void 0 || Math.abs(normalizeAngle180(prevAngle - groupAngle)) > 0.01) {
11775
- updates.angle = normalizeAngle180(groupAngle);
11776
- }
11777
- }
11778
- if (isValidLogicalGroupFrame(groupFrame)) {
11779
- const prevW = Number(groupNode.width);
11780
- const prevH = Number(groupNode.height);
11781
- if (!Number.isFinite(prevW) || Math.abs(prevW - groupFrame.width) > 0.5) updates.width = groupFrame.width;
11782
- if (!Number.isFinite(prevH) || Math.abs(prevH - groupFrame.height) > 0.5) updates.height = groupFrame.height;
11783
- if (groupFrameWasInferred) {
11784
- const storePos = absoluteToStorePosition(groupFrame.left, groupFrame.top, groupId, (pageNow == null ? void 0 : pageNow.children) ?? []);
11785
- const prevLeft = Number(groupNode.left ?? 0);
11786
- const prevTop = Number(groupNode.top ?? 0);
11787
- if (!Number.isFinite(prevLeft) || Math.abs(prevLeft - storePos.left) > 0.5) updates.left = storePos.left;
11788
- if (!Number.isFinite(prevTop) || Math.abs(prevTop - storePos.top) > 0.5) updates.top = storePos.top;
11789
- }
11790
- }
11791
- if (Object.keys(updates).length > 0) {
11792
- useEditorStore.getState().updateNode(groupId, updates, { recordHistory: false, skipLayoutRecalc: true });
11793
- }
11850
+ if (!groupFrame && groupNode && isGroup(groupNode) && typeof groupAngle === "number" && Number.isFinite(groupAngle)) {
11851
+ groupFrame = contentFrame ?? orientedFrameFromWorldPoints(memberWorldPoints, normalizeAngle180(groupAngle));
11852
+ isValidLogicalGroupFrame(groupFrame);
11794
11853
  }
11795
11854
  if (groupAngle !== void 0) {
11796
11855
  selection.__pixldocsGroupAngle = groupAngle;
@@ -25333,9 +25392,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
25333
25392
  }
25334
25393
  return svgString;
25335
25394
  }
25336
- const resolvedPackageVersion = "0.5.396";
25395
+ const resolvedPackageVersion = "0.5.398";
25337
25396
  const PACKAGE_VERSION = resolvedPackageVersion;
25338
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.396";
25397
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.398";
25339
25398
  const roundParityValue = (value) => {
25340
25399
  if (typeof value !== "number") return value;
25341
25400
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -26149,7 +26208,7 @@ class PixldocsRenderer {
26149
26208
  await this.waitForCanvasScene(container, cloned, i);
26150
26209
  }
26151
26210
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
26152
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-RZWtHBw4.js");
26211
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-CtTnRtOo.js");
26153
26212
  const prepared = preparePagesForExport(
26154
26213
  cloned.pages,
26155
26214
  canvasWidth,
@@ -28469,7 +28528,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
28469
28528
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
28470
28529
  sanitizeSvgTreeForPdf(svgToDraw);
28471
28530
  try {
28472
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-RZWtHBw4.js");
28531
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-CtTnRtOo.js");
28473
28532
  try {
28474
28533
  await logTextMeasurementDiagnostic(svgToDraw);
28475
28534
  } catch {
@@ -28869,4 +28928,4 @@ export {
28869
28928
  buildTeaserBlurFlatKeys as y,
28870
28929
  collectFontDescriptorsFromConfig as z
28871
28930
  };
28872
- //# sourceMappingURL=index-BTGqkKaE.js.map
28931
+ //# sourceMappingURL=index-C4zpif_Z.js.map