@pixldocs/canvas-renderer 0.5.395 → 0.5.396

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.
@@ -107,6 +107,7 @@ const createDefaultGroup = (partial) => ({
107
107
  locked: false,
108
108
  left: 0,
109
109
  top: 0,
110
+ angle: 0,
110
111
  ...partial
111
112
  });
112
113
  const PAGE_BACKGROUND_ELEMENT_ID = "__pageBackground__";
@@ -829,9 +830,17 @@ function getNodeBounds(node, pageChildren, options) {
829
830
  let width;
830
831
  let height;
831
832
  if (isGroup(node) && (pageChildren == null ? void 0 : pageChildren.length) !== void 0) {
832
- const size = groupBoundsFromChildren(node, pageChildren ?? []);
833
- width = size.width;
834
- height = size.height;
833
+ const group = node;
834
+ const storedWidth = Number(group.width);
835
+ const storedHeight = Number(group.height);
836
+ if (!isStackLayoutMode(group.layoutMode) && storedWidth > 0 && storedHeight > 0) {
837
+ width = storedWidth;
838
+ height = storedHeight;
839
+ } else {
840
+ const size = groupBoundsFromChildren(group, pageChildren ?? []);
841
+ width = size.width;
842
+ height = size.height;
843
+ }
835
844
  } else {
836
845
  width = simpleWidth(node);
837
846
  height = simpleHeight(node);
@@ -10506,6 +10515,65 @@ const normalizeAngle180 = (angle) => {
10506
10515
  const n = (angle % 360 + 360) % 360;
10507
10516
  return n > 180 ? n - 360 : n;
10508
10517
  };
10518
+ const isValidLogicalGroupFrame = (frame) => !!frame && Number.isFinite(frame.left) && Number.isFinite(frame.top) && Number.isFinite(frame.width) && frame.width > 0 && Number.isFinite(frame.height) && frame.height > 0;
10519
+ const frameFromStoredGroupNode = (group, pageChildren, options) => {
10520
+ const width = Number(group.width);
10521
+ const height = Number(group.height);
10522
+ if (!Number.isFinite(width) || width <= 0 || !Number.isFinite(height) || height <= 0) return null;
10523
+ try {
10524
+ const abs = getAbsoluteBounds(group, pageChildren, options);
10525
+ return { left: abs.left, top: abs.top, width, height };
10526
+ } catch {
10527
+ return null;
10528
+ }
10529
+ };
10530
+ const orientedFrameFromWorldPoints = (points, angle) => {
10531
+ if (points.length === 0 || !Number.isFinite(angle)) return null;
10532
+ const rad = -angle * Math.PI / 180;
10533
+ const cos = Math.cos(rad);
10534
+ const sin = Math.sin(rad);
10535
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
10536
+ for (const p of points) {
10537
+ const xr = p.x * cos - p.y * sin;
10538
+ const yr = p.x * sin + p.y * cos;
10539
+ minX = Math.min(minX, xr);
10540
+ minY = Math.min(minY, yr);
10541
+ maxX = Math.max(maxX, xr);
10542
+ maxY = Math.max(maxY, yr);
10543
+ }
10544
+ if (![minX, minY, maxX, maxY].every(Number.isFinite)) return null;
10545
+ const width = Math.max(1, maxX - minX);
10546
+ const height = Math.max(1, maxY - minY);
10547
+ const centerXRot = minX + width / 2;
10548
+ const centerYRot = minY + height / 2;
10549
+ const back = angle * Math.PI / 180;
10550
+ const c = Math.cos(back);
10551
+ const s = Math.sin(back);
10552
+ const centerX = centerXRot * c - centerYRot * s;
10553
+ const centerY = centerXRot * s + centerYRot * c;
10554
+ return { left: centerX - width / 2, top: centerY - height / 2, width, height };
10555
+ };
10556
+ const collectFabricObjectWorldPoints = (objects) => {
10557
+ const points = [];
10558
+ for (const obj of objects) {
10559
+ try {
10560
+ obj.setCoords();
10561
+ } catch {
10562
+ }
10563
+ const coords = typeof obj.getCoords === "function" ? obj.getCoords() : null;
10564
+ if (Array.isArray(coords) && coords.length) {
10565
+ points.push(...coords.map((p) => ({ x: p.x, y: p.y })));
10566
+ continue;
10567
+ }
10568
+ const aC = obj.aCoords;
10569
+ if (!aC) continue;
10570
+ for (const key of ["tl", "tr", "br", "bl"]) {
10571
+ const p = aC[key];
10572
+ if (p) points.push({ x: p.x, y: p.y });
10573
+ }
10574
+ }
10575
+ return points;
10576
+ };
10509
10577
  let ensureCanvaControlRenders = () => {
10510
10578
  };
10511
10579
  try {
@@ -11662,11 +11730,18 @@ const PageCanvas = forwardRef(
11662
11730
  const pageNow = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId);
11663
11731
  const groupNode = pageNow ? findNodeById(pageNow.children ?? [], groupId) : null;
11664
11732
  let groupAngle = groupNode && isGroup(groupNode) && typeof groupNode.angle === "number" ? groupNode.angle : void 0;
11733
+ const members = selection.getObjects();
11734
+ if (groupAngle === void 0 && groupNode && isGroup(groupNode)) {
11735
+ const storedW = Number(groupNode.width);
11736
+ const storedH = Number(groupNode.height);
11737
+ if (storedW > 0 && storedH > 0) {
11738
+ groupAngle = 0;
11739
+ }
11740
+ }
11665
11741
  if (groupAngle === void 0 && groupNode && isGroup(groupNode)) {
11666
11742
  try {
11667
- const kids = selection.getObjects();
11668
11743
  const selectionMatrix = selection.calcTransformMatrix();
11669
- const worldAngles = kids.map((kid) => normalizeAngle180(fabric.util.qrDecompose(
11744
+ const worldAngles = members.map((kid) => normalizeAngle180(fabric.util.qrDecompose(
11670
11745
  fabric.util.multiplyTransformMatrices(
11671
11746
  selectionMatrix,
11672
11747
  kid.calcOwnMatrix()
@@ -11682,15 +11757,41 @@ const PageCanvas = forwardRef(
11682
11757
  const inferredAngle = (_a2 = buckets[0]) == null ? void 0 : _a2.angle;
11683
11758
  if (typeof inferredAngle === "number" && Number.isFinite(inferredAngle) && Math.abs(inferredAngle) > 0.01) {
11684
11759
  groupAngle = inferredAngle;
11685
- useEditorStore.getState().updateNode(
11686
- groupId,
11687
- { angle: inferredAngle },
11688
- { recordHistory: false, skipLayoutRecalc: true }
11689
- );
11690
11760
  }
11691
11761
  } catch {
11692
11762
  }
11693
11763
  }
11764
+ 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);
11769
+ }
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
+ }
11794
+ }
11694
11795
  if (groupAngle !== void 0) {
11695
11796
  selection.__pixldocsGroupAngle = groupAngle;
11696
11797
  const aligned = selection.__pixldocsAlignedAngle;
@@ -11701,7 +11802,6 @@ const PageCanvas = forwardRef(
11701
11802
  delete selection.__pixldocsGroupAngle;
11702
11803
  }
11703
11804
  selection.hasBorders = true;
11704
- const members = selection.getObjects();
11705
11805
  for (const prev of suppressGroupMemberBordersRef.current) {
11706
11806
  if (members.includes(prev)) continue;
11707
11807
  const origBorders = prev.__pixldocsOrigHasBorders;
@@ -11733,21 +11833,6 @@ const PageCanvas = forwardRef(
11733
11833
  m.lockScalingY = false;
11734
11834
  }
11735
11835
  }
11736
- const groupFrame = groupNode && isGroup(groupNode) ? (() => {
11737
- try {
11738
- const abs = getAbsoluteBounds(groupNode, (pageNow == null ? void 0 : pageNow.children) ?? []);
11739
- const storedW = Number(groupNode.width);
11740
- const storedH = Number(groupNode.height);
11741
- return {
11742
- left: abs.left,
11743
- top: abs.top,
11744
- width: Number.isFinite(storedW) && storedW > 0 ? storedW : abs.width,
11745
- height: Number.isFinite(storedH) && storedH > 0 ? storedH : abs.height
11746
- };
11747
- } catch {
11748
- return null;
11749
- }
11750
- })() : null;
11751
11836
  applyWarpAwareSelectionBorders(selection, groupAngle, groupFrame);
11752
11837
  }, [pageId]);
11753
11838
  const pageBoundsOptions = useMemo(
@@ -13316,16 +13401,18 @@ const PageCanvas = forwardRef(
13316
13401
  const groupNode = findNodeById(pageChildren2, groupId);
13317
13402
  if (!groupNode) return;
13318
13403
  const groupAbs = getAbsoluteBounds(groupNode, pageChildren2);
13404
+ const storedGroupFrame = groupNode && isGroup(groupNode) ? frameFromStoredGroupNode(groupNode, pageChildren2, pageBoundsOptions) : null;
13405
+ const groupFrame = storedGroupFrame ?? groupAbs;
13319
13406
  const rect = active.getBoundingRect();
13320
13407
  groupSelectionTransformStartRef.current = {
13321
13408
  groupId,
13322
13409
  selection: active,
13323
13410
  selectionLeft: rect.left,
13324
13411
  selectionTop: rect.top,
13325
- groupLeft: groupAbs.left,
13326
- groupTop: groupAbs.top,
13327
- groupWidth: groupAbs.width,
13328
- groupHeight: groupAbs.height,
13412
+ groupLeft: groupFrame.left,
13413
+ groupTop: groupFrame.top,
13414
+ groupWidth: groupFrame.width,
13415
+ groupHeight: groupFrame.height,
13329
13416
  selectionAngle: ((active.angle ?? 0) % 360 + 360) % 360
13330
13417
  };
13331
13418
  logRotDriftSelectionSnapshot("transform-start", active, {
@@ -15462,13 +15549,37 @@ const PageCanvas = forwardRef(
15462
15549
  360 - Math.abs(currentSelAngle - startSelAngle)
15463
15550
  );
15464
15551
  const hadRotation = isActiveSelection && activeObj && angleDelta > 0.01;
15465
- if (hadRotation && activeObj instanceof fabric.ActiveSelection && activeGroupSelectionId === groupToMove.id) {
15466
- useEditorStore.getState().updateNode(
15467
- groupToMove.id,
15468
- { angle: currentSelAngle },
15469
- { recordHistory: false, skipLayoutRecalc: true }
15470
- );
15471
- activeObj.__pixldocsGroupAngle = currentSelAngle;
15552
+ if ((hadScale || hadRotation) && activeObj instanceof fabric.ActiveSelection && activeGroupSelectionId === groupToMove.id) {
15553
+ const groupTransformUpdates = {};
15554
+ if (hadRotation) {
15555
+ groupTransformUpdates.angle = normalizeAngle180(currentSelAngle);
15556
+ activeObj.__pixldocsGroupAngle = groupTransformUpdates.angle;
15557
+ }
15558
+ if (hadScale && (transformStart == null ? void 0 : transformStart.groupId) === groupToMove.id) {
15559
+ const center = activeObj.getCenterPoint();
15560
+ const nextWidth = Math.max(1, transformStart.groupWidth * Math.abs(activeObj.scaleX ?? 1));
15561
+ const nextHeight = Math.max(1, transformStart.groupHeight * Math.abs(activeObj.scaleY ?? 1));
15562
+ const storePos = absoluteToStorePosition(
15563
+ center.x - nextWidth / 2,
15564
+ center.y - nextHeight / 2,
15565
+ groupToMove.id,
15566
+ pageChildren2
15567
+ );
15568
+ groupTransformUpdates.left = storePos.left;
15569
+ groupTransformUpdates.top = storePos.top;
15570
+ groupTransformUpdates.width = nextWidth;
15571
+ groupTransformUpdates.height = nextHeight;
15572
+ } else if (!Number.isFinite(Number(groupToMove.width)) || !Number.isFinite(Number(groupToMove.height))) {
15573
+ groupTransformUpdates.width = (transformStart == null ? void 0 : transformStart.groupWidth) ?? groupAbs.width;
15574
+ groupTransformUpdates.height = (transformStart == null ? void 0 : transformStart.groupHeight) ?? groupAbs.height;
15575
+ }
15576
+ if (Object.keys(groupTransformUpdates).length > 0) {
15577
+ useEditorStore.getState().updateNode(
15578
+ groupToMove.id,
15579
+ groupTransformUpdates,
15580
+ { recordHistory: false, skipLayoutRecalc: true }
15581
+ );
15582
+ }
15472
15583
  }
15473
15584
  if (!hadScale && !hadRotation && (Math.abs(deltaX) > 0.1 || Math.abs(deltaY) > 0.1)) {
15474
15585
  const { updateNode: updateNodeStore, commitHistory: commitHistoryStore, getCurrentElements } = useEditorStore.getState();
@@ -25222,9 +25333,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
25222
25333
  }
25223
25334
  return svgString;
25224
25335
  }
25225
- const resolvedPackageVersion = "0.5.395";
25336
+ const resolvedPackageVersion = "0.5.396";
25226
25337
  const PACKAGE_VERSION = resolvedPackageVersion;
25227
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.395";
25338
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.396";
25228
25339
  const roundParityValue = (value) => {
25229
25340
  if (typeof value !== "number") return value;
25230
25341
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -26038,7 +26149,7 @@ class PixldocsRenderer {
26038
26149
  await this.waitForCanvasScene(container, cloned, i);
26039
26150
  }
26040
26151
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
26041
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-DXadS763.js");
26152
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-RZWtHBw4.js");
26042
26153
  const prepared = preparePagesForExport(
26043
26154
  cloned.pages,
26044
26155
  canvasWidth,
@@ -28358,7 +28469,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
28358
28469
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
28359
28470
  sanitizeSvgTreeForPdf(svgToDraw);
28360
28471
  try {
28361
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-DXadS763.js");
28472
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-RZWtHBw4.js");
28362
28473
  try {
28363
28474
  await logTextMeasurementDiagnostic(svgToDraw);
28364
28475
  } catch {
@@ -28758,4 +28869,4 @@ export {
28758
28869
  buildTeaserBlurFlatKeys as y,
28759
28870
  collectFontDescriptorsFromConfig as z
28760
28871
  };
28761
- //# sourceMappingURL=index-Bl3vMS3U.js.map
28872
+ //# sourceMappingURL=index-BTGqkKaE.js.map