@pixldocs/canvas-renderer 0.5.393 → 0.5.395

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.
@@ -10502,6 +10502,10 @@ function bakeEdgeFade(source, fade) {
10502
10502
  }
10503
10503
  const SELECTION_PRIMARY = "hsl(217, 91%, 60%)";
10504
10504
  const SELECTION_BORDER_SCALE = 2;
10505
+ const normalizeAngle180 = (angle) => {
10506
+ const n = (angle % 360 + 360) % 360;
10507
+ return n > 180 ? n - 360 : n;
10508
+ };
10505
10509
  let ensureCanvaControlRenders = () => {
10506
10510
  };
10507
10511
  try {
@@ -11432,7 +11436,7 @@ const bakeTextboxScaleIntoTypography = (obj, sourceElement) => {
11432
11436
  };
11433
11437
  return updates;
11434
11438
  };
11435
- function applyWarpAwareSelectionBorders(selection) {
11439
+ function applyWarpAwareSelectionBorders(selection, preferredGroupAngle, preferredGroupFrame) {
11436
11440
  var _a2;
11437
11441
  if (selection.__pixldocsOrigASHasBorders !== void 0) {
11438
11442
  selection.hasBorders = selection.__pixldocsOrigASHasBorders;
@@ -11444,17 +11448,13 @@ function applyWarpAwareSelectionBorders(selection) {
11444
11448
  if (selection.__pixldocsAlignedAngle == null) {
11445
11449
  const kids = selection.getObjects();
11446
11450
  if (kids.length >= 1) {
11447
- const norm = (a) => {
11448
- const n = (a % 360 + 360) % 360;
11449
- return n > 180 ? n - 360 : n;
11450
- };
11451
- const angleDelta = (a, b) => Math.abs(norm(a - b));
11451
+ const angleDelta = (a, b) => Math.abs(normalizeAngle180(a - b));
11452
11452
  const selectionMatrix = selection.calcTransformMatrix();
11453
11453
  const worldMatrices = kids.map((k) => fabric.util.multiplyTransformMatrices(
11454
11454
  selectionMatrix,
11455
11455
  k.calcOwnMatrix()
11456
11456
  ));
11457
- const worldAngles = worldMatrices.map((m) => norm(fabric.util.qrDecompose(m).angle ?? 0));
11457
+ const worldAngles = worldMatrices.map((m) => normalizeAngle180(fabric.util.qrDecompose(m).angle ?? 0));
11458
11458
  const worldPoints = [];
11459
11459
  for (const k of kids) {
11460
11460
  try {
@@ -11499,9 +11499,11 @@ function applyWarpAwareSelectionBorders(selection) {
11499
11499
  for (const b of buckets) b.area = orientedAreaForAngle(b.angle);
11500
11500
  buckets.sort((a, b) => b.count - a.count || a.area - b.area || Math.abs(b.angle) - Math.abs(a.angle));
11501
11501
  const dominant = buckets[0];
11502
- let targetAngle = null;
11502
+ const rawPreferredGroupAngle = typeof preferredGroupAngle === "number" && Number.isFinite(preferredGroupAngle) ? preferredGroupAngle : typeof selection.__pixldocsGroupAngle === "number" && Number.isFinite(selection.__pixldocsGroupAngle) ? selection.__pixldocsGroupAngle : null;
11503
+ const preferredAngle = rawPreferredGroupAngle != null ? normalizeAngle180(rawPreferredGroupAngle) : null;
11504
+ let targetAngle = preferredAngle;
11503
11505
  const isLogicalGroupSelection = !!selection.__pixldocsGroupSelection;
11504
- if (dominant && Math.abs(dominant.angle) > 0.5 && (isLogicalGroupSelection || kids.length === 1 || dominant.count >= 2 || dominant.count === kids.length)) {
11506
+ if (targetAngle == null && dominant && Math.abs(dominant.angle) > 0.5 && (isLogicalGroupSelection || kids.length === 1 || dominant.count >= 2 || dominant.count === kids.length)) {
11505
11507
  targetAngle = dominant.angle;
11506
11508
  }
11507
11509
  if (targetAngle != null) {
@@ -11542,11 +11544,30 @@ function applyWarpAwareSelectionBorders(selection) {
11542
11544
  targetAngle,
11543
11545
  worldAngles
11544
11546
  });
11547
+ 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;
11545
11548
  selection.set({ angle: targetAngle, scaleX: 1, scaleY: 1, skewX: 0, skewY: 0 });
11549
+ if (fixedFrame) {
11550
+ selection.set({ width: fixedFrame.width, height: fixedFrame.height, originX: "center", originY: "center" });
11551
+ selection.setPositionByOrigin(
11552
+ new fabric.Point(fixedFrame.left + fixedFrame.width / 2, fixedFrame.top + fixedFrame.height / 2),
11553
+ "center",
11554
+ "center"
11555
+ );
11556
+ }
11546
11557
  restoreKidsFromWorld();
11547
- try {
11548
- (_a2 = selection.triggerLayout) == null ? void 0 : _a2.call(selection);
11549
- } catch {
11558
+ if (!fixedFrame) {
11559
+ try {
11560
+ (_a2 = selection.triggerLayout) == null ? void 0 : _a2.call(selection);
11561
+ } catch {
11562
+ }
11563
+ }
11564
+ if (fixedFrame) {
11565
+ selection.set({ width: fixedFrame.width, height: fixedFrame.height, originX: "center", originY: "center" });
11566
+ selection.setPositionByOrigin(
11567
+ new fabric.Point(fixedFrame.left + fixedFrame.width / 2, fixedFrame.top + fixedFrame.height / 2),
11568
+ "center",
11569
+ "center"
11570
+ );
11550
11571
  }
11551
11572
  restoreKidsFromWorld();
11552
11573
  selection.setCoords();
@@ -11635,9 +11656,50 @@ const PageCanvas = forwardRef(
11635
11656
  const [ready, setReady] = useState(false);
11636
11657
  const [unlockRequestId, setUnlockRequestId] = useState(0);
11637
11658
  const applyLogicalGroupSelectionVisualState = useCallback((selection, groupId) => {
11638
- var _a2;
11659
+ var _a2, _b2;
11639
11660
  selection.__pixldocsGroupSelection = groupId;
11640
11661
  delete selection.__pixldocsLogicalGroupIds;
11662
+ const pageNow = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId);
11663
+ const groupNode = pageNow ? findNodeById(pageNow.children ?? [], groupId) : null;
11664
+ let groupAngle = groupNode && isGroup(groupNode) && typeof groupNode.angle === "number" ? groupNode.angle : void 0;
11665
+ if (groupAngle === void 0 && groupNode && isGroup(groupNode)) {
11666
+ try {
11667
+ const kids = selection.getObjects();
11668
+ const selectionMatrix = selection.calcTransformMatrix();
11669
+ const worldAngles = kids.map((kid) => normalizeAngle180(fabric.util.qrDecompose(
11670
+ fabric.util.multiplyTransformMatrices(
11671
+ selectionMatrix,
11672
+ kid.calcOwnMatrix()
11673
+ )
11674
+ ).angle ?? 0));
11675
+ const buckets = [];
11676
+ for (const angle of worldAngles) {
11677
+ const bucket = buckets.find((candidate) => Math.abs(normalizeAngle180(candidate.angle - angle)) <= 2);
11678
+ if (bucket) bucket.count += 1;
11679
+ else buckets.push({ angle, count: 1 });
11680
+ }
11681
+ buckets.sort((a, b) => b.count - a.count || Math.abs(b.angle) - Math.abs(a.angle));
11682
+ const inferredAngle = (_a2 = buckets[0]) == null ? void 0 : _a2.angle;
11683
+ if (typeof inferredAngle === "number" && Number.isFinite(inferredAngle) && Math.abs(inferredAngle) > 0.01) {
11684
+ groupAngle = inferredAngle;
11685
+ useEditorStore.getState().updateNode(
11686
+ groupId,
11687
+ { angle: inferredAngle },
11688
+ { recordHistory: false, skipLayoutRecalc: true }
11689
+ );
11690
+ }
11691
+ } catch {
11692
+ }
11693
+ }
11694
+ if (groupAngle !== void 0) {
11695
+ selection.__pixldocsGroupAngle = groupAngle;
11696
+ const aligned = selection.__pixldocsAlignedAngle;
11697
+ if (typeof aligned === "number" && Math.abs(normalizeAngle180(aligned - groupAngle)) > 0.01) {
11698
+ delete selection.__pixldocsAlignedAngle;
11699
+ }
11700
+ } else {
11701
+ delete selection.__pixldocsGroupAngle;
11702
+ }
11641
11703
  selection.hasBorders = true;
11642
11704
  const members = selection.getObjects();
11643
11705
  for (const prev of suppressGroupMemberBordersRef.current) {
@@ -11662,7 +11724,7 @@ const PageCanvas = forwardRef(
11662
11724
  if (m.__pixldocsOrigHasControls === void 0) m.__pixldocsOrigHasControls = m.hasControls;
11663
11725
  m.hasBorders = false;
11664
11726
  m.hasControls = false;
11665
- if (m.__cropGroup || ((_a2 = m._ct) == null ? void 0 : _a2.isCropGroup)) {
11727
+ if (m.__cropGroup || ((_b2 = m._ct) == null ? void 0 : _b2.isCropGroup)) {
11666
11728
  if (m.__pixldocsOrigLockScalingX === void 0) {
11667
11729
  m.__pixldocsOrigLockScalingX = m.lockScalingX;
11668
11730
  m.__pixldocsOrigLockScalingY = m.lockScalingY;
@@ -11671,8 +11733,23 @@ const PageCanvas = forwardRef(
11671
11733
  m.lockScalingY = false;
11672
11734
  }
11673
11735
  }
11674
- applyWarpAwareSelectionBorders(selection);
11675
- }, []);
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
+ applyWarpAwareSelectionBorders(selection, groupAngle, groupFrame);
11752
+ }, [pageId]);
11676
11753
  const pageBoundsOptions = useMemo(
11677
11754
  () => ({ pageContentWidth: canvasWidth, pageContentHeight: canvasHeight }),
11678
11755
  [canvasWidth, canvasHeight]
@@ -11774,7 +11851,11 @@ const PageCanvas = forwardRef(
11774
11851
  const activeMembers = activeBeforeRestore.getObjects();
11775
11852
  const sameMembers = activeMembers.length === members.length && members.every((member) => activeMembers.includes(member));
11776
11853
  const sameGroup = activeBeforeRestore.__pixldocsGroupSelection === groupId;
11777
- const alreadyAligned = activeBeforeRestore.__pixldocsAlignedAngle != null;
11854
+ const pageNow = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId);
11855
+ const groupNode = pageNow ? findNodeById(pageNow.children ?? [], groupId) : null;
11856
+ const savedAngle = groupNode && isGroup(groupNode) && typeof groupNode.angle === "number" ? groupNode.angle : null;
11857
+ const alignedAngle = activeBeforeRestore.__pixldocsAlignedAngle;
11858
+ const alreadyAligned = typeof alignedAngle === "number" && (savedAngle == null || Math.abs(normalizeAngle180(alignedAngle - savedAngle)) <= 0.01);
11778
11859
  if (sameMembers && sameGroup && alreadyAligned) {
11779
11860
  ensureCanvaControlRenders(activeBeforeRestore);
11780
11861
  return;
@@ -11791,9 +11872,11 @@ const PageCanvas = forwardRef(
11791
11872
  members.forEach((m) => m.setCoords());
11792
11873
  } catch {
11793
11874
  }
11794
- try {
11795
- (_a2 = selection.triggerLayout) == null ? void 0 : _a2.call(selection);
11796
- } catch {
11875
+ if (!selection.__pixldocsGroupSelection) {
11876
+ try {
11877
+ (_a2 = selection.triggerLayout) == null ? void 0 : _a2.call(selection);
11878
+ } catch {
11879
+ }
11797
11880
  }
11798
11881
  selection.setCoords();
11799
11882
  fc.requestRenderAll();
@@ -13241,6 +13324,8 @@ const PageCanvas = forwardRef(
13241
13324
  selectionTop: rect.top,
13242
13325
  groupLeft: groupAbs.left,
13243
13326
  groupTop: groupAbs.top,
13327
+ groupWidth: groupAbs.width,
13328
+ groupHeight: groupAbs.height,
13244
13329
  selectionAngle: ((active.angle ?? 0) % 360 + 360) % 360
13245
13330
  };
13246
13331
  logRotDriftSelectionSnapshot("transform-start", active, {
@@ -13408,7 +13493,11 @@ const PageCanvas = forwardRef(
13408
13493
  const activeIds = active.getObjects().map((obj) => getObjectId(obj)).filter((id) => !!id && id !== "__background__");
13409
13494
  const sameMembers = activeIds.length === snapshot.memberIds.length && snapshot.memberIds.every((id) => activeIds.includes(id));
13410
13495
  const sameGroup = active.__pixldocsGroupSelection === snapshot.groupSelectionId;
13411
- const alreadyAligned = active.__pixldocsAlignedAngle != null;
13496
+ const pageNow = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId);
13497
+ const groupNode = pageNow ? findNodeById(pageNow.children ?? [], snapshot.groupSelectionId) : null;
13498
+ const savedAngle = groupNode && isGroup(groupNode) && typeof groupNode.angle === "number" ? groupNode.angle : null;
13499
+ const alignedAngle = active.__pixldocsAlignedAngle;
13500
+ const alreadyAligned = typeof alignedAngle === "number" && (savedAngle == null || Math.abs(normalizeAngle180(alignedAngle - savedAngle)) <= 0.01);
13412
13501
  if (sameMembers && sameGroup && alreadyAligned) {
13413
13502
  ensureCanvaControlRenders(active);
13414
13503
  return;
@@ -13564,15 +13653,32 @@ const PageCanvas = forwardRef(
13564
13653
  if (oid && memberIds.has(oid)) members.push(o);
13565
13654
  }
13566
13655
  if (members.length === 0) return null;
13567
- const TOL = 2;
13568
- const norm = (a) => {
13569
- const n = (a % 360 + 360) % 360;
13570
- return n > 180 ? n - 360 : n;
13571
- };
13572
- const angleDelta = (a, b) => {
13573
- const d = Math.abs(norm(a) - norm(b));
13574
- return Math.min(d, 360 - d);
13575
- };
13656
+ const savedGroupAngle = typeof g.angle === "number" && Number.isFinite(g.angle) ? normalizeAngle180(g.angle) : null;
13657
+ const savedGroupWidth = Number(g.width);
13658
+ const savedGroupHeight = Number(g.height);
13659
+ if (savedGroupAngle != null && savedGroupWidth > 0 && savedGroupHeight > 0) {
13660
+ const pageNow = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId);
13661
+ const pageChildrenNow = (pageNow == null ? void 0 : pageNow.children) ?? [];
13662
+ const abs = getAbsoluteBounds(g, pageChildrenNow);
13663
+ const cx = abs.left + savedGroupWidth / 2;
13664
+ const cy = abs.top + savedGroupHeight / 2;
13665
+ const rad2 = savedGroupAngle * Math.PI / 180;
13666
+ const c = Math.cos(rad2), s = Math.sin(rad2);
13667
+ const rotate = (x, y) => {
13668
+ const dx = x - cx;
13669
+ const dy = y - cy;
13670
+ return { x: cx + dx * c - dy * s, y: cy + dx * s + dy * c };
13671
+ };
13672
+ return {
13673
+ corners: [
13674
+ rotate(abs.left, abs.top),
13675
+ rotate(abs.left + savedGroupWidth, abs.top),
13676
+ rotate(abs.left + savedGroupWidth, abs.top + savedGroupHeight),
13677
+ rotate(abs.left, abs.top + savedGroupHeight)
13678
+ ],
13679
+ angle: savedGroupAngle
13680
+ };
13681
+ }
13576
13682
  const worldPoints = [];
13577
13683
  for (const m of members) {
13578
13684
  (_a2 = m.setCoords) == null ? void 0 : _a2.call(m);
@@ -13583,31 +13689,35 @@ const PageCanvas = forwardRef(
13583
13689
  if (p) worldPoints.push({ x: p.x, y: p.y });
13584
13690
  }
13585
13691
  }
13586
- const orientedAreaForAngle = (angle) => {
13587
- if (worldPoints.length === 0) return Number.POSITIVE_INFINITY;
13588
- const r = -angle * Math.PI / 180;
13589
- const c = Math.cos(r), s = Math.sin(r);
13590
- let nX = Infinity, nY = Infinity, xX = -Infinity, xY = -Infinity;
13591
- for (const p of worldPoints) {
13592
- const xr = p.x * c - p.y * s;
13593
- const yr = p.x * s + p.y * c;
13594
- if (xr < nX) nX = xr;
13595
- if (yr < nY) nY = yr;
13596
- if (xr > xX) xX = xr;
13597
- if (yr > xY) xY = yr;
13598
- }
13599
- return Math.max(1, (xX - nX) * (xY - nY));
13692
+ const getLegacyDominantAngle = () => {
13693
+ var _a3;
13694
+ const areaFor = (angle) => {
13695
+ if (worldPoints.length === 0) return Number.POSITIVE_INFINITY;
13696
+ const r = -angle * Math.PI / 180;
13697
+ const c = Math.cos(r), s = Math.sin(r);
13698
+ let nX = Infinity, nY = Infinity, xX = -Infinity, xY = -Infinity;
13699
+ for (const p of worldPoints) {
13700
+ const xr = p.x * c - p.y * s;
13701
+ const yr = p.x * s + p.y * c;
13702
+ if (xr < nX) nX = xr;
13703
+ if (yr < nY) nY = yr;
13704
+ if (xr > xX) xX = xr;
13705
+ if (yr > xY) xY = yr;
13706
+ }
13707
+ return Math.max(1, (xX - nX) * (xY - nY));
13708
+ };
13709
+ const buckets = [];
13710
+ for (const m of members) {
13711
+ const a = normalizeAngle180(m.angle ?? 0);
13712
+ const b = buckets.find((x) => Math.abs(normalizeAngle180(x.angle - a)) <= 2);
13713
+ if (b) b.count++;
13714
+ else buckets.push({ angle: a, count: 1, area: Number.POSITIVE_INFINITY });
13715
+ }
13716
+ for (const b of buckets) b.area = areaFor(b.angle);
13717
+ buckets.sort((a, b) => b.count - a.count || a.area - b.area || Math.abs(b.angle) - Math.abs(a.angle));
13718
+ return ((_a3 = buckets[0]) == null ? void 0 : _a3.angle) ?? 0;
13600
13719
  };
13601
- const buckets = [];
13602
- for (const m of members) {
13603
- const a = norm(m.angle ?? 0);
13604
- const b = buckets.find((x) => angleDelta(x.angle, a) <= TOL);
13605
- if (b) b.count++;
13606
- else buckets.push({ angle: a, count: 1, area: Number.POSITIVE_INFINITY });
13607
- }
13608
- for (const b of buckets) b.area = orientedAreaForAngle(b.angle);
13609
- buckets.sort((a, b) => b.count - a.count || a.area - b.area || Math.abs(b.angle) - Math.abs(a.angle));
13610
- const a0 = buckets[0].angle;
13720
+ const a0 = savedGroupAngle ?? getLegacyDominantAngle();
13611
13721
  const rad = -a0 * Math.PI / 180;
13612
13722
  const cos = Math.cos(rad), sin = Math.sin(rad);
13613
13723
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
@@ -14808,6 +14918,7 @@ const PageCanvas = forwardRef(
14808
14918
  fabricCanvas.on("object:rotating", (e) => {
14809
14919
  var _a2, _b2;
14810
14920
  markSimpleTransform(e);
14921
+ prepareGroupSelectionTransformStart(e.target);
14811
14922
  didTransformRef.current = true;
14812
14923
  const tr = e.target;
14813
14924
  if (shouldLogRotDriftLiveTick(tr, "rotating")) {
@@ -14997,7 +15108,7 @@ const PageCanvas = forwardRef(
14997
15108
  const groupLeft = fabricCenterX - w / 2;
14998
15109
  const groupTop = fabricCenterY - h / 2;
14999
15110
  const storePosGroup = absoluteToStorePosition(groupLeft, groupTop, movedGroupId, pageChildrenSec);
15000
- useEditorStore.getState().updateNode(movedGroupId, { left: storePosGroup.left, top: storePosGroup.top }, { recordHistory: false, skipLayoutRecalc: true });
15111
+ useEditorStore.getState().updateNode(movedGroupId, { left: storePosGroup.left, top: storePosGroup.top, angle: fabricSectionGroup.angle ?? 0 }, { recordHistory: false, skipLayoutRecalc: true });
15001
15112
  }
15002
15113
  commitHistory();
15003
15114
  unlockEditsSoon();
@@ -15140,7 +15251,7 @@ const PageCanvas = forwardRef(
15140
15251
  const groupLeft = centerX - w / 2;
15141
15252
  const groupTop = centerY - h / 2;
15142
15253
  const storePosGroup = absoluteToStorePosition(groupLeft, groupTop, groupId, pageChildrenSec);
15143
- useEditorStore.getState().updateNode(groupId, { left: storePosGroup.left, top: storePosGroup.top }, { recordHistory: false, skipLayoutRecalc: true });
15254
+ useEditorStore.getState().updateNode(groupId, { left: storePosGroup.left, top: storePosGroup.top, angle: active.angle ?? 0 }, { recordHistory: false, skipLayoutRecalc: true });
15144
15255
  }
15145
15256
  const node = findNodeById(pageChildrenSec, groupId);
15146
15257
  if (isChildModified && node && !groupMoved) {
@@ -15169,7 +15280,7 @@ const PageCanvas = forwardRef(
15169
15280
  const groupLeft = active.originX === "center" ? centerX - w / 2 : centerX;
15170
15281
  const groupTop = active.originY === "center" ? centerY - h / 2 : centerY;
15171
15282
  const storePos = absoluteToStorePosition(groupLeft, groupTop, groupId, pageChildren3);
15172
- useEditorStore.getState().updateNode(groupId, { left: storePos.left, top: storePos.top }, { recordHistory: false, skipLayoutRecalc: true });
15283
+ useEditorStore.getState().updateNode(groupId, { left: storePos.left, top: storePos.top, angle: active.angle ?? 0 }, { recordHistory: false, skipLayoutRecalc: true });
15173
15284
  commitHistory();
15174
15285
  unlockEditsSoon();
15175
15286
  return;
@@ -15351,6 +15462,14 @@ const PageCanvas = forwardRef(
15351
15462
  360 - Math.abs(currentSelAngle - startSelAngle)
15352
15463
  );
15353
15464
  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;
15472
+ }
15354
15473
  if (!hadScale && !hadRotation && (Math.abs(deltaX) > 0.1 || Math.abs(deltaY) > 0.1)) {
15355
15474
  const { updateNode: updateNodeStore, commitHistory: commitHistoryStore, getCurrentElements } = useEditorStore.getState();
15356
15475
  const newLeft = (groupToMove.left ?? 0) + deltaX;
@@ -15986,9 +16105,11 @@ const PageCanvas = forwardRef(
15986
16105
  } catch {
15987
16106
  }
15988
16107
  fabricCanvas.setActiveObject(newSel);
15989
- try {
15990
- (_j = newSel.triggerLayout) == null ? void 0 : _j.call(newSel);
15991
- } catch {
16108
+ if (!wasGroupSel) {
16109
+ try {
16110
+ (_j = newSel.triggerLayout) == null ? void 0 : _j.call(newSel);
16111
+ } catch {
16112
+ }
15992
16113
  }
15993
16114
  try {
15994
16115
  for (const member of membersToReselect) member.setCoords();
@@ -16365,7 +16486,12 @@ const PageCanvas = forwardRef(
16365
16486
  const prevAS = activeBeforeSync instanceof fabric.ActiveSelection ? activeBeforeSync : null;
16366
16487
  const prevMembers = prevAS ? prevAS.getObjects() : [];
16367
16488
  const sameMembers = !!prevAS && prevMembers.length === freshMembers.length && prevMembers.every((m) => freshMembers.includes(m));
16368
- const alreadyAligned = sameMembers && prevAS.__pixldocsAlignedAngle != null;
16489
+ const savedSnapshotAngle = activeSelectionSnapshot.groupSelectionId ? (() => {
16490
+ const groupNode = findNodeById(pageTree, activeSelectionSnapshot.groupSelectionId);
16491
+ return groupNode && isGroup(groupNode) && typeof groupNode.angle === "number" ? groupNode.angle : null;
16492
+ })() : null;
16493
+ const prevAlignedAngle = sameMembers ? prevAS.__pixldocsAlignedAngle : null;
16494
+ const alreadyAligned = sameMembers && typeof prevAlignedAngle === "number" && (savedSnapshotAngle == null || Math.abs(normalizeAngle180(prevAlignedAngle - savedSnapshotAngle)) <= 0.01);
16369
16495
  if (sameMembers && alreadyAligned) {
16370
16496
  try {
16371
16497
  ensureCanvaControlRenders(prevAS);
@@ -17407,11 +17533,10 @@ const PageCanvas = forwardRef(
17407
17533
  if (sameSelection && (isFlatGroupSelection || isPureSingleGroupSelection)) {
17408
17534
  if (selectedGroupSelectionId && active instanceof fabric.ActiveSelection) {
17409
17535
  if (isPureSingleGroupSelection) {
17410
- active.__pixldocsGroupSelection = selectedGroupSelectionId;
17411
- delete active.__pixldocsLogicalGroupIds;
17412
- suppressGroupMemberBordersRef.current = active.getObjects();
17536
+ applyLogicalGroupSelectionVisualState(active, selectedGroupSelectionId);
17413
17537
  } else {
17414
17538
  delete active.__pixldocsGroupSelection;
17539
+ delete active.__pixldocsGroupAngle;
17415
17540
  active.__pixldocsLogicalGroupIds = selectedGroupIds;
17416
17541
  active.hasBorders = true;
17417
17542
  suppressGroupMemberBordersRef.current = active.getObjects().filter((m) => {
@@ -17451,10 +17576,10 @@ const PageCanvas = forwardRef(
17451
17576
  const selection = new fabric.ActiveSelection(toSelect, { canvas: fc });
17452
17577
  if (selectedGroupSelectionId) {
17453
17578
  if (isPureSingleGroupSelection) {
17454
- selection.__pixldocsGroupSelection = selectedGroupSelectionId;
17455
- suppressGroupMemberBordersRef.current = toSelect;
17579
+ applyLogicalGroupSelectionVisualState(selection, selectedGroupSelectionId);
17456
17580
  } else {
17457
17581
  selection.__pixldocsLogicalGroupIds = selectedGroupIds;
17582
+ delete selection.__pixldocsGroupAngle;
17458
17583
  selection.hasBorders = true;
17459
17584
  suppressGroupMemberBordersRef.current = toSelect.filter((m) => {
17460
17585
  const id = getObjectId(m);
@@ -25097,9 +25222,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
25097
25222
  }
25098
25223
  return svgString;
25099
25224
  }
25100
- const resolvedPackageVersion = "0.5.393";
25225
+ const resolvedPackageVersion = "0.5.395";
25101
25226
  const PACKAGE_VERSION = resolvedPackageVersion;
25102
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.393";
25227
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.395";
25103
25228
  const roundParityValue = (value) => {
25104
25229
  if (typeof value !== "number") return value;
25105
25230
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -25913,7 +26038,7 @@ class PixldocsRenderer {
25913
26038
  await this.waitForCanvasScene(container, cloned, i);
25914
26039
  }
25915
26040
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
25916
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-DBJQBWsb.js");
26041
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-DXadS763.js");
25917
26042
  const prepared = preparePagesForExport(
25918
26043
  cloned.pages,
25919
26044
  canvasWidth,
@@ -28233,7 +28358,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
28233
28358
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
28234
28359
  sanitizeSvgTreeForPdf(svgToDraw);
28235
28360
  try {
28236
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-DBJQBWsb.js");
28361
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-DXadS763.js");
28237
28362
  try {
28238
28363
  await logTextMeasurementDiagnostic(svgToDraw);
28239
28364
  } catch {
@@ -28633,4 +28758,4 @@ export {
28633
28758
  buildTeaserBlurFlatKeys as y,
28634
28759
  collectFontDescriptorsFromConfig as z
28635
28760
  };
28636
- //# sourceMappingURL=index-CaUhUYZP.js.map
28761
+ //# sourceMappingURL=index-Bl3vMS3U.js.map