@pixldocs/canvas-renderer 0.5.410 → 0.5.412

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.
@@ -4704,11 +4704,19 @@ const svgMaskApply = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.define
4704
4704
  syncSvgMaskClipPath
4705
4705
  }, Symbol.toStringTag, { value: "Module" }));
4706
4706
  const SELECTION_BORDER_SCALE$1 = 2;
4707
- const ROTATED_GROUP_IMAGE_RESIZE_DEBUG_PREFIX = "[Pixldocs][rotated-group-image-resize]";
4708
- const ROTATED_GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES = 400;
4707
+ const ROTATED_GROUP_IMAGE_RESIZE_DEBUG_PREFIX$1 = "[Pixldocs][rotated-group-image-resize]";
4708
+ const ROTATED_GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES$1 = 400;
4709
4709
  function isInsideRotatedActiveSelection(obj) {
4710
- const parent = obj.group;
4711
- if (!(parent instanceof fabric.ActiveSelection)) return false;
4710
+ var _a2;
4711
+ const debugObj = obj;
4712
+ const ownAngle = Math.abs(((obj.angle ?? 0) % 360 + 360) % 360);
4713
+ if ((debugObj.__cropData || debugObj.__cropGroup || ((_a2 = debugObj._ct) == null ? void 0 : _a2.isCropGroup)) && Math.min(ownAngle, 360 - ownAngle) > 0.5) return true;
4714
+ const logicalParentAngle = Math.abs(((debugObj.__pixldocsParentGroupAngle ?? 0) % 360 + 360) % 360);
4715
+ if (debugObj.__pixldocsParentGroupId && Math.min(logicalParentAngle, 360 - logicalParentAngle) > 0.5) return true;
4716
+ const parent = debugObj.group;
4717
+ if (!parent) return false;
4718
+ const pType = parent.type;
4719
+ if (pType !== "activeSelection" && pType !== "group") return false;
4712
4720
  const angle = Math.abs(((parent.angle ?? 0) % 360 + 360) % 360);
4713
4721
  return Math.min(angle, 360 - angle) > 0.5;
4714
4722
  }
@@ -4782,10 +4790,15 @@ function logRotatedGroupImageResize(phase, target, payload = {}) {
4782
4790
  signX: start.signX,
4783
4791
  signY: start.signY
4784
4792
  } : void 0;
