@pixldocs/canvas-renderer 0.5.354 → 0.5.355

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.
@@ -10500,105 +10500,6 @@ function bakeEdgeFade(source, fade) {
10500
10500
  }
10501
10501
  return canvas;
10502
10502
  }
10503
- const normalizeSignedAngle = (angle) => (angle % 360 + 540) % 360 - 180;
10504
- const rotatedTopLeftToCenter = (left, top, width, height, angleDeg = 0) => {
10505
- const angle = angleDeg * Math.PI / 180;
10506
- const cos = Math.cos(angle);
10507
- const sin = Math.sin(angle);
10508
- return {
10509
- x: left + width / 2 * cos - height / 2 * sin,
10510
- y: top + width / 2 * sin + height / 2 * cos
10511
- };
10512
- };
10513
- const centerToRotatedTopLeft = (centerX, centerY, width, height, angleDeg = 0) => {
10514
- const angle = angleDeg * Math.PI / 180;
10515
- const cos = Math.cos(angle);
10516
- const sin = Math.sin(angle);
10517
- return {
10518
- left: centerX - width / 2 * cos + height / 2 * sin,
10519
- top: centerY - width / 2 * sin - height / 2 * cos
10520
- };
10521
- };
10522
- const getGroupTransformFrame = (group, pageChildren, options) => {
10523
- const bounds = getNodeBounds(group, pageChildren);
10524
- const width = Math.max(1, Number(group.width ?? bounds.width) || bounds.width || 1);
10525
- const height = Math.max(1, Number(group.height ?? bounds.height) || bounds.height || 1);
10526
- return {
10527
- left: Number(group.left ?? bounds.left ?? 0) || 0,
10528
- top: Number(group.top ?? bounds.top ?? 0) || 0,
10529
- width,
10530
- height,
10531
- angle: Number(group.angle ?? 0) || 0
10532
- };
10533
- };
10534
- const getGroupLocalToParentMatrix = (group, pageChildren, options) => {
10535
- const frame = getGroupTransformFrame(group, pageChildren);
10536
- const rad = frame.angle * Math.PI / 180;
10537
- const cos = Math.cos(rad);
10538
- const sin = Math.sin(rad);
10539
- return [
10540
- cos,
10541
- sin,
10542
- -sin,
10543
- cos,
10544
- frame.left,
10545
- frame.top
10546
- ];
10547
- };
10548
- const getAncestorGroupTransform = (nodeId, pageChildren, fabric2, options) => {
10549
- let matrix = [1, 0, 0, 1, 0, 0];
10550
- let angle = 0;
10551
- const chain = [];
10552
- let currentId = nodeId;
10553
- for (let guard = 0; guard < 32; guard++) {
10554
- const parent = findParentGroup(pageChildren, currentId);
10555
- if (!parent) break;
10556
- chain.unshift(parent);
10557
- currentId = parent.id;
10558
- }
10559
- for (const group of chain) {
10560
- matrix = fabric2.util.multiplyTransformMatrices(
10561
- matrix,
10562
- getGroupLocalToParentMatrix(group, pageChildren)
10563
- );
10564
- angle += Number(group.angle ?? 0) || 0;
10565
- }
10566
- return { matrix, angle: normalizeSignedAngle(angle) };
10567
- };
10568
- const getElementFabricPlacement$1 = (element, pageChildren, fabric2, options) => {
10569
- if (!pageChildren.length) {
10570
- return { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
10571
- }
10572
- const ancestor = getAncestorGroupTransform(element.id, pageChildren, fabric2);
10573
- const point = fabric2.util.transformPoint(
10574
- new fabric2.Point(element.left ?? 0, element.top ?? 0),
10575
- ancestor.matrix
10576
- );
10577
- return {
10578
- left: point.x,
10579
- top: point.y,
10580
- angle: normalizeSignedAngle(ancestor.angle + Number(element.angle ?? 0))
10581
- };
10582
- };
10583
- const getGroupAbsoluteTransformFrame$1 = (group, pageChildren, fabric2, options) => {
10584
- const frame = getGroupTransformFrame(group, pageChildren);
10585
- const ancestor = getAncestorGroupTransform(group.id, pageChildren, fabric2);
10586
- const centerLocal = rotatedTopLeftToCenter(frame.left, frame.top, frame.width, frame.height, frame.angle);
10587
- const center = fabric2.util.transformPoint(new fabric2.Point(centerLocal.x, centerLocal.y), ancestor.matrix);
10588
- const topLeft = fabric2.util.transformPoint(new fabric2.Point(frame.left, frame.top), ancestor.matrix);
10589
- return {
10590
- left: topLeft.x,
10591
- top: topLeft.y,
10592
- width: frame.width,
10593
- height: frame.height,
10594
- centerX: center.x,
10595
- centerY: center.y,
10596
- angle: normalizeSignedAngle(ancestor.angle + frame.angle)
10597
- };
10598
- };
10599
- function preserveLogicalGroupTagDuringMove(selection, groupId) {
10600
- selection.__pixldocsGroupSelection = groupId;
10601
- }
10602
10503
  const SELECTION_PRIMARY = "hsl(217, 91%, 60%)";
10603
10504
  const SELECTION_BORDER_SCALE = 2;
10604
10505
  let ensureCanvaControlRenders = () => {
@@ -11052,18 +10953,12 @@ try {
11052
10953
  } catch (e) {
11053
10954
  }
11054
10955
  };
11055
- const wrapControlsFactory = (key) => {
11056
- if (typeof cu[key] !== "function") return;
11057
- const descriptor = Object.getOwnPropertyDescriptor(cu, key);
11058
- if (descriptor && descriptor.writable === false && !descriptor.set) return;
11059
- const original = cu[key].bind(cu);
11060
- try {
11061
- cu[key] = () => installPillRenders(original());
11062
- } catch {
11063
- }
11064
- };
11065
- wrapControlsFactory("createObjectDefaultControls");
11066
- wrapControlsFactory("createTextboxDefaultControls");
10956
+ const origObj = cu.createObjectDefaultControls.bind(cu);
10957
+ cu.createObjectDefaultControls = () => installPillRenders(origObj());
10958
+ if (typeof cu.createTextboxDefaultControls === "function") {
10959
+ const origTb = cu.createTextboxDefaultControls.bind(cu);
10960
+ cu.createTextboxDefaultControls = () => installPillRenders(origTb());
10961
+ }
11067
10962
  const wrapClassCreateControls = (Klass) => {
11068
10963
  if (!Klass || typeof Klass.createControls !== "function") return;
11069
10964
  const orig = Klass.createControls.bind(Klass);
@@ -11130,8 +11025,6 @@ const scaleUpdateNumber = (updates, source, key, factor) => {
11130
11025
  };
11131
11026
  const GROUP_TEXT_RESIZE_DEBUG_PREFIX = "[Pixldocs][group-text-corner-resize]";
11132
11027
  const GROUP_TEXT_RESIZE_DEBUG_MAX_ENTRIES = 200;
11133
- const GROUP_IMAGE_RESIZE_DEBUG_PREFIX = "[Pixldocs][group-image-side-resize]";
11134
- const GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES = 300;
11135
11028
  const isCornerResizeHandle = (handle) => handle === "tl" || handle === "tr" || handle === "bl" || handle === "br";
11136
11029
  const summarizeFabricObjectForResizeDebug = (obj) => {
11137
11030
  var _a2;
@@ -11194,43 +11087,6 @@ const logGroupTextResizeDebug = (phase, payload) => {
11194
11087
  console.log(GROUP_TEXT_RESIZE_DEBUG_PREFIX, phase, payload);
11195
11088
  }
11196
11089
  };
11197
- const isGroupResizeImageLikeObject = (obj) => {
11198
- var _a2;
11199
- return !!obj && (obj instanceof fabric.FabricImage || obj instanceof fabric.Group && (obj.__cropGroup || ((_a2 = obj._ct) == null ? void 0 : _a2.isCropGroup)));
11200
- };
11201
- const logGroupImageResizeDebug = (phase, payload) => {
11202
- if (typeof console === "undefined") return;
11203
- try {
11204
- const seen = /* @__PURE__ */ new WeakSet();
11205
- const normalize = (value) => {
11206
- if (value == null) return value;
11207
- const valueType = typeof value;
11208
- if (valueType === "number") return Number.isFinite(value) ? Math.round(value * 1e3) / 1e3 : String(value);
11209
- if (valueType === "string" || valueType === "boolean") return value;
11210
- if (valueType === "function") return `[Function ${value.name || "anonymous"}]`;
11211
- if (Array.isArray(value)) return value.map((entry) => normalize(entry));
11212
- if (valueType === "object") {
11213
- if (seen.has(value)) return "[Circular]";
11214
- seen.add(value);
11215
- if (value instanceof fabric.FabricObject) return normalize(summarizeFabricObjectForResizeDebug(value));
11216
- const output = {};
11217
- Object.entries(value).forEach(([key, entry]) => {
11218
- output[key] = normalize(entry);
11219
- });
11220
- return output;
11221
- }
11222
- return String(value);
11223
- };
11224
- const normalizedPayload = normalize(payload);
11225
- const line = `${GROUP_IMAGE_RESIZE_DEBUG_PREFIX} ${phase} ${JSON.stringify(normalizedPayload)}`;
11226
- const debugWindow = window;
11227
- debugWindow.__pixldocsGroupImageResizeLogs = Array.isArray(debugWindow.__pixldocsGroupImageResizeLogs) ? debugWindow.__pixldocsGroupImageResizeLogs.slice(-GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES + 1) : [];
11228
- debugWindow.__pixldocsGroupImageResizeLogs.push(line);
11229
- console.log(line);
11230
- } catch {
11231
- console.log(GROUP_IMAGE_RESIZE_DEBUG_PREFIX, phase, payload);
11232
- }
11233
- };
11234
11090
  const bakeTextboxScaleIntoTypography = (obj, sourceElement) => {
11235
11091
  const sx = Math.abs(obj.scaleX ?? 1) || 1;
11236
11092
  const sy = Math.abs(obj.scaleY ?? 1) || 1;
@@ -11304,8 +11160,6 @@ const bakeTextboxScaleIntoTypography = (obj, sourceElement) => {
11304
11160
  };
11305
11161
  return updates;
11306
11162
  };
11307
- const getElementFabricPlacement = (element, pageChildren, options) => getElementFabricPlacement$1(element, pageChildren, fabric);
11308
- const getGroupAbsoluteTransformFrame = (group, pageChildren, options) => getGroupAbsoluteTransformFrame$1(group, pageChildren, fabric);
11309
11163
  function applyWarpAwareSelectionBorders(selection) {
11310
11164
  var _a2;
11311
11165
  if (selection.__pixldocsOrigASHasBorders !== void 0) {
@@ -11314,7 +11168,6 @@ function applyWarpAwareSelectionBorders(selection) {
11314
11168
  }
11315
11169
  selection.hasBorders = true;
11316
11170
  selection.hasControls = true;
11317
- if (selection.__pixldocsGroupSelection) return;
11318
11171
  try {
11319
11172
  if (selection.__pixldocsAlignedAngle == null) {
11320
11173
  const kids = selection.getObjects();
@@ -11441,46 +11294,10 @@ const PageCanvas = forwardRef(
11441
11294
  const [ready, setReady] = useState(false);
11442
11295
  const [unlockRequestId, setUnlockRequestId] = useState(0);
11443
11296
  const applyLogicalGroupSelectionVisualState = useCallback((selection, groupId) => {
11444
- var _a2, _b2;
11297
+ var _a2;
11445
11298
  selection.__pixldocsGroupSelection = groupId;
11446
11299
  delete selection.__pixldocsLogicalGroupIds;
11447
11300
  selection.hasBorders = true;
11448
- try {
11449
- const membersBeforeFrame = selection.getObjects();
11450
- const selectionMatrixBefore = selection.calcTransformMatrix();
11451
- const memberWorldMatrices = membersBeforeFrame.map((member) => fabric.util.multiplyTransformMatrices(
11452
- selectionMatrixBefore,
11453
- member.calcOwnMatrix()
11454
- ));
11455
- const pageChildren2 = ((_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
11456
- const groupNode = findNodeById(pageChildren2, groupId);
11457
- const groupFrame = groupNode && isGroup(groupNode) ? getGroupAbsoluteTransformFrame(groupNode, pageChildren2, pageBoundsOptions) : null;
11458
- const groupAngle = groupFrame ? groupFrame.angle : 0;
11459
- if (Number.isFinite(groupAngle)) {
11460
- selection.set({ angle: groupAngle, scaleX: 1, scaleY: 1, skewX: 0, skewY: 0 });
11461
- if (groupFrame) {
11462
- selection.setPositionByOrigin(
11463
- new fabric.Point(groupFrame.centerX, groupFrame.centerY),
11464
- "center",
11465
- "center"
11466
- );
11467
- }
11468
- const invSelectionAfter = fabric.util.invertTransform(
11469
- selection.calcTransformMatrix()
11470
- );
11471
- membersBeforeFrame.forEach((member, index) => {
11472
- const localMatrix = fabric.util.multiplyTransformMatrices(
11473
- invSelectionAfter,
11474
- memberWorldMatrices[index]
11475
- );
11476
- fabric.util.applyTransformToObject(member, localMatrix);
11477
- member.setCoords();
11478
- member.dirty = true;
11479
- });
11480
- selection.setCoords();
11481
- }
11482
- } catch {
11483
- }
11484
11301
  const members = selection.getObjects();
11485
11302
  for (const prev of suppressGroupMemberBordersRef.current) {
11486
11303
  if (members.includes(prev)) continue;
@@ -11504,7 +11321,7 @@ const PageCanvas = forwardRef(
11504
11321
  if (m.__pixldocsOrigHasControls === void 0) m.__pixldocsOrigHasControls = m.hasControls;
11505
11322
  m.hasBorders = false;
11506
11323
  m.hasControls = false;
11507
- if (m.__cropGroup || ((_b2 = m._ct) == null ? void 0 : _b2.isCropGroup)) {
11324
+ if (m.__cropGroup || ((_a2 = m._ct) == null ? void 0 : _a2.isCropGroup)) {
11508
11325
  if (m.__pixldocsOrigLockScalingX === void 0) {
11509
11326
  m.__pixldocsOrigLockScalingX = m.lockScalingX;
11510
11327
  m.__pixldocsOrigLockScalingY = m.lockScalingY;
@@ -11514,7 +11331,7 @@ const PageCanvas = forwardRef(
11514
11331
  }
11515
11332
  }
11516
11333
  applyWarpAwareSelectionBorders(selection);
11517
- }, [pageId]);
11334
+ }, []);
11518
11335
  const pageBoundsOptions = useMemo(
11519
11336
  () => ({ pageContentWidth: canvasWidth, pageContentHeight: canvasHeight }),
11520
11337
  [canvasWidth, canvasHeight]
@@ -11588,6 +11405,7 @@ const PageCanvas = forwardRef(
11588
11405
  const preserveSelectionAfterTransformIdRef = useRef(null);
11589
11406
  const groupSelectionTransformStartRef = useRef(null);
11590
11407
  const activeSelectionMoveStartRef = useRef(null);
11408
+ const sectionGroupTransientImagesRef = useRef(null);
11591
11409
  setGroupOverlayLiveBoundsRef.current = setGroupOverlayLiveBounds;
11592
11410
  const {
11593
11411
  selectElements,
@@ -12433,6 +12251,7 @@ const PageCanvas = forwardRef(
12433
12251
  fabricCanvas.__fontCleanup = fontCleanup;
12434
12252
  fabricCanvas.__isUserTransforming = false;
12435
12253
  fabricCanvas.on("mouse:down", () => {
12254
+ groupSelectionTransformStartRef.current = null;
12436
12255
  activeSelectionMoveStartRef.current = null;
12437
12256
  activeSelectionResizeHandleRef.current = null;
12438
12257
  const active = fabricCanvas.getActiveObject();
@@ -12443,7 +12262,6 @@ const PageCanvas = forwardRef(
12443
12262
  selectionLeft: rect.left,
12444
12263
  selectionTop: rect.top
12445
12264
  };
12446
- prepareGroupSelectionTransformStart(active);
12447
12265
  }
12448
12266
  if (fabricCanvas._currentTransform) {
12449
12267
  fabricCanvas.__isUserTransforming = true;
@@ -12505,8 +12323,101 @@ const PageCanvas = forwardRef(
12505
12323
  });
12506
12324
  }
12507
12325
  });
12508
- fabricCanvas.on("object:moving", () => {
12326
+ const collectSectionGroupImageDescendantObjects = (groupNode) => {
12327
+ const ids = getAllElementIds(groupNode.children ?? []);
12328
+ if (ids.length === 0) return [];
12329
+ const elementById = new Map(elementsRef.current.map((el) => [el.id, el]));
12330
+ const out = [];
12331
+ for (const id of ids) {
12332
+ const el = elementById.get(id);
12333
+ if (!el || el.type !== "image") continue;
12334
+ const obj = fabricCanvas.getObjects().find((o) => getObjectId(o) === id);
12335
+ if (obj) out.push(obj);
12336
+ }
12337
+ return out;
12338
+ };
12339
+ const ensureSectionGroupTransientSnapshot = (group) => {
12340
+ var _a2;
12341
+ if (!group || !(group instanceof fabric.Group)) return false;
12342
+ if (!group.__docuforgeSectionGroup) return false;
12343
+ const groupId = getObjectId(group);
12344
+ if (!groupId) return false;
12345
+ const existing = sectionGroupTransientImagesRef.current;
12346
+ if (existing && existing.groupId === groupId && existing.group === group) return true;
12347
+ const pageChildrenLocal = ((_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
12348
+ const node = findNodeById(pageChildrenLocal, groupId);
12349
+ if (!node || !isGroup(node)) return false;
12350
+ const images = collectSectionGroupImageDescendantObjects(node);
12351
+ const gcx = group.left ?? 0;
12352
+ const gcy = group.top ?? 0;
12353
+ const gangle = group.angle ?? 0;
12354
+ const gsx = group.scaleX ?? 1;
12355
+ const gsy = group.scaleY ?? 1;
12356
+ const rad = -gangle * Math.PI / 180;
12357
+ const cos0 = Math.cos(rad);
12358
+ const sin0 = Math.sin(rad);
12359
+ const snap = images.map((obj) => {
12360
+ const icx = obj.left ?? 0;
12361
+ const icy = obj.top ?? 0;
12362
+ const dx = icx - gcx;
12363
+ const dy = icy - gcy;
12364
+ const rx = dx * cos0 - dy * sin0;
12365
+ const ry = dx * sin0 + dy * cos0;
12366
+ return {
12367
+ obj,
12368
+ localX: gsx ? rx / gsx : rx,
12369
+ localY: gsy ? ry / gsy : ry,
12370
+ relAngle: (obj.angle ?? 0) - gangle,
12371
+ relSx: (obj.scaleX ?? 1) / (gsx || 1),
12372
+ relSy: (obj.scaleY ?? 1) / (gsy || 1)
12373
+ };
12374
+ });
12375
+ sectionGroupTransientImagesRef.current = {
12376
+ groupId,
12377
+ group,
12378
+ group0: { cx: gcx, cy: gcy, angle: gangle, sx: gsx, sy: gsy },
12379
+ images: snap
12380
+ };
12381
+ return true;
12382
+ };
12383
+ const applySectionGroupTransientTransform = () => {
12384
+ const snap = sectionGroupTransientImagesRef.current;
12385
+ if (!snap || snap.images.length === 0) return;
12386
+ const group = snap.group;
12387
+ const gcx = group.left ?? 0;
12388
+ const gcy = group.top ?? 0;
12389
+ const gangle = group.angle ?? 0;
12390
+ const gsx = group.scaleX ?? 1;
12391
+ const gsy = group.scaleY ?? 1;
12392
+ const rad = gangle * Math.PI / 180;
12393
+ const cos = Math.cos(rad);
12394
+ const sin = Math.sin(rad);
12395
+ for (const entry of snap.images) {
12396
+ const lx = entry.localX * gsx;
12397
+ const ly = entry.localY * gsy;
12398
+ const wx = lx * cos - ly * sin;
12399
+ const wy = lx * sin + ly * cos;
12400
+ entry.obj.set({
12401
+ left: gcx + wx,
12402
+ top: gcy + wy,
12403
+ angle: entry.relAngle + gangle,
12404
+ scaleX: entry.relSx * gsx,
12405
+ scaleY: entry.relSy * gsy
12406
+ });
12407
+ entry.obj.setCoords();
12408
+ entry.obj.dirty = true;
12409
+ }
12410
+ };
12411
+ const clearSectionGroupTransientSnapshot = () => {
12412
+ sectionGroupTransientImagesRef.current = null;
12413
+ };
12414
+ const maybeFollowSectionGroupTransient = (target) => {
12415
+ if (!ensureSectionGroupTransientSnapshot(target)) return;
12416
+ applySectionGroupTransientTransform();
12417
+ };
12418
+ fabricCanvas.on("object:moving", (e) => {
12509
12419
  var _a2, _b2;
12420
+ maybeFollowSectionGroupTransient((e == null ? void 0 : e.target) ?? null);
12510
12421
  fabricCanvas.__isUserTransforming = true;
12511
12422
  didTransformRef.current = true;
12512
12423
  if (drilledGroupIdRef.current) {
@@ -12548,8 +12459,9 @@ const PageCanvas = forwardRef(
12548
12459
  });
12549
12460
  }
12550
12461
  });
12551
- fabricCanvas.on("object:rotating", () => {
12462
+ fabricCanvas.on("object:rotating", (e) => {
12552
12463
  var _a2;
12464
+ maybeFollowSectionGroupTransient((e == null ? void 0 : e.target) ?? null);
12553
12465
  fabricCanvas.__isUserTransforming = true;
12554
12466
  didTransformRef.current = true;
12555
12467
  if (drilledGroupIdRef.current) {
@@ -12559,6 +12471,12 @@ const PageCanvas = forwardRef(
12559
12471
  }
12560
12472
  }
12561
12473
  });
12474
+ fabricCanvas.on("object:scaling", (e) => {
12475
+ maybeFollowSectionGroupTransient((e == null ? void 0 : e.target) ?? null);
12476
+ });
12477
+ fabricCanvas.on("mouse:up", () => {
12478
+ clearSectionGroupTransientSnapshot();
12479
+ });
12562
12480
  const syncSelectionToStore = () => {
12563
12481
  var _a2, _b2, _c, _d;
12564
12482
  if (!isActiveRef.current || isRebuildingRef.current || isSyncingSelectionToFabricRef.current || !allowSelection) return;
@@ -12945,22 +12863,16 @@ const PageCanvas = forwardRef(
12945
12863
  const pageChildren2 = ((_b2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _b2.children) ?? [];
12946
12864
  const groupNode = findNodeById(pageChildren2, groupId);
12947
12865
  if (!groupNode) return;
12948
- const groupFrame = isGroup(groupNode) ? getGroupAbsoluteTransformFrame(groupNode, pageChildren2) : null;
12949
- const groupAbs = groupFrame ?? getAbsoluteBounds(groupNode, pageChildren2);
12866
+ const groupAbs = getAbsoluteBounds(groupNode, pageChildren2);
12950
12867
  const rect = active.getBoundingRect();
12951
- const center = active.getCenterPoint();
12952
12868
  groupSelectionTransformStartRef.current = {
12953
12869
  groupId,
12954
12870
  selection: active,
12955
12871
  selectionLeft: rect.left,
12956
12872
  selectionTop: rect.top,
12957
- selectionCenterX: center.x,
12958
- selectionCenterY: center.y,
12959
12873
  groupLeft: groupAbs.left,
12960
12874
  groupTop: groupAbs.top,
12961
- groupWidth: groupAbs.width,
12962
- groupHeight: groupAbs.height,
12963
- selectionAngle: (((groupFrame == null ? void 0 : groupFrame.angle) ?? active.angle ?? 0) % 360 + 360) % 360
12875
+ selectionAngle: ((active.angle ?? 0) % 360 + 360) % 360
12964
12876
  };
12965
12877
  };
12966
12878
  const restoreGroupSelectionVisualState = (selection, groupId) => {
@@ -13294,36 +13206,9 @@ const PageCanvas = forwardRef(
13294
13206
  });
13295
13207
  };
13296
13208
  fabricCanvas.__updateDrilledGroupOutline = updateDrilledGroupOutline;
13297
- const isPointerOnSelectionControl = (selection, event) => {
13298
- var _a2;
13299
- try {
13300
- selection.setCoords();
13301
- const controls = selection.oCoords ?? ((_a2 = selection.calcOCoords) == null ? void 0 : _a2.call(selection));
13302
- const el = fabricCanvas.upperCanvasEl ?? fabricCanvas.lowerCanvasEl;
13303
- const rect = el == null ? void 0 : el.getBoundingClientRect();
13304
- if (!controls || !rect || !event) return false;
13305
- const x = Number(event.clientX) - rect.left;
13306
- const y = Number(event.clientY) - rect.top;
13307
- return Object.values(controls).some((control) => {
13308
- const pts = (control == null ? void 0 : control.touchCorner) ?? (control == null ? void 0 : control.corner);
13309
- const corners = pts ? Object.values(pts) : [];
13310
- if (!corners.length) return false;
13311
- const minX = Math.min(...corners.map((p) => p.x)) - 2;
13312
- const maxX = Math.max(...corners.map((p) => p.x)) + 2;
13313
- const minY = Math.min(...corners.map((p) => p.y)) - 2;
13314
- const maxY = Math.max(...corners.map((p) => p.y)) + 2;
13315
- return x >= minX && x <= maxX && y >= minY && y <= maxY;
13316
- });
13317
- } catch {
13318
- return false;
13319
- }
13320
- };
13321
13209
  fabricCanvas.on("mouse:down:before", (opt) => {
13322
13210
  var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
13323
13211
  const activeBeforeMouseDown = fabricCanvas.getActiveObject();
13324
- if (activeBeforeMouseDown instanceof fabric.ActiveSelection && activeBeforeMouseDown.__pixldocsGroupSelection) {
13325
- prepareGroupSelectionTransformStart(activeBeforeMouseDown);
13326
- }
13327
13212
  if (editLockRef.current) {
13328
13213
  const active = fabricCanvas.getActiveObject();
13329
13214
  if (active && (((_a2 = active._ct) == null ? void 0 : _a2.isCropGroup) || active.__cropGroup)) {
@@ -13341,8 +13226,7 @@ const PageCanvas = forwardRef(
13341
13226
  }
13342
13227
  let target = opt.target;
13343
13228
  let targetId = target ? getObjectId(target) : null;
13344
- const pointerOnActiveSelectionControl = activeBeforeMouseDown instanceof fabric.ActiveSelection ? isPointerOnSelectionControl(activeBeforeMouseDown, opt.e) : false;
13345
- if (target instanceof fabric.ActiveSelection && target.__pixldocsGroupSelection && target === fabricCanvas.getActiveObject() && !target.__corner && !pointerOnActiveSelectionControl) {
13229
+ if (target instanceof fabric.ActiveSelection && target.__pixldocsGroupSelection && target === fabricCanvas.getActiveObject()) {
13346
13230
  const child = pickChildInActiveSelectionAtPointer(target, opt.e);
13347
13231
  const childId = child ? getObjectId(child) : null;
13348
13232
  if (child && childId) {
@@ -13391,7 +13275,7 @@ const PageCanvas = forwardRef(
13391
13275
  let effectiveTargetId = targetId;
13392
13276
  const activeNowEarly = fabricCanvas.getActiveObject();
13393
13277
  const asGroupId = target instanceof fabric.ActiveSelection ? target.__pixldocsGroupSelection : void 0;
13394
- if (target instanceof fabric.ActiveSelection && asGroupId && target === activeNowEarly && !target.__corner && !pointerOnActiveSelectionControl) {
13278
+ if (target instanceof fabric.ActiveSelection && asGroupId && target === activeNowEarly) {
13395
13279
  const child = pickChildInActiveSelectionAtPointer(target, opt.e);
13396
13280
  const childId = child ? getObjectId(child) : null;
13397
13281
  if (child && childId) {
@@ -13424,7 +13308,6 @@ const PageCanvas = forwardRef(
13424
13308
  restoreGroupSelectionVisualState(selection, parent.id);
13425
13309
  fabricCanvas.setActiveObject(selection);
13426
13310
  selection.setCoords();
13427
- prepareGroupSelectionTransformStart(selection);
13428
13311
  fabricCanvas._target = selection;
13429
13312
  opt.target = selection;
13430
13313
  pendingGroupPromotionRef.current = { groupId: parent.id, selection };
@@ -13467,7 +13350,6 @@ const PageCanvas = forwardRef(
13467
13350
  restoreGroupSelectionVisualState(selection, parent.id);
13468
13351
  fabricCanvas.setActiveObject(selection);
13469
13352
  selection.setCoords();
13470
- prepareGroupSelectionTransformStart(selection);
13471
13353
  fabricCanvas._target = selection;
13472
13354
  opt.target = selection;
13473
13355
  pendingGroupPromotionRef.current = { groupId: parent.id, selection };
@@ -13736,29 +13618,34 @@ const PageCanvas = forwardRef(
13736
13618
  });
13737
13619
  const markSimpleTransform = (e) => {
13738
13620
  if (!isActiveRef.current) return;
13739
- prepareGroupSelectionTransformStart(e.target);
13740
13621
  markTransforming(e.target);
13741
13622
  };
13742
13623
  const getObjectFrameBoundsInSelection = (selection, obj, frameWidth, frameHeight) => {
13743
13624
  const w = Math.max(1, frameWidth ?? obj.width ?? 1);
13744
13625
  const h = Math.max(1, frameHeight ?? obj.height ?? 1);
13626
+ const originX = obj.originX ?? "left";
13627
+ const originY = obj.originY ?? "top";
13628
+ const localLeft = originX === "center" ? -w / 2 : originX === "right" ? -w : 0;
13629
+ const localTop = originY === "center" ? -h / 2 : originY === "bottom" ? -h : 0;
13745
13630
  const matrix = fabric.util.multiplyTransformMatrices(
13746
13631
  selection.calcTransformMatrix(),
13747
13632
  obj.calcOwnMatrix()
13748
13633
  );
13749
- const decomposed = fabric.util.qrDecompose(matrix);
13750
- const scaledW = Math.max(1, w * Math.abs(decomposed.scaleX || 1));
13751
- const scaledH = Math.max(1, h * Math.abs(decomposed.scaleY || 1));
13752
- const angleRad = (decomposed.angle ?? 0) * Math.PI / 180;
13753
- const cos = Math.cos(angleRad);
13754
- const sin = Math.sin(angleRad);
13755
- const left = decomposed.translateX - scaledW / 2 * cos + scaledH / 2 * sin;
13756
- const top = decomposed.translateY - scaledW / 2 * sin - scaledH / 2 * cos;
13634
+ const points = [
13635
+ new fabric.Point(localLeft, localTop),
13636
+ new fabric.Point(localLeft + w, localTop),
13637
+ new fabric.Point(localLeft + w, localTop + h),
13638
+ new fabric.Point(localLeft, localTop + h)
13639
+ ].map((point) => fabric.util.transformPoint(point, matrix));
13640
+ const xs = points.map((p) => p.x);
13641
+ const ys = points.map((p) => p.y);
13642
+ const left = Math.min(...xs);
13643
+ const top = Math.min(...ys);
13757
13644
  return {
13758
13645
  left,
13759
13646
  top,
13760
- width: scaledW,
13761
- height: scaledH
13647
+ width: Math.max(1, Math.max(...xs) - left),
13648
+ height: Math.max(1, Math.max(...ys) - top)
13762
13649
  };
13763
13650
  };
13764
13651
  fabricCanvas.on("object:added", (e) => {
@@ -13773,30 +13660,10 @@ const PageCanvas = forwardRef(
13773
13660
  fabricCanvas.on("selection:cleared", () => {
13774
13661
  });
13775
13662
  fabricCanvas.on("object:scaling", (e) => {
13776
- var _a2, _b2, _c, _d, _e, _f, _g, _h;
13663
+ var _a2, _b2, _c, _d, _e, _f;
13777
13664
  if (!isActiveRef.current) return;
13778
13665
  const t = e.target;
13779
13666
  if (t) lastResizeScaleTargetRef.current = t;
13780
- try {
13781
- const transformDbg = e.transform;
13782
- const cornerDbg = (transformDbg == null ? void 0 : transformDbg.corner) || "";
13783
- const children = t instanceof fabric.Group || t instanceof fabric.ActiveSelection ? t.getObjects() : [];
13784
- logGroupImageResizeDebug("scaling-entry", {
13785
- time: Math.round(performance.now()),
13786
- corner: cornerDbg,
13787
- targetType: t == null ? void 0 : t.type,
13788
- targetCtor: (_a2 = t == null ? void 0 : t.constructor) == null ? void 0 : _a2.name,
13789
- isActiveSelection: t instanceof fabric.ActiveSelection,
13790
- isGroup: t instanceof fabric.Group,
13791
- isCropGroup: !!(t && (t.__cropGroup || ((_b2 = t._ct) == null ? void 0 : _b2.isCropGroup))),
13792
- childCount: children.length,
13793
- childTypes: children.map((c) => c == null ? void 0 : c.type),
13794
- hasImageChild: children.some((c) => isGroupResizeImageLikeObject(c)),
13795
- target: t ? summarizeFabricObjectForResizeDebug(t) : null
13796
- });
13797
- } catch (err) {
13798
- console.warn("[Pixldocs][group-image-side-resize] scaling-entry log failed", err);
13799
- }
13800
13667
  prepareGroupSelectionTransformStart(t);
13801
13668
  markTransforming(t);
13802
13669
  didTransformRef.current = true;
@@ -13960,7 +13827,7 @@ const PageCanvas = forwardRef(
13960
13827
  time: Math.round(performance.now()),
13961
13828
  corner,
13962
13829
  groupSelectionId: obj.__pixldocsGroupSelection,
13963
- currentTransformAction: (_c = fabricCanvas._currentTransform) == null ? void 0 : _c.action,
13830
+ currentTransformAction: (_a2 = fabricCanvas._currentTransform) == null ? void 0 : _a2.action,
13964
13831
  selection: summarizeFabricObjectForResizeDebug(obj),
13965
13832
  textChildren: obj.getObjects().filter((child) => child instanceof fabric.Textbox).map((child) => summarizeFabricObjectForResizeDebug(child))
13966
13833
  };
@@ -13970,43 +13837,19 @@ const PageCanvas = forwardRef(
13970
13837
  const isXSide = corner === "ml" || corner === "mr";
13971
13838
  const sAxis = isXSide ? Math.abs(obj.scaleX ?? 1) : Math.abs(obj.scaleY ?? 1);
13972
13839
  if (sAxis > 1e-3) {
13973
- const hasRotatedChild = obj.getObjects().some((c) => {
13974
- const a = ((c.angle ?? 0) % 180 + 180) % 180;
13975
- return !(a < 0.5 || a > 179.5);
13976
- });
13977
- const selectionAngle = ((obj.angle ?? 0) % 180 + 180) % 180;
13978
- const isSelectionRotated = !(selectionAngle < 0.5 || selectionAngle > 179.5);
13979
- const shouldPinNonTextChildren = hasRotatedChild || isSelectionRotated;
13980
- const shouldDebugGroupImageResize = obj.getObjects().some((child) => isGroupResizeImageLikeObject(child));
13981
- if (shouldDebugGroupImageResize) {
13982
- logGroupImageResizeDebug("live-start", {
13983
- time: Math.round(performance.now()),
13984
- corner,
13985
- isXSide,
13986
- sAxis,
13987
- hasRotatedChild,
13988
- isSelectionRotated,
13989
- shouldPinNonTextChildren,
13990
- groupSelectionId: obj.__pixldocsGroupSelection,
13991
- selection: summarizeFabricObjectForResizeDebug(obj),
13992
- children: obj.getObjects().map((child) => summarizeFabricObjectForResizeDebug(child))
13993
- });
13994
- }
13995
- if ((isXSide || shouldPinNonTextChildren) && ((_d = groupShiftReflowSnapshotRef.current) == null ? void 0 : _d.selection) !== obj) {
13840
+ if (isXSide && ((_b2 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _b2.selection) !== obj) {
13996
13841
  groupShiftReflowSnapshotRef.current = null;
13997
13842
  const logicalGroupId = obj.__pixldocsGroupSelection;
13998
13843
  if (logicalGroupId) {
13999
13844
  try {
14000
13845
  const state = useEditorStore.getState();
14001
- const pageChildren2 = ((_e = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _e.children) ?? [];
13846
+ const pageChildren2 = ((_c = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
14002
13847
  const groupNode = findNodeById(pageChildren2, logicalGroupId);
14003
13848
  if (groupNode && isGroup(groupNode) && !isStackLayoutMode(groupNode.layoutMode)) {
14004
13849
  const entries = obj.getObjects().map((c) => ({
14005
13850
  obj: c,
14006
13851
  id: getObjectId(c) ?? "",
14007
- left0: c.left ?? 0,
14008
13852
  top0: c.top ?? 0,
14009
- width0: (c.width ?? 0) * Math.abs(c.scaleX ?? 1),
14010
13853
  height0: (c.height ?? 0) * Math.abs(c.scaleY ?? 1)
14011
13854
  })).filter((e2) => e2.id).sort((a, b) => a.top0 - b.top0);
14012
13855
  if (entries.length > 1) {
@@ -14029,150 +13872,78 @@ const PageCanvas = forwardRef(
14029
13872
  const asTop0 = obj.top ?? 0;
14030
13873
  const asRect0 = obj.getBoundingRect();
14031
13874
  let didReflowTextChild = false;
14032
- if (hasRotatedChild) {
14033
- if (isXSide) {
14034
- obj._set("width", asW0 * sAxis);
14035
- obj._set("scaleX", 1);
14036
- } else {
14037
- obj._set("height", asH0 * sAxis);
14038
- obj._set("scaleY", 1);
14039
- }
14040
- }
14041
- const childCounterScale = hasRotatedChild ? 1 : 1 / sAxis;
14042
- let restoredNonTextAfterLayout = false;
14043
- const restoreNonTextChildren = (pins) => {
14044
- var _a3, _b3;
14045
- if (!shouldPinNonTextChildren || ((_a3 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _a3.selection) !== obj) return;
14046
- for (const entry of groupShiftReflowSnapshotRef.current.children) {
14047
- const child = entry.obj;
14048
- if (child instanceof fabric.Textbox) continue;
14049
- if (child instanceof fabric.FabricImage || child instanceof fabric.Group && (child.__cropGroup || ((_b3 = child._ct) == null ? void 0 : _b3.isCropGroup))) {
14050
- const pin = pins == null ? void 0 : pins.get(child);
14051
- let targetLeft = hasRotatedChild && isXSide ? entry.left0 * sAxis : entry.left0;
14052
- let targetTop = hasRotatedChild && !isXSide ? entry.top0 * sAxis : entry.top0;
14053
- if (pin == null ? void 0 : pin.worldCenter) {
14054
- try {
14055
- const invSelectionMatrix = fabric.util.invertTransform(obj.calcTransformMatrix());
14056
- const localCenter = fabric.util.transformPoint(pin.worldCenter, invSelectionMatrix);
14057
- targetLeft = localCenter.x;
14058
- targetTop = localCenter.y;
14059
- } catch {
14060
- targetLeft = pin.left ?? targetLeft;
14061
- targetTop = pin.top ?? targetTop;
14062
- }
14063
- } else {
14064
- targetLeft = (pin == null ? void 0 : pin.left) ?? targetLeft;
14065
- targetTop = (pin == null ? void 0 : pin.top) ?? targetTop;
14066
- }
14067
- const beforeRestore = shouldDebugGroupImageResize ? summarizeFabricObjectForResizeDebug(child) : null;
14068
- if (Math.abs((child.left ?? 0) - targetLeft) > 0.01) child._set("left", targetLeft);
14069
- if (Math.abs((child.top ?? 0) - targetTop) > 0.01) child._set("top", targetTop);
14070
- if (isXSide) child._set("scaleX", childCounterScale);
14071
- else child._set("scaleY", childCounterScale);
14072
- child.setCoords();
14073
- child.dirty = true;
14074
- if (shouldDebugGroupImageResize) {
14075
- logGroupImageResizeDebug("restore-non-text", {
14076
- time: Math.round(performance.now()),
14077
- corner,
14078
- childId: getObjectId(child),
14079
- targetLeft,
14080
- targetTop,
14081
- pin,
14082
- before: beforeRestore,
14083
- after: summarizeFabricObjectForResizeDebug(child)
14084
- });
14085
- }
14086
- }
14087
- }
14088
- };
14089
- const projectRotatedTextPosition = (child) => {
14090
- var _a3;
14091
- if (!hasRotatedChild || ((_a3 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _a3.selection) !== obj) return;
14092
- const entry = groupShiftReflowSnapshotRef.current.children.find((candidate) => candidate.obj === child);
14093
- if (!entry) return;
14094
- if (isXSide) child._set("left", entry.left0 * sAxis);
14095
- else child._set("top", entry.top0 * sAxis);
14096
- };
14097
13875
  for (const child of obj.getObjects()) {
14098
- if (child instanceof fabric.Group && (child.__cropGroup || ((_f = child._ct) == null ? void 0 : _f.isCropGroup))) {
14099
- const beforeImageChildResize = shouldDebugGroupImageResize ? summarizeFabricObjectForResizeDebug(child) : null;
13876
+ if (child instanceof fabric.Group && (child.__cropGroup || ((_d = child._ct) == null ? void 0 : _d.isCropGroup))) {
14100
13877
  const ct = child.__cropData;
14101
- if (ct) {
13878
+ if (!ct) continue;
13879
+ if (isXSide) {
14102
13880
  if (child.__asLiveOrigW == null) {
14103
- child.__asLiveOrigW = ct.frameW ?? child.width ?? 1;
13881
+ const baseW = child.width ?? ct.frameW ?? 0;
13882
+ child.__asLiveOrigW = baseW * (child.scaleX ?? 1);
14104
13883
  }
14105
- if (child.__asLiveOrigH == null) {
14106
- child.__asLiveOrigH = ct.frameH ?? child.height ?? 1;
14107
- }
14108
- if (isXSide) {
14109
- const newW = Math.max(1, Number(child.__asLiveOrigW) * sAxis);
13884
+ const origW = child.__asLiveOrigW;
13885
+ const newW = Math.max(20, origW * sAxis);
13886
+ if (Math.abs((child.width ?? 0) - newW) > 0.5) {
14110
13887
  ct.frameW = newW;
14111
13888
  child._set("width", newW);
14112
- } else {
14113
- const newH = Math.max(1, Number(child.__asLiveOrigH) * sAxis);
13889
+ child._set("scaleX", 1 / sAxis);
13890
+ try {
13891
+ updateCoverLayout(child);
13892
+ } catch {
13893
+ }
13894
+ child.setCoords();
13895
+ child.dirty = true;
13896
+ }
13897
+ } else {
13898
+ if (child.__asLiveOrigH == null) {
13899
+ const baseH = child.height ?? ct.frameH ?? 0;
13900
+ child.__asLiveOrigH = baseH * (child.scaleY ?? 1);
13901
+ }
13902
+ const origH = child.__asLiveOrigH;
13903
+ const newH = Math.max(20, origH * sAxis);
13904
+ if (Math.abs((child.height ?? 0) - newH) > 0.5) {
14114
13905
  ct.frameH = newH;
14115
13906
  child._set("height", newH);
13907
+ child._set("scaleY", 1 / sAxis);
13908
+ try {
13909
+ updateCoverLayout(child);
13910
+ } catch {
13911
+ }
13912
+ child.setCoords();
13913
+ child.dirty = true;
14116
13914
  }
14117
- try {
14118
- updateCoverLayout(child);
14119
- } catch {
14120
- }
14121
- }
14122
- if (isXSide) child._set("scaleX", childCounterScale);
14123
- else child._set("scaleY", childCounterScale);
14124
- child.setCoords();
14125
- child.dirty = true;
14126
- if (shouldDebugGroupImageResize) {
14127
- logGroupImageResizeDebug("live-crop-child-resized", {
14128
- time: Math.round(performance.now()),
14129
- corner,
14130
- sAxis,
14131
- childCounterScale,
14132
- before: beforeImageChildResize,
14133
- after: summarizeFabricObjectForResizeDebug(child),
14134
- cropData: ct ? { frameW: ct.frameW, frameH: ct.frameH } : null
14135
- });
14136
13915
  }
14137
- didReflowTextChild = true;
14138
13916
  continue;
14139
13917
  }
14140
13918
  if (child instanceof fabric.FabricImage && !child.__cropGroup && !child.smartElementType) {
14141
- const beforeImageChildResize = shouldDebugGroupImageResize ? summarizeFabricObjectForResizeDebug(child) : null;
14142
13919
  if (isXSide) {
14143
13920
  if (child.__asLiveOrigW == null) {
14144
- child.__asLiveOrigW = (child.width ?? 0) * Math.abs(child.scaleX ?? 1);
13921
+ child.__asLiveOrigW = (child.width ?? 0) * (child.scaleX ?? 1);
13922
+ }
13923
+ const origW = child.__asLiveOrigW;
13924
+ const newW = Math.max(1, origW * sAxis);
13925
+ if (Math.abs((child.width ?? 0) - newW) > 0.5) {
13926
+ child._set("width", newW);
13927
+ child._set("scaleX", 1 / sAxis);
13928
+ child.setCoords();
13929
+ child.dirty = true;
14145
13930
  }
14146
- const newW = Math.max(1, Number(child.__asLiveOrigW) * sAxis);
14147
- child._set("width", newW);
14148
13931
  } else {
14149
13932
  if (child.__asLiveOrigH == null) {
14150
- child.__asLiveOrigH = (child.height ?? 0) * Math.abs(child.scaleY ?? 1);
13933
+ child.__asLiveOrigH = (child.height ?? 0) * (child.scaleY ?? 1);
13934
+ }
13935
+ const origH = child.__asLiveOrigH;
13936
+ const newH = Math.max(1, origH * sAxis);
13937
+ if (Math.abs((child.height ?? 0) - newH) > 0.5) {
13938
+ child._set("height", newH);
13939
+ child._set("scaleY", 1 / sAxis);
13940
+ child.setCoords();
13941
+ child.dirty = true;
14151
13942
  }
14152
- const newH = Math.max(1, Number(child.__asLiveOrigH) * sAxis);
14153
- child._set("height", newH);
14154
- }
14155
- if (isXSide) child._set("scaleX", childCounterScale);
14156
- else child._set("scaleY", childCounterScale);
14157
- child.setCoords();
14158
- child.dirty = true;
14159
- if (shouldDebugGroupImageResize) {
14160
- logGroupImageResizeDebug("live-image-child-resized", {
14161
- time: Math.round(performance.now()),
14162
- corner,
14163
- sAxis,
14164
- childCounterScale,
14165
- liveOrigW: child.__asLiveOrigW,
14166
- liveOrigH: child.__asLiveOrigH,
14167
- before: beforeImageChildResize,
14168
- after: summarizeFabricObjectForResizeDebug(child)
14169
- });
14170
13943
  }
14171
- didReflowTextChild = true;
14172
13944
  continue;
14173
13945
  }
14174
13946
  if (!(child instanceof fabric.Textbox)) continue;
14175
- projectRotatedTextPosition(child);
14176
13947
  if (isXSide) {
14177
13948
  if (child.__asLiveOrigW == null) {
14178
13949
  child.__asLiveOrigW = (child.width ?? 0) * (child.scaleX ?? 1);
@@ -14181,7 +13952,7 @@ const PageCanvas = forwardRef(
14181
13952
  const newW = Math.max(20, origW * sAxis);
14182
13953
  if (Math.abs((child.width ?? 0) - newW) > 0.5) {
14183
13954
  child._set("width", newW);
14184
- child._set("scaleX", childCounterScale);
13955
+ child._set("scaleX", 1 / sAxis);
14185
13956
  try {
14186
13957
  child.initDimensions();
14187
13958
  } catch {
@@ -14194,14 +13965,10 @@ const PageCanvas = forwardRef(
14194
13965
  if (child.__asLiveOrigH == null) {
14195
13966
  child.__asLiveOrigH = (child.height ?? 0) * (child.scaleY ?? 1);
14196
13967
  }
14197
- if (child.__asLiveOrigMinH == null) {
14198
- const m = Number(child.minBoxHeight);
14199
- if (Number.isFinite(m) && m > 0) child.__asLiveOrigMinH = m;
14200
- }
14201
13968
  const origH = child.__asLiveOrigH;
14202
13969
  const newH = Math.max(20, origH * sAxis);
14203
13970
  child.minBoxHeight = newH;
14204
- child._set("scaleY", childCounterScale);
13971
+ child._set("scaleY", 1 / sAxis);
14205
13972
  try {
14206
13973
  child.initDimensions();
14207
13974
  } catch {
@@ -14211,7 +13978,7 @@ const PageCanvas = forwardRef(
14211
13978
  didReflowTextChild = true;
14212
13979
  }
14213
13980
  }
14214
- if (isXSide && !shouldPinNonTextChildren && ((_g = groupShiftReflowSnapshotRef.current) == null ? void 0 : _g.selection) === obj) {
13981
+ if (isXSide && ((_e = groupShiftReflowSnapshotRef.current) == null ? void 0 : _e.selection) === obj) {
14215
13982
  const snap = groupShiftReflowSnapshotRef.current;
14216
13983
  const anchorEntry = snap.children[0];
14217
13984
  const anchorTopLive = anchorEntry.obj.top ?? 0;
@@ -14244,26 +14011,10 @@ const PageCanvas = forwardRef(
14244
14011
  if (cornersBefore) {
14245
14012
  fixedMidBefore = corner === "ml" ? { x: (cornersBefore.tr.x + cornersBefore.br.x) / 2, y: (cornersBefore.tr.y + cornersBefore.br.y) / 2 } : { x: (cornersBefore.tl.x + cornersBefore.bl.x) / 2, y: (cornersBefore.tl.y + cornersBefore.bl.y) / 2 };
14246
14013
  }
14247
- const nonTextPinsBeforeLayout = shouldPinNonTextChildren ? new Map(obj.getObjects().map((child) => [child, {
14248
- left: child.left ?? 0,
14249
- top: child.top ?? 0,
14250
- worldCenter: child instanceof fabric.Textbox ? void 0 : child.getCenterPoint()
14251
- }])) : void 0;
14252
14014
  try {
14253
14015
  obj.triggerLayout();
14254
14016
  } catch {
14255
14017
  }
14256
- restoreNonTextChildren(nonTextPinsBeforeLayout);
14257
- restoredNonTextAfterLayout = !!nonTextPinsBeforeLayout;
14258
- if (shouldDebugGroupImageResize) {
14259
- logGroupImageResizeDebug("after-trigger-layout", {
14260
- time: Math.round(performance.now()),
14261
- corner,
14262
- selection: summarizeFabricObjectForResizeDebug(obj),
14263
- nonTextPinsBeforeLayout,
14264
- children: obj.getObjects().map((child) => summarizeFabricObjectForResizeDebug(child))
14265
- });
14266
- }
14267
14018
  obj._set("width", asW0);
14268
14019
  obj._set("scaleX", asSx0);
14269
14020
  obj._set("scaleY", asSy0);
@@ -14289,19 +14040,9 @@ const PageCanvas = forwardRef(
14289
14040
  obj._set("left", asLeft0);
14290
14041
  obj._set("top", asTop0);
14291
14042
  }
14292
- if (!restoredNonTextAfterLayout) restoreNonTextChildren();
14293
14043
  obj._set("width", asW0);
14294
14044
  obj._set("scaleX", asSx0);
14295
14045
  obj._set("scaleY", asSy0);
14296
- if (hasRotatedChild) {
14297
- if (isXSide) {
14298
- obj._set("width", asW0 * sAxis);
14299
- obj._set("scaleX", 1);
14300
- } else {
14301
- obj._set("height", asH0 * sAxis);
14302
- obj._set("scaleY", 1);
14303
- }
14304
- }
14305
14046
  obj.setCoords();
14306
14047
  obj.dirty = true;
14307
14048
  }
@@ -14393,7 +14134,7 @@ const PageCanvas = forwardRef(
14393
14134
  setGuides(gridGuidesForScale.length ? [...scaleGuides, ...gridGuidesForScale] : scaleGuides);
14394
14135
  if (drilledGroupIdRef.current) {
14395
14136
  try {
14396
- (_h = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _h.call(fabricCanvas);
14137
+ (_f = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _f.call(fabricCanvas);
14397
14138
  } catch {
14398
14139
  }
14399
14140
  }
@@ -14484,37 +14225,9 @@ const PageCanvas = forwardRef(
14484
14225
  }
14485
14226
  });
14486
14227
  fabricCanvas.on("object:rotating", (e) => {
14487
- var _a2, _b2;
14488
- prepareGroupSelectionTransformStart(e.target);
14489
14228
  markSimpleTransform(e);
14490
14229
  didTransformRef.current = true;
14491
14230
  const tr = e.target;
14492
- try {
14493
- const children = tr instanceof fabric.Group || tr instanceof fabric.ActiveSelection ? tr.getObjects() : [];
14494
- logGroupImageResizeDebug("rotating-entry", {
14495
- time: Math.round(performance.now()),
14496
- angle: tr == null ? void 0 : tr.angle,
14497
- targetType: tr == null ? void 0 : tr.type,
14498
- targetCtor: (_a2 = tr == null ? void 0 : tr.constructor) == null ? void 0 : _a2.name,
14499
- isActiveSelection: tr instanceof fabric.ActiveSelection,
14500
- isGroup: tr instanceof fabric.Group,
14501
- isCropGroup: !!(tr && (tr.__cropGroup || ((_b2 = tr._ct) == null ? void 0 : _b2.isCropGroup))),
14502
- childCount: children.length,
14503
- childTypes: children.map((c) => c == null ? void 0 : c.type),
14504
- hasImageChild: children.some((c) => isGroupResizeImageLikeObject(c)),
14505
- target: tr ? summarizeFabricObjectForResizeDebug(tr) : null,
14506
- children: children.map((c) => {
14507
- var _a3;
14508
- return {
14509
- type: c == null ? void 0 : c.type,
14510
- ctor: (_a3 = c == null ? void 0 : c.constructor) == null ? void 0 : _a3.name,
14511
- summary: summarizeFabricObjectForResizeDebug(c)
14512
- };
14513
- })
14514
- });
14515
- } catch (err) {
14516
- console.warn("[Pixldocs][group-image-side-resize] rotating-entry log failed", err);
14517
- }
14518
14231
  try {
14519
14232
  const getCursor = fabricCanvas.__pixldocsGetRotateCursor;
14520
14233
  const upper = fabricCanvas.upperCanvasEl;
@@ -14557,7 +14270,7 @@ const PageCanvas = forwardRef(
14557
14270
  setDrilledGroupBounds(null);
14558
14271
  drilledGroupIdRef.current = null;
14559
14272
  if (activeDuringMove instanceof fabric.ActiveSelection && groupIdToKeep) {
14560
- preserveLogicalGroupTagDuringMove(activeDuringMove, groupIdToKeep);
14273
+ restoreGroupSelectionVisualState(activeDuringMove, groupIdToKeep);
14561
14274
  }
14562
14275
  }
14563
14276
  if (e.target) e.target.__pixldocsDragMoved = true;
@@ -14610,7 +14323,7 @@ const PageCanvas = forwardRef(
14610
14323
  });
14611
14324
  let cropGroupSaveTimer = null;
14612
14325
  fabricCanvas.on("object:modified", (e) => {
14613
- var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k;
14326
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i;
14614
14327
  try {
14615
14328
  dragStarted = false;
14616
14329
  setGuides([]);
@@ -14619,43 +14332,18 @@ const PageCanvas = forwardRef(
14619
14332
  groupResizeActiveSnapRef.current = null;
14620
14333
  onDragEnd == null ? void 0 : onDragEnd();
14621
14334
  try {
14622
- const mt = e.target;
14623
- const children = mt instanceof fabric.Group || mt instanceof fabric.ActiveSelection ? mt.getObjects() : [];
14624
- logGroupImageResizeDebug("modified-entry", {
14625
- time: Math.round(performance.now()),
14626
- didTransform: didTransformRef.current,
14627
- targetType: mt == null ? void 0 : mt.type,
14628
- targetCtor: (_a2 = mt == null ? void 0 : mt.constructor) == null ? void 0 : _a2.name,
14629
- isActiveSelection: mt instanceof fabric.ActiveSelection,
14630
- isGroup: mt instanceof fabric.Group,
14631
- angle: mt == null ? void 0 : mt.angle,
14632
- childCount: children.length,
14633
- childTypes: children.map((c) => c == null ? void 0 : c.type),
14634
- hasImageChild: children.some((c) => isGroupResizeImageLikeObject(c)),
14635
- target: mt ? summarizeFabricObjectForResizeDebug(mt) : null,
14636
- children: children.map((c) => {
14637
- var _a3;
14638
- return {
14639
- type: c == null ? void 0 : c.type,
14640
- ctor: (_a3 = c == null ? void 0 : c.constructor) == null ? void 0 : _a3.name,
14641
- summary: summarizeFabricObjectForResizeDebug(c)
14642
- };
14643
- })
14644
- });
14645
- } catch (err) {
14646
- console.warn("[Pixldocs][group-image-side-resize] modified-entry log failed", err);
14647
- }
14648
- const modifiedTarget = e.target;
14649
- if (modifiedTarget instanceof fabric.ActiveSelection && modifiedTarget.getObjects().length === 0) {
14650
- didTransformRef.current = false;
14651
- groupSelectionTransformStartRef.current = null;
14652
- activeSelectionMoveStartRef.current = null;
14653
- activeSelectionResizeHandleRef.current = null;
14654
- unlockEditsSoon();
14655
- return;
14335
+ const t = e.target;
14336
+ if (t instanceof fabric.ActiveSelection) {
14337
+ for (const child of t.getObjects()) {
14338
+ delete child.__asLiveOrigW;
14339
+ delete child.__asLiveOrigH;
14340
+ }
14341
+ }
14342
+ } catch {
14656
14343
  }
14657
14344
  groupShiftReflowSnapshotRef.current = null;
14658
14345
  lockEdits();
14346
+ const modifiedTarget = e.target;
14659
14347
  const modifiedTargetId = modifiedTarget ? getObjectId(modifiedTarget) : null;
14660
14348
  const modifiedTargetElement = modifiedTargetId ? elementsRef.current.find((el) => el.id === modifiedTargetId) : null;
14661
14349
  if (modifiedTarget && (modifiedTargetElement == null ? void 0 : modifiedTargetElement.type) === "shape") {
@@ -14680,7 +14368,7 @@ const PageCanvas = forwardRef(
14680
14368
  const active = fabricCanvas.getActiveObject();
14681
14369
  const activeId = active ? getObjectId(active) : null;
14682
14370
  if (active && activeId && activeId !== "__background__" && !(active instanceof fabric.Group)) {
14683
- const pageChildrenForParent = ((_b2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _b2.children) ?? [];
14371
+ const pageChildrenForParent = ((_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
14684
14372
  const parentGroup = findParentGroup(pageChildrenForParent, activeId);
14685
14373
  if (parentGroup && isGroup(parentGroup) && parentGroup.backgroundColor) {
14686
14374
  let fabricSectionGroup = active.group && active.group instanceof fabric.Group ? active.group : null;
@@ -14762,7 +14450,7 @@ const PageCanvas = forwardRef(
14762
14450
  useEditorStore.getState().reflowStackGroupInPage(pageId, groupId);
14763
14451
  }
14764
14452
  const stateAfter = useEditorStore.getState();
14765
- const pageAfter = ((_c = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
14453
+ const pageAfter = ((_b2 = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _b2.children) ?? [];
14766
14454
  const groupNodeAfter = findNodeById(pageAfter, groupId);
14767
14455
  if (groupNodeAfter) {
14768
14456
  const abs = getAbsoluteBounds(groupNodeAfter, pageAfter);
@@ -14798,9 +14486,8 @@ const PageCanvas = forwardRef(
14798
14486
  const stateCrop = useEditorStore.getState();
14799
14487
  const pageCrop = stateCrop.canvas.pages.find((p) => p.id === pageId);
14800
14488
  const pageChildrenCrop = (pageCrop == null ? void 0 : pageCrop.children) ?? [];
14801
- const angleRad = (active.angle ?? 0) * Math.PI / 180;
14802
- const absLeft = (active.left ?? 0) - ct.frameW / 2 * Math.cos(angleRad) + ct.frameH / 2 * Math.sin(angleRad);
14803
- const absTop = (active.top ?? 0) - ct.frameW / 2 * Math.sin(angleRad) - ct.frameH / 2 * Math.cos(angleRad);
14489
+ const absLeft = (active.left ?? 0) - ct.frameW / 2;
14490
+ const absTop = (active.top ?? 0) - ct.frameH / 2;
14804
14491
  const storePosCrop = absoluteToStorePosition(absLeft, absTop, objId, pageChildrenCrop);
14805
14492
  updateElement2(objId, {
14806
14493
  width: ct.frameW,
@@ -14825,7 +14512,7 @@ const PageCanvas = forwardRef(
14825
14512
  }
14826
14513
  if (active && active instanceof fabric.Group && active.__docuforgeSectionGroup && getObjectId(active)) {
14827
14514
  const groupId = getObjectId(active);
14828
- const pageChildrenSec = ((_d = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _d.children) ?? [];
14515
+ const pageChildrenSec = ((_c = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
14829
14516
  const modifiedTarget2 = e == null ? void 0 : e.target;
14830
14517
  const resizeScaleTarget = lastResizeScaleTargetRef.current;
14831
14518
  lastResizeScaleTargetRef.current = null;
@@ -14856,7 +14543,7 @@ const PageCanvas = forwardRef(
14856
14543
  const node = findNodeById(pageChildrenSec, groupId);
14857
14544
  if (isChildModified && node && !groupMoved) {
14858
14545
  const stateAfter = useEditorStore.getState();
14859
- const pageAfter = ((_e = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _e.children) ?? [];
14546
+ const pageAfter = ((_d = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _d.children) ?? [];
14860
14547
  const groupNodeAfter = findNodeById(pageAfter, groupId);
14861
14548
  if (groupNodeAfter) {
14862
14549
  const abs = getAbsoluteBounds(groupNodeAfter, pageAfter);
@@ -14872,7 +14559,7 @@ const PageCanvas = forwardRef(
14872
14559
  }
14873
14560
  if (active && active instanceof fabric.Group && !(active instanceof fabric.ActiveSelection) && getObjectId(active)) {
14874
14561
  const groupId = getObjectId(active);
14875
- const pageChildren3 = ((_f = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _f.children) ?? [];
14562
+ const pageChildren3 = ((_e = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _e.children) ?? [];
14876
14563
  const w = (active.width ?? 0) * (active.scaleX ?? 1);
14877
14564
  const h = (active.height ?? 0) * (active.scaleY ?? 1);
14878
14565
  const centerX = active.left ?? 0;
@@ -14894,7 +14581,7 @@ const PageCanvas = forwardRef(
14894
14581
  }
14895
14582
  const activeObj = fabricCanvas.getActiveObject();
14896
14583
  let activeObjects = fabricCanvas.getActiveObjects();
14897
- const activeSelectionMoveStart = activeObj instanceof fabric.ActiveSelection && ((_g = activeSelectionMoveStartRef.current) == null ? void 0 : _g.selection) === activeObj ? activeSelectionMoveStartRef.current : null;
14584
+ const activeSelectionMoveStart = activeObj instanceof fabric.ActiveSelection && ((_f = activeSelectionMoveStartRef.current) == null ? void 0 : _f.selection) === activeObj ? activeSelectionMoveStartRef.current : null;
14898
14585
  const activeSelectionDelta = activeObj instanceof fabric.ActiveSelection && activeSelectionMoveStart ? (() => {
14899
14586
  const rect = activeObj.getBoundingRect();
14900
14587
  return {
@@ -14911,18 +14598,6 @@ const PageCanvas = forwardRef(
14911
14598
  const isActiveSelection = activeObj instanceof fabric.ActiveSelection || activeObjects.length > 1;
14912
14599
  const activeSelectionResizeHandle = isActiveSelection ? activeSelectionResizeHandleRef.current : null;
14913
14600
  const debugGroupTextCornerResize = activeObj instanceof fabric.ActiveSelection && isCornerResizeHandle(activeSelectionResizeHandle) && activeObjects.some((candidate) => candidate instanceof fabric.Textbox);
14914
- const debugGroupImageSideResize = activeObj instanceof fabric.ActiveSelection && (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") && activeObjects.some((candidate) => isGroupResizeImageLikeObject(candidate));
14915
- if (debugGroupImageSideResize) {
14916
- logGroupImageResizeDebug("modified-start", {
14917
- time: Math.round(performance.now()),
14918
- handle: activeSelectionResizeHandle,
14919
- target: summarizeFabricObjectForResizeDebug(modifiedTarget),
14920
- selection: summarizeFabricObjectForResizeDebug(activeObj),
14921
- activeObjectIds: activeObjects.map((candidate) => getObjectId(candidate)),
14922
- selectedStoreIds: useEditorStore.getState().canvas.selectedIds,
14923
- members: activeObjects.map((candidate) => summarizeFabricObjectForResizeDebug(candidate))
14924
- });
14925
- }
14926
14601
  if (debugGroupTextCornerResize) {
14927
14602
  logGroupTextResizeDebug("modified-start", {
14928
14603
  time: Math.round(performance.now()),
@@ -14955,14 +14630,7 @@ const PageCanvas = forwardRef(
14955
14630
  const node = findNodeById(pageChildren2, id);
14956
14631
  return !!(node && isGroup(node));
14957
14632
  });
14958
- const activeSelectionHadTransform = activeObj instanceof fabric.ActiveSelection && (Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01 || (() => {
14959
- var _a3;
14960
- const normAngle = (angle) => (angle % 360 + 360) % 360;
14961
- const startAngle = ((_a3 = groupSelectionTransformStartRef.current) == null ? void 0 : _a3.selection) === activeObj ? groupSelectionTransformStartRef.current.selectionAngle : 0;
14962
- const currentAngle = normAngle(activeObj.angle ?? 0);
14963
- const diff = Math.abs(currentAngle - normAngle(startAngle));
14964
- return Math.min(diff, 360 - diff) > 1;
14965
- })());
14633
+ const activeSelectionHadTransform = activeObj instanceof fabric.ActiveSelection && (Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01 || Math.abs((activeObj.angle ?? 0) % 360) > 0.01);
14966
14634
  if (!anyCropGroup && activeSelectionDelta && !activeSelectionHadTransform && selectedLogicalGroupIds.length > 0) {
14967
14635
  const selectedStoreIds = useEditorStore.getState().canvas.selectedIds ?? [];
14968
14636
  const groupMemberIds = /* @__PURE__ */ new Set();
@@ -15003,13 +14671,7 @@ const PageCanvas = forwardRef(
15003
14671
  return;
15004
14672
  }
15005
14673
  }
15006
- const isActiveSelectionSideResize = isActiveSelection && (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb");
15007
- const normalizeAngle = (angle) => (angle % 360 + 360) % 360;
15008
- const shortestAngleDelta = (a, b) => {
15009
- const diff = Math.abs(normalizeAngle(a) - normalizeAngle(b));
15010
- return Math.min(diff, 360 - diff);
15011
- };
15012
- if (selectedElementIds.length > 0) {
14674
+ if (selectedElementIds.length > 0 && !anyCropGroup) {
15013
14675
  const firstObj = activeObjects[0];
15014
14676
  const firstId = getObjectId(firstObj);
15015
14677
  const parentGroups = selectedElementIds.map((id) => findParentGroup(pageChildren2, id)).filter((g) => g !== null);
@@ -15032,9 +14694,9 @@ const PageCanvas = forwardRef(
15032
14694
  let movedGroupLeft = groupAbs.left;
15033
14695
  let movedGroupTop = groupAbs.top;
15034
14696
  if (activeObj instanceof fabric.ActiveSelection && (transformStart == null ? void 0 : transformStart.groupId) === groupToMove.id) {
15035
- const selectionCenter = activeObj.getCenterPoint();
15036
- movedGroupLeft = transformStart.groupLeft + (selectionCenter.x - transformStart.selectionCenterX);
15037
- movedGroupTop = transformStart.groupTop + (selectionCenter.y - transformStart.selectionCenterY);
14697
+ const selectionRect = activeObj.getBoundingRect();
14698
+ movedGroupLeft = transformStart.groupLeft + (selectionRect.left - transformStart.selectionLeft);
14699
+ movedGroupTop = transformStart.groupTop + (selectionRect.top - transformStart.selectionTop);
15038
14700
  } else if (activeObj instanceof fabric.ActiveSelection && firstId && firstObj) {
15039
14701
  const firstNode = findNodeById(pageChildren2, firstId);
15040
14702
  if (firstNode) {
@@ -15070,58 +14732,19 @@ const PageCanvas = forwardRef(
15070
14732
  }
15071
14733
  const deltaX = movedGroupLeft - groupAbs.left;
15072
14734
  const deltaY = movedGroupTop - groupAbs.top;
15073
- const hadResizeHandle = isActiveSelection && !!activeSelectionResizeHandle;
15074
- const hadScale = isActiveSelection && activeObj && (hadResizeHandle || Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01);
15075
- const startSelAngle = normalizeAngle((transformStart == null ? void 0 : transformStart.selectionAngle) ?? 0);
15076
- const currentSelAngle = isActiveSelection && activeObj ? normalizeAngle(activeObj.angle ?? 0) : 0;
15077
- const storedGroupAngle = normalizeAngle(Number(groupToMove.angle ?? 0));
15078
- const effectiveStartAngle = transformStart ? startSelAngle : storedGroupAngle;
15079
- const angleDelta = shortestAngleDelta(currentSelAngle, effectiveStartAngle);
15080
- const hadRotation = isActiveSelection && activeObj && angleDelta > 1;
15081
- if (activeGroupSelectionId === groupToMove.id && hadRotation && !hadScale && !activeSelectionResizeHandle && activeObj instanceof fabric.ActiveSelection) {
15082
- const { updateNode: updateNodeStore, commitHistory: commitHistoryStore, getCurrentElements } = useEditorStore.getState();
15083
- const center = activeObj.getCenterPoint();
15084
- const baseCenterX = (transformStart == null ? void 0 : transformStart.selectionCenterX) ?? groupAbs.left + groupAbs.width / 2;
15085
- const baseCenterY = (transformStart == null ? void 0 : transformStart.selectionCenterY) ?? groupAbs.top + groupAbs.height / 2;
15086
- const nextAbsLeft = groupAbs.left + (center.x - baseCenterX);
15087
- const nextAbsTop = groupAbs.top + (center.y - baseCenterY);
15088
- const storePos = absoluteToStorePosition(nextAbsLeft, nextAbsTop, groupToMove.id, pageChildren2);
15089
- updateNodeStore(groupToMove.id, {
15090
- left: storePos.left,
15091
- top: storePos.top,
15092
- angle: currentSelAngle
15093
- }, { recordHistory: false, skipLayoutRecalc: true });
15094
- commitHistoryStore();
15095
- restoreGroupSelectionVisualState(activeObj, groupToMove.id);
15096
- fabricCanvas.setActiveObject(activeObj);
15097
- activeObj.setCoords();
15098
- selectElements([groupToMove.id], false, false);
15099
- fabricCanvas.requestRenderAll();
15100
- elementsRef.current = getCurrentElements();
15101
- const restoreSnapshot = {
15102
- memberIds: activeObj.getObjects().map((obj) => getObjectId(obj)).filter((id) => !!id && id !== "__background__"),
15103
- groupSelectionId: groupToMove.id,
15104
- expiresAt: Date.now() + 1200
15105
- };
15106
- recentGroupSelectionRestoreRef.current = restoreSnapshot;
15107
- activeObj.getObjects().forEach((obj) => {
15108
- const objId = getObjectId(obj);
15109
- if (objId && objId !== "__background__") {
15110
- justModifiedIdsRef.current.add(objId);
15111
- modifiedIdsThisRound.add(objId);
15112
- }
15113
- });
15114
- setTimeout(() => modifiedIdsThisRound.forEach((id) => justModifiedIdsRef.current.delete(id)), 150);
15115
- groupSelectionTransformStartRef.current = null;
15116
- activeSelectionMoveStartRef.current = null;
15117
- activeSelectionResizeHandleRef.current = null;
15118
- unlockEditsSoon();
15119
- return;
15120
- }
15121
- if (!isActiveSelectionSideResize && !hadScale && !hadRotation && (Math.abs(deltaX) > 0.1 || Math.abs(deltaY) > 0.1)) {
14735
+ const hadScale = isActiveSelection && activeObj && (Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01);
14736
+ const startSelAngle = (((transformStart == null ? void 0 : transformStart.selectionAngle) ?? 0) % 360 + 360) % 360;
14737
+ const currentSelAngle = isActiveSelection && activeObj ? ((activeObj.angle ?? 0) % 360 + 360) % 360 : 0;
14738
+ const angleDelta = Math.min(
14739
+ Math.abs(currentSelAngle - startSelAngle),
14740
+ 360 - Math.abs(currentSelAngle - startSelAngle)
14741
+ );
14742
+ const hadRotation = isActiveSelection && activeObj && angleDelta > 0.01;
14743
+ if (!hadScale && !hadRotation && (Math.abs(deltaX) > 0.1 || Math.abs(deltaY) > 0.1)) {
15122
14744
  const { updateNode: updateNodeStore, commitHistory: commitHistoryStore, getCurrentElements } = useEditorStore.getState();
15123
- const storePos = absoluteToStorePosition(movedGroupLeft, movedGroupTop, groupToMove.id, pageChildren2);
15124
- updateNodeStore(groupToMove.id, { left: storePos.left, top: storePos.top }, { recordHistory: false, skipLayoutRecalc: true });
14745
+ const newLeft = (groupToMove.left ?? 0) + deltaX;
14746
+ const newTop = (groupToMove.top ?? 0) + deltaY;
14747
+ updateNodeStore(groupToMove.id, { left: newLeft, top: newTop }, { recordHistory: false, skipLayoutRecalc: true });
15125
14748
  commitHistoryStore();
15126
14749
  pendingGroupDrillInRef.current = null;
15127
14750
  fabricCanvas.__activeEditingGroupId = null;
@@ -15146,8 +14769,6 @@ const PageCanvas = forwardRef(
15146
14769
  }
15147
14770
  setTimeout(() => modifiedIdsThisRound.forEach((id) => justModifiedIdsRef.current.delete(id)), 150);
15148
14771
  groupSelectionTransformStartRef.current = null;
15149
- activeSelectionMoveStartRef.current = null;
15150
- activeSelectionResizeHandleRef.current = null;
15151
14772
  const restoreSnapshot = {
15152
14773
  memberIds: targetObjects.map((obj) => getObjectId(obj)).filter((id) => !!id && id !== "__background__"),
15153
14774
  groupSelectionId,
@@ -15161,38 +14782,6 @@ const PageCanvas = forwardRef(
15161
14782
  }
15162
14783
  }
15163
14784
  const pendingCropGroupFrameBakes = [];
15164
- const logicalGroupSelectionId = activeObj instanceof fabric.ActiveSelection ? activeObj.__pixldocsGroupSelection : void 0;
15165
- const isLogicalGroupAS = !!logicalGroupSelectionId && !(activeObj == null ? void 0 : activeObj.__cropGroup) && !(activeObj == null ? void 0 : activeObj.__docuforgeSectionGroup);
15166
- const logicalGroupNodeForBake = logicalGroupSelectionId ? findNodeById(pageChildren2, logicalGroupSelectionId) : null;
15167
- const asAngleForBake = isLogicalGroupAS && activeObj ? normalizeAngle(Number(activeObj.angle ?? 0)) : 0;
15168
- const logicalGroupFinalFrame = (() => {
15169
- var _a3;
15170
- if (!isLogicalGroupAS || !logicalGroupSelectionId || !(activeObj instanceof fabric.ActiveSelection)) return null;
15171
- const baseline = ((_a3 = groupSelectionTransformStartRef.current) == null ? void 0 : _a3.groupId) === logicalGroupSelectionId ? groupSelectionTransformStartRef.current : null;
15172
- const localWidth = Math.max(1, (activeObj.width ?? (baseline == null ? void 0 : baseline.groupWidth) ?? 1) * Math.abs(activeObj.scaleX ?? 1));
15173
- const localHeight = Math.max(1, (activeObj.height ?? (baseline == null ? void 0 : baseline.groupHeight) ?? 1) * Math.abs(activeObj.scaleY ?? 1));
15174
- const center = activeObj.getCenterPoint();
15175
- const topLeft = centerToRotatedTopLeft(center.x, center.y, localWidth, localHeight, asAngleForBake);
15176
- return {
15177
- groupId: logicalGroupSelectionId,
15178
- left: topLeft.left,
15179
- top: topLeft.top,
15180
- width: localWidth,
15181
- height: localHeight,
15182
- centerX: center.x,
15183
- centerY: center.y,
15184
- angle: asAngleForBake,
15185
- matrix: fabric.util.composeMatrix({
15186
- translateX: center.x,
15187
- translateY: center.y,
15188
- angle: asAngleForBake,
15189
- scaleX: 1,
15190
- scaleY: 1,
15191
- skewX: 0,
15192
- skewY: 0
15193
- })
15194
- };
15195
- })();
15196
14785
  for (const obj of activeObjects) {
15197
14786
  const objId = getObjectId(obj);
15198
14787
  if (!objId || objId === "__background__") continue;
@@ -15238,15 +14827,16 @@ const PageCanvas = forwardRef(
15238
14827
  modifiedIdsThisRound.add(objId);
15239
14828
  let absoluteLeft;
15240
14829
  let absoluteTop;
15241
- const initialTopLeft = centerToRotatedTopLeft(
15242
- decomposed.translateX ?? (obj.left ?? 0),
15243
- decomposed.translateY ?? (obj.top ?? 0),
15244
- intrinsicWidth * Math.abs(decomposed.scaleX || 1),
15245
- intrinsicHeight * Math.abs(decomposed.scaleY || 1),
15246
- decomposed.angle ?? 0
15247
- );
15248
- absoluteLeft = initialTopLeft.left;
15249
- absoluteTop = initialTopLeft.top;
14830
+ if (isActiveSelection && activeObj) {
14831
+ const selectionMatrix = activeObj.calcTransformMatrix();
14832
+ const relativePoint = { x: obj.left ?? 0, y: obj.top ?? 0 };
14833
+ const absolutePoint = fabric.util.transformPoint(relativePoint, selectionMatrix);
14834
+ absoluteLeft = absolutePoint.x;
14835
+ absoluteTop = absolutePoint.y;
14836
+ } else {
14837
+ absoluteLeft = obj.left ?? 0;
14838
+ absoluteTop = obj.top ?? 0;
14839
+ }
15250
14840
  if (obj instanceof fabric.Group && obj.__cropGroup) {
15251
14841
  const ct = obj.__cropData;
15252
14842
  if (isActiveSelection && activeObj instanceof fabric.ActiveSelection) {
@@ -15256,22 +14846,14 @@ const PageCanvas = forwardRef(
15256
14846
  } else {
15257
14847
  const w = ((ct == null ? void 0 : ct.frameW) ?? obj.width ?? 0) * Math.abs(obj.scaleX ?? 1);
15258
14848
  const h = ((ct == null ? void 0 : ct.frameH) ?? obj.height ?? 0) * Math.abs(obj.scaleY ?? 1);
15259
- const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
15260
- absoluteLeft = (decomposed.translateX ?? absoluteLeft ?? 0) - w / 2 * Math.cos(angleRad) + h / 2 * Math.sin(angleRad);
15261
- absoluteTop = (decomposed.translateY ?? absoluteTop ?? 0) - w / 2 * Math.sin(angleRad) - h / 2 * Math.cos(angleRad);
14849
+ absoluteLeft = (absoluteLeft ?? 0) - w / 2;
14850
+ absoluteTop = (absoluteTop ?? 0) - h / 2;
15262
14851
  }
15263
14852
  } else if (obj instanceof fabric.FabricImage && (obj.originX === "center" || obj.originY === "center")) {
15264
- if (isActiveSelection && activeObj instanceof fabric.ActiveSelection) {
15265
- const frameBounds = getObjectFrameBoundsInSelection(activeObj, obj, obj.width ?? 0, obj.height ?? 0);
15266
- absoluteLeft = frameBounds.left;
15267
- absoluteTop = frameBounds.top;
15268
- } else {
15269
- const w = (obj.width ?? 0) * (obj.scaleX ?? 1);
15270
- const h = (obj.height ?? 0) * (obj.scaleY ?? 1);
15271
- const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
15272
- absoluteLeft = (decomposed.translateX ?? absoluteLeft ?? 0) - w / 2 * Math.cos(angleRad) + h / 2 * Math.sin(angleRad);
15273
- absoluteTop = (decomposed.translateY ?? absoluteTop ?? 0) - w / 2 * Math.sin(angleRad) - h / 2 * Math.cos(angleRad);
15274
- }
14853
+ const w = (obj.width ?? 0) * (obj.scaleX ?? 1);
14854
+ const h = (obj.height ?? 0) * (obj.scaleY ?? 1);
14855
+ absoluteLeft = (absoluteLeft ?? 0) - w / 2;
14856
+ absoluteTop = (absoluteTop ?? 0) - h / 2;
15275
14857
  }
15276
14858
  const preserveCornerGeometry = (sourceElement == null ? void 0 : sourceElement.type) === "shape" && (sourceElement.shapeType === "circle" || sourceElement.shapeType === "rounded-rect" || sourceElement.shapeType === "triangle");
15277
14859
  let finalWidth = intrinsicWidth;
@@ -15279,10 +14861,6 @@ const PageCanvas = forwardRef(
15279
14861
  let finalScaleX = decomposed.scaleX;
15280
14862
  let finalScaleY = decomposed.scaleY;
15281
14863
  let finalAbsoluteMatrix = absoluteMatrix;
15282
- let finalAngle = decomposed.angle;
15283
- let finalSkewX = decomposed.skewX;
15284
- let finalSkewY = decomposed.skewY;
15285
- let finalAngleFromDecomposed = true;
15286
14864
  if (obj instanceof fabric.Group && obj.__cropGroup) {
15287
14865
  const ct = obj.__cropData;
15288
14866
  if (ct) {
@@ -15299,14 +14877,12 @@ const PageCanvas = forwardRef(
15299
14877
  absoluteLeft = frameBounds.left;
15300
14878
  absoluteTop = frameBounds.top;
15301
14879
  } else {
15302
- const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
15303
- absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2 * Math.cos(angleRad) + finalHeight / 2 * Math.sin(angleRad);
15304
- absoluteTop = (decomposed.translateY ?? absoluteTop) - finalWidth / 2 * Math.sin(angleRad) - finalHeight / 2 * Math.cos(angleRad);
14880
+ absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2;
14881
+ absoluteTop = (decomposed.translateY ?? absoluteTop) - finalHeight / 2;
15305
14882
  }
15306
- const finalCenter = rotatedTopLeftToCenter(absoluteLeft, absoluteTop, finalWidth, finalHeight, decomposed.angle ?? (obj.angle ?? 0));
15307
14883
  finalAbsoluteMatrix = fabric.util.composeMatrix({
15308
- translateX: finalCenter.x,
15309
- translateY: finalCenter.y,
14884
+ translateX: absoluteLeft + finalWidth / 2,
14885
+ translateY: absoluteTop + finalHeight / 2,
15310
14886
  angle: decomposed.angle ?? (obj.angle ?? 0),
15311
14887
  scaleX: 1,
15312
14888
  scaleY: 1,
@@ -15341,12 +14917,6 @@ const PageCanvas = forwardRef(
15341
14917
  finalHeight = bakedH;
15342
14918
  finalScaleX = 1;
15343
14919
  finalScaleY = 1;
15344
- if (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") {
15345
- finalAngle = (sourceElement == null ? void 0 : sourceElement.angle) ?? obj.angle ?? decomposed.angle;
15346
- finalSkewX = (sourceElement == null ? void 0 : sourceElement.skewX) ?? obj.skewX ?? 0;
15347
- finalSkewY = (sourceElement == null ? void 0 : sourceElement.skewY) ?? obj.skewY ?? 0;
15348
- if ((sourceElement == null ? void 0 : sourceElement.angle) !== void 0 || obj.angle !== void 0) finalAngleFromDecomposed = false;
15349
- }
15350
14920
  obj.set({ scaleX: 1, scaleY: 1 });
15351
14921
  const newSrc = renderSmartElementToDataUri(sourceElement.smartElementType, sourceElement.smartProps, bakedW, bakedH);
15352
14922
  if (newSrc) {
@@ -15362,7 +14932,6 @@ const PageCanvas = forwardRef(
15362
14932
  useEditorStore.getState().updateElement(objId, { src: newSrc }, { recordHistory: false, skipLayoutRecalc: true });
15363
14933
  }
15364
14934
  } else if (isActiveSelection && (Math.abs((decomposed.scaleX ?? 1) - 1) > 1e-3 || Math.abs((decomposed.scaleY ?? 1) - 1) > 1e-3)) {
15365
- const debugImageBeforeBake = debugGroupImageSideResize ? summarizeFabricObjectForResizeDebug(obj) : null;
15366
14935
  const sx = Math.abs(decomposed.scaleX || 1);
15367
14936
  const sy = Math.abs(decomposed.scaleY || 1);
15368
14937
  const handle = activeSelectionResizeHandle;
@@ -15396,9 +14965,22 @@ const PageCanvas = forwardRef(
15396
14965
  const localScaleX = 1 / sx;
15397
14966
  const localScaleY = 1 / sy;
15398
14967
  obj.set({ scaleX: localScaleX, scaleY: localScaleY });
15399
- const selectionMatrix = (_h = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _h.call(activeObj);
14968
+ const selectionMatrix = (_g = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _g.call(activeObj);
15400
14969
  const localCenter = selectionMatrix ? fabric.util.transformPoint(preBakeCenter, fabric.util.invertTransform(selectionMatrix)) : preBakeCenter;
15401
- obj.setPositionByOrigin(localCenter, "center", "center");
14970
+ const localWidth = bakedW * localScaleX;
14971
+ const localHeight = bakedH * localScaleY;
14972
+ const isCenterOrigin = obj.originX === "center" || obj.originY === "center";
14973
+ if (isCenterOrigin) {
14974
+ obj.set({
14975
+ left: localCenter.x,
14976
+ top: localCenter.y
14977
+ });
14978
+ } else {
14979
+ obj.set({
14980
+ left: localCenter.x - localWidth / 2,
14981
+ top: localCenter.y - localHeight / 2
14982
+ });
14983
+ }
15402
14984
  }
15403
14985
  obj.dirty = true;
15404
14986
  if (activeObj) activeObj.dirty = true;
@@ -15409,63 +14991,34 @@ const PageCanvas = forwardRef(
15409
14991
  finalHeight = bakedH;
15410
14992
  finalScaleX = 1;
15411
14993
  finalScaleY = 1;
15412
- if (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") {
15413
- finalAngle = (sourceElement == null ? void 0 : sourceElement.angle) ?? obj.angle ?? decomposed.angle;
15414
- finalSkewX = (sourceElement == null ? void 0 : sourceElement.skewX) ?? obj.skewX ?? 0;
15415
- finalSkewY = (sourceElement == null ? void 0 : sourceElement.skewY) ?? obj.skewY ?? 0;
15416
- if ((sourceElement == null ? void 0 : sourceElement.angle) !== void 0 || obj.angle !== void 0) finalAngleFromDecomposed = false;
15417
- }
15418
14994
  try {
15419
- const angleRad = (finalAngle ?? 0) * Math.PI / 180;
14995
+ const angleRad = (decomposed.angle ?? 0) * Math.PI / 180;
15420
14996
  const cos = Math.cos(angleRad);
15421
14997
  const sin = Math.sin(angleRad);
15422
14998
  const hw = finalWidth / 2;
15423
14999
  const hh = finalHeight / 2;
15424
- absoluteLeft = decomposed.translateX - hw * cos + hh * sin;
15425
- absoluteTop = decomposed.translateY - hw * sin - hh * cos;
15000
+ const corners = [
15001
+ { x: -hw, y: -hh },
15002
+ { x: hw, y: -hh },
15003
+ { x: hw, y: hh },
15004
+ { x: -hw, y: hh }
15005
+ ].map((p) => ({
15006
+ x: decomposed.translateX + p.x * cos - p.y * sin,
15007
+ y: decomposed.translateY + p.x * sin + p.y * cos
15008
+ }));
15009
+ absoluteLeft = Math.min(...corners.map((p) => p.x));
15010
+ absoluteTop = Math.min(...corners.map((p) => p.y));
15426
15011
  } catch {
15427
15012
  }
15428
15013
  finalAbsoluteMatrix = fabric.util.composeMatrix({
15429
15014
  translateX: decomposed.translateX,
15430
15015
  translateY: decomposed.translateY,
15431
- angle: finalAngle ?? 0,
15016
+ angle: decomposed.angle ?? 0,
15432
15017
  scaleX: 1,
15433
15018
  scaleY: 1,
15434
- skewX: finalSkewX ?? 0,
15435
- skewY: finalSkewY ?? 0
15019
+ skewX: 0,
15020
+ skewY: 0
15436
15021
  });
15437
- if (debugGroupImageSideResize) {
15438
- logGroupImageResizeDebug("image-bake", {
15439
- time: Math.round(performance.now()),
15440
- handle: activeSelectionResizeHandle,
15441
- imageId: objId,
15442
- source: sourceElement ? {
15443
- left: sourceElement.left,
15444
- top: sourceElement.top,
15445
- width: sourceElement.width,
15446
- height: sourceElement.height,
15447
- angle: sourceElement.angle,
15448
- scaleX: sourceElement.scaleX,
15449
- scaleY: sourceElement.scaleY
15450
- } : null,
15451
- factors: { sx, sy, fx, fy, isCornerHandle },
15452
- beforeBake: debugImageBeforeBake,
15453
- afterBake: summarizeFabricObjectForResizeDebug(obj),
15454
- persistedGeometry: {
15455
- absoluteLeft,
15456
- absoluteTop,
15457
- finalWidth,
15458
- finalHeight,
15459
- finalScaleX,
15460
- finalScaleY,
15461
- finalAngle,
15462
- finalSkewX,
15463
- finalSkewY,
15464
- decomposed,
15465
- finalAbsoluteMatrix
15466
- }
15467
- });
15468
- }
15469
15022
  } else {
15470
15023
  finalWidth = intrinsicWidth;
15471
15024
  finalHeight = intrinsicHeight;
@@ -15475,33 +15028,16 @@ const PageCanvas = forwardRef(
15475
15028
  finalHeight = 0;
15476
15029
  finalScaleX = 1;
15477
15030
  finalScaleY = 1;
15478
- if (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") {
15479
- finalAngle = (sourceElement == null ? void 0 : sourceElement.angle) ?? obj.angle ?? decomposed.angle;
15480
- finalSkewX = (sourceElement == null ? void 0 : sourceElement.skewX) ?? obj.skewX ?? 0;
15481
- finalSkewY = (sourceElement == null ? void 0 : sourceElement.skewY) ?? obj.skewY ?? 0;
15482
- if ((sourceElement == null ? void 0 : sourceElement.angle) !== void 0 || obj.angle !== void 0) finalAngleFromDecomposed = false;
15483
- }
15484
- } else if (obj instanceof fabric.Textbox && isActiveSelection && (activeSelectionResizeHandle != null || obj.__asLiveOrigW != null || obj.__asLiveOrigH != null || Math.abs((decomposed.scaleX ?? 1) - 1) > 1e-3 || Math.abs((decomposed.scaleY ?? 1) - 1) > 1e-3)) {
15485
- const liveOrigW = obj.__asLiveOrigW;
15486
- const liveOrigH = obj.__asLiveOrigH;
15487
- const decSx = Math.abs(decomposed.scaleX || 1);
15488
- const decSy = Math.abs(decomposed.scaleY || 1);
15489
- const sx = Math.abs(decSx - 1) < 1e-3 && liveOrigW && liveOrigW > 0 ? Math.max(1e-3, (obj.width ?? liveOrigW) / liveOrigW) : decSx;
15490
- const baseHForRecover = Number(
15491
- obj.minBoxHeight ?? obj.height ?? liveOrigH ?? 1
15492
- );
15493
- const sy = Math.abs(decSy - 1) < 1e-3 && liveOrigH && liveOrigH > 0 ? Math.max(1e-3, baseHForRecover / liveOrigH) : decSy;
15031
+ } else if (obj instanceof fabric.Textbox && isActiveSelection && (Math.abs((decomposed.scaleX ?? 1) - 1) > 1e-3 || Math.abs((decomposed.scaleY ?? 1) - 1) > 1e-3)) {
15032
+ const sx = Math.abs(decomposed.scaleX || 1);
15033
+ const sy = Math.abs(decomposed.scaleY || 1);
15494
15034
  const isLikelyUniformCorner = !activeSelectionResizeHandle && Math.abs(sx - sy) < 0.01 && Math.abs(sx - 1) > 1e-3;
15495
15035
  const isCornerHandle = activeSelectionResizeHandle === "tl" || activeSelectionResizeHandle === "tr" || activeSelectionResizeHandle === "bl" || activeSelectionResizeHandle === "br" || isLikelyUniformCorner;
15496
15036
  const isHeightSideHandle = activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb";
15497
15037
  const fontScale = isCornerHandle ? Math.max(1e-3, Math.sqrt(sx * sy)) : 1;
15498
- const widthBase = liveOrigW && liveOrigW > 0 ? liveOrigW : intrinsicWidth;
15499
- const heightBase = liveOrigH && liveOrigH > 0 ? liveOrigH : intrinsicHeight;
15500
- const bakedWidth = Math.max(20, widthBase * sx);
15501
- const liveMinHOrig = obj.__asLiveOrigMinH;
15502
- const currentMinH = Number(obj.minBoxHeight ?? (sourceElement == null ? void 0 : sourceElement.minBoxHeight));
15503
- const minHBase = Number.isFinite(liveMinHOrig) && liveMinHOrig > 0 ? liveMinHOrig : liveOrigH && liveOrigH > 0 ? currentMinH / sy : currentMinH;
15504
- const nextMinH = Number.isFinite(minHBase) && minHBase > 0 ? minHBase * sy : isHeightSideHandle ? Math.max(1, heightBase * sy) : void 0;
15038
+ const bakedWidth = Math.max(20, intrinsicWidth * sx);
15039
+ const baseMinH = Number(obj.minBoxHeight ?? (sourceElement == null ? void 0 : sourceElement.minBoxHeight));
15040
+ const nextMinH = Number.isFinite(baseMinH) && baseMinH > 0 ? baseMinH * sy : isHeightSideHandle ? Math.max(1, intrinsicHeight * sy) : void 0;
15505
15041
  const bakedTextScaleUpdates = { width: bakedWidth };
15506
15042
  const debugTextBeforeBake = debugGroupTextCornerResize ? summarizeFabricObjectForResizeDebug(obj) : null;
15507
15043
  finalScaleX = 1;
@@ -15560,9 +15096,14 @@ const PageCanvas = forwardRef(
15560
15096
  const localScaleX = 1 / sx;
15561
15097
  const localScaleY = 1 / sy;
15562
15098
  obj.set({ scaleX: localScaleX, scaleY: localScaleY });
15563
- const selectionMatrix = (_i = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _i.call(activeObj);
15099
+ const selectionMatrix = (_h = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _h.call(activeObj);
15564
15100
  const localCenter = selectionMatrix ? fabric.util.transformPoint(preBakeCenter, fabric.util.invertTransform(selectionMatrix)) : preBakeCenter;
15565
- obj.setPositionByOrigin(localCenter, "center", "center");
15101
+ const localWidth = bakedWidth * localScaleX;
15102
+ const localHeight = (obj.height ?? intrinsicHeight) * localScaleY;
15103
+ obj.set({
15104
+ left: localCenter.x - localWidth / 2,
15105
+ top: localCenter.y - localHeight / 2
15106
+ });
15566
15107
  } else {
15567
15108
  obj.setPositionByOrigin(preBakeCenter, "center", "center");
15568
15109
  }
@@ -15575,23 +15116,32 @@ const PageCanvas = forwardRef(
15575
15116
  } catch {
15576
15117
  }
15577
15118
  try {
15578
- const angleRad = (finalAngle ?? 0) * Math.PI / 180;
15119
+ const angleRad = (decomposed.angle ?? 0) * Math.PI / 180;
15579
15120
  const cos = Math.cos(angleRad);
15580
15121
  const sin = Math.sin(angleRad);
15581
15122
  const hw = finalWidth / 2;
15582
15123
  const hh = finalHeight / 2;
15583
- absoluteLeft = decomposed.translateX - hw * cos + hh * sin;
15584
- absoluteTop = decomposed.translateY - hw * sin - hh * cos;
15124
+ const corners = [
15125
+ { x: -hw, y: -hh },
15126
+ { x: hw, y: -hh },
15127
+ { x: hw, y: hh },
15128
+ { x: -hw, y: hh }
15129
+ ].map((p) => ({
15130
+ x: decomposed.translateX + p.x * cos - p.y * sin,
15131
+ y: decomposed.translateY + p.x * sin + p.y * cos
15132
+ }));
15133
+ absoluteLeft = Math.min(...corners.map((p) => p.x));
15134
+ absoluteTop = Math.min(...corners.map((p) => p.y));
15585
15135
  } catch {
15586
15136
  }
15587
15137
  finalAbsoluteMatrix = fabric.util.composeMatrix({
15588
15138
  translateX: decomposed.translateX,
15589
15139
  translateY: decomposed.translateY,
15590
- angle: finalAngle ?? 0,
15140
+ angle: decomposed.angle ?? 0,
15591
15141
  scaleX: 1,
15592
15142
  scaleY: 1,
15593
- skewX: finalSkewX ?? 0,
15594
- skewY: finalSkewY ?? 0
15143
+ skewX: 0,
15144
+ skewY: 0
15595
15145
  });
15596
15146
  if (debugGroupTextCornerResize) {
15597
15147
  logGroupTextResizeDebug("text-bake", {
@@ -15646,21 +15196,7 @@ const PageCanvas = forwardRef(
15646
15196
  const state = useEditorStore.getState();
15647
15197
  const page = state.canvas.pages.find((p) => p.id === pageId);
15648
15198
  const pageChildrenForSave = (page == null ? void 0 : page.children) ?? [];
15649
- const storePos = (logicalGroupFinalFrame == null ? void 0 : logicalGroupFinalFrame.groupId) === logicalGroupSelectionId ? (() => {
15650
- const localCenter = fabric.util.transformPoint(
15651
- new fabric.Point(decomposed.translateX ?? 0, decomposed.translateY ?? 0),
15652
- fabric.util.invertTransform(logicalGroupFinalFrame.matrix)
15653
- );
15654
- const localAngle = finalAngleFromDecomposed ? ((Number(finalAngle ?? 0) - asAngleForBake) % 360 + 540) % 360 - 180 : Number(finalAngle ?? 0);
15655
- const localAngleRad = localAngle * Math.PI / 180;
15656
- return {
15657
- left: localCenter.x - finalWidth / 2 * Math.cos(localAngleRad) + finalHeight / 2 * Math.sin(localAngleRad) + logicalGroupFinalFrame.width / 2,
15658
- top: localCenter.y - finalWidth / 2 * Math.sin(localAngleRad) - finalHeight / 2 * Math.cos(localAngleRad) + logicalGroupFinalFrame.height / 2
15659
- };
15660
- })() : absoluteToStorePosition(absoluteLeft, absoluteTop, objId, pageChildrenForSave);
15661
- if (isLogicalGroupAS && finalAngleFromDecomposed && typeof finalAngle === "number") {
15662
- finalAngle = ((finalAngle - asAngleForBake) % 360 + 540) % 360 - 180;
15663
- }
15199
+ const storePos = absoluteToStorePosition(absoluteLeft, absoluteTop, objId, pageChildrenForSave);
15664
15200
  const isLineObj = obj instanceof fabric.Line;
15665
15201
  const isAutoShrinkText = (sourceElement == null ? void 0 : sourceElement.type) === "text" && sourceElement.overflowPolicy === "auto-shrink";
15666
15202
  const autoShrinkStoredHeight = isAutoShrinkText ? sourceElement.height : void 0;
@@ -15672,17 +15208,13 @@ const PageCanvas = forwardRef(
15672
15208
  // so finalWidth already reflects the new width chosen by the user.
15673
15209
  width: finalWidth,
15674
15210
  height: isLineObj ? 0 : isAutoShrinkText ? typeof autoShrinkStoredHeight === "number" ? autoShrinkStoredHeight : finalHeight : finalHeight,
15675
- angle: finalAngle,
15676
- skewX: isLineObj ? 0 : finalSkewX,
15677
- skewY: isLineObj ? 0 : finalSkewY,
15211
+ angle: decomposed.angle,
15212
+ skewX: isLineObj ? 0 : decomposed.skewX,
15213
+ skewY: isLineObj ? 0 : decomposed.skewY,
15678
15214
  scaleX: finalScaleX,
15679
- scaleY: finalScaleY
15215
+ scaleY: finalScaleY,
15216
+ transformMatrix: finalAbsoluteMatrix
15680
15217
  };
15681
- if (!isLogicalGroupAS) {
15682
- elementUpdate.transformMatrix = finalAbsoluteMatrix;
15683
- } else {
15684
- elementUpdate.transformMatrix = void 0;
15685
- }
15686
15218
  if (obj instanceof fabric.Textbox) {
15687
15219
  const bakedTextScaleUpdates = obj.__pixldocsBakedTextScaleUpdates;
15688
15220
  if (bakedTextScaleUpdates && typeof bakedTextScaleUpdates === "object") {
@@ -15713,41 +15245,10 @@ const PageCanvas = forwardRef(
15713
15245
  objectBeforeStoreWrite: summarizeFabricObjectForResizeDebug(obj)
15714
15246
  });
15715
15247
  }
15716
- if (debugGroupImageSideResize && isGroupResizeImageLikeObject(obj)) {
15717
- logGroupImageResizeDebug("store-update-image", {
15718
- time: Math.round(performance.now()),
15719
- handle: activeSelectionResizeHandle,
15720
- imageId: objId,
15721
- storePos,
15722
- elementUpdate,
15723
- objectBeforeStoreWrite: summarizeFabricObjectForResizeDebug(obj)
15724
- });
15725
- }
15726
15248
  updateElement(objId, elementUpdate, { recordHistory: false, skipLayoutRecalc: true });
15727
15249
  obj.setCoords();
15728
- delete obj.__asLiveOrigW;
15729
- delete obj.__asLiveOrigH;
15730
- delete obj.__asLiveOrigMinH;
15731
15250
  }
15732
- if (isLogicalGroupAS && logicalGroupSelectionId && activeObj instanceof fabric.ActiveSelection) {
15733
- try {
15734
- const pageChildrenForGroup = ((_j = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _j.children) ?? [];
15735
- const groupNode = findNodeById(pageChildrenForGroup, logicalGroupSelectionId);
15736
- if (groupNode && logicalGroupFinalFrame) {
15737
- const storePosGroup = absoluteToStorePosition(logicalGroupFinalFrame.left, logicalGroupFinalFrame.top, logicalGroupSelectionId, pageChildrenForGroup);
15738
- useEditorStore.getState().updateNode(logicalGroupSelectionId, {
15739
- left: storePosGroup.left,
15740
- top: storePosGroup.top,
15741
- width: logicalGroupFinalFrame.width,
15742
- height: logicalGroupFinalFrame.height,
15743
- angle: logicalGroupFinalFrame.angle
15744
- }, { recordHistory: false, skipLayoutRecalc: true });
15745
- }
15746
- } catch (err) {
15747
- console.warn("[Pixldocs] logical-group envelope persist failed", err);
15748
- }
15749
- }
15750
- const pageChildrenForReflow = ((_k = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _k.children) ?? [];
15251
+ const pageChildrenForReflow = ((_i = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _i.children) ?? [];
15751
15252
  const stackGroupsToReflow = /* @__PURE__ */ new Set();
15752
15253
  for (const id of modifiedIdsThisRound) {
15753
15254
  const parent = findParentGroup(pageChildrenForReflow, id);
@@ -15774,16 +15275,6 @@ const PageCanvas = forwardRef(
15774
15275
  renderOnAddRemove: fabricCanvas.renderOnAddRemove
15775
15276
  });
15776
15277
  }
15777
- if (debugGroupImageSideResize) {
15778
- logGroupImageResizeDebug("before-reselect", {
15779
- time: Math.round(performance.now()),
15780
- handle: activeSelectionResizeHandle,
15781
- wasGroupSel,
15782
- selection: summarizeFabricObjectForResizeDebug(activeObj),
15783
- members: membersToReselect.map((member) => summarizeFabricObjectForResizeDebug(member)),
15784
- renderOnAddRemove: fabricCanvas.renderOnAddRemove
15785
- });
15786
- }
15787
15278
  const prevRenderOnAddRemove = fabricCanvas.renderOnAddRemove;
15788
15279
  fabricCanvas.renderOnAddRemove = false;
15789
15280
  skipSelectionClearOnDiscardRef.current = true;
@@ -15798,10 +15289,9 @@ const PageCanvas = forwardRef(
15798
15289
  if (!ct) continue;
15799
15290
  ct.frameW = bake.width;
15800
15291
  ct.frameH = bake.height;
15801
- const bakeCenter = rotatedTopLeftToCenter(bake.left, bake.top, bake.width, bake.height, bake.angle);
15802
15292
  bake.obj.set({
15803
- left: bakeCenter.x,
15804
- top: bakeCenter.y,
15293
+ left: bake.left + bake.width / 2,
15294
+ top: bake.top + bake.height / 2,
15805
15295
  width: bake.width,
15806
15296
  height: bake.height,
15807
15297
  scaleX: 1,
@@ -15828,16 +15318,6 @@ const PageCanvas = forwardRef(
15828
15318
  renderOnAddRemove: fabricCanvas.renderOnAddRemove
15829
15319
  });
15830
15320
  }
15831
- if (debugGroupImageSideResize) {
15832
- logGroupImageResizeDebug("after-reselect", {
15833
- time: Math.round(performance.now()),
15834
- handle: activeSelectionResizeHandle,
15835
- wasGroupSel,
15836
- selection: summarizeFabricObjectForResizeDebug(newSel),
15837
- members: membersToReselect.map((member) => summarizeFabricObjectForResizeDebug(member)),
15838
- renderOnAddRemove: fabricCanvas.renderOnAddRemove
15839
- });
15840
- }
15841
15321
  } else if (membersToReselect.length === 1) {
15842
15322
  fabricCanvas.setActiveObject(membersToReselect[0]);
15843
15323
  }
@@ -15874,7 +15354,6 @@ const PageCanvas = forwardRef(
15874
15354
  const activeObj = fabricCanvas.getActiveObject();
15875
15355
  if (!(activeObj instanceof fabric.ActiveSelection)) return;
15876
15356
  if (skipActiveSelectionBakeOnClearRef.current) return;
15877
- if (activeObj.__pixldocsGroupSelection) return;
15878
15357
  const selectionMatrix = activeObj.calcTransformMatrix();
15879
15358
  for (const obj of deselected) {
15880
15359
  const objId = getObjectId(obj);
@@ -16344,7 +15823,7 @@ const PageCanvas = forwardRef(
16344
15823
  const nextHeight = Math.max(minVisiblePlaceholder, Number(resolvedSizeImg.height) || 50);
16345
15824
  const storePosImg = pageChildren ? (() => {
16346
15825
  const node = findNodeById(pageChildren, element.id);
16347
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
15826
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16348
15827
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16349
15828
  const elementForPlaceholder = { ...element, width: nextWidth, height: nextHeight };
16350
15829
  const placeholder = isCropGroup2 ? createImagePlaceholderForGroup(elementForPlaceholder) : createImagePlaceholder(elementForPlaceholder);
@@ -16407,14 +15886,13 @@ const PageCanvas = forwardRef(
16407
15886
  }
16408
15887
  const cropPos = pageChildren ? (() => {
16409
15888
  const node = findNodeById(pageChildren, element.id);
16410
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16411
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16412
- const cropCenter = rotatedTopLeftToCenter(cropPos.left, cropPos.top, ct.frameW ?? 0, ct.frameH ?? 0, cropPos.angle ?? element.angle ?? 0);
16413
- const cropCenterX = cropCenter.x;
16414
- const cropCenterY = cropCenter.y;
15889
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
15890
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
15891
+ const cropCenterX = cropPos.left + (ct.frameW ?? 0) / 2;
15892
+ const cropCenterY = cropPos.top + (ct.frameH ?? 0) / 2;
16415
15893
  if (element.left !== void 0) existingObj.set({ left: cropCenterX });
16416
15894
  if (element.top !== void 0) existingObj.set({ top: cropCenterY });
16417
- existingObj.set({ angle: cropPos.angle ?? element.angle ?? 0 });
15895
+ if (element.angle !== void 0) existingObj.set({ angle: element.angle });
16418
15896
  existingObj.set({
16419
15897
  flipX: element.flipX ?? false,
16420
15898
  flipY: element.flipY ?? false
@@ -16537,8 +16015,8 @@ const PageCanvas = forwardRef(
16537
16015
  if (isPlaceholderGroup) {
16538
16016
  const storePosImg = pageChildren ? (() => {
16539
16017
  const node = findNodeById(pageChildren, element.id);
16540
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16541
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16018
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16019
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
16542
16020
  const resolvedSizeImg = (pageChildren == null ? void 0 : pageChildren.length) ? getNodeBounds(element, pageChildren) : { width: typeof element.width === "number" ? element.width : 200, height: typeof element.height === "number" ? element.height : 50 };
16543
16021
  const hasExplicitSize = typeof element.width === "number" && Number.isFinite(element.width) && element.width > 0 && typeof element.height === "number" && Number.isFinite(element.height) && element.height > 0;
16544
16022
  const minVisiblePlaceholder = hasExplicitSize ? 1 : 20;
@@ -16552,7 +16030,7 @@ const PageCanvas = forwardRef(
16552
16030
  top: storePosImg.top + nextHeight / 2,
16553
16031
  originX: "center",
16554
16032
  originY: "center",
16555
- angle: storePosImg.angle ?? element.angle ?? 0,
16033
+ angle: element.angle ?? 0,
16556
16034
  opacity: isHidden ? 0 : element.opacity ?? 1,
16557
16035
  flipX: element.flipX ?? false,
16558
16036
  flipY: element.flipY ?? false,
@@ -16601,8 +16079,8 @@ const PageCanvas = forwardRef(
16601
16079
  const visibilityChanged = previousVisible !== currentVisible;
16602
16080
  const storePosForImg = pageChildren ? (() => {
16603
16081
  const node = findNodeById(pageChildren, element.id);
16604
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16605
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16082
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16083
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
16606
16084
  const positionChanged = Math.abs((existingObj.left ?? 0) - storePosForImg.left) > 0.1 || Math.abs((existingObj.top ?? 0) - storePosForImg.top) > 0.1;
16607
16085
  if (visibilityChanged && !positionChanged || visibilityUpdateInProgressRef.current) {
16608
16086
  const isDynamicField = dynamicFieldIds.includes(element.id);
@@ -16644,7 +16122,7 @@ const PageCanvas = forwardRef(
16644
16122
  const fabricTop = existingObj.top ?? 0;
16645
16123
  const storePos = pageChildren ? (() => {
16646
16124
  const node = findNodeById(pageChildren, element.id);
16647
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16125
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16648
16126
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16649
16127
  const storeLeft = storePos.left;
16650
16128
  const storeTop = storePos.top;
@@ -16771,7 +16249,7 @@ const PageCanvas = forwardRef(
16771
16249
  setObjectData(placeholder, element.id);
16772
16250
  const absPosImg = pageTree.length > 0 ? (() => {
16773
16251
  const node = findNodeById(pageTree, element.id);
16774
- return node && isElement(node) ? getElementFabricPlacement(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16252
+ return node ? getAbsoluteBounds(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16775
16253
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16776
16254
  const placeholderWidth = Number((placeholder.width ?? 0) * (placeholder.scaleX ?? 1));
16777
16255
  const placeholderHeight = Number((placeholder.height ?? 0) * (placeholder.scaleY ?? 1));
@@ -16820,7 +16298,7 @@ const PageCanvas = forwardRef(
16820
16298
  if (obj) {
16821
16299
  const absPos = pageTree.length > 0 ? (() => {
16822
16300
  const node = findNodeById(pageTree, element.id);
16823
- return node && isElement(node) ? getElementFabricPlacement(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16301
+ return node ? getAbsoluteBounds(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16824
16302
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16825
16303
  obj.set({ left: absPos.left, top: absPos.top });
16826
16304
  obj.setCoords();
@@ -17210,7 +16688,9 @@ const PageCanvas = forwardRef(
17210
16688
  if (sameSelection && isFlatGroupSelection) {
17211
16689
  if (selectedGroupSelectionId && active instanceof fabric.ActiveSelection) {
17212
16690
  if (isPureSingleGroupSelection) {
17213
- applyLogicalGroupSelectionVisualState(active, selectedGroupSelectionId);
16691
+ active.__pixldocsGroupSelection = selectedGroupSelectionId;
16692
+ delete active.__pixldocsLogicalGroupIds;
16693
+ suppressGroupMemberBordersRef.current = active.getObjects();
17214
16694
  } else {
17215
16695
  delete active.__pixldocsGroupSelection;
17216
16696
  active.__pixldocsLogicalGroupIds = selectedGroupIds;
@@ -17250,7 +16730,8 @@ const PageCanvas = forwardRef(
17250
16730
  const selection = new fabric.ActiveSelection(toSelect, { canvas: fc });
17251
16731
  if (selectedGroupSelectionId) {
17252
16732
  if (isPureSingleGroupSelection) {
17253
- applyLogicalGroupSelectionVisualState(selection, selectedGroupSelectionId);
16733
+ selection.__pixldocsGroupSelection = selectedGroupSelectionId;
16734
+ suppressGroupMemberBordersRef.current = toSelect;
17254
16735
  } else {
17255
16736
  selection.__pixldocsLogicalGroupIds = selectedGroupIds;
17256
16737
  selection.hasBorders = true;
@@ -17308,9 +16789,8 @@ const PageCanvas = forwardRef(
17308
16789
  const currentPageTree = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
17309
16790
  const fabricPos = currentPageTree.length > 0 ? (() => {
17310
16791
  const node = findNodeById(currentPageTree, element.id);
17311
- return node && isElement(node) ? getElementFabricPlacement(node, currentPageTree) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
17312
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
17313
- const fabricAngle = fabricPos.angle ?? element.angle ?? 0;
16792
+ return node ? getAbsoluteBounds(node, currentPageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16793
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
17314
16794
  const resolvedSize = currentPageTree.length > 0 ? getNodeBounds(element, currentPageTree) : { width: typeof element.width === "number" ? element.width : 200, height: typeof element.height === "number" ? element.height : 50 };
17315
16795
  const shouldPreserveSmallSize = typeof element.width === "number" && Number.isFinite(element.width) && element.width > 0 && typeof element.height === "number" && Number.isFinite(element.height) && element.height > 0;
17316
16796
  const minVisible = shouldPreserveSmallSize ? 1 : 20;
@@ -17345,9 +16825,8 @@ const PageCanvas = forwardRef(
17345
16825
  ct.shape = clipShape === "circle" ? "circle" : clipShape === "rounded" ? "roundRect" : "rect";
17346
16826
  ct.rx = rxRatio;
17347
16827
  obj.__maintainResolution = element.maintainResolution !== false;
17348
- const center = rotatedTopLeftToCenter(fabricPos.left, fabricPos.top, elementWidth, elementHeight, element.angle ?? 0);
17349
- const centerX = center.x;
17350
- const centerY = center.y;
16828
+ const centerX = fabricPos.left + elementWidth / 2;
16829
+ const centerY = fabricPos.top + elementHeight / 2;
17351
16830
  const cropSetProps = {
17352
16831
  width: elementWidth,
17353
16832
  height: elementHeight,
@@ -17567,7 +17046,7 @@ const PageCanvas = forwardRef(
17567
17046
  y1: 0,
17568
17047
  x2: lineLen,
17569
17048
  y2: 0,
17570
- angle: fabricAngle,
17049
+ angle: element.angle ?? 0,
17571
17050
  scaleX: 1,
17572
17051
  scaleY: 1,
17573
17052
  skewX: 0,
@@ -17587,8 +17066,7 @@ const PageCanvas = forwardRef(
17587
17066
  if (!skipPositionUpdate && (obj instanceof fabric.FabricImage && obj.originX === "center" || obj instanceof fabric.Group && obj.__cropGroup)) {
17588
17067
  const vW = rW * effectiveScaleX;
17589
17068
  const vH = rH * effectiveScaleY;
17590
- const center = rotatedTopLeftToCenter(fabricPos.left, fabricPos.top, vW, vH, element.angle ?? 0);
17591
- posIfNotSkipped = { left: center.x, top: center.y };
17069
+ posIfNotSkipped = { left: fabricPos.left + vW / 2, top: fabricPos.top + vH / 2 };
17592
17070
  }
17593
17071
  if (element.transformMatrix && element.transformMatrix.length === 6) {
17594
17072
  if (isTextbox) {
@@ -17597,7 +17075,7 @@ const PageCanvas = forwardRef(
17597
17075
  width: rW,
17598
17076
  scaleX: effectiveScaleX,
17599
17077
  scaleY: effectiveScaleY,
17600
- angle: fabricAngle,
17078
+ angle: element.angle ?? 0,
17601
17079
  skewX: element.skewX ?? 0,
17602
17080
  skewY: appliedSkewY
17603
17081
  });
@@ -17606,7 +17084,7 @@ const PageCanvas = forwardRef(
17606
17084
  ...posIfNotSkipped,
17607
17085
  scaleX: effectiveScaleX,
17608
17086
  scaleY: effectiveScaleY,
17609
- angle: fabricAngle,
17087
+ angle: element.angle ?? 0,
17610
17088
  skewX: element.skewX ?? 0,
17611
17089
  skewY: element.skewY ?? 0
17612
17090
  });
@@ -17617,7 +17095,7 @@ const PageCanvas = forwardRef(
17617
17095
  obj.set({
17618
17096
  ...posIfNotSkipped,
17619
17097
  width: rW,
17620
- angle: fabricAngle,
17098
+ angle: element.angle ?? 0,
17621
17099
  skewX: element.skewX ?? 0,
17622
17100
  skewY: appliedSkewY,
17623
17101
  scaleX: effectiveScaleX * baseScaleX,
@@ -17626,7 +17104,7 @@ const PageCanvas = forwardRef(
17626
17104
  } else {
17627
17105
  obj.set({
17628
17106
  ...posIfNotSkipped,
17629
- angle: fabricAngle,
17107
+ angle: element.angle ?? 0,
17630
17108
  skewX: element.skewX ?? 0,
17631
17109
  skewY: element.skewY ?? 0,
17632
17110
  scaleX: effectiveScaleX * baseScaleX,
@@ -18379,14 +17857,14 @@ const PageCanvas = forwardRef(
18379
17857
  const pageTreeForCreate = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_f = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _f.children) ?? [];
18380
17858
  const createPos = pageTreeForCreate.length > 0 ? (() => {
18381
17859
  const node = findNodeById(pageTreeForCreate, element.id);
18382
- return node && isElement(node) ? getElementFabricPlacement(node, pageTreeForCreate, pageBoundsOptions) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
18383
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
17860
+ return node ? getAbsoluteBounds(node, pageTreeForCreate) : { left: element.left ?? 0, top: element.top ?? 0 };
17861
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
18384
17862
  img.set({
18385
17863
  left: createPos.left,
18386
17864
  top: createPos.top,
18387
17865
  scaleX: finalScaleX,
18388
17866
  scaleY: finalScaleY,
18389
- angle: createPos.angle ?? element.angle ?? 0,
17867
+ angle: element.angle ?? 0,
18390
17868
  skewX: element.skewX ?? 0,
18391
17869
  skewY: element.skewY ?? 0,
18392
17870
  flipX: element.flipX ?? false,
@@ -18473,8 +17951,8 @@ const PageCanvas = forwardRef(
18473
17951
  const pageTreeForCrop = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_n = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _n.children) ?? [];
18474
17952
  const createPosForCrop = pageTreeForCrop.length > 0 ? (() => {
18475
17953
  const node = findNodeById(pageTreeForCrop, element.id);
18476
- return node && isElement(node) ? getElementFabricPlacement(node, pageTreeForCrop, pageBoundsOptions) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
18477
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
17954
+ return node ? getAbsoluteBounds(node, pageTreeForCrop) : { left: element.left ?? 0, top: element.top ?? 0 };
17955
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
18478
17956
  const nodeForCreate = pageTreeForCrop.length ? findNodeById(pageTreeForCrop, element.id) : null;
18479
17957
  const createW = nodeForCreate && isElement(nodeForCreate) ? nodeForCreate.width : elementWidth;
18480
17958
  const createH = nodeForCreate && isElement(nodeForCreate) ? nodeForCreate.height : elementHeight;
@@ -18482,9 +17960,8 @@ const PageCanvas = forwardRef(
18482
17960
  const createSy = nodeForCreate && isElement(nodeForCreate) ? nodeForCreate.scaleY ?? 1 : element.scaleY ?? 1;
18483
17961
  const frameW = Math.max(1, Number(createW) || 200) * createSx;
18484
17962
  const frameH = Math.max(1, Number(createH) || 50) * createSy;
18485
- const createCenter = rotatedTopLeftToCenter(createPosForCrop.left, createPosForCrop.top, frameW, frameH, createPosForCrop.angle ?? element.angle ?? 0);
18486
- const createCenterX = createCenter.x;
18487
- const createCenterY = createCenter.y;
17963
+ const createCenterX = createPosForCrop.left + frameW / 2;
17964
+ const createCenterY = createPosForCrop.top + frameH / 2;
18488
17965
  const cropGroup = await createMaskedImageElement({
18489
17966
  image: img,
18490
17967
  frameW,
@@ -18497,7 +17974,7 @@ const PageCanvas = forwardRef(
18497
17974
  strokeWidth: 0,
18498
17975
  left: createCenterX,
18499
17976
  top: createCenterY,
18500
- angle: createPosForCrop.angle ?? element.angle ?? 0,
17977
+ angle: element.angle ?? 0,
18501
17978
  opacity: isHidden ? 0 : element.opacity ?? 1,
18502
17979
  selectable: allowSelection && !isHidden,
18503
17980
  evented: canBeEvented && !isHidden,
@@ -24887,9 +24364,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
24887
24364
  }
24888
24365
  return svgString;
24889
24366
  }
24890
- const resolvedPackageVersion = "0.5.354";
24367
+ const resolvedPackageVersion = "0.5.355";
24891
24368
  const PACKAGE_VERSION = resolvedPackageVersion;
24892
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.354";
24369
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.355";
24893
24370
  const roundParityValue = (value) => {
24894
24371
  if (typeof value !== "number") return value;
24895
24372
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -25703,7 +25180,7 @@ class PixldocsRenderer {
25703
25180
  await this.waitForCanvasScene(container, cloned, i);
25704
25181
  }
25705
25182
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
25706
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-B54V1hcn.js");
25183
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-CIYQWsck.js");
25707
25184
  const prepared = preparePagesForExport(
25708
25185
  cloned.pages,
25709
25186
  canvasWidth,
@@ -28023,7 +27500,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
28023
27500
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
28024
27501
  sanitizeSvgTreeForPdf(svgToDraw);
28025
27502
  try {
28026
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-B54V1hcn.js");
27503
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-CIYQWsck.js");
28027
27504
  try {
28028
27505
  await logTextMeasurementDiagnostic(svgToDraw);
28029
27506
  } catch {
@@ -28423,4 +27900,4 @@ export {
28423
27900
  buildTeaserBlurFlatKeys as y,
28424
27901
  collectFontDescriptorsFromConfig as z
28425
27902
  };
28426
- //# sourceMappingURL=index-yEgXeiie.js.map
27903
+ //# sourceMappingURL=index-CJNRmC-X.js.map