4785
- const line = `${ROTATED_GROUP_IMAGE_RESIZE_DEBUG_PREFIX} ${phase} ${JSON.stringify(normalize({
4793
+ const line = `${ROTATED_GROUP_IMAGE_RESIZE_DEBUG_PREFIX$1} ${phase} ${JSON.stringify(normalize({
4786
4794
  ...payload,
4787
4795
  target: summarizeResizeObject(target),
4788
4796
  parent: summarizeResizeObject(parent),
4797
+ logicalParent: debugTarget.__pixldocsParentGroupId ? {
4798
+ id: debugTarget.__pixldocsParentGroupId,
4799
+ type: debugTarget.__pixldocsParentGroupType,
4800
+ angle: debugTarget.__pixldocsParentGroupAngle
4801
+ } : void 0,
4789
4802
  frameW: ct == null ? void 0 : ct.frameW,
4790
4803
  frameH: ct == null ? void 0 : ct.frameH,
4791
4804
  img: summarizeResizeObject(ct == null ? void 0 : ct._img),
@@ -4794,12 +4807,12 @@ function logRotatedGroupImageResize(phase, target, payload = {}) {
4794
4807
  }))}`;
4795
4808
  if (typeof window !== "undefined") {
4796
4809
  const debugWindow = window;
4797
- debugWindow.__pixldocsRotatedGroupImageResizeLogs = Array.isArray(debugWindow.__pixldocsRotatedGroupImageResizeLogs) ? debugWindow.__pixldocsRotatedGroupImageResizeLogs.slice(-ROTATED_GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES + 1) : [];
4810
+ debugWindow.__pixldocsRotatedGroupImageResizeLogs = Array.isArray(debugWindow.__pixldocsRotatedGroupImageResizeLogs) ? debugWindow.__pixldocsRotatedGroupImageResizeLogs.slice(-ROTATED_GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES$1 + 1) : [];
4798
4811
  debugWindow.__pixldocsRotatedGroupImageResizeLogs.push(line);
4799
4812
  }
4800
4813
  console.log(line);
4801
4814
  } catch {
4802
- console.log(ROTATED_GROUP_IMAGE_RESIZE_DEBUG_PREFIX, phase, payload);
4815
+ console.log(ROTATED_GROUP_IMAGE_RESIZE_DEBUG_PREFIX$1, phase, payload);
4803
4816
  }
4804
4817
  }
4805
4818
  function clamp$1(v, min, max) {
@@ -5282,6 +5295,12 @@ function installCanvaMaskControls(g) {
5282
5295
  logRotatedGroupImageResize("snap-skipped-active-selection-child", target, { corner });
5283
5296
  return;
5284
5297
  }
5298
+ const ownAngle = Math.abs(((target.angle ?? 0) % 360 + 360) % 360);
5299
+ const parentAngle = Math.abs(((target.__pixldocsParentGroupAngle ?? 0) % 360 + 360) % 360);
5300
+ if (Math.min(ownAngle, 360 - ownAngle) > 0.5 || Math.min(parentAngle, 360 - parentAngle) > 0.5) {
5301
+ logRotatedGroupImageResize("snap-skipped-rotated-image", target, { corner, ownAngle, parentAngle });
5302
+ return;
5303
+ }
5285
5304
  const handler = target.__resizeSnapHandler;
5286
5305
  if (typeof handler === "function") {
5287
5306
  logRotatedGroupImageResize("snap-before", target, { corner });
@@ -11382,10 +11401,34 @@ const summarizeFabricObjectForResizeDebug = (obj) => {
11382
11401
  const logGroupTextResizeDebug = (phase, payload) => {
11383
11402
  return;
11384
11403
  };
11404
+ const ROTATED_GROUP_IMAGE_RESIZE_DEBUG_PREFIX = "[Pixldocs][rotated-group-image-resize]";
11405
+ const ROTATED_GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES = 400;
11385
11406
  const roundRotDriftNumber = (value) => {
11386
11407
  if (typeof value !== "number") return value;
11387
11408
  return Number.isFinite(value) ? Math.round(value * 1e3) / 1e3 : String(value);
11388
11409
  };
11410
+ const normalizeRotDriftPayload = (value) => {
11411
+ const seen = /* @__PURE__ */ new WeakSet();
11412
+ const normalize = (entry) => {
11413
+ if (entry == null) return entry;
11414
+ const valueType = typeof entry;
11415
+ if (valueType === "number") return roundRotDriftNumber(entry);
11416
+ if (valueType === "string" || valueType === "boolean") return entry;
11417
+ if (Array.isArray(entry)) return entry.map((item) => normalize(item));
11418
+ if (valueType === "object") {
11419
+ if (seen.has(entry)) return "[Circular]";
11420
+ seen.add(entry);
11421
+ if (entry instanceof fabric.FabricObject) return normalize(summarizeRotDriftObject(entry));
11422
+ const output = {};
11423
+ Object.entries(entry).forEach(([key, item]) => {
11424
+ output[key] = normalize(item);
11425
+ });
11426
+ return output;
11427
+ }
11428
+ return String(entry);
11429
+ };
11430
+ return normalize(value);
11431
+ };
11389
11432
  const matrixForRotDriftLog = (matrix) => {
11390
11433
  if (!matrix) return void 0;
11391
11434
  return matrix.map((entry) => roundRotDriftNumber(entry));
@@ -11443,6 +11486,20 @@ const summarizeRotDriftObject = (obj, worldMatrix) => {
11443
11486
  const logRotGroupImageDrift = (phase, payload) => {
11444
11487
  return;
11445
11488
  };
11489
+ const logRotatedGroupImageResizeDebug = (phase, payload) => {
11490
+ if (typeof console === "undefined") return;
11491
+ try {
11492
+ const line = `${ROTATED_GROUP_IMAGE_RESIZE_DEBUG_PREFIX} ${phase} ${JSON.stringify(normalizeRotDriftPayload(payload))}`;
11493
+ if (typeof window !== "undefined") {
11494
+ const debugWindow = window;
11495
+ debugWindow.__pixldocsRotatedGroupImageResizeLogs = Array.isArray(debugWindow.__pixldocsRotatedGroupImageResizeLogs) ? debugWindow.__pixldocsRotatedGroupImageResizeLogs.slice(-ROTATED_GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES + 1) : [];
11496
+ debugWindow.__pixldocsRotatedGroupImageResizeLogs.push(line);
11497
+ }
11498
+ console.log(line);
11499
+ } catch {
11500
+ console.log(ROTATED_GROUP_IMAGE_RESIZE_DEBUG_PREFIX, phase, payload);
11501
+ }
11502
+ };
11446
11503
  const shouldLogRotDriftLiveTick = (target, phase) => {
11447
11504
  return false;
11448
11505
  };
@@ -12248,6 +12305,22 @@ const PageCanvas = forwardRef(
12248
12305
  [canvasWidth, canvasHeight, getLogicalGroupSnapBoundsCallback, getResizeExcludeIdsCallback]
12249
12306
  );
12250
12307
  const installImageResizeControlsWithSnap = useCallback((group) => {
12308
+ var _a2;
12309
+ try {
12310
+ const groupId = getObjectId(group);
12311
+ const pageChildrenNow = ((_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
12312
+ const parent = groupId ? findParentGroup(pageChildrenNow, groupId) : null;
12313
+ if (parent) {
12314
+ group.__pixldocsParentGroupId = parent.id;
12315
+ group.__pixldocsParentGroupAngle = parent.angle ?? 0;
12316
+ group.__pixldocsParentGroupType = "logical-group";
12317
+ } else {
12318
+ delete group.__pixldocsParentGroupId;
12319
+ delete group.__pixldocsParentGroupAngle;
12320
+ delete group.__pixldocsParentGroupType;
12321
+ }
12322
+ } catch {
12323
+ }
12251
12324
  group.__resizeSnapHandler = (target, corner) => {
12252
12325
  const fc = fabricRef.current ?? target.canvas;
12253
12326
  if (!fc || !isActiveRef.current || !corner) return;
@@ -14281,7 +14354,7 @@ const PageCanvas = forwardRef(
14281
14354
  fabricCanvas.on("selection:cleared", () => {
14282
14355
  });
14283
14356
  fabricCanvas.on("object:scaling", (e) => {
14284
- var _a2, _b2, _c2, _d, _e, _f, _g, _h, _i, _j;
14357
+ var _a2, _b2, _c2, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
14285
14358
  if (!isActiveRef.current) return;
14286
14359
  const t = e.target;
14287
14360
  if (t) lastResizeScaleTargetRef.current = t;
@@ -14452,12 +14525,61 @@ const PageCanvas = forwardRef(
14452
14525
  const corner = (transform == null ? void 0 : transform.corner) || "";
14453
14526
  if (obj instanceof fabric.ActiveSelection && corner) {
14454
14527
  activeSelectionResizeHandleRef.current = corner;
14528
+ const imageChildrenForResizeDebug = obj.getObjects().filter(
14529
+ (child) => {
14530
+ var _a3;
14531
+ return child instanceof fabric.FabricImage || child instanceof fabric.Group && (child.__cropGroup || ((_a3 = child._ct) == null ? void 0 : _a3.isCropGroup));
14532
+ }
14533
+ );
14534
+ const normalizedSelectionAngle = ((obj.angle ?? 0) % 360 + 360) % 360;
14535
+ const activeLogicalGroupId = obj.__pixldocsGroupSelection;
14536
+ const transformStartForDebug = activeLogicalGroupId && ((_c2 = groupSelectionTransformStartRef.current) == null ? void 0 : _c2.groupId) === activeLogicalGroupId ? groupSelectionTransformStartRef.current : null;
14537
+ const logicalGroupAngle = (transformStartForDebug == null ? void 0 : transformStartForDebug.groupAngle) ?? obj.__pixldocsFrozenGroupAngle ?? 0;
14538
+ const normalizedLogicalGroupAngle = (logicalGroupAngle % 360 + 360) % 360;
14539
+ const isRotatedImageSelection = imageChildrenForResizeDebug.length > 0 && (Math.min(normalizedSelectionAngle, 360 - normalizedSelectionAngle) > 0.5 || Math.min(normalizedLogicalGroupAngle, 360 - normalizedLogicalGroupAngle) > 0.5);
14540
+ if (isRotatedImageSelection) {
14541
+ const countKey = "__pixldocsRotatedImageResizeScaleTickCount";
14542
+ const count = (obj[countKey] ?? 0) + 1;
14543
+ obj[countKey] = count;
14544
+ if (count <= 5 || count % 8 === 0) {
14545
+ logRotatedGroupImageResizeDebug("active-selection-scaling", {
14546
+ time: Math.round(performance.now()),
14547
+ tick: count,
14548
+ handle: corner,
14549
+ groupSelectionId: activeLogicalGroupId,
14550
+ selectedStoreIds: useEditorStore.getState().canvas.selectedIds,
14551
+ route: typeof window !== "undefined" ? window.location.pathname : void 0,
14552
+ transformAction: (_d = fabricCanvas._currentTransform) == null ? void 0 : _d.action,
14553
+ transformCorner: (_e = fabricCanvas._currentTransform) == null ? void 0 : _e.corner,
14554
+ transformOriginal: (() => {
14555
+ var _a3;
14556
+ const original = (_a3 = fabricCanvas._currentTransform) == null ? void 0 : _a3.original;
14557
+ return original ? {
14558
+ left: original.left,
14559
+ top: original.top,
14560
+ width: original.width,
14561
+ height: original.height,
14562
+ scaleX: original.scaleX,
14563
+ scaleY: original.scaleY,
14564
+ angle: original.angle
14565
+ } : null;
14566
+ })(),
14567
+ transformStart: transformStartForDebug,
14568
+ selection: summarizeRotDriftObject(obj),
14569
+ imageChildren: imageChildrenForResizeDebug.map((child, childIndex) => ({
14570
+ childIndex,
14571
+ id: getObjectId(child),
14572
+ object: summarizeRotDriftObject(child)
14573
+ }))
14574
+ });
14575
+ }
14576
+ }
14455
14577
  if (isCornerResizeHandle(corner) && obj.getObjects().some((child) => child instanceof fabric.Textbox)) {
14456
14578
  obj.__pixldocsLastGroupTextScaleDebug = {
14457
14579
  time: Math.round(performance.now()),
14458
14580
  corner,
14459
14581
  groupSelectionId: obj.__pixldocsGroupSelection,
14460
- currentTransformAction: (_c2 = fabricCanvas._currentTransform) == null ? void 0 : _c2.action,
14582
+ currentTransformAction: (_f = fabricCanvas._currentTransform) == null ? void 0 : _f.action,
14461
14583
  selection: summarizeFabricObjectForResizeDebug(obj),
14462
14584
  textChildren: obj.getObjects().filter((child) => child instanceof fabric.Textbox).map((child) => summarizeFabricObjectForResizeDebug(child))
14463
14585
  };
@@ -14466,17 +14588,17 @@ const PageCanvas = forwardRef(
14466
14588
  if (obj instanceof fabric.ActiveSelection && (corner === "ml" || corner === "mr" || corner === "mt" || corner === "mb")) {
14467
14589
  const isXSide = corner === "ml" || corner === "mr";
14468
14590
  const _cur = fabricCanvas._currentTransform;
14469
- const startSx = Math.abs(Number(((_d = _cur == null ? void 0 : _cur.original) == null ? void 0 : _d.scaleX) ?? 1)) || 1;
14470
- const startSy = Math.abs(Number(((_e = _cur == null ? void 0 : _cur.original) == null ? void 0 : _e.scaleY) ?? 1)) || 1;
14591
+ const startSx = Math.abs(Number(((_g = _cur == null ? void 0 : _cur.original) == null ? void 0 : _g.scaleX) ?? 1)) || 1;
14592
+ const startSy = Math.abs(Number(((_h = _cur == null ? void 0 : _cur.original) == null ? void 0 : _h.scaleY) ?? 1)) || 1;
14471
14593
  const sAxis = isXSide ? Math.abs((obj.scaleX ?? 1) / startSx) : Math.abs((obj.scaleY ?? 1) / startSy);
14472
14594
  if (sAxis > 1e-3) {
14473
- if (isXSide && ((_f = groupShiftReflowSnapshotRef.current) == null ? void 0 : _f.selection) !== obj) {
14595
+ if (isXSide && ((_i = groupShiftReflowSnapshotRef.current) == null ? void 0 : _i.selection) !== obj) {
14474
14596
  groupShiftReflowSnapshotRef.current = null;
14475
14597
  const logicalGroupId = obj.__pixldocsGroupSelection;
14476
14598
  if (logicalGroupId) {
14477
14599
  try {
14478
14600
  const state = useEditorStore.getState();
14479
- const pageChildren2 = ((_g = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _g.children) ?? [];
14601
+ const pageChildren2 = ((_j = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _j.children) ?? [];
14480
14602
  const groupNode = findNodeById(pageChildren2, logicalGroupId);
14481
14603
  if (groupNode && isGroup(groupNode) && !isStackLayoutMode(groupNode.layoutMode)) {
14482
14604
  const entries = obj.getObjects().map((c) => ({
@@ -14514,7 +14636,7 @@ const PageCanvas = forwardRef(
14514
14636
  }
14515
14637
  continue;
14516
14638
  }
14517
- if (child instanceof fabric.Group && (child.__cropGroup || ((_h = child._ct) == null ? void 0 : _h.isCropGroup))) {
14639
+ if (child instanceof fabric.Group && (child.__cropGroup || ((_k = child._ct) == null ? void 0 : _k.isCropGroup))) {
14518
14640
  const ct = child.__cropData;
14519
14641
  if (!ct) continue;
14520
14642
  if (child.__asLiveOrigAngle == null) {
@@ -14681,7 +14803,7 @@ const PageCanvas = forwardRef(
14681
14803
  child.dirty = true;
14682
14804
  didReflowTextChild = true;
14683
14805
  }
14684
- if (isXSide && ((_i = groupShiftReflowSnapshotRef.current) == null ? void 0 : _i.selection) === obj) {
14806
+ if (isXSide && ((_l = groupShiftReflowSnapshotRef.current) == null ? void 0 : _l.selection) === obj) {
14685
14807
  const snap = groupShiftReflowSnapshotRef.current;
14686
14808
  const anchorEntry = snap.children[0];
14687
14809
  const anchorTopLive = anchorEntry.obj.top ?? 0;
@@ -14842,7 +14964,7 @@ const PageCanvas = forwardRef(
14842
14964
  setGuides(gridGuidesForScale.length ? [...scaleGuides, ...gridGuidesForScale] : scaleGuides);
14843
14965
  if (drilledGroupIdRef.current) {
14844
14966
  try {
14845
- (_j = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _j.call(fabricCanvas);
14967
+ (_m = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _m.call(fabricCanvas);
14846
14968
  } catch {
14847
14969
  }
14848
14970
  }
@@ -15066,7 +15188,6 @@ const PageCanvas = forwardRef(
15066
15188
  delete child.__asLiveOrigW;
15067
15189
  delete child.__asLiveOrigH;
15068
15190
  delete child.__asLiveRotSnap;
15069
- delete child.__asLiveOrigAngle;
15070
15191
  }
15071
15192
  }
15072
15193
  } catch {
@@ -15629,48 +15750,99 @@ const PageCanvas = forwardRef(
15629
15750
  if (obj instanceof fabric.Group && obj.__cropGroup) {
15630
15751
  const ct = obj.__cropData;
15631
15752
  if (ct) {
15632
- const sourceFrameW = Math.max(1, ct.frameW ?? obj.width ?? 1);
15633
- const sourceFrameH = Math.max(1, ct.frameH ?? obj.height ?? 1);
15634
- const appliedScaleX = isActiveSelection && activeObj ? Math.abs((activeObj.scaleX ?? 1) * (obj.scaleX ?? 1)) : Math.abs(obj.scaleX ?? 1);
15635
- const appliedScaleY = isActiveSelection && activeObj ? Math.abs((activeObj.scaleY ?? 1) * (obj.scaleY ?? 1)) : Math.abs(obj.scaleY ?? 1);
15636
- finalWidth = Math.max(1, sourceFrameW * appliedScaleX);
15637
- finalHeight = Math.max(1, sourceFrameH * appliedScaleY);
15638
- finalScaleX = 1;
15639
- finalScaleY = 1;
15640
- if (isActiveSelection && activeObj instanceof fabric.ActiveSelection) {
15641
- absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2;
15642
- absoluteTop = (decomposed.translateY ?? absoluteTop) - finalHeight / 2;
15643
- } else {
15644
- absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2;
15645
- absoluteTop = (decomposed.translateY ?? absoluteTop) - finalHeight / 2;
15646
- }
15647
- finalAbsoluteMatrix = fabric.util.composeMatrix({
15648
- translateX: absoluteLeft + finalWidth / 2,
15649
- translateY: absoluteTop + finalHeight / 2,
15650
- angle: decomposed.angle ?? (obj.angle ?? 0),
15651
- scaleX: 1,
15652
- scaleY: 1,
15653
- skewX: 0,
15654
- skewY: 0
15655
- });
15656
- if (isActiveSelection && activeObj instanceof fabric.ActiveSelection) {
15753
+ const cropChildLocalAngle = obj.__asLiveOrigAngle != null ? obj.__asLiveOrigAngle : obj.angle ?? 0;
15754
+ const cropChildNormAngle = (cropChildLocalAngle % 360 + 360) % 360;
15755
+ const cropChildIsRotated = Math.abs(cropChildNormAngle) > 0.5 && Math.abs(cropChildNormAngle - 360) > 0.5;
15756
+ const cropHandle = activeSelectionResizeHandle;
15757
+ const cropIsSideHandle = cropHandle === "ml" || cropHandle === "mr" || cropHandle === "mt" || cropHandle === "mb";
15758
+ const cropIsXSide = cropHandle === "ml" || cropHandle === "mr";
15759
+ if (isActiveSelection && activeObj instanceof fabric.ActiveSelection && cropChildIsRotated && cropIsSideHandle) {
15760
+ const sourceFrameW = Math.max(1, ct.frameW ?? obj.width ?? 1);
15761
+ const sourceFrameH = Math.max(1, ct.frameH ?? obj.height ?? 1);
15762
+ const asSx = Math.abs(activeObj.scaleX ?? 1);
15763
+ const asSy = Math.abs(activeObj.scaleY ?? 1);
15764
+ const axisScale = cropIsXSide ? asSx : asSy;
15765
+ const thetaC = fabric.util.degreesToRadians(cropChildLocalAngle);
15766
+ const cosC = Math.cos(thetaC);
15767
+ const sinC = Math.sin(thetaC);
15768
+ const sLocal = axisScale * cosC * cosC + sinC * sinC;
15769
+ const ownSx = Math.abs(obj.scaleX ?? 1);
15770
+ const ownSy = Math.abs(obj.scaleY ?? 1);
15771
+ const newFrameW = cropIsXSide ? sourceFrameW * ownSx * sLocal : sourceFrameW * ownSx;
15772
+ const newFrameH = cropIsXSide ? sourceFrameH * ownSy : sourceFrameH * ownSy * sLocal;
15773
+ finalWidth = Math.max(1, newFrameW);
15774
+ finalHeight = Math.max(1, newFrameH);
15775
+ finalScaleX = 1;
15776
+ finalScaleY = 1;
15777
+ const worldCx = decomposed.translateX ?? 0;
15778
+ const worldCy = decomposed.translateY ?? 0;
15779
+ const worldAngle = (activeObj.angle ?? 0) + cropChildLocalAngle;
15780
+ absoluteLeft = worldCx - finalWidth / 2;
15781
+ absoluteTop = worldCy - finalHeight / 2;
15782
+ finalAbsoluteMatrix = fabric.util.composeMatrix({
15783
+ translateX: worldCx,
15784
+ translateY: worldCy,
15785
+ angle: worldAngle,
15786
+ scaleX: 1,
15787
+ scaleY: 1,
15788
+ skewX: 0,
15789
+ skewY: 0
15790
+ });
15657
15791
  pendingCropGroupFrameBakes.push({
15658
15792
  obj,
15659
15793
  width: finalWidth,
15660
15794
  height: finalHeight,
15661
15795
  left: absoluteLeft,
15662
15796
  top: absoluteTop,
15663
- angle: decomposed.angle ?? (obj.angle ?? 0)
15797
+ angle: worldAngle
15664
15798
  });
15665
- } else {
15799
+ obj.__lastResizeHandle = null;
15666
15800
  ct.frameW = finalWidth;
15667
15801
  ct.frameH = finalHeight;
15668
- obj.set({ width: finalWidth, height: finalHeight, scaleX: 1, scaleY: 1 });
15669
- updateCoverLayout(obj);
15670
- }
15671
- obj.__lastResizeHandle = null;
15672
- if (!isActiveSelection) {
15673
- fabricCanvas.setActiveObject(obj);
15802
+ } else {
15803
+ const sourceFrameW = Math.max(1, ct.frameW ?? obj.width ?? 1);
15804
+ const sourceFrameH = Math.max(1, ct.frameH ?? obj.height ?? 1);
15805
+ const appliedScaleX = isActiveSelection && activeObj ? Math.abs((activeObj.scaleX ?? 1) * (obj.scaleX ?? 1)) : Math.abs(obj.scaleX ?? 1);
15806
+ const appliedScaleY = isActiveSelection && activeObj ? Math.abs((activeObj.scaleY ?? 1) * (obj.scaleY ?? 1)) : Math.abs(obj.scaleY ?? 1);
15807
+ finalWidth = Math.max(1, sourceFrameW * appliedScaleX);
15808
+ finalHeight = Math.max(1, sourceFrameH * appliedScaleY);
15809
+ finalScaleX = 1;
15810
+ finalScaleY = 1;
15811
+ if (isActiveSelection && activeObj instanceof fabric.ActiveSelection) {
15812
+ absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2;
15813
+ absoluteTop = (decomposed.translateY ?? absoluteTop) - finalHeight / 2;
15814
+ } else {
15815
+ absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2;
15816
+ absoluteTop = (decomposed.translateY ?? absoluteTop) - finalHeight / 2;
15817
+ }
15818
+ finalAbsoluteMatrix = fabric.util.composeMatrix({
15819
+ translateX: absoluteLeft + finalWidth / 2,
15820
+ translateY: absoluteTop + finalHeight / 2,
15821
+ angle: decomposed.angle ?? (obj.angle ?? 0),
15822
+ scaleX: 1,
15823
+ scaleY: 1,
15824
+ skewX: 0,
15825
+ skewY: 0
15826
+ });
15827
+ if (isActiveSelection && activeObj instanceof fabric.ActiveSelection) {
15828
+ pendingCropGroupFrameBakes.push({
15829
+ obj,
15830
+ width: finalWidth,
15831
+ height: finalHeight,
15832
+ left: absoluteLeft,
15833
+ top: absoluteTop,
15834
+ angle: decomposed.angle ?? (obj.angle ?? 0)
15835
+ });
15836
+ } else {
15837
+ ct.frameW = finalWidth;
15838
+ ct.frameH = finalHeight;
15839
+ obj.set({ width: finalWidth, height: finalHeight, scaleX: 1, scaleY: 1 });
15840
+ updateCoverLayout(obj);
15841
+ }
15842
+ obj.__lastResizeHandle = null;
15843
+ if (!isActiveSelection) {
15844
+ fabricCanvas.setActiveObject(obj);
15845
+ }
15674
15846
  }
15675
15847
  }
15676
15848
  } else if (obj instanceof fabric.FabricImage) {
@@ -15696,79 +15868,130 @@ const PageCanvas = forwardRef(
15696
15868
  useEditorStore.getState().updateElement(objId, { src: newSrc }, { recordHistory: false, skipLayoutRecalc: true });
15697
15869
  }
15698
15870
  } else if (isActiveSelection && (Math.abs((decomposed.scaleX ?? 1) - 1) > 1e-3 || Math.abs((decomposed.scaleY ?? 1) - 1) > 1e-3)) {
15699
- const sx = Math.abs(decomposed.scaleX || 1);
15700
- const sy = Math.abs(decomposed.scaleY || 1);
15701
- const handle = activeSelectionResizeHandle;
15702
- const isCornerHandle = handle === "tl" || handle === "tr" || handle === "bl" || handle === "br" || // Fallback: if handle ref is missing and sx≈sy with non-1 magnitude,
15703
- // treat as a uniform corner drag.
15704
- !handle && Math.abs(sx - sy) < 0.01 && Math.abs(sx - 1) > 1e-3;
15705
- let fx;
15706
- let fy;
15707
- if (isCornerHandle) {
15708
- const u = Math.max(1e-3, Math.sqrt(sx * sy));
15709
- fx = u;
15710
- fy = u;
15711
- } else {
15712
- fx = sx;
15713
- fy = sy;
15714
- }
15715
- const bakedW = Math.max(1, intrinsicWidth * fx);
15716
- const bakedH = Math.max(1, intrinsicHeight * fy);
15717
- try {
15718
- const preBakeCenter = obj.getCenterPoint();
15719
- const prevObjCaching = obj.objectCaching;
15720
- obj.set({
15721
- width: bakedW,
15722
- height: bakedH,
15871
+ const imgChildLocalAngle = obj.__asLiveOrigAngle != null ? obj.__asLiveOrigAngle : obj.angle ?? 0;
15872
+ const imgChildNormAngle = (imgChildLocalAngle % 360 + 360) % 360;
15873
+ const imgChildIsRotated = Math.abs(imgChildNormAngle) > 0.5 && Math.abs(imgChildNormAngle - 360) > 0.5;
15874
+ const imgHandle = activeSelectionResizeHandle;
15875
+ const imgIsSideHandle = imgHandle === "ml" || imgHandle === "mr" || imgHandle === "mt" || imgHandle === "mb";
15876
+ const imgIsXSide = imgHandle === "ml" || imgHandle === "mr";
15877
+ if (imgChildIsRotated && imgIsSideHandle && activeObj instanceof fabric.ActiveSelection) {
15878
+ const asSx = Math.abs(activeObj.scaleX ?? 1);
15879
+ const asSy = Math.abs(activeObj.scaleY ?? 1);
15880
+ const axisScale = imgIsXSide ? asSx : asSy;
15881
+ const thetaI = fabric.util.degreesToRadians(imgChildLocalAngle);
15882
+ const cI = Math.cos(thetaI);
15883
+ const sI = Math.sin(thetaI);
15884
+ const sLocalI = axisScale * cI * cI + sI * sI;
15885
+ const ownSx = Math.abs(obj.scaleX ?? 1);
15886
+ const ownSy = Math.abs(obj.scaleY ?? 1);
15887
+ const bakedW = Math.max(1, intrinsicWidth * ownSx * (imgIsXSide ? sLocalI : 1));
15888
+ const bakedH = Math.max(1, intrinsicHeight * ownSy * (imgIsXSide ? 1 : sLocalI));
15889
+ try {
15890
+ obj.set({
15891
+ width: bakedW,
15892
+ height: bakedH,
15893
+ scaleX: 1,
15894
+ scaleY: 1,
15895
+ skewX: 0,
15896
+ skewY: 0
15897
+ });
15898
+ obj.dirty = true;
15899
+ obj.setCoords();
15900
+ } catch {
15901
+ }
15902
+ finalWidth = bakedW;
15903
+ finalHeight = bakedH;
15904
+ finalScaleX = 1;
15905
+ finalScaleY = 1;
15906
+ const worldCx = decomposed.translateX ?? 0;
15907
+ const worldCy = decomposed.translateY ?? 0;
15908
+ const worldAngleI = (activeObj.angle ?? 0) + imgChildLocalAngle;
15909
+ absoluteLeft = worldCx - finalWidth / 2;
15910
+ absoluteTop = worldCy - finalHeight / 2;
15911
+ finalAbsoluteMatrix = fabric.util.composeMatrix({
15912
+ translateX: worldCx,
15913
+ translateY: worldCy,
15914
+ angle: worldAngleI,
15723
15915
  scaleX: 1,
15724
15916
  scaleY: 1,
15725
- objectCaching: false
15917
+ skewX: 0,
15918
+ skewY: 0
15726
15919
  });
15727
- obj.objectCaching = prevObjCaching;
15728
- if (sx > 0 && sy > 0) {
15729
- const localScaleX = 1 / sx;
15730
- const localScaleY = 1 / sy;
15731
- obj.set({ scaleX: localScaleX, scaleY: localScaleY });
15732
- const selectionMatrix = (_h = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _h.call(activeObj);
15733
- const localCenter = selectionMatrix ? fabric.util.transformPoint(preBakeCenter, fabric.util.invertTransform(selectionMatrix)) : preBakeCenter;
15734
- const localWidth = bakedW * localScaleX;
15735
- const localHeight = bakedH * localScaleY;
15736
- const isCenterOrigin = obj.originX === "center" || obj.originY === "center";
15737
- if (isCenterOrigin) {
15738
- obj.set({
15739
- left: localCenter.x,
15740
- top: localCenter.y
15741
- });
15742
- } else {
15743
- obj.set({
15744
- left: localCenter.x - localWidth / 2,
15745
- top: localCenter.y - localHeight / 2
15746
- });
15920
+ } else {
15921
+ const sx = Math.abs(decomposed.scaleX || 1);
15922
+ const sy = Math.abs(decomposed.scaleY || 1);
15923
+ const handle = activeSelectionResizeHandle;
15924
+ const isCornerHandle = handle === "tl" || handle === "tr" || handle === "bl" || handle === "br" || // Fallback: if handle ref is missing and sx≈sy with non-1 magnitude,
15925
+ // treat as a uniform corner drag.
15926
+ !handle && Math.abs(sx - sy) < 0.01 && Math.abs(sx - 1) > 1e-3;
15927
+ let fx;
15928
+ let fy;
15929
+ if (isCornerHandle) {
15930
+ const u = Math.max(1e-3, Math.sqrt(sx * sy));
15931
+ fx = u;
15932
+ fy = u;
15933
+ } else {
15934
+ fx = sx;
15935
+ fy = sy;
15936
+ }
15937
+ const bakedW = Math.max(1, intrinsicWidth * fx);
15938
+ const bakedH = Math.max(1, intrinsicHeight * fy);
15939
+ try {
15940
+ const preBakeCenter = obj.getCenterPoint();
15941
+ const prevObjCaching = obj.objectCaching;
15942
+ obj.set({
15943
+ width: bakedW,
15944
+ height: bakedH,
15945
+ scaleX: 1,
15946
+ scaleY: 1,
15947
+ objectCaching: false
15948
+ });
15949
+ obj.objectCaching = prevObjCaching;
15950
+ if (sx > 0 && sy > 0) {
15951
+ const localScaleX = 1 / sx;
15952
+ const localScaleY = 1 / sy;
15953
+ obj.set({ scaleX: localScaleX, scaleY: localScaleY });
15954
+ const selectionMatrix = (_h = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _h.call(activeObj);
15955
+ const localCenter = selectionMatrix ? fabric.util.transformPoint(preBakeCenter, fabric.util.invertTransform(selectionMatrix)) : preBakeCenter;
15956
+ const localWidth = bakedW * localScaleX;
15957
+ const localHeight = bakedH * localScaleY;
15958
+ const isCenterOrigin = obj.originX === "center" || obj.originY === "center";
15959
+ if (isCenterOrigin) {
15960
+ obj.set({
15961
+ left: localCenter.x,
15962
+ top: localCenter.y
15963
+ });
15964
+ } else {
15965
+ obj.set({
15966
+ left: localCenter.x - localWidth / 2,
15967
+ top: localCenter.y - localHeight / 2
15968
+ });
15969
+ }
15747
15970
  }
15971
+ obj.dirty = true;
15972
+ if (activeObj) activeObj.dirty = true;
15973
+ obj.setCoords();
15974
+ } catch {
15748
15975
  }
15749
- obj.dirty = true;
15750
- if (activeObj) activeObj.dirty = true;
15751
- obj.setCoords();
15752
- } catch {
15753
- }
15754
- finalWidth = bakedW;
15755
- finalHeight = bakedH;
15756
- finalScaleX = 1;
15757
- finalScaleY = 1;
15758
- try {
15759
- absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2;
15760
- absoluteTop = (decomposed.translateY ?? absoluteTop) - finalHeight / 2;
15761
- } catch {
15976
+ finalWidth = bakedW;
15977
+ finalHeight = bakedH;
15978
+ finalScaleX = 1;
15979
+ finalScaleY = 1;
15980
+ try {
15981
+ absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2;
15982
+ absoluteTop = (decomposed.translateY ?? absoluteTop) - finalHeight / 2;
15983
+ } catch {
15984
+ }
15985
+ finalAbsoluteMatrix = fabric.util.composeMatrix({
15986
+ translateX: decomposed.translateX,
15987
+ translateY: decomposed.translateY,
15988
+ angle: decomposed.angle ?? 0,
15989
+ scaleX: 1,
15990
+ scaleY: 1,
15991
+ skewX: 0,
15992
+ skewY: 0
15993
+ });
15762
15994
  }
15763
- finalAbsoluteMatrix = fabric.util.composeMatrix({
15764
- translateX: decomposed.translateX,
15765
- translateY: decomposed.translateY,
15766
- angle: decomposed.angle ?? 0,
15767
- scaleX: 1,
15768
- scaleY: 1,
15769
- skewX: 0,
15770
- skewY: 0
15771
- });
15772
15995
  } else {
15773
15996
  finalWidth = intrinsicWidth;
15774
15997
  finalHeight = intrinsicHeight;
@@ -16024,6 +16247,44 @@ const PageCanvas = forwardRef(
16024
16247
  }
16025
16248
  }
16026
16249
  }
16250
+ const isCropGroupObj = obj instanceof fabric.Group && obj.__cropGroup;
16251
+ const isPlainImageObj = obj instanceof fabric.FabricImage && !obj.__cropGroup && !obj.smartElementType;
16252
+ if (isActiveSelection && isActiveSelectionSideHandle && (isCropGroupObj || isPlainImageObj)) {
16253
+ const childLocalAngleSrc = obj.__asLiveOrigAngle != null ? obj.__asLiveOrigAngle : Number.isFinite(sourceElement == null ? void 0 : sourceElement.angle) ? sourceElement.angle ?? 0 : obj.angle ?? 0;
16254
+ const normAng = (childLocalAngleSrc % 360 + 360) % 360;
16255
+ const isRotatedImg = Math.min(normAng, 360 - normAng) > 0.5;
16256
+ if (isRotatedImg && activeObj instanceof fabric.ActiveSelection) {
16257
+ try {
16258
+ const cleanAngleI = (activeObj.angle ?? 0) + childLocalAngleSrc;
16259
+ const cleanW = Math.max(1, Number(elementUpdate.width ?? finalWidth));
16260
+ const cleanH = Math.max(1, Number(elementUpdate.height ?? finalHeight));
16261
+ const cx = decomposed.translateX ?? absoluteLeft + cleanW / 2;
16262
+ const cy = decomposed.translateY ?? absoluteTop + cleanH / 2;
16263
+ const cleanAbsLeft = cx - cleanW / 2;
16264
+ const cleanAbsTop = cy - cleanH / 2;
16265
+ const cleanStorePos = absoluteToStorePosition(cleanAbsLeft, cleanAbsTop, objId, pageChildrenForSave);
16266
+ elementUpdate.left = cleanStorePos.left;
16267
+ elementUpdate.top = cleanStorePos.top;
16268
+ elementUpdate.width = cleanW;
16269
+ elementUpdate.height = cleanH;
16270
+ elementUpdate.angle = cleanAngleI;
16271
+ elementUpdate.scaleX = 1;
16272
+ elementUpdate.scaleY = 1;
16273
+ elementUpdate.skewX = 0;
16274
+ elementUpdate.skewY = 0;
16275
+ elementUpdate.transformMatrix = fabric.util.composeMatrix({
16276
+ translateX: cx,
16277
+ translateY: cy,
16278
+ angle: cleanAngleI,
16279
+ scaleX: 1,
16280
+ scaleY: 1,
16281
+ skewX: 0,
16282
+ skewY: 0
16283
+ });
16284
+ } catch {
16285
+ }
16286
+ }
16287
+ }
16027
16288
  if (debugGroupTextCornerResize && obj instanceof fabric.Textbox) {
16028
16289
  logGroupTextResizeDebug("store-update-text", {
16029
16290
  time: Math.round(performance.now()),
@@ -16184,6 +16445,15 @@ const PageCanvas = forwardRef(
16184
16445
  groupSelectionTransformStartRef.current = null;
16185
16446
  activeSelectionMoveStartRef.current = null;
16186
16447
  activeSelectionResizeHandleRef.current = null;
16448
+ try {
16449
+ const t = e.target;
16450
+ if (t instanceof fabric.ActiveSelection) {
16451
+ for (const child of t.getObjects()) {
16452
+ delete child.__asLiveOrigAngle;
16453
+ }
16454
+ }
16455
+ } catch {
16456
+ }
16187
16457
  setTimeout(() => modifiedIdsThisRound.forEach((id) => justModifiedIdsRef.current.delete(id)), 150);
16188
16458
  commitHistory();
16189
16459
  unlockEditsSoon();
@@ -25251,9 +25521,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
25251
25521
  }
25252
25522
  return svgString;
25253
25523
  }
25254
- const resolvedPackageVersion = "0.5.410";
25524
+ const resolvedPackageVersion = "0.5.412";
25255
25525
  const PACKAGE_VERSION = resolvedPackageVersion;
25256
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.410";
25526
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.412";
25257
25527
  const roundParityValue = (value) => {
25258
25528
  if (typeof value !== "number") return value;
25259
25529
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -26067,7 +26337,7 @@ class PixldocsRenderer {
26067
26337
  await this.waitForCanvasScene(container, cloned, i);
26068
26338
  }
26069
26339
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
26070
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-DE2UhH5g.js");
26340
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-pDEJNOs8.js");
26071
26341
  const prepared = preparePagesForExport(
26072
26342
  cloned.pages,
26073
26343
  canvasWidth,
@@ -28387,7 +28657,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
28387
28657
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
28388
28658
  sanitizeSvgTreeForPdf(svgToDraw);
28389
28659
  try {
28390
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-DE2UhH5g.js");
28660
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-pDEJNOs8.js");
28391
28661
  try {
28392
28662
  await logTextMeasurementDiagnostic(svgToDraw);
28393
28663
  } catch {
@@ -28787,4 +29057,4 @@ export {
28787
29057
  buildTeaserBlurFlatKeys as y,
28788
29058
  collectFontDescriptorsFromConfig as z
28789
29059
  };
28790
- //# sourceMappingURL=index-CS_cFpCL.js.map
29060
+ //# sourceMappingURL=index-CVR5UGAs.js.map