@pixldocs/canvas-renderer 0.5.354 → 0.5.356

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.
@@ -10518,105 +10518,6 @@ function bakeEdgeFade(source, fade) {
10518
10518
  }
10519
10519
  return canvas;
10520
10520
  }
10521
- const normalizeSignedAngle = (angle) => (angle % 360 + 540) % 360 - 180;
10522
- const rotatedTopLeftToCenter = (left, top, width, height, angleDeg = 0) => {
10523
- const angle = angleDeg * Math.PI / 180;
10524
- const cos = Math.cos(angle);
10525
- const sin = Math.sin(angle);
10526
- return {
10527
- x: left + width / 2 * cos - height / 2 * sin,
10528
- y: top + width / 2 * sin + height / 2 * cos
10529
- };
10530
- };
10531
- const centerToRotatedTopLeft = (centerX, centerY, width, height, angleDeg = 0) => {
10532
- const angle = angleDeg * Math.PI / 180;
10533
- const cos = Math.cos(angle);
10534
- const sin = Math.sin(angle);
10535
- return {
10536
- left: centerX - width / 2 * cos + height / 2 * sin,
10537
- top: centerY - width / 2 * sin - height / 2 * cos
10538
- };
10539
- };
10540
- const getGroupTransformFrame = (group, pageChildren, options) => {
10541
- const bounds = getNodeBounds(group, pageChildren);
10542
- const width = Math.max(1, Number(group.width ?? bounds.width) || bounds.width || 1);
10543
- const height = Math.max(1, Number(group.height ?? bounds.height) || bounds.height || 1);
10544
- return {
10545
- left: Number(group.left ?? bounds.left ?? 0) || 0,
10546
- top: Number(group.top ?? bounds.top ?? 0) || 0,
10547
- width,
10548
- height,
10549
- angle: Number(group.angle ?? 0) || 0
10550
- };
10551
- };
10552
- const getGroupLocalToParentMatrix = (group, pageChildren, options) => {
10553
- const frame = getGroupTransformFrame(group, pageChildren);
10554
- const rad = frame.angle * Math.PI / 180;
10555
- const cos = Math.cos(rad);
10556
- const sin = Math.sin(rad);
10557
- return [
10558
- cos,
10559
- sin,
10560
- -sin,
10561
- cos,
10562
- frame.left,
10563
- frame.top
10564
- ];
10565
- };
10566
- const getAncestorGroupTransform = (nodeId, pageChildren, fabric2, options) => {
10567
- let matrix = [1, 0, 0, 1, 0, 0];
10568
- let angle = 0;
10569
- const chain = [];
10570
- let currentId = nodeId;
10571
- for (let guard = 0; guard < 32; guard++) {
10572
- const parent = findParentGroup(pageChildren, currentId);
10573
- if (!parent) break;
10574
- chain.unshift(parent);
10575
- currentId = parent.id;
10576
- }
10577
- for (const group of chain) {
10578
- matrix = fabric2.util.multiplyTransformMatrices(
10579
- matrix,
10580
- getGroupLocalToParentMatrix(group, pageChildren)
10581
- );
10582
- angle += Number(group.angle ?? 0) || 0;
10583
- }
10584
- return { matrix, angle: normalizeSignedAngle(angle) };
10585
- };
10586
- const getElementFabricPlacement$1 = (element, pageChildren, fabric2, options) => {
10587
- if (!pageChildren.length) {
10588
- return { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
10589
- }
10590
- const ancestor = getAncestorGroupTransform(element.id, pageChildren, fabric2);
10591
- const point = fabric2.util.transformPoint(
10592
- new fabric2.Point(element.left ?? 0, element.top ?? 0),
10593
- ancestor.matrix
10594
- );
10595
- return {
10596
- left: point.x,
10597
- top: point.y,
10598
- angle: normalizeSignedAngle(ancestor.angle + Number(element.angle ?? 0))
10599
- };
10600
- };
10601
- const getGroupAbsoluteTransformFrame$1 = (group, pageChildren, fabric2, options) => {
10602
- const frame = getGroupTransformFrame(group, pageChildren);
10603
- const ancestor = getAncestorGroupTransform(group.id, pageChildren, fabric2);
10604
- const centerLocal = rotatedTopLeftToCenter(frame.left, frame.top, frame.width, frame.height, frame.angle);
10605
- const center = fabric2.util.transformPoint(new fabric2.Point(centerLocal.x, centerLocal.y), ancestor.matrix);
10606
- const topLeft = fabric2.util.transformPoint(new fabric2.Point(frame.left, frame.top), ancestor.matrix);
10607
- return {
10608
- left: topLeft.x,
10609
- top: topLeft.y,
10610
- width: frame.width,
10611
- height: frame.height,
10612
- centerX: center.x,
10613
- centerY: center.y,
10614
- angle: normalizeSignedAngle(ancestor.angle + frame.angle)
10615
- };
10616
- };
10617
- function preserveLogicalGroupTagDuringMove(selection, groupId) {
10618
- selection.__pixldocsGroupSelection = groupId;
10619
- }
10620
10521
  const SELECTION_PRIMARY = "hsl(217, 91%, 60%)";
10621
10522
  const SELECTION_BORDER_SCALE = 2;
10622
10523
  let ensureCanvaControlRenders = () => {
@@ -11070,18 +10971,12 @@ try {
11070
10971
  } catch (e) {
11071
10972
  }
11072
10973
  };
11073
- const wrapControlsFactory = (key) => {
11074
- if (typeof cu[key] !== "function") return;
11075
- const descriptor = Object.getOwnPropertyDescriptor(cu, key);
11076
- if (descriptor && descriptor.writable === false && !descriptor.set) return;
11077
- const original = cu[key].bind(cu);
11078
- try {
11079
- cu[key] = () => installPillRenders(original());
11080
- } catch {
11081
- }
11082
- };
11083
- wrapControlsFactory("createObjectDefaultControls");
11084
- wrapControlsFactory("createTextboxDefaultControls");
10974
+ const origObj = cu.createObjectDefaultControls.bind(cu);
10975
+ cu.createObjectDefaultControls = () => installPillRenders(origObj());
10976
+ if (typeof cu.createTextboxDefaultControls === "function") {
10977
+ const origTb = cu.createTextboxDefaultControls.bind(cu);
10978
+ cu.createTextboxDefaultControls = () => installPillRenders(origTb());
10979
+ }
11085
10980
  const wrapClassCreateControls = (Klass) => {
11086
10981
  if (!Klass || typeof Klass.createControls !== "function") return;
11087
10982
  const orig = Klass.createControls.bind(Klass);
@@ -11148,8 +11043,6 @@ const scaleUpdateNumber = (updates, source, key, factor) => {
11148
11043
  };
11149
11044
  const GROUP_TEXT_RESIZE_DEBUG_PREFIX = "[Pixldocs][group-text-corner-resize]";
11150
11045
  const GROUP_TEXT_RESIZE_DEBUG_MAX_ENTRIES = 200;
11151
- const GROUP_IMAGE_RESIZE_DEBUG_PREFIX = "[Pixldocs][group-image-side-resize]";
11152
- const GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES = 300;
11153
11046
  const isCornerResizeHandle = (handle) => handle === "tl" || handle === "tr" || handle === "bl" || handle === "br";
11154
11047
  const summarizeFabricObjectForResizeDebug = (obj) => {
11155
11048
  var _a2;
@@ -11212,43 +11105,6 @@ const logGroupTextResizeDebug = (phase, payload) => {
11212
11105
  console.log(GROUP_TEXT_RESIZE_DEBUG_PREFIX, phase, payload);
11213
11106
  }
11214
11107
  };
11215
- const isGroupResizeImageLikeObject = (obj) => {
11216
- var _a2;
11217
- return !!obj && (obj instanceof fabric__namespace.FabricImage || obj instanceof fabric__namespace.Group && (obj.__cropGroup || ((_a2 = obj._ct) == null ? void 0 : _a2.isCropGroup)));
11218
- };
11219
- const logGroupImageResizeDebug = (phase, payload) => {
11220
- if (typeof console === "undefined") return;
11221
- try {
11222
- const seen = /* @__PURE__ */ new WeakSet();
11223
- const normalize = (value) => {
11224
- if (value == null) return value;
11225
- const valueType = typeof value;
11226
- if (valueType === "number") return Number.isFinite(value) ? Math.round(value * 1e3) / 1e3 : String(value);
11227
- if (valueType === "string" || valueType === "boolean") return value;
11228
- if (valueType === "function") return `[Function ${value.name || "anonymous"}]`;
11229
- if (Array.isArray(value)) return value.map((entry) => normalize(entry));
11230
- if (valueType === "object") {
11231
- if (seen.has(value)) return "[Circular]";
11232
- seen.add(value);
11233
- if (value instanceof fabric__namespace.FabricObject) return normalize(summarizeFabricObjectForResizeDebug(value));
11234
- const output = {};
11235
- Object.entries(value).forEach(([key, entry]) => {
11236
- output[key] = normalize(entry);
11237
- });
11238
- return output;
11239
- }
11240
- return String(value);
11241
- };
11242
- const normalizedPayload = normalize(payload);
11243
- const line = `${GROUP_IMAGE_RESIZE_DEBUG_PREFIX} ${phase} ${JSON.stringify(normalizedPayload)}`;
11244
- const debugWindow = window;
11245
- debugWindow.__pixldocsGroupImageResizeLogs = Array.isArray(debugWindow.__pixldocsGroupImageResizeLogs) ? debugWindow.__pixldocsGroupImageResizeLogs.slice(-GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES + 1) : [];
11246
- debugWindow.__pixldocsGroupImageResizeLogs.push(line);
11247
- console.log(line);
11248
- } catch {
11249
- console.log(GROUP_IMAGE_RESIZE_DEBUG_PREFIX, phase, payload);
11250
- }
11251
- };
11252
11108
  const bakeTextboxScaleIntoTypography = (obj, sourceElement) => {
11253
11109
  const sx = Math.abs(obj.scaleX ?? 1) || 1;
11254
11110
  const sy = Math.abs(obj.scaleY ?? 1) || 1;
@@ -11322,8 +11178,6 @@ const bakeTextboxScaleIntoTypography = (obj, sourceElement) => {
11322
11178
  };
11323
11179
  return updates;
11324
11180
  };
11325
- const getElementFabricPlacement = (element, pageChildren, options) => getElementFabricPlacement$1(element, pageChildren, fabric__namespace);
11326
- const getGroupAbsoluteTransformFrame = (group, pageChildren, options) => getGroupAbsoluteTransformFrame$1(group, pageChildren, fabric__namespace);
11327
11181
  function applyWarpAwareSelectionBorders(selection) {
11328
11182
  var _a2;
11329
11183
  if (selection.__pixldocsOrigASHasBorders !== void 0) {
@@ -11332,7 +11186,6 @@ function applyWarpAwareSelectionBorders(selection) {
11332
11186
  }
11333
11187
  selection.hasBorders = true;
11334
11188
  selection.hasControls = true;
11335
- if (selection.__pixldocsGroupSelection) return;
11336
11189
  try {
11337
11190
  if (selection.__pixldocsAlignedAngle == null) {
11338
11191
  const kids = selection.getObjects();
@@ -11380,6 +11233,37 @@ function applyWarpAwareSelectionBorders(selection) {
11380
11233
  selection.setCoords();
11381
11234
  selection.dirty = true;
11382
11235
  selection.__pixldocsAlignedAngle = targetAngle;
11236
+ try {
11237
+ const kidSummary = kids.map((c) => ({
11238
+ id: c.id ?? c.__pixldocsId,
11239
+ type: c.type,
11240
+ left: c.left,
11241
+ top: c.top,
11242
+ angle: c.angle,
11243
+ scaleX: c.scaleX,
11244
+ scaleY: c.scaleY,
11245
+ originX: c.originX,
11246
+ originY: c.originY,
11247
+ width: c.width,
11248
+ height: c.height
11249
+ }));
11250
+ console.info("[Pixldocs][rot-group-image-drift] aligned-on-select", {
11251
+ targetAngle,
11252
+ selection: {
11253
+ left: selection.left,
11254
+ top: selection.top,
11255
+ angle: selection.angle,
11256
+ scaleX: selection.scaleX,
11257
+ scaleY: selection.scaleY,
11258
+ width: selection.width,
11259
+ height: selection.height,
11260
+ originX: selection.originX,
11261
+ originY: selection.originY
11262
+ },
11263
+ kids: kidSummary
11264
+ });
11265
+ } catch {
11266
+ }
11383
11267
  }
11384
11268
  }
11385
11269
  }
@@ -11459,46 +11343,10 @@ const PageCanvas = react.forwardRef(
11459
11343
  const [ready, setReady] = react.useState(false);
11460
11344
  const [unlockRequestId, setUnlockRequestId] = react.useState(0);
11461
11345
  const applyLogicalGroupSelectionVisualState = react.useCallback((selection, groupId) => {
11462
- var _a2, _b2;
11346
+ var _a2;
11463
11347
  selection.__pixldocsGroupSelection = groupId;
11464
11348
  delete selection.__pixldocsLogicalGroupIds;
11465
11349
  selection.hasBorders = true;
11466
- try {
11467
- const membersBeforeFrame = selection.getObjects();
11468
- const selectionMatrixBefore = selection.calcTransformMatrix();
11469
- const memberWorldMatrices = membersBeforeFrame.map((member) => fabric__namespace.util.multiplyTransformMatrices(
11470
- selectionMatrixBefore,
11471
- member.calcOwnMatrix()
11472
- ));
11473
- const pageChildren2 = ((_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
11474
- const groupNode = findNodeById(pageChildren2, groupId);
11475
- const groupFrame = groupNode && isGroup(groupNode) ? getGroupAbsoluteTransformFrame(groupNode, pageChildren2, pageBoundsOptions) : null;
11476
- const groupAngle = groupFrame ? groupFrame.angle : 0;
11477
- if (Number.isFinite(groupAngle)) {
11478
- selection.set({ angle: groupAngle, scaleX: 1, scaleY: 1, skewX: 0, skewY: 0 });
11479
- if (groupFrame) {
11480
- selection.setPositionByOrigin(
11481
- new fabric__namespace.Point(groupFrame.centerX, groupFrame.centerY),
11482
- "center",
11483
- "center"
11484
- );
11485
- }
11486
- const invSelectionAfter = fabric__namespace.util.invertTransform(
11487
- selection.calcTransformMatrix()
11488
- );
11489
- membersBeforeFrame.forEach((member, index) => {
11490
- const localMatrix = fabric__namespace.util.multiplyTransformMatrices(
11491
- invSelectionAfter,
11492
- memberWorldMatrices[index]
11493
- );
11494
- fabric__namespace.util.applyTransformToObject(member, localMatrix);
11495
- member.setCoords();
11496
- member.dirty = true;
11497
- });
11498
- selection.setCoords();
11499
- }
11500
- } catch {
11501
- }
11502
11350
  const members = selection.getObjects();
11503
11351
  for (const prev of suppressGroupMemberBordersRef.current) {
11504
11352
  if (members.includes(prev)) continue;
@@ -11522,7 +11370,7 @@ const PageCanvas = react.forwardRef(
11522
11370
  if (m.__pixldocsOrigHasControls === void 0) m.__pixldocsOrigHasControls = m.hasControls;
11523
11371
  m.hasBorders = false;
11524
11372
  m.hasControls = false;
11525
- if (m.__cropGroup || ((_b2 = m._ct) == null ? void 0 : _b2.isCropGroup)) {
11373
+ if (m.__cropGroup || ((_a2 = m._ct) == null ? void 0 : _a2.isCropGroup)) {
11526
11374
  if (m.__pixldocsOrigLockScalingX === void 0) {
11527
11375
  m.__pixldocsOrigLockScalingX = m.lockScalingX;
11528
11376
  m.__pixldocsOrigLockScalingY = m.lockScalingY;
@@ -11532,7 +11380,7 @@ const PageCanvas = react.forwardRef(
11532
11380
  }
11533
11381
  }
11534
11382
  applyWarpAwareSelectionBorders(selection);
11535
- }, [pageId]);
11383
+ }, []);
11536
11384
  const pageBoundsOptions = react.useMemo(
11537
11385
  () => ({ pageContentWidth: canvasWidth, pageContentHeight: canvasHeight }),
11538
11386
  [canvasWidth, canvasHeight]
@@ -11606,6 +11454,7 @@ const PageCanvas = react.forwardRef(
11606
11454
  const preserveSelectionAfterTransformIdRef = react.useRef(null);
11607
11455
  const groupSelectionTransformStartRef = react.useRef(null);
11608
11456
  const activeSelectionMoveStartRef = react.useRef(null);
11457
+ const sectionGroupTransientImagesRef = react.useRef(null);
11609
11458
  setGroupOverlayLiveBoundsRef.current = setGroupOverlayLiveBounds;
11610
11459
  const {
11611
11460
  selectElements,
@@ -12451,6 +12300,7 @@ const PageCanvas = react.forwardRef(
12451
12300
  fabricCanvas.__fontCleanup = fontCleanup;
12452
12301
  fabricCanvas.__isUserTransforming = false;
12453
12302
  fabricCanvas.on("mouse:down", () => {
12303
+ groupSelectionTransformStartRef.current = null;
12454
12304
  activeSelectionMoveStartRef.current = null;
12455
12305
  activeSelectionResizeHandleRef.current = null;
12456
12306
  const active = fabricCanvas.getActiveObject();
@@ -12461,7 +12311,6 @@ const PageCanvas = react.forwardRef(
12461
12311
  selectionLeft: rect.left,
12462
12312
  selectionTop: rect.top
12463
12313
  };
12464
- prepareGroupSelectionTransformStart(active);
12465
12314
  }
12466
12315
  if (fabricCanvas._currentTransform) {
12467
12316
  fabricCanvas.__isUserTransforming = true;
@@ -12523,8 +12372,101 @@ const PageCanvas = react.forwardRef(
12523
12372
  });
12524
12373
  }
12525
12374
  });
12526
- fabricCanvas.on("object:moving", () => {
12375
+ const collectSectionGroupImageDescendantObjects = (groupNode) => {
12376
+ const ids = getAllElementIds(groupNode.children ?? []);
12377
+ if (ids.length === 0) return [];
12378
+ const elementById = new Map(elementsRef.current.map((el) => [el.id, el]));
12379
+ const out = [];
12380
+ for (const id of ids) {
12381
+ const el = elementById.get(id);
12382
+ if (!el || el.type !== "image") continue;
12383
+ const obj = fabricCanvas.getObjects().find((o) => getObjectId(o) === id);
12384
+ if (obj) out.push(obj);
12385
+ }
12386
+ return out;
12387
+ };
12388
+ const ensureSectionGroupTransientSnapshot = (group) => {
12389
+ var _a2;
12390
+ if (!group || !(group instanceof fabric__namespace.Group)) return false;
12391
+ if (!group.__docuforgeSectionGroup) return false;
12392
+ const groupId = getObjectId(group);
12393
+ if (!groupId) return false;
12394
+ const existing = sectionGroupTransientImagesRef.current;
12395
+ if (existing && existing.groupId === groupId && existing.group === group) return true;
12396
+ const pageChildrenLocal = ((_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
12397
+ const node = findNodeById(pageChildrenLocal, groupId);
12398
+ if (!node || !isGroup(node)) return false;
12399
+ const images = collectSectionGroupImageDescendantObjects(node);
12400
+ const gcx = group.left ?? 0;
12401
+ const gcy = group.top ?? 0;
12402
+ const gangle = group.angle ?? 0;
12403
+ const gsx = group.scaleX ?? 1;
12404
+ const gsy = group.scaleY ?? 1;
12405
+ const rad = -gangle * Math.PI / 180;
12406
+ const cos0 = Math.cos(rad);
12407
+ const sin0 = Math.sin(rad);
12408
+ const snap = images.map((obj) => {
12409
+ const icx = obj.left ?? 0;
12410
+ const icy = obj.top ?? 0;
12411
+ const dx = icx - gcx;
12412
+ const dy = icy - gcy;
12413
+ const rx = dx * cos0 - dy * sin0;
12414
+ const ry = dx * sin0 + dy * cos0;
12415
+ return {
12416
+ obj,
12417
+ localX: gsx ? rx / gsx : rx,
12418
+ localY: gsy ? ry / gsy : ry,
12419
+ relAngle: (obj.angle ?? 0) - gangle,
12420
+ relSx: (obj.scaleX ?? 1) / (gsx || 1),
12421
+ relSy: (obj.scaleY ?? 1) / (gsy || 1)
12422
+ };
12423
+ });
12424
+ sectionGroupTransientImagesRef.current = {
12425
+ groupId,
12426
+ group,
12427
+ group0: { cx: gcx, cy: gcy, angle: gangle, sx: gsx, sy: gsy },
12428
+ images: snap
12429
+ };
12430
+ return true;
12431
+ };
12432
+ const applySectionGroupTransientTransform = () => {
12433
+ const snap = sectionGroupTransientImagesRef.current;
12434
+ if (!snap || snap.images.length === 0) return;
12435
+ const group = snap.group;
12436
+ const gcx = group.left ?? 0;
12437
+ const gcy = group.top ?? 0;
12438
+ const gangle = group.angle ?? 0;
12439
+ const gsx = group.scaleX ?? 1;
12440
+ const gsy = group.scaleY ?? 1;
12441
+ const rad = gangle * Math.PI / 180;
12442
+ const cos = Math.cos(rad);
12443
+ const sin = Math.sin(rad);
12444
+ for (const entry of snap.images) {
12445
+ const lx = entry.localX * gsx;
12446
+ const ly = entry.localY * gsy;
12447
+ const wx = lx * cos - ly * sin;
12448
+ const wy = lx * sin + ly * cos;
12449
+ entry.obj.set({
12450
+ left: gcx + wx,
12451
+ top: gcy + wy,
12452
+ angle: entry.relAngle + gangle,
12453
+ scaleX: entry.relSx * gsx,
12454
+ scaleY: entry.relSy * gsy
12455
+ });
12456
+ entry.obj.setCoords();
12457
+ entry.obj.dirty = true;
12458
+ }
12459
+ };
12460
+ const clearSectionGroupTransientSnapshot = () => {
12461
+ sectionGroupTransientImagesRef.current = null;
12462
+ };
12463
+ const maybeFollowSectionGroupTransient = (target) => {
12464
+ if (!ensureSectionGroupTransientSnapshot(target)) return;
12465
+ applySectionGroupTransientTransform();
12466
+ };
12467
+ fabricCanvas.on("object:moving", (e) => {
12527
12468
  var _a2, _b2;
12469
+ maybeFollowSectionGroupTransient((e == null ? void 0 : e.target) ?? null);
12528
12470
  fabricCanvas.__isUserTransforming = true;
12529
12471
  didTransformRef.current = true;
12530
12472
  if (drilledGroupIdRef.current) {
@@ -12566,8 +12508,9 @@ const PageCanvas = react.forwardRef(
12566
12508
  });
12567
12509
  }
12568
12510
  });
12569
- fabricCanvas.on("object:rotating", () => {
12511
+ fabricCanvas.on("object:rotating", (e) => {
12570
12512
  var _a2;
12513
+ maybeFollowSectionGroupTransient((e == null ? void 0 : e.target) ?? null);
12571
12514
  fabricCanvas.__isUserTransforming = true;
12572
12515
  didTransformRef.current = true;
12573
12516
  if (drilledGroupIdRef.current) {
@@ -12577,6 +12520,12 @@ const PageCanvas = react.forwardRef(
12577
12520
  }
12578
12521
  }
12579
12522
  });
12523
+ fabricCanvas.on("object:scaling", (e) => {
12524
+ maybeFollowSectionGroupTransient((e == null ? void 0 : e.target) ?? null);
12525
+ });
12526
+ fabricCanvas.on("mouse:up", () => {
12527
+ clearSectionGroupTransientSnapshot();
12528
+ });
12580
12529
  const syncSelectionToStore = () => {
12581
12530
  var _a2, _b2, _c, _d;
12582
12531
  if (!isActiveRef.current || isRebuildingRef.current || isSyncingSelectionToFabricRef.current || !allowSelection) return;
@@ -12963,22 +12912,16 @@ const PageCanvas = react.forwardRef(
12963
12912
  const pageChildren2 = ((_b2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _b2.children) ?? [];
12964
12913
  const groupNode = findNodeById(pageChildren2, groupId);
12965
12914
  if (!groupNode) return;
12966
- const groupFrame = isGroup(groupNode) ? getGroupAbsoluteTransformFrame(groupNode, pageChildren2) : null;
12967
- const groupAbs = groupFrame ?? getAbsoluteBounds(groupNode, pageChildren2);
12915
+ const groupAbs = getAbsoluteBounds(groupNode, pageChildren2);
12968
12916
  const rect = active.getBoundingRect();
12969
- const center = active.getCenterPoint();
12970
12917
  groupSelectionTransformStartRef.current = {
12971
12918
  groupId,
12972
12919
  selection: active,
12973
12920
  selectionLeft: rect.left,
12974
12921
  selectionTop: rect.top,
12975
- selectionCenterX: center.x,
12976
- selectionCenterY: center.y,
12977
12922
  groupLeft: groupAbs.left,
12978
12923
  groupTop: groupAbs.top,
12979
- groupWidth: groupAbs.width,
12980
- groupHeight: groupAbs.height,
12981
- selectionAngle: (((groupFrame == null ? void 0 : groupFrame.angle) ?? active.angle ?? 0) % 360 + 360) % 360
12924
+ selectionAngle: ((active.angle ?? 0) % 360 + 360) % 360
12982
12925
  };
12983
12926
  };
12984
12927
  const restoreGroupSelectionVisualState = (selection, groupId) => {
@@ -13312,36 +13255,9 @@ const PageCanvas = react.forwardRef(
13312
13255
  });
13313
13256
  };
13314
13257
  fabricCanvas.__updateDrilledGroupOutline = updateDrilledGroupOutline;
13315
- const isPointerOnSelectionControl = (selection, event) => {
13316
- var _a2;
13317
- try {
13318
- selection.setCoords();
13319
- const controls = selection.oCoords ?? ((_a2 = selection.calcOCoords) == null ? void 0 : _a2.call(selection));
13320
- const el = fabricCanvas.upperCanvasEl ?? fabricCanvas.lowerCanvasEl;
13321
- const rect = el == null ? void 0 : el.getBoundingClientRect();
13322
- if (!controls || !rect || !event) return false;
13323
- const x = Number(event.clientX) - rect.left;
13324
- const y = Number(event.clientY) - rect.top;
13325
- return Object.values(controls).some((control) => {
13326
- const pts = (control == null ? void 0 : control.touchCorner) ?? (control == null ? void 0 : control.corner);
13327
- const corners = pts ? Object.values(pts) : [];
13328
- if (!corners.length) return false;
13329
- const minX = Math.min(...corners.map((p) => p.x)) - 2;
13330
- const maxX = Math.max(...corners.map((p) => p.x)) + 2;
13331
- const minY = Math.min(...corners.map((p) => p.y)) - 2;
13332
- const maxY = Math.max(...corners.map((p) => p.y)) + 2;
13333
- return x >= minX && x <= maxX && y >= minY && y <= maxY;
13334
- });
13335
- } catch {
13336
- return false;
13337
- }
13338
- };
13339
13258
  fabricCanvas.on("mouse:down:before", (opt) => {
13340
13259
  var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
13341
13260
  const activeBeforeMouseDown = fabricCanvas.getActiveObject();
13342
- if (activeBeforeMouseDown instanceof fabric__namespace.ActiveSelection && activeBeforeMouseDown.__pixldocsGroupSelection) {
13343
- prepareGroupSelectionTransformStart(activeBeforeMouseDown);
13344
- }
13345
13261
  if (editLockRef.current) {
13346
13262
  const active = fabricCanvas.getActiveObject();
13347
13263
  if (active && (((_a2 = active._ct) == null ? void 0 : _a2.isCropGroup) || active.__cropGroup)) {
@@ -13359,8 +13275,7 @@ const PageCanvas = react.forwardRef(
13359
13275
  }
13360
13276
  let target = opt.target;
13361
13277
  let targetId = target ? getObjectId(target) : null;
13362
- const pointerOnActiveSelectionControl = activeBeforeMouseDown instanceof fabric__namespace.ActiveSelection ? isPointerOnSelectionControl(activeBeforeMouseDown, opt.e) : false;
13363
- if (target instanceof fabric__namespace.ActiveSelection && target.__pixldocsGroupSelection && target === fabricCanvas.getActiveObject() && !target.__corner && !pointerOnActiveSelectionControl) {
13278
+ if (target instanceof fabric__namespace.ActiveSelection && target.__pixldocsGroupSelection && target === fabricCanvas.getActiveObject()) {
13364
13279
  const child = pickChildInActiveSelectionAtPointer(target, opt.e);
13365
13280
  const childId = child ? getObjectId(child) : null;
13366
13281
  if (child && childId) {
@@ -13409,7 +13324,7 @@ const PageCanvas = react.forwardRef(
13409
13324
  let effectiveTargetId = targetId;
13410
13325
  const activeNowEarly = fabricCanvas.getActiveObject();
13411
13326
  const asGroupId = target instanceof fabric__namespace.ActiveSelection ? target.__pixldocsGroupSelection : void 0;
13412
- if (target instanceof fabric__namespace.ActiveSelection && asGroupId && target === activeNowEarly && !target.__corner && !pointerOnActiveSelectionControl) {
13327
+ if (target instanceof fabric__namespace.ActiveSelection && asGroupId && target === activeNowEarly) {
13413
13328
  const child = pickChildInActiveSelectionAtPointer(target, opt.e);
13414
13329
  const childId = child ? getObjectId(child) : null;
13415
13330
  if (child && childId) {
@@ -13442,7 +13357,6 @@ const PageCanvas = react.forwardRef(
13442
13357
  restoreGroupSelectionVisualState(selection, parent.id);
13443
13358
  fabricCanvas.setActiveObject(selection);
13444
13359
  selection.setCoords();
13445
- prepareGroupSelectionTransformStart(selection);
13446
13360
  fabricCanvas._target = selection;
13447
13361
  opt.target = selection;
13448
13362
  pendingGroupPromotionRef.current = { groupId: parent.id, selection };
@@ -13485,7 +13399,6 @@ const PageCanvas = react.forwardRef(
13485
13399
  restoreGroupSelectionVisualState(selection, parent.id);
13486
13400
  fabricCanvas.setActiveObject(selection);
13487
13401
  selection.setCoords();
13488
- prepareGroupSelectionTransformStart(selection);
13489
13402
  fabricCanvas._target = selection;
13490
13403
  opt.target = selection;
13491
13404
  pendingGroupPromotionRef.current = { groupId: parent.id, selection };
@@ -13754,29 +13667,34 @@ const PageCanvas = react.forwardRef(
13754
13667
  });
13755
13668
  const markSimpleTransform = (e) => {
13756
13669
  if (!isActiveRef.current) return;
13757
- prepareGroupSelectionTransformStart(e.target);
13758
13670
  markTransforming(e.target);
13759
13671
  };
13760
13672
  const getObjectFrameBoundsInSelection = (selection, obj, frameWidth, frameHeight) => {
13761
13673
  const w = Math.max(1, frameWidth ?? obj.width ?? 1);
13762
13674
  const h = Math.max(1, frameHeight ?? obj.height ?? 1);
13675
+ const originX = obj.originX ?? "left";
13676
+ const originY = obj.originY ?? "top";
13677
+ const localLeft = originX === "center" ? -w / 2 : originX === "right" ? -w : 0;
13678
+ const localTop = originY === "center" ? -h / 2 : originY === "bottom" ? -h : 0;
13763
13679
  const matrix = fabric__namespace.util.multiplyTransformMatrices(
13764
13680
  selection.calcTransformMatrix(),
13765
13681
  obj.calcOwnMatrix()
13766
13682
  );
13767
- const decomposed = fabric__namespace.util.qrDecompose(matrix);
13768
- const scaledW = Math.max(1, w * Math.abs(decomposed.scaleX || 1));
13769
- const scaledH = Math.max(1, h * Math.abs(decomposed.scaleY || 1));
13770
- const angleRad = (decomposed.angle ?? 0) * Math.PI / 180;
13771
- const cos = Math.cos(angleRad);
13772
- const sin = Math.sin(angleRad);
13773
- const left = decomposed.translateX - scaledW / 2 * cos + scaledH / 2 * sin;
13774
- const top = decomposed.translateY - scaledW / 2 * sin - scaledH / 2 * cos;
13683
+ const points = [
13684
+ new fabric__namespace.Point(localLeft, localTop),
13685
+ new fabric__namespace.Point(localLeft + w, localTop),
13686
+ new fabric__namespace.Point(localLeft + w, localTop + h),
13687
+ new fabric__namespace.Point(localLeft, localTop + h)
13688
+ ].map((point) => fabric__namespace.util.transformPoint(point, matrix));
13689
+ const xs = points.map((p) => p.x);
13690
+ const ys = points.map((p) => p.y);
13691
+ const left = Math.min(...xs);
13692
+ const top = Math.min(...ys);
13775
13693
  return {
13776
13694
  left,
13777
13695
  top,
13778
- width: scaledW,
13779
- height: scaledH
13696
+ width: Math.max(1, Math.max(...xs) - left),
13697
+ height: Math.max(1, Math.max(...ys) - top)
13780
13698
  };
13781
13699
  };
13782
13700
  fabricCanvas.on("object:added", (e) => {
@@ -13791,30 +13709,10 @@ const PageCanvas = react.forwardRef(
13791
13709
  fabricCanvas.on("selection:cleared", () => {
13792
13710
  });
13793
13711
  fabricCanvas.on("object:scaling", (e) => {
13794
- var _a2, _b2, _c, _d, _e, _f, _g, _h;
13712
+ var _a2, _b2, _c, _d, _e, _f;
13795
13713
  if (!isActiveRef.current) return;
13796
13714
  const t = e.target;
13797
13715
  if (t) lastResizeScaleTargetRef.current = t;
13798
- try {
13799
- const transformDbg = e.transform;
13800
- const cornerDbg = (transformDbg == null ? void 0 : transformDbg.corner) || "";
13801
- const children = t instanceof fabric__namespace.Group || t instanceof fabric__namespace.ActiveSelection ? t.getObjects() : [];
13802
- logGroupImageResizeDebug("scaling-entry", {
13803
- time: Math.round(performance.now()),
13804
- corner: cornerDbg,
13805
- targetType: t == null ? void 0 : t.type,
13806
- targetCtor: (_a2 = t == null ? void 0 : t.constructor) == null ? void 0 : _a2.name,
13807
- isActiveSelection: t instanceof fabric__namespace.ActiveSelection,
13808
- isGroup: t instanceof fabric__namespace.Group,
13809
- isCropGroup: !!(t && (t.__cropGroup || ((_b2 = t._ct) == null ? void 0 : _b2.isCropGroup))),
13810
- childCount: children.length,
13811
- childTypes: children.map((c) => c == null ? void 0 : c.type),
13812
- hasImageChild: children.some((c) => isGroupResizeImageLikeObject(c)),
13813
- target: t ? summarizeFabricObjectForResizeDebug(t) : null
13814
- });
13815
- } catch (err) {
13816
- console.warn("[Pixldocs][group-image-side-resize] scaling-entry log failed", err);
13817
- }
13818
13716
  prepareGroupSelectionTransformStart(t);
13819
13717
  markTransforming(t);
13820
13718
  didTransformRef.current = true;
@@ -13978,7 +13876,7 @@ const PageCanvas = react.forwardRef(
13978
13876
  time: Math.round(performance.now()),
13979
13877
  corner,
13980
13878
  groupSelectionId: obj.__pixldocsGroupSelection,
13981
- currentTransformAction: (_c = fabricCanvas._currentTransform) == null ? void 0 : _c.action,
13879
+ currentTransformAction: (_a2 = fabricCanvas._currentTransform) == null ? void 0 : _a2.action,
13982
13880
  selection: summarizeFabricObjectForResizeDebug(obj),
13983
13881
  textChildren: obj.getObjects().filter((child) => child instanceof fabric__namespace.Textbox).map((child) => summarizeFabricObjectForResizeDebug(child))
13984
13882
  };
@@ -13988,43 +13886,19 @@ const PageCanvas = react.forwardRef(
13988
13886
  const isXSide = corner === "ml" || corner === "mr";
13989
13887
  const sAxis = isXSide ? Math.abs(obj.scaleX ?? 1) : Math.abs(obj.scaleY ?? 1);
13990
13888
  if (sAxis > 1e-3) {
13991
- const hasRotatedChild = obj.getObjects().some((c) => {
13992
- const a = ((c.angle ?? 0) % 180 + 180) % 180;
13993
- return !(a < 0.5 || a > 179.5);
13994
- });
13995
- const selectionAngle = ((obj.angle ?? 0) % 180 + 180) % 180;
13996
- const isSelectionRotated = !(selectionAngle < 0.5 || selectionAngle > 179.5);
13997
- const shouldPinNonTextChildren = hasRotatedChild || isSelectionRotated;
13998
- const shouldDebugGroupImageResize = obj.getObjects().some((child) => isGroupResizeImageLikeObject(child));
13999
- if (shouldDebugGroupImageResize) {
14000
- logGroupImageResizeDebug("live-start", {
14001
- time: Math.round(performance.now()),
14002
- corner,
14003
- isXSide,
14004
- sAxis,
14005
- hasRotatedChild,
14006
- isSelectionRotated,
14007
- shouldPinNonTextChildren,
14008
- groupSelectionId: obj.__pixldocsGroupSelection,
14009
- selection: summarizeFabricObjectForResizeDebug(obj),
14010
- children: obj.getObjects().map((child) => summarizeFabricObjectForResizeDebug(child))
14011
- });
14012
- }
14013
- if ((isXSide || shouldPinNonTextChildren) && ((_d = groupShiftReflowSnapshotRef.current) == null ? void 0 : _d.selection) !== obj) {
13889
+ if (isXSide && ((_b2 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _b2.selection) !== obj) {
14014
13890
  groupShiftReflowSnapshotRef.current = null;
14015
13891
  const logicalGroupId = obj.__pixldocsGroupSelection;
14016
13892
  if (logicalGroupId) {
14017
13893
  try {
14018
13894
  const state = useEditorStore.getState();
14019
- const pageChildren2 = ((_e = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _e.children) ?? [];
13895
+ const pageChildren2 = ((_c = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
14020
13896
  const groupNode = findNodeById(pageChildren2, logicalGroupId);
14021
13897
  if (groupNode && isGroup(groupNode) && !isStackLayoutMode(groupNode.layoutMode)) {
14022
13898
  const entries = obj.getObjects().map((c) => ({
14023
13899
  obj: c,
14024
13900
  id: getObjectId(c) ?? "",
14025
- left0: c.left ?? 0,
14026
13901
  top0: c.top ?? 0,
14027
- width0: (c.width ?? 0) * Math.abs(c.scaleX ?? 1),
14028
13902
  height0: (c.height ?? 0) * Math.abs(c.scaleY ?? 1)
14029
13903
  })).filter((e2) => e2.id).sort((a, b) => a.top0 - b.top0);
14030
13904
  if (entries.length > 1) {
@@ -14047,150 +13921,78 @@ const PageCanvas = react.forwardRef(
14047
13921
  const asTop0 = obj.top ?? 0;
14048
13922
  const asRect0 = obj.getBoundingRect();
14049
13923
  let didReflowTextChild = false;
14050
- if (hasRotatedChild) {
14051
- if (isXSide) {
14052
- obj._set("width", asW0 * sAxis);
14053
- obj._set("scaleX", 1);
14054
- } else {
14055
- obj._set("height", asH0 * sAxis);
14056
- obj._set("scaleY", 1);
14057
- }
14058
- }
14059
- const childCounterScale = hasRotatedChild ? 1 : 1 / sAxis;
14060
- let restoredNonTextAfterLayout = false;
14061
- const restoreNonTextChildren = (pins) => {
14062
- var _a3, _b3;
14063
- if (!shouldPinNonTextChildren || ((_a3 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _a3.selection) !== obj) return;
14064
- for (const entry of groupShiftReflowSnapshotRef.current.children) {
14065
- const child = entry.obj;
14066
- if (child instanceof fabric__namespace.Textbox) continue;
14067
- if (child instanceof fabric__namespace.FabricImage || child instanceof fabric__namespace.Group && (child.__cropGroup || ((_b3 = child._ct) == null ? void 0 : _b3.isCropGroup))) {
14068
- const pin = pins == null ? void 0 : pins.get(child);
14069
- let targetLeft = hasRotatedChild && isXSide ? entry.left0 * sAxis : entry.left0;
14070
- let targetTop = hasRotatedChild && !isXSide ? entry.top0 * sAxis : entry.top0;
14071
- if (pin == null ? void 0 : pin.worldCenter) {
14072
- try {
14073
- const invSelectionMatrix = fabric__namespace.util.invertTransform(obj.calcTransformMatrix());
14074
- const localCenter = fabric__namespace.util.transformPoint(pin.worldCenter, invSelectionMatrix);
14075
- targetLeft = localCenter.x;
14076
- targetTop = localCenter.y;
14077
- } catch {
14078
- targetLeft = pin.left ?? targetLeft;
14079
- targetTop = pin.top ?? targetTop;
14080
- }
14081
- } else {
14082
- targetLeft = (pin == null ? void 0 : pin.left) ?? targetLeft;
14083
- targetTop = (pin == null ? void 0 : pin.top) ?? targetTop;
14084
- }
14085
- const beforeRestore = shouldDebugGroupImageResize ? summarizeFabricObjectForResizeDebug(child) : null;
14086
- if (Math.abs((child.left ?? 0) - targetLeft) > 0.01) child._set("left", targetLeft);
14087
- if (Math.abs((child.top ?? 0) - targetTop) > 0.01) child._set("top", targetTop);
14088
- if (isXSide) child._set("scaleX", childCounterScale);
14089
- else child._set("scaleY", childCounterScale);
14090
- child.setCoords();
14091
- child.dirty = true;
14092
- if (shouldDebugGroupImageResize) {
14093
- logGroupImageResizeDebug("restore-non-text", {
14094
- time: Math.round(performance.now()),
14095
- corner,
14096
- childId: getObjectId(child),
14097
- targetLeft,
14098
- targetTop,
14099
- pin,
14100
- before: beforeRestore,
14101
- after: summarizeFabricObjectForResizeDebug(child)
14102
- });
14103
- }
14104
- }
14105
- }
14106
- };
14107
- const projectRotatedTextPosition = (child) => {
14108
- var _a3;
14109
- if (!hasRotatedChild || ((_a3 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _a3.selection) !== obj) return;
14110
- const entry = groupShiftReflowSnapshotRef.current.children.find((candidate) => candidate.obj === child);
14111
- if (!entry) return;
14112
- if (isXSide) child._set("left", entry.left0 * sAxis);
14113
- else child._set("top", entry.top0 * sAxis);
14114
- };
14115
13924
  for (const child of obj.getObjects()) {
14116
- if (child instanceof fabric__namespace.Group && (child.__cropGroup || ((_f = child._ct) == null ? void 0 : _f.isCropGroup))) {
14117
- const beforeImageChildResize = shouldDebugGroupImageResize ? summarizeFabricObjectForResizeDebug(child) : null;
13925
+ if (child instanceof fabric__namespace.Group && (child.__cropGroup || ((_d = child._ct) == null ? void 0 : _d.isCropGroup))) {
14118
13926
  const ct = child.__cropData;
14119
- if (ct) {
13927
+ if (!ct) continue;
13928
+ if (isXSide) {
14120
13929
  if (child.__asLiveOrigW == null) {
14121
- child.__asLiveOrigW = ct.frameW ?? child.width ?? 1;
13930
+ const baseW = child.width ?? ct.frameW ?? 0;
13931
+ child.__asLiveOrigW = baseW * (child.scaleX ?? 1);
14122
13932
  }
14123
- if (child.__asLiveOrigH == null) {
14124
- child.__asLiveOrigH = ct.frameH ?? child.height ?? 1;
14125
- }
14126
- if (isXSide) {
14127
- const newW = Math.max(1, Number(child.__asLiveOrigW) * sAxis);
13933
+ const origW = child.__asLiveOrigW;
13934
+ const newW = Math.max(20, origW * sAxis);
13935
+ if (Math.abs((child.width ?? 0) - newW) > 0.5) {
14128
13936
  ct.frameW = newW;
14129
13937
  child._set("width", newW);
14130
- } else {
14131
- const newH = Math.max(1, Number(child.__asLiveOrigH) * sAxis);
13938
+ child._set("scaleX", 1 / sAxis);
13939
+ try {
13940
+ updateCoverLayout(child);
13941
+ } catch {
13942
+ }
13943
+ child.setCoords();
13944
+ child.dirty = true;
13945
+ }
13946
+ } else {
13947
+ if (child.__asLiveOrigH == null) {
13948
+ const baseH = child.height ?? ct.frameH ?? 0;
13949
+ child.__asLiveOrigH = baseH * (child.scaleY ?? 1);
13950
+ }
13951
+ const origH = child.__asLiveOrigH;
13952
+ const newH = Math.max(20, origH * sAxis);
13953
+ if (Math.abs((child.height ?? 0) - newH) > 0.5) {
14132
13954
  ct.frameH = newH;
14133
13955
  child._set("height", newH);
13956
+ child._set("scaleY", 1 / sAxis);
13957
+ try {
13958
+ updateCoverLayout(child);
13959
+ } catch {
13960
+ }
13961
+ child.setCoords();
13962
+ child.dirty = true;
14134
13963
  }
14135
- try {
14136
- updateCoverLayout(child);
14137
- } catch {
14138
- }
14139
- }
14140
- if (isXSide) child._set("scaleX", childCounterScale);
14141
- else child._set("scaleY", childCounterScale);
14142
- child.setCoords();
14143
- child.dirty = true;
14144
- if (shouldDebugGroupImageResize) {
14145
- logGroupImageResizeDebug("live-crop-child-resized", {
14146
- time: Math.round(performance.now()),
14147
- corner,
14148
- sAxis,
14149
- childCounterScale,
14150
- before: beforeImageChildResize,
14151
- after: summarizeFabricObjectForResizeDebug(child),
14152
- cropData: ct ? { frameW: ct.frameW, frameH: ct.frameH } : null
14153
- });
14154
13964
  }
14155
- didReflowTextChild = true;
14156
13965
  continue;
14157
13966
  }
14158
13967
  if (child instanceof fabric__namespace.FabricImage && !child.__cropGroup && !child.smartElementType) {
14159
- const beforeImageChildResize = shouldDebugGroupImageResize ? summarizeFabricObjectForResizeDebug(child) : null;
14160
13968
  if (isXSide) {
14161
13969
  if (child.__asLiveOrigW == null) {
14162
- child.__asLiveOrigW = (child.width ?? 0) * Math.abs(child.scaleX ?? 1);
13970
+ child.__asLiveOrigW = (child.width ?? 0) * (child.scaleX ?? 1);
13971
+ }
13972
+ const origW = child.__asLiveOrigW;
13973
+ const newW = Math.max(1, origW * sAxis);
13974
+ if (Math.abs((child.width ?? 0) - newW) > 0.5) {
13975
+ child._set("width", newW);
13976
+ child._set("scaleX", 1 / sAxis);
13977
+ child.setCoords();
13978
+ child.dirty = true;
14163
13979
  }
14164
- const newW = Math.max(1, Number(child.__asLiveOrigW) * sAxis);
14165
- child._set("width", newW);
14166
13980
  } else {
14167
13981
  if (child.__asLiveOrigH == null) {
14168
- child.__asLiveOrigH = (child.height ?? 0) * Math.abs(child.scaleY ?? 1);
13982
+ child.__asLiveOrigH = (child.height ?? 0) * (child.scaleY ?? 1);
13983
+ }
13984
+ const origH = child.__asLiveOrigH;
13985
+ const newH = Math.max(1, origH * sAxis);
13986
+ if (Math.abs((child.height ?? 0) - newH) > 0.5) {
13987
+ child._set("height", newH);
13988
+ child._set("scaleY", 1 / sAxis);
13989
+ child.setCoords();
13990
+ child.dirty = true;
14169
13991
  }
14170
- const newH = Math.max(1, Number(child.__asLiveOrigH) * sAxis);
14171
- child._set("height", newH);
14172
- }
14173
- if (isXSide) child._set("scaleX", childCounterScale);
14174
- else child._set("scaleY", childCounterScale);
14175
- child.setCoords();
14176
- child.dirty = true;
14177
- if (shouldDebugGroupImageResize) {
14178
- logGroupImageResizeDebug("live-image-child-resized", {
14179
- time: Math.round(performance.now()),
14180
- corner,
14181
- sAxis,
14182
- childCounterScale,
14183
- liveOrigW: child.__asLiveOrigW,
14184
- liveOrigH: child.__asLiveOrigH,
14185
- before: beforeImageChildResize,
14186
- after: summarizeFabricObjectForResizeDebug(child)
14187
- });
14188
13992
  }
14189
- didReflowTextChild = true;
14190
13993
  continue;
14191
13994
  }
14192
13995
  if (!(child instanceof fabric__namespace.Textbox)) continue;
14193
- projectRotatedTextPosition(child);
14194
13996
  if (isXSide) {
14195
13997
  if (child.__asLiveOrigW == null) {
14196
13998
  child.__asLiveOrigW = (child.width ?? 0) * (child.scaleX ?? 1);
@@ -14199,7 +14001,7 @@ const PageCanvas = react.forwardRef(
14199
14001
  const newW = Math.max(20, origW * sAxis);
14200
14002
  if (Math.abs((child.width ?? 0) - newW) > 0.5) {
14201
14003
  child._set("width", newW);
14202
- child._set("scaleX", childCounterScale);
14004
+ child._set("scaleX", 1 / sAxis);
14203
14005
  try {
14204
14006
  child.initDimensions();
14205
14007
  } catch {
@@ -14212,14 +14014,10 @@ const PageCanvas = react.forwardRef(
14212
14014
  if (child.__asLiveOrigH == null) {
14213
14015
  child.__asLiveOrigH = (child.height ?? 0) * (child.scaleY ?? 1);
14214
14016
  }
14215
- if (child.__asLiveOrigMinH == null) {
14216
- const m = Number(child.minBoxHeight);
14217
- if (Number.isFinite(m) && m > 0) child.__asLiveOrigMinH = m;
14218
- }
14219
14017
  const origH = child.__asLiveOrigH;
14220
14018
  const newH = Math.max(20, origH * sAxis);
14221
14019
  child.minBoxHeight = newH;
14222
- child._set("scaleY", childCounterScale);
14020
+ child._set("scaleY", 1 / sAxis);
14223
14021
  try {
14224
14022
  child.initDimensions();
14225
14023
  } catch {
@@ -14229,7 +14027,7 @@ const PageCanvas = react.forwardRef(
14229
14027
  didReflowTextChild = true;
14230
14028
  }
14231
14029
  }
14232
- if (isXSide && !shouldPinNonTextChildren && ((_g = groupShiftReflowSnapshotRef.current) == null ? void 0 : _g.selection) === obj) {
14030
+ if (isXSide && ((_e = groupShiftReflowSnapshotRef.current) == null ? void 0 : _e.selection) === obj) {
14233
14031
  const snap = groupShiftReflowSnapshotRef.current;
14234
14032
  const anchorEntry = snap.children[0];
14235
14033
  const anchorTopLive = anchorEntry.obj.top ?? 0;
@@ -14262,26 +14060,10 @@ const PageCanvas = react.forwardRef(
14262
14060
  if (cornersBefore) {
14263
14061
  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 };
14264
14062
  }
14265
- const nonTextPinsBeforeLayout = shouldPinNonTextChildren ? new Map(obj.getObjects().map((child) => [child, {
14266
- left: child.left ?? 0,
14267
- top: child.top ?? 0,
14268
- worldCenter: child instanceof fabric__namespace.Textbox ? void 0 : child.getCenterPoint()
14269
- }])) : void 0;
14270
14063
  try {
14271
14064
  obj.triggerLayout();
14272
14065
  } catch {
14273
14066
  }
14274
- restoreNonTextChildren(nonTextPinsBeforeLayout);
14275
- restoredNonTextAfterLayout = !!nonTextPinsBeforeLayout;
14276
- if (shouldDebugGroupImageResize) {
14277
- logGroupImageResizeDebug("after-trigger-layout", {
14278
- time: Math.round(performance.now()),
14279
- corner,
14280
- selection: summarizeFabricObjectForResizeDebug(obj),
14281
- nonTextPinsBeforeLayout,
14282
- children: obj.getObjects().map((child) => summarizeFabricObjectForResizeDebug(child))
14283
- });
14284
- }
14285
14067
  obj._set("width", asW0);
14286
14068
  obj._set("scaleX", asSx0);
14287
14069
  obj._set("scaleY", asSy0);
@@ -14307,19 +14089,9 @@ const PageCanvas = react.forwardRef(
14307
14089
  obj._set("left", asLeft0);
14308
14090
  obj._set("top", asTop0);
14309
14091
  }
14310
- if (!restoredNonTextAfterLayout) restoreNonTextChildren();
14311
14092
  obj._set("width", asW0);
14312
14093
  obj._set("scaleX", asSx0);
14313
14094
  obj._set("scaleY", asSy0);
14314
- if (hasRotatedChild) {
14315
- if (isXSide) {
14316
- obj._set("width", asW0 * sAxis);
14317
- obj._set("scaleX", 1);
14318
- } else {
14319
- obj._set("height", asH0 * sAxis);
14320
- obj._set("scaleY", 1);
14321
- }
14322
- }
14323
14095
  obj.setCoords();
14324
14096
  obj.dirty = true;
14325
14097
  }
@@ -14411,7 +14183,7 @@ const PageCanvas = react.forwardRef(
14411
14183
  setGuides(gridGuidesForScale.length ? [...scaleGuides, ...gridGuidesForScale] : scaleGuides);
14412
14184
  if (drilledGroupIdRef.current) {
14413
14185
  try {
14414
- (_h = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _h.call(fabricCanvas);
14186
+ (_f = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _f.call(fabricCanvas);
14415
14187
  } catch {
14416
14188
  }
14417
14189
  }
@@ -14502,36 +14274,44 @@ const PageCanvas = react.forwardRef(
14502
14274
  }
14503
14275
  });
14504
14276
  fabricCanvas.on("object:rotating", (e) => {
14505
- var _a2, _b2;
14506
- prepareGroupSelectionTransformStart(e.target);
14507
14277
  markSimpleTransform(e);
14508
14278
  didTransformRef.current = true;
14509
14279
  const tr = e.target;
14510
14280
  try {
14511
- const children = tr instanceof fabric__namespace.Group || tr instanceof fabric__namespace.ActiveSelection ? tr.getObjects() : [];
14512
- logGroupImageResizeDebug("rotating-entry", {
14513
- time: Math.round(performance.now()),
14514
- angle: tr == null ? void 0 : tr.angle,
14515
- targetType: tr == null ? void 0 : tr.type,
14516
- targetCtor: (_a2 = tr == null ? void 0 : tr.constructor) == null ? void 0 : _a2.name,
14517
- isActiveSelection: tr instanceof fabric__namespace.ActiveSelection,
14518
- isGroup: tr instanceof fabric__namespace.Group,
14519
- isCropGroup: !!(tr && (tr.__cropGroup || ((_b2 = tr._ct) == null ? void 0 : _b2.isCropGroup))),
14520
- childCount: children.length,
14521
- childTypes: children.map((c) => c == null ? void 0 : c.type),
14522
- hasImageChild: children.some((c) => isGroupResizeImageLikeObject(c)),
14523
- target: tr ? summarizeFabricObjectForResizeDebug(tr) : null,
14524
- children: children.map((c) => {
14525
- var _a3;
14526
- return {
14527
- type: c == null ? void 0 : c.type,
14528
- ctor: (_a3 = c == null ? void 0 : c.constructor) == null ? void 0 : _a3.name,
14529
- summary: summarizeFabricObjectForResizeDebug(c)
14530
- };
14531
- })
14532
- });
14533
- } catch (err) {
14534
- console.warn("[Pixldocs][group-image-side-resize] rotating-entry log failed", err);
14281
+ const t = tr;
14282
+ if (t) {
14283
+ const childSummary = (t._objects ?? []).map((c) => ({
14284
+ id: getObjectId(c),
14285
+ type: c.type,
14286
+ left: c.left,
14287
+ top: c.top,
14288
+ angle: c.angle,
14289
+ scaleX: c.scaleX,
14290
+ scaleY: c.scaleY,
14291
+ originX: c.originX,
14292
+ originY: c.originY,
14293
+ width: c.width,
14294
+ height: c.height
14295
+ }));
14296
+ console.info("[Pixldocs][rot-group-image-drift] rotating", {
14297
+ targetType: t.type,
14298
+ isAS: t instanceof fabric__namespace.ActiveSelection,
14299
+ isGroup: t instanceof fabric__namespace.Group,
14300
+ targetId: getObjectId(t),
14301
+ left: t.left,
14302
+ top: t.top,
14303
+ angle: t.angle,
14304
+ scaleX: t.scaleX,
14305
+ scaleY: t.scaleY,
14306
+ width: t.width,
14307
+ height: t.height,
14308
+ originX: t.originX,
14309
+ originY: t.originY,
14310
+ childCount: (t._objects ?? []).length,
14311
+ children: childSummary
14312
+ });
14313
+ }
14314
+ } catch {
14535
14315
  }
14536
14316
  try {
14537
14317
  const getCursor = fabricCanvas.__pixldocsGetRotateCursor;
@@ -14565,6 +14345,42 @@ const PageCanvas = react.forwardRef(
14565
14345
  prepareGroupSelectionTransformStart(e.target);
14566
14346
  markTransforming(e.target);
14567
14347
  didTransformRef.current = true;
14348
+ try {
14349
+ const t = e.target;
14350
+ if (t && (t.angle ?? 0) !== 0) {
14351
+ const childSummary = (t._objects ?? []).map((c) => ({
14352
+ id: getObjectId(c),
14353
+ type: c.type,
14354
+ left: c.left,
14355
+ top: c.top,
14356
+ angle: c.angle,
14357
+ scaleX: c.scaleX,
14358
+ scaleY: c.scaleY,
14359
+ originX: c.originX,
14360
+ originY: c.originY,
14361
+ width: c.width,
14362
+ height: c.height
14363
+ }));
14364
+ console.info("[Pixldocs][rot-group-image-drift] moving", {
14365
+ targetType: t.type,
14366
+ isAS: t instanceof fabric__namespace.ActiveSelection,
14367
+ isGroup: t instanceof fabric__namespace.Group,
14368
+ targetId: getObjectId(t),
14369
+ left: t.left,
14370
+ top: t.top,
14371
+ angle: t.angle,
14372
+ scaleX: t.scaleX,
14373
+ scaleY: t.scaleY,
14374
+ width: t.width,
14375
+ height: t.height,
14376
+ originX: t.originX,
14377
+ originY: t.originY,
14378
+ childCount: (t._objects ?? []).length,
14379
+ children: childSummary
14380
+ });
14381
+ }
14382
+ } catch {
14383
+ }
14568
14384
  const activeDuringMove = fabricCanvas.getActiveObject();
14569
14385
  const movingLogicalGroupId = activeDuringMove instanceof fabric__namespace.ActiveSelection ? activeDuringMove.__pixldocsGroupSelection : void 0;
14570
14386
  const pendingMoveDrill = pendingGroupDrillInRef.current;
@@ -14575,7 +14391,7 @@ const PageCanvas = react.forwardRef(
14575
14391
  setDrilledGroupBounds(null);
14576
14392
  drilledGroupIdRef.current = null;
14577
14393
  if (activeDuringMove instanceof fabric__namespace.ActiveSelection && groupIdToKeep) {
14578
- preserveLogicalGroupTagDuringMove(activeDuringMove, groupIdToKeep);
14394
+ restoreGroupSelectionVisualState(activeDuringMove, groupIdToKeep);
14579
14395
  }
14580
14396
  }
14581
14397
  if (e.target) e.target.__pixldocsDragMoved = true;
@@ -14628,7 +14444,7 @@ const PageCanvas = react.forwardRef(
14628
14444
  });
14629
14445
  let cropGroupSaveTimer = null;
14630
14446
  fabricCanvas.on("object:modified", (e) => {
14631
- var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k;
14447
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i;
14632
14448
  try {
14633
14449
  dragStarted = false;
14634
14450
  setGuides([]);
@@ -14637,43 +14453,18 @@ const PageCanvas = react.forwardRef(
14637
14453
  groupResizeActiveSnapRef.current = null;
14638
14454
  onDragEnd == null ? void 0 : onDragEnd();
14639
14455
  try {
14640
- const mt = e.target;
14641
- const children = mt instanceof fabric__namespace.Group || mt instanceof fabric__namespace.ActiveSelection ? mt.getObjects() : [];
14642
- logGroupImageResizeDebug("modified-entry", {
14643
- time: Math.round(performance.now()),
14644
- didTransform: didTransformRef.current,
14645
- targetType: mt == null ? void 0 : mt.type,
14646
- targetCtor: (_a2 = mt == null ? void 0 : mt.constructor) == null ? void 0 : _a2.name,
14647
- isActiveSelection: mt instanceof fabric__namespace.ActiveSelection,
14648
- isGroup: mt instanceof fabric__namespace.Group,
14649
- angle: mt == null ? void 0 : mt.angle,
14650
- childCount: children.length,
14651
- childTypes: children.map((c) => c == null ? void 0 : c.type),
14652
- hasImageChild: children.some((c) => isGroupResizeImageLikeObject(c)),
14653
- target: mt ? summarizeFabricObjectForResizeDebug(mt) : null,
14654
- children: children.map((c) => {
14655
- var _a3;
14656
- return {
14657
- type: c == null ? void 0 : c.type,
14658
- ctor: (_a3 = c == null ? void 0 : c.constructor) == null ? void 0 : _a3.name,
14659
- summary: summarizeFabricObjectForResizeDebug(c)
14660
- };
14661
- })
14662
- });
14663
- } catch (err) {
14664
- console.warn("[Pixldocs][group-image-side-resize] modified-entry log failed", err);
14665
- }
14666
- const modifiedTarget = e.target;
14667
- if (modifiedTarget instanceof fabric__namespace.ActiveSelection && modifiedTarget.getObjects().length === 0) {
14668
- didTransformRef.current = false;
14669
- groupSelectionTransformStartRef.current = null;
14670
- activeSelectionMoveStartRef.current = null;
14671
- activeSelectionResizeHandleRef.current = null;
14672
- unlockEditsSoon();
14673
- return;
14456
+ const t = e.target;
14457
+ if (t instanceof fabric__namespace.ActiveSelection) {
14458
+ for (const child of t.getObjects()) {
14459
+ delete child.__asLiveOrigW;
14460
+ delete child.__asLiveOrigH;
14461
+ }
14462
+ }
14463
+ } catch {
14674
14464
  }
14675
14465
  groupShiftReflowSnapshotRef.current = null;
14676
14466
  lockEdits();
14467
+ const modifiedTarget = e.target;
14677
14468
  const modifiedTargetId = modifiedTarget ? getObjectId(modifiedTarget) : null;
14678
14469
  const modifiedTargetElement = modifiedTargetId ? elementsRef.current.find((el) => el.id === modifiedTargetId) : null;
14679
14470
  if (modifiedTarget && (modifiedTargetElement == null ? void 0 : modifiedTargetElement.type) === "shape") {
@@ -14698,7 +14489,7 @@ const PageCanvas = react.forwardRef(
14698
14489
  const active = fabricCanvas.getActiveObject();
14699
14490
  const activeId = active ? getObjectId(active) : null;
14700
14491
  if (active && activeId && activeId !== "__background__" && !(active instanceof fabric__namespace.Group)) {
14701
- const pageChildrenForParent = ((_b2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _b2.children) ?? [];
14492
+ const pageChildrenForParent = ((_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
14702
14493
  const parentGroup = findParentGroup(pageChildrenForParent, activeId);
14703
14494
  if (parentGroup && isGroup(parentGroup) && parentGroup.backgroundColor) {
14704
14495
  let fabricSectionGroup = active.group && active.group instanceof fabric__namespace.Group ? active.group : null;
@@ -14780,7 +14571,7 @@ const PageCanvas = react.forwardRef(
14780
14571
  useEditorStore.getState().reflowStackGroupInPage(pageId, groupId);
14781
14572
  }
14782
14573
  const stateAfter = useEditorStore.getState();
14783
- const pageAfter = ((_c = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
14574
+ const pageAfter = ((_b2 = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _b2.children) ?? [];
14784
14575
  const groupNodeAfter = findNodeById(pageAfter, groupId);
14785
14576
  if (groupNodeAfter) {
14786
14577
  const abs = getAbsoluteBounds(groupNodeAfter, pageAfter);
@@ -14816,9 +14607,8 @@ const PageCanvas = react.forwardRef(
14816
14607
  const stateCrop = useEditorStore.getState();
14817
14608
  const pageCrop = stateCrop.canvas.pages.find((p) => p.id === pageId);
14818
14609
  const pageChildrenCrop = (pageCrop == null ? void 0 : pageCrop.children) ?? [];
14819
- const angleRad = (active.angle ?? 0) * Math.PI / 180;
14820
- const absLeft = (active.left ?? 0) - ct.frameW / 2 * Math.cos(angleRad) + ct.frameH / 2 * Math.sin(angleRad);
14821
- const absTop = (active.top ?? 0) - ct.frameW / 2 * Math.sin(angleRad) - ct.frameH / 2 * Math.cos(angleRad);
14610
+ const absLeft = (active.left ?? 0) - ct.frameW / 2;
14611
+ const absTop = (active.top ?? 0) - ct.frameH / 2;
14822
14612
  const storePosCrop = absoluteToStorePosition(absLeft, absTop, objId, pageChildrenCrop);
14823
14613
  updateElement2(objId, {
14824
14614
  width: ct.frameW,
@@ -14843,7 +14633,7 @@ const PageCanvas = react.forwardRef(
14843
14633
  }
14844
14634
  if (active && active instanceof fabric__namespace.Group && active.__docuforgeSectionGroup && getObjectId(active)) {
14845
14635
  const groupId = getObjectId(active);
14846
- const pageChildrenSec = ((_d = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _d.children) ?? [];
14636
+ const pageChildrenSec = ((_c = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
14847
14637
  const modifiedTarget2 = e == null ? void 0 : e.target;
14848
14638
  const resizeScaleTarget = lastResizeScaleTargetRef.current;
14849
14639
  lastResizeScaleTargetRef.current = null;
@@ -14874,7 +14664,7 @@ const PageCanvas = react.forwardRef(
14874
14664
  const node = findNodeById(pageChildrenSec, groupId);
14875
14665
  if (isChildModified && node && !groupMoved) {
14876
14666
  const stateAfter = useEditorStore.getState();
14877
- const pageAfter = ((_e = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _e.children) ?? [];
14667
+ const pageAfter = ((_d = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _d.children) ?? [];
14878
14668
  const groupNodeAfter = findNodeById(pageAfter, groupId);
14879
14669
  if (groupNodeAfter) {
14880
14670
  const abs = getAbsoluteBounds(groupNodeAfter, pageAfter);
@@ -14890,7 +14680,7 @@ const PageCanvas = react.forwardRef(
14890
14680
  }
14891
14681
  if (active && active instanceof fabric__namespace.Group && !(active instanceof fabric__namespace.ActiveSelection) && getObjectId(active)) {
14892
14682
  const groupId = getObjectId(active);
14893
- const pageChildren3 = ((_f = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _f.children) ?? [];
14683
+ const pageChildren3 = ((_e = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _e.children) ?? [];
14894
14684
  const w = (active.width ?? 0) * (active.scaleX ?? 1);
14895
14685
  const h = (active.height ?? 0) * (active.scaleY ?? 1);
14896
14686
  const centerX = active.left ?? 0;
@@ -14912,7 +14702,7 @@ const PageCanvas = react.forwardRef(
14912
14702
  }
14913
14703
  const activeObj = fabricCanvas.getActiveObject();
14914
14704
  let activeObjects = fabricCanvas.getActiveObjects();
14915
- const activeSelectionMoveStart = activeObj instanceof fabric__namespace.ActiveSelection && ((_g = activeSelectionMoveStartRef.current) == null ? void 0 : _g.selection) === activeObj ? activeSelectionMoveStartRef.current : null;
14705
+ const activeSelectionMoveStart = activeObj instanceof fabric__namespace.ActiveSelection && ((_f = activeSelectionMoveStartRef.current) == null ? void 0 : _f.selection) === activeObj ? activeSelectionMoveStartRef.current : null;
14916
14706
  const activeSelectionDelta = activeObj instanceof fabric__namespace.ActiveSelection && activeSelectionMoveStart ? (() => {
14917
14707
  const rect = activeObj.getBoundingRect();
14918
14708
  return {
@@ -14929,18 +14719,6 @@ const PageCanvas = react.forwardRef(
14929
14719
  const isActiveSelection = activeObj instanceof fabric__namespace.ActiveSelection || activeObjects.length > 1;
14930
14720
  const activeSelectionResizeHandle = isActiveSelection ? activeSelectionResizeHandleRef.current : null;
14931
14721
  const debugGroupTextCornerResize = activeObj instanceof fabric__namespace.ActiveSelection && isCornerResizeHandle(activeSelectionResizeHandle) && activeObjects.some((candidate) => candidate instanceof fabric__namespace.Textbox);
14932
- const debugGroupImageSideResize = activeObj instanceof fabric__namespace.ActiveSelection && (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") && activeObjects.some((candidate) => isGroupResizeImageLikeObject(candidate));
14933
- if (debugGroupImageSideResize) {
14934
- logGroupImageResizeDebug("modified-start", {
14935
- time: Math.round(performance.now()),
14936
- handle: activeSelectionResizeHandle,
14937
- target: summarizeFabricObjectForResizeDebug(modifiedTarget),
14938
- selection: summarizeFabricObjectForResizeDebug(activeObj),
14939
- activeObjectIds: activeObjects.map((candidate) => getObjectId(candidate)),
14940
- selectedStoreIds: useEditorStore.getState().canvas.selectedIds,
14941
- members: activeObjects.map((candidate) => summarizeFabricObjectForResizeDebug(candidate))
14942
- });
14943
- }
14944
14722
  if (debugGroupTextCornerResize) {
14945
14723
  logGroupTextResizeDebug("modified-start", {
14946
14724
  time: Math.round(performance.now()),
@@ -14973,14 +14751,7 @@ const PageCanvas = react.forwardRef(
14973
14751
  const node = findNodeById(pageChildren2, id);
14974
14752
  return !!(node && isGroup(node));
14975
14753
  });
14976
- const activeSelectionHadTransform = activeObj instanceof fabric__namespace.ActiveSelection && (Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01 || (() => {
14977
- var _a3;
14978
- const normAngle = (angle) => (angle % 360 + 360) % 360;
14979
- const startAngle = ((_a3 = groupSelectionTransformStartRef.current) == null ? void 0 : _a3.selection) === activeObj ? groupSelectionTransformStartRef.current.selectionAngle : 0;
14980
- const currentAngle = normAngle(activeObj.angle ?? 0);
14981
- const diff = Math.abs(currentAngle - normAngle(startAngle));
14982
- return Math.min(diff, 360 - diff) > 1;
14983
- })());
14754
+ const activeSelectionHadTransform = activeObj instanceof fabric__namespace.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);
14984
14755
  if (!anyCropGroup && activeSelectionDelta && !activeSelectionHadTransform && selectedLogicalGroupIds.length > 0) {
14985
14756
  const selectedStoreIds = useEditorStore.getState().canvas.selectedIds ?? [];
14986
14757
  const groupMemberIds = /* @__PURE__ */ new Set();
@@ -15021,13 +14792,7 @@ const PageCanvas = react.forwardRef(
15021
14792
  return;
15022
14793
  }
15023
14794
  }
15024
- const isActiveSelectionSideResize = isActiveSelection && (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb");
15025
- const normalizeAngle = (angle) => (angle % 360 + 360) % 360;
15026
- const shortestAngleDelta = (a, b) => {
15027
- const diff = Math.abs(normalizeAngle(a) - normalizeAngle(b));
15028
- return Math.min(diff, 360 - diff);
15029
- };
15030
- if (selectedElementIds.length > 0) {
14795
+ if (selectedElementIds.length > 0 && !anyCropGroup) {
15031
14796
  const firstObj = activeObjects[0];
15032
14797
  const firstId = getObjectId(firstObj);
15033
14798
  const parentGroups = selectedElementIds.map((id) => findParentGroup(pageChildren2, id)).filter((g) => g !== null);
@@ -15050,9 +14815,9 @@ const PageCanvas = react.forwardRef(
15050
14815
  let movedGroupLeft = groupAbs.left;
15051
14816
  let movedGroupTop = groupAbs.top;
15052
14817
  if (activeObj instanceof fabric__namespace.ActiveSelection && (transformStart == null ? void 0 : transformStart.groupId) === groupToMove.id) {
15053
- const selectionCenter = activeObj.getCenterPoint();
15054
- movedGroupLeft = transformStart.groupLeft + (selectionCenter.x - transformStart.selectionCenterX);
15055
- movedGroupTop = transformStart.groupTop + (selectionCenter.y - transformStart.selectionCenterY);
14818
+ const selectionRect = activeObj.getBoundingRect();
14819
+ movedGroupLeft = transformStart.groupLeft + (selectionRect.left - transformStart.selectionLeft);
14820
+ movedGroupTop = transformStart.groupTop + (selectionRect.top - transformStart.selectionTop);
15056
14821
  } else if (activeObj instanceof fabric__namespace.ActiveSelection && firstId && firstObj) {
15057
14822
  const firstNode = findNodeById(pageChildren2, firstId);
15058
14823
  if (firstNode) {
@@ -15088,58 +14853,19 @@ const PageCanvas = react.forwardRef(
15088
14853
  }
15089
14854
  const deltaX = movedGroupLeft - groupAbs.left;
15090
14855
  const deltaY = movedGroupTop - groupAbs.top;
15091
- const hadResizeHandle = isActiveSelection && !!activeSelectionResizeHandle;
15092
- const hadScale = isActiveSelection && activeObj && (hadResizeHandle || Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01);
15093
- const startSelAngle = normalizeAngle((transformStart == null ? void 0 : transformStart.selectionAngle) ?? 0);
15094
- const currentSelAngle = isActiveSelection && activeObj ? normalizeAngle(activeObj.angle ?? 0) : 0;
15095
- const storedGroupAngle = normalizeAngle(Number(groupToMove.angle ?? 0));
15096
- const effectiveStartAngle = transformStart ? startSelAngle : storedGroupAngle;
15097
- const angleDelta = shortestAngleDelta(currentSelAngle, effectiveStartAngle);
15098
- const hadRotation = isActiveSelection && activeObj && angleDelta > 1;
15099
- if (activeGroupSelectionId === groupToMove.id && hadRotation && !hadScale && !activeSelectionResizeHandle && activeObj instanceof fabric__namespace.ActiveSelection) {
15100
- const { updateNode: updateNodeStore, commitHistory: commitHistoryStore, getCurrentElements } = useEditorStore.getState();
15101
- const center = activeObj.getCenterPoint();
15102
- const baseCenterX = (transformStart == null ? void 0 : transformStart.selectionCenterX) ?? groupAbs.left + groupAbs.width / 2;
15103
- const baseCenterY = (transformStart == null ? void 0 : transformStart.selectionCenterY) ?? groupAbs.top + groupAbs.height / 2;
15104
- const nextAbsLeft = groupAbs.left + (center.x - baseCenterX);
15105
- const nextAbsTop = groupAbs.top + (center.y - baseCenterY);
15106
- const storePos = absoluteToStorePosition(nextAbsLeft, nextAbsTop, groupToMove.id, pageChildren2);
15107
- updateNodeStore(groupToMove.id, {
15108
- left: storePos.left,
15109
- top: storePos.top,
15110
- angle: currentSelAngle
15111
- }, { recordHistory: false, skipLayoutRecalc: true });
15112
- commitHistoryStore();
15113
- restoreGroupSelectionVisualState(activeObj, groupToMove.id);
15114
- fabricCanvas.setActiveObject(activeObj);
15115
- activeObj.setCoords();
15116
- selectElements([groupToMove.id], false, false);
15117
- fabricCanvas.requestRenderAll();
15118
- elementsRef.current = getCurrentElements();
15119
- const restoreSnapshot = {
15120
- memberIds: activeObj.getObjects().map((obj) => getObjectId(obj)).filter((id) => !!id && id !== "__background__"),
15121
- groupSelectionId: groupToMove.id,
15122
- expiresAt: Date.now() + 1200
15123
- };
15124
- recentGroupSelectionRestoreRef.current = restoreSnapshot;
15125
- activeObj.getObjects().forEach((obj) => {
15126
- const objId = getObjectId(obj);
15127
- if (objId && objId !== "__background__") {
15128
- justModifiedIdsRef.current.add(objId);
15129
- modifiedIdsThisRound.add(objId);
15130
- }
15131
- });
15132
- setTimeout(() => modifiedIdsThisRound.forEach((id) => justModifiedIdsRef.current.delete(id)), 150);
15133
- groupSelectionTransformStartRef.current = null;
15134
- activeSelectionMoveStartRef.current = null;
15135
- activeSelectionResizeHandleRef.current = null;
15136
- unlockEditsSoon();
15137
- return;
15138
- }
15139
- if (!isActiveSelectionSideResize && !hadScale && !hadRotation && (Math.abs(deltaX) > 0.1 || Math.abs(deltaY) > 0.1)) {
14856
+ const hadScale = isActiveSelection && activeObj && (Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01);
14857
+ const startSelAngle = (((transformStart == null ? void 0 : transformStart.selectionAngle) ?? 0) % 360 + 360) % 360;
14858
+ const currentSelAngle = isActiveSelection && activeObj ? ((activeObj.angle ?? 0) % 360 + 360) % 360 : 0;
14859
+ const angleDelta = Math.min(
14860
+ Math.abs(currentSelAngle - startSelAngle),
14861
+ 360 - Math.abs(currentSelAngle - startSelAngle)
14862
+ );
14863
+ const hadRotation = isActiveSelection && activeObj && angleDelta > 0.01;
14864
+ if (!hadScale && !hadRotation && (Math.abs(deltaX) > 0.1 || Math.abs(deltaY) > 0.1)) {
15140
14865
  const { updateNode: updateNodeStore, commitHistory: commitHistoryStore, getCurrentElements } = useEditorStore.getState();
15141
- const storePos = absoluteToStorePosition(movedGroupLeft, movedGroupTop, groupToMove.id, pageChildren2);
15142
- updateNodeStore(groupToMove.id, { left: storePos.left, top: storePos.top }, { recordHistory: false, skipLayoutRecalc: true });
14866
+ const newLeft = (groupToMove.left ?? 0) + deltaX;
14867
+ const newTop = (groupToMove.top ?? 0) + deltaY;
14868
+ updateNodeStore(groupToMove.id, { left: newLeft, top: newTop }, { recordHistory: false, skipLayoutRecalc: true });
15143
14869
  commitHistoryStore();
15144
14870
  pendingGroupDrillInRef.current = null;
15145
14871
  fabricCanvas.__activeEditingGroupId = null;
@@ -15164,8 +14890,6 @@ const PageCanvas = react.forwardRef(
15164
14890
  }
15165
14891
  setTimeout(() => modifiedIdsThisRound.forEach((id) => justModifiedIdsRef.current.delete(id)), 150);
15166
14892
  groupSelectionTransformStartRef.current = null;
15167
- activeSelectionMoveStartRef.current = null;
15168
- activeSelectionResizeHandleRef.current = null;
15169
14893
  const restoreSnapshot = {
15170
14894
  memberIds: targetObjects.map((obj) => getObjectId(obj)).filter((id) => !!id && id !== "__background__"),
15171
14895
  groupSelectionId,
@@ -15179,38 +14903,6 @@ const PageCanvas = react.forwardRef(
15179
14903
  }
15180
14904
  }
15181
14905
  const pendingCropGroupFrameBakes = [];
15182
- const logicalGroupSelectionId = activeObj instanceof fabric__namespace.ActiveSelection ? activeObj.__pixldocsGroupSelection : void 0;
15183
- const isLogicalGroupAS = !!logicalGroupSelectionId && !(activeObj == null ? void 0 : activeObj.__cropGroup) && !(activeObj == null ? void 0 : activeObj.__docuforgeSectionGroup);
15184
- const logicalGroupNodeForBake = logicalGroupSelectionId ? findNodeById(pageChildren2, logicalGroupSelectionId) : null;
15185
- const asAngleForBake = isLogicalGroupAS && activeObj ? normalizeAngle(Number(activeObj.angle ?? 0)) : 0;
15186
- const logicalGroupFinalFrame = (() => {
15187
- var _a3;
15188
- if (!isLogicalGroupAS || !logicalGroupSelectionId || !(activeObj instanceof fabric__namespace.ActiveSelection)) return null;
15189
- const baseline = ((_a3 = groupSelectionTransformStartRef.current) == null ? void 0 : _a3.groupId) === logicalGroupSelectionId ? groupSelectionTransformStartRef.current : null;
15190
- const localWidth = Math.max(1, (activeObj.width ?? (baseline == null ? void 0 : baseline.groupWidth) ?? 1) * Math.abs(activeObj.scaleX ?? 1));
15191
- const localHeight = Math.max(1, (activeObj.height ?? (baseline == null ? void 0 : baseline.groupHeight) ?? 1) * Math.abs(activeObj.scaleY ?? 1));
15192
- const center = activeObj.getCenterPoint();
15193
- const topLeft = centerToRotatedTopLeft(center.x, center.y, localWidth, localHeight, asAngleForBake);
15194
- return {
15195
- groupId: logicalGroupSelectionId,
15196
- left: topLeft.left,
15197
- top: topLeft.top,
15198
- width: localWidth,
15199
- height: localHeight,
15200
- centerX: center.x,
15201
- centerY: center.y,
15202
- angle: asAngleForBake,
15203
- matrix: fabric__namespace.util.composeMatrix({
15204
- translateX: center.x,
15205
- translateY: center.y,
15206
- angle: asAngleForBake,
15207
- scaleX: 1,
15208
- scaleY: 1,
15209
- skewX: 0,
15210
- skewY: 0
15211
- })
15212
- };
15213
- })();
15214
14906
  for (const obj of activeObjects) {
15215
14907
  const objId = getObjectId(obj);
15216
14908
  if (!objId || objId === "__background__") continue;
@@ -15256,15 +14948,16 @@ const PageCanvas = react.forwardRef(
15256
14948
  modifiedIdsThisRound.add(objId);
15257
14949
  let absoluteLeft;
15258
14950
  let absoluteTop;
15259
- const initialTopLeft = centerToRotatedTopLeft(
15260
- decomposed.translateX ?? (obj.left ?? 0),
15261
- decomposed.translateY ?? (obj.top ?? 0),
15262
- intrinsicWidth * Math.abs(decomposed.scaleX || 1),
15263
- intrinsicHeight * Math.abs(decomposed.scaleY || 1),
15264
- decomposed.angle ?? 0
15265
- );
15266
- absoluteLeft = initialTopLeft.left;
15267
- absoluteTop = initialTopLeft.top;
14951
+ if (isActiveSelection && activeObj) {
14952
+ const selectionMatrix = activeObj.calcTransformMatrix();
14953
+ const relativePoint = { x: obj.left ?? 0, y: obj.top ?? 0 };
14954
+ const absolutePoint = fabric__namespace.util.transformPoint(relativePoint, selectionMatrix);
14955
+ absoluteLeft = absolutePoint.x;
14956
+ absoluteTop = absolutePoint.y;
14957
+ } else {
14958
+ absoluteLeft = obj.left ?? 0;
14959
+ absoluteTop = obj.top ?? 0;
14960
+ }
15268
14961
  if (obj instanceof fabric__namespace.Group && obj.__cropGroup) {
15269
14962
  const ct = obj.__cropData;
15270
14963
  if (isActiveSelection && activeObj instanceof fabric__namespace.ActiveSelection) {
@@ -15274,22 +14967,14 @@ const PageCanvas = react.forwardRef(
15274
14967
  } else {
15275
14968
  const w = ((ct == null ? void 0 : ct.frameW) ?? obj.width ?? 0) * Math.abs(obj.scaleX ?? 1);
15276
14969
  const h = ((ct == null ? void 0 : ct.frameH) ?? obj.height ?? 0) * Math.abs(obj.scaleY ?? 1);
15277
- const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
15278
- absoluteLeft = (decomposed.translateX ?? absoluteLeft ?? 0) - w / 2 * Math.cos(angleRad) + h / 2 * Math.sin(angleRad);
15279
- absoluteTop = (decomposed.translateY ?? absoluteTop ?? 0) - w / 2 * Math.sin(angleRad) - h / 2 * Math.cos(angleRad);
14970
+ absoluteLeft = (absoluteLeft ?? 0) - w / 2;
14971
+ absoluteTop = (absoluteTop ?? 0) - h / 2;
15280
14972
  }
15281
14973
  } else if (obj instanceof fabric__namespace.FabricImage && (obj.originX === "center" || obj.originY === "center")) {
15282
- if (isActiveSelection && activeObj instanceof fabric__namespace.ActiveSelection) {
15283
- const frameBounds = getObjectFrameBoundsInSelection(activeObj, obj, obj.width ?? 0, obj.height ?? 0);
15284
- absoluteLeft = frameBounds.left;
15285
- absoluteTop = frameBounds.top;
15286
- } else {
15287
- const w = (obj.width ?? 0) * (obj.scaleX ?? 1);
15288
- const h = (obj.height ?? 0) * (obj.scaleY ?? 1);
15289
- const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
15290
- absoluteLeft = (decomposed.translateX ?? absoluteLeft ?? 0) - w / 2 * Math.cos(angleRad) + h / 2 * Math.sin(angleRad);
15291
- absoluteTop = (decomposed.translateY ?? absoluteTop ?? 0) - w / 2 * Math.sin(angleRad) - h / 2 * Math.cos(angleRad);
15292
- }
14974
+ const w = (obj.width ?? 0) * (obj.scaleX ?? 1);
14975
+ const h = (obj.height ?? 0) * (obj.scaleY ?? 1);
14976
+ absoluteLeft = (absoluteLeft ?? 0) - w / 2;
14977
+ absoluteTop = (absoluteTop ?? 0) - h / 2;
15293
14978
  }
15294
14979
  const preserveCornerGeometry = (sourceElement == null ? void 0 : sourceElement.type) === "shape" && (sourceElement.shapeType === "circle" || sourceElement.shapeType === "rounded-rect" || sourceElement.shapeType === "triangle");
15295
14980
  let finalWidth = intrinsicWidth;
@@ -15297,10 +14982,6 @@ const PageCanvas = react.forwardRef(
15297
14982
  let finalScaleX = decomposed.scaleX;
15298
14983
  let finalScaleY = decomposed.scaleY;
15299
14984
  let finalAbsoluteMatrix = absoluteMatrix;
15300
- let finalAngle = decomposed.angle;
15301
- let finalSkewX = decomposed.skewX;
15302
- let finalSkewY = decomposed.skewY;
15303
- let finalAngleFromDecomposed = true;
15304
14985
  if (obj instanceof fabric__namespace.Group && obj.__cropGroup) {
15305
14986
  const ct = obj.__cropData;
15306
14987
  if (ct) {
@@ -15317,14 +14998,12 @@ const PageCanvas = react.forwardRef(
15317
14998
  absoluteLeft = frameBounds.left;
15318
14999
  absoluteTop = frameBounds.top;
15319
15000
  } else {
15320
- const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
15321
- absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2 * Math.cos(angleRad) + finalHeight / 2 * Math.sin(angleRad);
15322
- absoluteTop = (decomposed.translateY ?? absoluteTop) - finalWidth / 2 * Math.sin(angleRad) - finalHeight / 2 * Math.cos(angleRad);
15001
+ absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2;
15002
+ absoluteTop = (decomposed.translateY ?? absoluteTop) - finalHeight / 2;
15323
15003
  }
15324
- const finalCenter = rotatedTopLeftToCenter(absoluteLeft, absoluteTop, finalWidth, finalHeight, decomposed.angle ?? (obj.angle ?? 0));
15325
15004
  finalAbsoluteMatrix = fabric__namespace.util.composeMatrix({
15326
- translateX: finalCenter.x,
15327
- translateY: finalCenter.y,
15005
+ translateX: absoluteLeft + finalWidth / 2,
15006
+ translateY: absoluteTop + finalHeight / 2,
15328
15007
  angle: decomposed.angle ?? (obj.angle ?? 0),
15329
15008
  scaleX: 1,
15330
15009
  scaleY: 1,
@@ -15359,12 +15038,6 @@ const PageCanvas = react.forwardRef(
15359
15038
  finalHeight = bakedH;
15360
15039
  finalScaleX = 1;
15361
15040
  finalScaleY = 1;
15362
- if (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") {
15363
- finalAngle = (sourceElement == null ? void 0 : sourceElement.angle) ?? obj.angle ?? decomposed.angle;
15364
- finalSkewX = (sourceElement == null ? void 0 : sourceElement.skewX) ?? obj.skewX ?? 0;
15365
- finalSkewY = (sourceElement == null ? void 0 : sourceElement.skewY) ?? obj.skewY ?? 0;
15366
- if ((sourceElement == null ? void 0 : sourceElement.angle) !== void 0 || obj.angle !== void 0) finalAngleFromDecomposed = false;
15367
- }
15368
15041
  obj.set({ scaleX: 1, scaleY: 1 });
15369
15042
  const newSrc = renderSmartElementToDataUri(sourceElement.smartElementType, sourceElement.smartProps, bakedW, bakedH);
15370
15043
  if (newSrc) {
@@ -15380,7 +15053,6 @@ const PageCanvas = react.forwardRef(
15380
15053
  useEditorStore.getState().updateElement(objId, { src: newSrc }, { recordHistory: false, skipLayoutRecalc: true });
15381
15054
  }
15382
15055
  } else if (isActiveSelection && (Math.abs((decomposed.scaleX ?? 1) - 1) > 1e-3 || Math.abs((decomposed.scaleY ?? 1) - 1) > 1e-3)) {
15383
- const debugImageBeforeBake = debugGroupImageSideResize ? summarizeFabricObjectForResizeDebug(obj) : null;
15384
15056
  const sx = Math.abs(decomposed.scaleX || 1);
15385
15057
  const sy = Math.abs(decomposed.scaleY || 1);
15386
15058
  const handle = activeSelectionResizeHandle;
@@ -15414,9 +15086,22 @@ const PageCanvas = react.forwardRef(
15414
15086
  const localScaleX = 1 / sx;
15415
15087
  const localScaleY = 1 / sy;
15416
15088
  obj.set({ scaleX: localScaleX, scaleY: localScaleY });
15417
- const selectionMatrix = (_h = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _h.call(activeObj);
15089
+ const selectionMatrix = (_g = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _g.call(activeObj);
15418
15090
  const localCenter = selectionMatrix ? fabric__namespace.util.transformPoint(preBakeCenter, fabric__namespace.util.invertTransform(selectionMatrix)) : preBakeCenter;
15419
- obj.setPositionByOrigin(localCenter, "center", "center");
15091
+ const localWidth = bakedW * localScaleX;
15092
+ const localHeight = bakedH * localScaleY;
15093
+ const isCenterOrigin = obj.originX === "center" || obj.originY === "center";
15094
+ if (isCenterOrigin) {
15095
+ obj.set({
15096
+ left: localCenter.x,
15097
+ top: localCenter.y
15098
+ });
15099
+ } else {
15100
+ obj.set({
15101
+ left: localCenter.x - localWidth / 2,
15102
+ top: localCenter.y - localHeight / 2
15103
+ });
15104
+ }
15420
15105
  }
15421
15106
  obj.dirty = true;
15422
15107
  if (activeObj) activeObj.dirty = true;
@@ -15427,63 +15112,34 @@ const PageCanvas = react.forwardRef(
15427
15112
  finalHeight = bakedH;
15428
15113
  finalScaleX = 1;
15429
15114
  finalScaleY = 1;
15430
- if (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") {
15431
- finalAngle = (sourceElement == null ? void 0 : sourceElement.angle) ?? obj.angle ?? decomposed.angle;
15432
- finalSkewX = (sourceElement == null ? void 0 : sourceElement.skewX) ?? obj.skewX ?? 0;
15433
- finalSkewY = (sourceElement == null ? void 0 : sourceElement.skewY) ?? obj.skewY ?? 0;
15434
- if ((sourceElement == null ? void 0 : sourceElement.angle) !== void 0 || obj.angle !== void 0) finalAngleFromDecomposed = false;
15435
- }
15436
15115
  try {
15437
- const angleRad = (finalAngle ?? 0) * Math.PI / 180;
15116
+ const angleRad = (decomposed.angle ?? 0) * Math.PI / 180;
15438
15117
  const cos = Math.cos(angleRad);
15439
15118
  const sin = Math.sin(angleRad);
15440
15119
  const hw = finalWidth / 2;
15441
15120
  const hh = finalHeight / 2;
15442
- absoluteLeft = decomposed.translateX - hw * cos + hh * sin;
15443
- absoluteTop = decomposed.translateY - hw * sin - hh * cos;
15121
+ const corners = [
15122
+ { x: -hw, y: -hh },
15123
+ { x: hw, y: -hh },
15124
+ { x: hw, y: hh },
15125
+ { x: -hw, y: hh }
15126
+ ].map((p) => ({
15127
+ x: decomposed.translateX + p.x * cos - p.y * sin,
15128
+ y: decomposed.translateY + p.x * sin + p.y * cos
15129
+ }));
15130
+ absoluteLeft = Math.min(...corners.map((p) => p.x));
15131
+ absoluteTop = Math.min(...corners.map((p) => p.y));
15444
15132
  } catch {
15445
15133
  }
15446
15134
  finalAbsoluteMatrix = fabric__namespace.util.composeMatrix({
15447
15135
  translateX: decomposed.translateX,
15448
15136
  translateY: decomposed.translateY,
15449
- angle: finalAngle ?? 0,
15137
+ angle: decomposed.angle ?? 0,
15450
15138
  scaleX: 1,
15451
15139
  scaleY: 1,
15452
- skewX: finalSkewX ?? 0,
15453
- skewY: finalSkewY ?? 0
15140
+ skewX: 0,
15141
+ skewY: 0
15454
15142
  });
15455
- if (debugGroupImageSideResize) {
15456
- logGroupImageResizeDebug("image-bake", {
15457
- time: Math.round(performance.now()),
15458
- handle: activeSelectionResizeHandle,
15459
- imageId: objId,
15460
- source: sourceElement ? {
15461
- left: sourceElement.left,
15462
- top: sourceElement.top,
15463
- width: sourceElement.width,
15464
- height: sourceElement.height,
15465
- angle: sourceElement.angle,
15466
- scaleX: sourceElement.scaleX,
15467
- scaleY: sourceElement.scaleY
15468
- } : null,
15469
- factors: { sx, sy, fx, fy, isCornerHandle },
15470
- beforeBake: debugImageBeforeBake,
15471
- afterBake: summarizeFabricObjectForResizeDebug(obj),
15472
- persistedGeometry: {
15473
- absoluteLeft,
15474
- absoluteTop,
15475
- finalWidth,
15476
- finalHeight,
15477
- finalScaleX,
15478
- finalScaleY,
15479
- finalAngle,
15480
- finalSkewX,
15481
- finalSkewY,
15482
- decomposed,
15483
- finalAbsoluteMatrix
15484
- }
15485
- });
15486
- }
15487
15143
  } else {
15488
15144
  finalWidth = intrinsicWidth;
15489
15145
  finalHeight = intrinsicHeight;
@@ -15493,33 +15149,16 @@ const PageCanvas = react.forwardRef(
15493
15149
  finalHeight = 0;
15494
15150
  finalScaleX = 1;
15495
15151
  finalScaleY = 1;
15496
- if (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") {
15497
- finalAngle = (sourceElement == null ? void 0 : sourceElement.angle) ?? obj.angle ?? decomposed.angle;
15498
- finalSkewX = (sourceElement == null ? void 0 : sourceElement.skewX) ?? obj.skewX ?? 0;
15499
- finalSkewY = (sourceElement == null ? void 0 : sourceElement.skewY) ?? obj.skewY ?? 0;
15500
- if ((sourceElement == null ? void 0 : sourceElement.angle) !== void 0 || obj.angle !== void 0) finalAngleFromDecomposed = false;
15501
- }
15502
- } else if (obj instanceof fabric__namespace.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)) {
15503
- const liveOrigW = obj.__asLiveOrigW;
15504
- const liveOrigH = obj.__asLiveOrigH;
15505
- const decSx = Math.abs(decomposed.scaleX || 1);
15506
- const decSy = Math.abs(decomposed.scaleY || 1);
15507
- const sx = Math.abs(decSx - 1) < 1e-3 && liveOrigW && liveOrigW > 0 ? Math.max(1e-3, (obj.width ?? liveOrigW) / liveOrigW) : decSx;
15508
- const baseHForRecover = Number(
15509
- obj.minBoxHeight ?? obj.height ?? liveOrigH ?? 1
15510
- );
15511
- const sy = Math.abs(decSy - 1) < 1e-3 && liveOrigH && liveOrigH > 0 ? Math.max(1e-3, baseHForRecover / liveOrigH) : decSy;
15152
+ } else if (obj instanceof fabric__namespace.Textbox && isActiveSelection && (Math.abs((decomposed.scaleX ?? 1) - 1) > 1e-3 || Math.abs((decomposed.scaleY ?? 1) - 1) > 1e-3)) {
15153
+ const sx = Math.abs(decomposed.scaleX || 1);
15154
+ const sy = Math.abs(decomposed.scaleY || 1);
15512
15155
  const isLikelyUniformCorner = !activeSelectionResizeHandle && Math.abs(sx - sy) < 0.01 && Math.abs(sx - 1) > 1e-3;
15513
15156
  const isCornerHandle = activeSelectionResizeHandle === "tl" || activeSelectionResizeHandle === "tr" || activeSelectionResizeHandle === "bl" || activeSelectionResizeHandle === "br" || isLikelyUniformCorner;
15514
15157
  const isHeightSideHandle = activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb";
15515
15158
  const fontScale = isCornerHandle ? Math.max(1e-3, Math.sqrt(sx * sy)) : 1;
15516
- const widthBase = liveOrigW && liveOrigW > 0 ? liveOrigW : intrinsicWidth;
15517
- const heightBase = liveOrigH && liveOrigH > 0 ? liveOrigH : intrinsicHeight;
15518
- const bakedWidth = Math.max(20, widthBase * sx);
15519
- const liveMinHOrig = obj.__asLiveOrigMinH;
15520
- const currentMinH = Number(obj.minBoxHeight ?? (sourceElement == null ? void 0 : sourceElement.minBoxHeight));
15521
- const minHBase = Number.isFinite(liveMinHOrig) && liveMinHOrig > 0 ? liveMinHOrig : liveOrigH && liveOrigH > 0 ? currentMinH / sy : currentMinH;
15522
- const nextMinH = Number.isFinite(minHBase) && minHBase > 0 ? minHBase * sy : isHeightSideHandle ? Math.max(1, heightBase * sy) : void 0;
15159
+ const bakedWidth = Math.max(20, intrinsicWidth * sx);
15160
+ const baseMinH = Number(obj.minBoxHeight ?? (sourceElement == null ? void 0 : sourceElement.minBoxHeight));
15161
+ const nextMinH = Number.isFinite(baseMinH) && baseMinH > 0 ? baseMinH * sy : isHeightSideHandle ? Math.max(1, intrinsicHeight * sy) : void 0;
15523
15162
  const bakedTextScaleUpdates = { width: bakedWidth };
15524
15163
  const debugTextBeforeBake = debugGroupTextCornerResize ? summarizeFabricObjectForResizeDebug(obj) : null;
15525
15164
  finalScaleX = 1;
@@ -15578,9 +15217,14 @@ const PageCanvas = react.forwardRef(
15578
15217
  const localScaleX = 1 / sx;
15579
15218
  const localScaleY = 1 / sy;
15580
15219
  obj.set({ scaleX: localScaleX, scaleY: localScaleY });
15581
- const selectionMatrix = (_i = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _i.call(activeObj);
15220
+ const selectionMatrix = (_h = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _h.call(activeObj);
15582
15221
  const localCenter = selectionMatrix ? fabric__namespace.util.transformPoint(preBakeCenter, fabric__namespace.util.invertTransform(selectionMatrix)) : preBakeCenter;
15583
- obj.setPositionByOrigin(localCenter, "center", "center");
15222
+ const localWidth = bakedWidth * localScaleX;
15223
+ const localHeight = (obj.height ?? intrinsicHeight) * localScaleY;
15224
+ obj.set({
15225
+ left: localCenter.x - localWidth / 2,
15226
+ top: localCenter.y - localHeight / 2
15227
+ });
15584
15228
  } else {
15585
15229
  obj.setPositionByOrigin(preBakeCenter, "center", "center");
15586
15230
  }
@@ -15593,23 +15237,32 @@ const PageCanvas = react.forwardRef(
15593
15237
  } catch {
15594
15238
  }
15595
15239
  try {
15596
- const angleRad = (finalAngle ?? 0) * Math.PI / 180;
15240
+ const angleRad = (decomposed.angle ?? 0) * Math.PI / 180;
15597
15241
  const cos = Math.cos(angleRad);
15598
15242
  const sin = Math.sin(angleRad);
15599
15243
  const hw = finalWidth / 2;
15600
15244
  const hh = finalHeight / 2;
15601
- absoluteLeft = decomposed.translateX - hw * cos + hh * sin;
15602
- absoluteTop = decomposed.translateY - hw * sin - hh * cos;
15245
+ const corners = [
15246
+ { x: -hw, y: -hh },
15247
+ { x: hw, y: -hh },
15248
+ { x: hw, y: hh },
15249
+ { x: -hw, y: hh }
15250
+ ].map((p) => ({
15251
+ x: decomposed.translateX + p.x * cos - p.y * sin,
15252
+ y: decomposed.translateY + p.x * sin + p.y * cos
15253
+ }));
15254
+ absoluteLeft = Math.min(...corners.map((p) => p.x));
15255
+ absoluteTop = Math.min(...corners.map((p) => p.y));
15603
15256
  } catch {
15604
15257
  }
15605
15258
  finalAbsoluteMatrix = fabric__namespace.util.composeMatrix({
15606
15259
  translateX: decomposed.translateX,
15607
15260
  translateY: decomposed.translateY,
15608
- angle: finalAngle ?? 0,
15261
+ angle: decomposed.angle ?? 0,
15609
15262
  scaleX: 1,
15610
15263
  scaleY: 1,
15611
- skewX: finalSkewX ?? 0,
15612
- skewY: finalSkewY ?? 0
15264
+ skewX: 0,
15265
+ skewY: 0
15613
15266
  });
15614
15267
  if (debugGroupTextCornerResize) {
15615
15268
  logGroupTextResizeDebug("text-bake", {
@@ -15664,21 +15317,7 @@ const PageCanvas = react.forwardRef(
15664
15317
  const state = useEditorStore.getState();
15665
15318
  const page = state.canvas.pages.find((p) => p.id === pageId);
15666
15319
  const pageChildrenForSave = (page == null ? void 0 : page.children) ?? [];
15667
- const storePos = (logicalGroupFinalFrame == null ? void 0 : logicalGroupFinalFrame.groupId) === logicalGroupSelectionId ? (() => {
15668
- const localCenter = fabric__namespace.util.transformPoint(
15669
- new fabric__namespace.Point(decomposed.translateX ?? 0, decomposed.translateY ?? 0),
15670
- fabric__namespace.util.invertTransform(logicalGroupFinalFrame.matrix)
15671
- );
15672
- const localAngle = finalAngleFromDecomposed ? ((Number(finalAngle ?? 0) - asAngleForBake) % 360 + 540) % 360 - 180 : Number(finalAngle ?? 0);
15673
- const localAngleRad = localAngle * Math.PI / 180;
15674
- return {
15675
- left: localCenter.x - finalWidth / 2 * Math.cos(localAngleRad) + finalHeight / 2 * Math.sin(localAngleRad) + logicalGroupFinalFrame.width / 2,
15676
- top: localCenter.y - finalWidth / 2 * Math.sin(localAngleRad) - finalHeight / 2 * Math.cos(localAngleRad) + logicalGroupFinalFrame.height / 2
15677
- };
15678
- })() : absoluteToStorePosition(absoluteLeft, absoluteTop, objId, pageChildrenForSave);
15679
- if (isLogicalGroupAS && finalAngleFromDecomposed && typeof finalAngle === "number") {
15680
- finalAngle = ((finalAngle - asAngleForBake) % 360 + 540) % 360 - 180;
15681
- }
15320
+ const storePos = absoluteToStorePosition(absoluteLeft, absoluteTop, objId, pageChildrenForSave);
15682
15321
  const isLineObj = obj instanceof fabric__namespace.Line;
15683
15322
  const isAutoShrinkText = (sourceElement == null ? void 0 : sourceElement.type) === "text" && sourceElement.overflowPolicy === "auto-shrink";
15684
15323
  const autoShrinkStoredHeight = isAutoShrinkText ? sourceElement.height : void 0;
@@ -15690,17 +15329,13 @@ const PageCanvas = react.forwardRef(
15690
15329
  // so finalWidth already reflects the new width chosen by the user.
15691
15330
  width: finalWidth,
15692
15331
  height: isLineObj ? 0 : isAutoShrinkText ? typeof autoShrinkStoredHeight === "number" ? autoShrinkStoredHeight : finalHeight : finalHeight,
15693
- angle: finalAngle,
15694
- skewX: isLineObj ? 0 : finalSkewX,
15695
- skewY: isLineObj ? 0 : finalSkewY,
15332
+ angle: decomposed.angle,
15333
+ skewX: isLineObj ? 0 : decomposed.skewX,
15334
+ skewY: isLineObj ? 0 : decomposed.skewY,
15696
15335
  scaleX: finalScaleX,
15697
- scaleY: finalScaleY
15336
+ scaleY: finalScaleY,
15337
+ transformMatrix: finalAbsoluteMatrix
15698
15338
  };
15699
- if (!isLogicalGroupAS) {
15700
- elementUpdate.transformMatrix = finalAbsoluteMatrix;
15701
- } else {
15702
- elementUpdate.transformMatrix = void 0;
15703
- }
15704
15339
  if (obj instanceof fabric__namespace.Textbox) {
15705
15340
  const bakedTextScaleUpdates = obj.__pixldocsBakedTextScaleUpdates;
15706
15341
  if (bakedTextScaleUpdates && typeof bakedTextScaleUpdates === "object") {
@@ -15731,41 +15366,10 @@ const PageCanvas = react.forwardRef(
15731
15366
  objectBeforeStoreWrite: summarizeFabricObjectForResizeDebug(obj)
15732
15367
  });
15733
15368
  }
15734
- if (debugGroupImageSideResize && isGroupResizeImageLikeObject(obj)) {
15735
- logGroupImageResizeDebug("store-update-image", {
15736
- time: Math.round(performance.now()),
15737
- handle: activeSelectionResizeHandle,
15738
- imageId: objId,
15739
- storePos,
15740
- elementUpdate,
15741
- objectBeforeStoreWrite: summarizeFabricObjectForResizeDebug(obj)
15742
- });
15743
- }
15744
15369
  updateElement(objId, elementUpdate, { recordHistory: false, skipLayoutRecalc: true });
15745
15370
  obj.setCoords();
15746
- delete obj.__asLiveOrigW;
15747
- delete obj.__asLiveOrigH;
15748
- delete obj.__asLiveOrigMinH;
15749
- }
15750
- if (isLogicalGroupAS && logicalGroupSelectionId && activeObj instanceof fabric__namespace.ActiveSelection) {
15751
- try {
15752
- const pageChildrenForGroup = ((_j = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _j.children) ?? [];
15753
- const groupNode = findNodeById(pageChildrenForGroup, logicalGroupSelectionId);
15754
- if (groupNode && logicalGroupFinalFrame) {
15755
- const storePosGroup = absoluteToStorePosition(logicalGroupFinalFrame.left, logicalGroupFinalFrame.top, logicalGroupSelectionId, pageChildrenForGroup);
15756
- useEditorStore.getState().updateNode(logicalGroupSelectionId, {
15757
- left: storePosGroup.left,
15758
- top: storePosGroup.top,
15759
- width: logicalGroupFinalFrame.width,
15760
- height: logicalGroupFinalFrame.height,
15761
- angle: logicalGroupFinalFrame.angle
15762
- }, { recordHistory: false, skipLayoutRecalc: true });
15763
- }
15764
- } catch (err) {
15765
- console.warn("[Pixldocs] logical-group envelope persist failed", err);
15766
- }
15767
15371
  }
15768
- const pageChildrenForReflow = ((_k = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _k.children) ?? [];
15372
+ const pageChildrenForReflow = ((_i = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _i.children) ?? [];
15769
15373
  const stackGroupsToReflow = /* @__PURE__ */ new Set();
15770
15374
  for (const id of modifiedIdsThisRound) {
15771
15375
  const parent = findParentGroup(pageChildrenForReflow, id);
@@ -15792,16 +15396,6 @@ const PageCanvas = react.forwardRef(
15792
15396
  renderOnAddRemove: fabricCanvas.renderOnAddRemove
15793
15397
  });
15794
15398
  }
15795
- if (debugGroupImageSideResize) {
15796
- logGroupImageResizeDebug("before-reselect", {
15797
- time: Math.round(performance.now()),
15798
- handle: activeSelectionResizeHandle,
15799
- wasGroupSel,
15800
- selection: summarizeFabricObjectForResizeDebug(activeObj),
15801
- members: membersToReselect.map((member) => summarizeFabricObjectForResizeDebug(member)),
15802
- renderOnAddRemove: fabricCanvas.renderOnAddRemove
15803
- });
15804
- }
15805
15399
  const prevRenderOnAddRemove = fabricCanvas.renderOnAddRemove;
15806
15400
  fabricCanvas.renderOnAddRemove = false;
15807
15401
  skipSelectionClearOnDiscardRef.current = true;
@@ -15816,10 +15410,9 @@ const PageCanvas = react.forwardRef(
15816
15410
  if (!ct) continue;
15817
15411
  ct.frameW = bake.width;
15818
15412
  ct.frameH = bake.height;
15819
- const bakeCenter = rotatedTopLeftToCenter(bake.left, bake.top, bake.width, bake.height, bake.angle);
15820
15413
  bake.obj.set({
15821
- left: bakeCenter.x,
15822
- top: bakeCenter.y,
15414
+ left: bake.left + bake.width / 2,
15415
+ top: bake.top + bake.height / 2,
15823
15416
  width: bake.width,
15824
15417
  height: bake.height,
15825
15418
  scaleX: 1,
@@ -15846,16 +15439,6 @@ const PageCanvas = react.forwardRef(
15846
15439
  renderOnAddRemove: fabricCanvas.renderOnAddRemove
15847
15440
  });
15848
15441
  }
15849
- if (debugGroupImageSideResize) {
15850
- logGroupImageResizeDebug("after-reselect", {
15851
- time: Math.round(performance.now()),
15852
- handle: activeSelectionResizeHandle,
15853
- wasGroupSel,
15854
- selection: summarizeFabricObjectForResizeDebug(newSel),
15855
- members: membersToReselect.map((member) => summarizeFabricObjectForResizeDebug(member)),
15856
- renderOnAddRemove: fabricCanvas.renderOnAddRemove
15857
- });
15858
- }
15859
15442
  } else if (membersToReselect.length === 1) {
15860
15443
  fabricCanvas.setActiveObject(membersToReselect[0]);
15861
15444
  }
@@ -15892,7 +15475,6 @@ const PageCanvas = react.forwardRef(
15892
15475
  const activeObj = fabricCanvas.getActiveObject();
15893
15476
  if (!(activeObj instanceof fabric__namespace.ActiveSelection)) return;
15894
15477
  if (skipActiveSelectionBakeOnClearRef.current) return;
15895
- if (activeObj.__pixldocsGroupSelection) return;
15896
15478
  const selectionMatrix = activeObj.calcTransformMatrix();
15897
15479
  for (const obj of deselected) {
15898
15480
  const objId = getObjectId(obj);
@@ -16362,7 +15944,7 @@ const PageCanvas = react.forwardRef(
16362
15944
  const nextHeight = Math.max(minVisiblePlaceholder, Number(resolvedSizeImg.height) || 50);
16363
15945
  const storePosImg = pageChildren ? (() => {
16364
15946
  const node = findNodeById(pageChildren, element.id);
16365
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
15947
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16366
15948
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16367
15949
  const elementForPlaceholder = { ...element, width: nextWidth, height: nextHeight };
16368
15950
  const placeholder = isCropGroup2 ? createImagePlaceholderForGroup(elementForPlaceholder) : createImagePlaceholder(elementForPlaceholder);
@@ -16425,14 +16007,13 @@ const PageCanvas = react.forwardRef(
16425
16007
  }
16426
16008
  const cropPos = pageChildren ? (() => {
16427
16009
  const node = findNodeById(pageChildren, element.id);
16428
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16429
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16430
- const cropCenter = rotatedTopLeftToCenter(cropPos.left, cropPos.top, ct.frameW ?? 0, ct.frameH ?? 0, cropPos.angle ?? element.angle ?? 0);
16431
- const cropCenterX = cropCenter.x;
16432
- const cropCenterY = cropCenter.y;
16010
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16011
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
16012
+ const cropCenterX = cropPos.left + (ct.frameW ?? 0) / 2;
16013
+ const cropCenterY = cropPos.top + (ct.frameH ?? 0) / 2;
16433
16014
  if (element.left !== void 0) existingObj.set({ left: cropCenterX });
16434
16015
  if (element.top !== void 0) existingObj.set({ top: cropCenterY });
16435
- existingObj.set({ angle: cropPos.angle ?? element.angle ?? 0 });
16016
+ if (element.angle !== void 0) existingObj.set({ angle: element.angle });
16436
16017
  existingObj.set({
16437
16018
  flipX: element.flipX ?? false,
16438
16019
  flipY: element.flipY ?? false
@@ -16555,8 +16136,8 @@ const PageCanvas = react.forwardRef(
16555
16136
  if (isPlaceholderGroup) {
16556
16137
  const storePosImg = pageChildren ? (() => {
16557
16138
  const node = findNodeById(pageChildren, element.id);
16558
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16559
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16139
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16140
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
16560
16141
  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 };
16561
16142
  const hasExplicitSize = typeof element.width === "number" && Number.isFinite(element.width) && element.width > 0 && typeof element.height === "number" && Number.isFinite(element.height) && element.height > 0;
16562
16143
  const minVisiblePlaceholder = hasExplicitSize ? 1 : 20;
@@ -16570,7 +16151,7 @@ const PageCanvas = react.forwardRef(
16570
16151
  top: storePosImg.top + nextHeight / 2,
16571
16152
  originX: "center",
16572
16153
  originY: "center",
16573
- angle: storePosImg.angle ?? element.angle ?? 0,
16154
+ angle: element.angle ?? 0,
16574
16155
  opacity: isHidden ? 0 : element.opacity ?? 1,
16575
16156
  flipX: element.flipX ?? false,
16576
16157
  flipY: element.flipY ?? false,
@@ -16619,8 +16200,8 @@ const PageCanvas = react.forwardRef(
16619
16200
  const visibilityChanged = previousVisible !== currentVisible;
16620
16201
  const storePosForImg = pageChildren ? (() => {
16621
16202
  const node = findNodeById(pageChildren, element.id);
16622
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16623
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16203
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16204
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
16624
16205
  const positionChanged = Math.abs((existingObj.left ?? 0) - storePosForImg.left) > 0.1 || Math.abs((existingObj.top ?? 0) - storePosForImg.top) > 0.1;
16625
16206
  if (visibilityChanged && !positionChanged || visibilityUpdateInProgressRef.current) {
16626
16207
  const isDynamicField = dynamicFieldIds.includes(element.id);
@@ -16662,7 +16243,7 @@ const PageCanvas = react.forwardRef(
16662
16243
  const fabricTop = existingObj.top ?? 0;
16663
16244
  const storePos = pageChildren ? (() => {
16664
16245
  const node = findNodeById(pageChildren, element.id);
16665
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16246
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16666
16247
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16667
16248
  const storeLeft = storePos.left;
16668
16249
  const storeTop = storePos.top;
@@ -16789,7 +16370,7 @@ const PageCanvas = react.forwardRef(
16789
16370
  setObjectData(placeholder, element.id);
16790
16371
  const absPosImg = pageTree.length > 0 ? (() => {
16791
16372
  const node = findNodeById(pageTree, element.id);
16792
- return node && isElement(node) ? getElementFabricPlacement(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16373
+ return node ? getAbsoluteBounds(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16793
16374
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16794
16375
  const placeholderWidth = Number((placeholder.width ?? 0) * (placeholder.scaleX ?? 1));
16795
16376
  const placeholderHeight = Number((placeholder.height ?? 0) * (placeholder.scaleY ?? 1));
@@ -16838,7 +16419,7 @@ const PageCanvas = react.forwardRef(
16838
16419
  if (obj) {
16839
16420
  const absPos = pageTree.length > 0 ? (() => {
16840
16421
  const node = findNodeById(pageTree, element.id);
16841
- return node && isElement(node) ? getElementFabricPlacement(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16422
+ return node ? getAbsoluteBounds(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16842
16423
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16843
16424
  obj.set({ left: absPos.left, top: absPos.top });
16844
16425
  obj.setCoords();
@@ -17228,7 +16809,9 @@ const PageCanvas = react.forwardRef(
17228
16809
  if (sameSelection && isFlatGroupSelection) {
17229
16810
  if (selectedGroupSelectionId && active instanceof fabric__namespace.ActiveSelection) {
17230
16811
  if (isPureSingleGroupSelection) {
17231
- applyLogicalGroupSelectionVisualState(active, selectedGroupSelectionId);
16812
+ active.__pixldocsGroupSelection = selectedGroupSelectionId;
16813
+ delete active.__pixldocsLogicalGroupIds;
16814
+ suppressGroupMemberBordersRef.current = active.getObjects();
17232
16815
  } else {
17233
16816
  delete active.__pixldocsGroupSelection;
17234
16817
  active.__pixldocsLogicalGroupIds = selectedGroupIds;
@@ -17268,7 +16851,8 @@ const PageCanvas = react.forwardRef(
17268
16851
  const selection = new fabric__namespace.ActiveSelection(toSelect, { canvas: fc });
17269
16852
  if (selectedGroupSelectionId) {
17270
16853
  if (isPureSingleGroupSelection) {
17271
- applyLogicalGroupSelectionVisualState(selection, selectedGroupSelectionId);
16854
+ selection.__pixldocsGroupSelection = selectedGroupSelectionId;
16855
+ suppressGroupMemberBordersRef.current = toSelect;
17272
16856
  } else {
17273
16857
  selection.__pixldocsLogicalGroupIds = selectedGroupIds;
17274
16858
  selection.hasBorders = true;
@@ -17326,9 +16910,8 @@ const PageCanvas = react.forwardRef(
17326
16910
  const currentPageTree = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
17327
16911
  const fabricPos = currentPageTree.length > 0 ? (() => {
17328
16912
  const node = findNodeById(currentPageTree, element.id);
17329
- return node && isElement(node) ? getElementFabricPlacement(node, currentPageTree) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
17330
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
17331
- const fabricAngle = fabricPos.angle ?? element.angle ?? 0;
16913
+ return node ? getAbsoluteBounds(node, currentPageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16914
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
17332
16915
  const resolvedSize = currentPageTree.length > 0 ? getNodeBounds(element, currentPageTree) : { width: typeof element.width === "number" ? element.width : 200, height: typeof element.height === "number" ? element.height : 50 };
17333
16916
  const shouldPreserveSmallSize = typeof element.width === "number" && Number.isFinite(element.width) && element.width > 0 && typeof element.height === "number" && Number.isFinite(element.height) && element.height > 0;
17334
16917
  const minVisible = shouldPreserveSmallSize ? 1 : 20;
@@ -17363,9 +16946,8 @@ const PageCanvas = react.forwardRef(
17363
16946
  ct.shape = clipShape === "circle" ? "circle" : clipShape === "rounded" ? "roundRect" : "rect";
17364
16947
  ct.rx = rxRatio;
17365
16948
  obj.__maintainResolution = element.maintainResolution !== false;
17366
- const center = rotatedTopLeftToCenter(fabricPos.left, fabricPos.top, elementWidth, elementHeight, element.angle ?? 0);
17367
- const centerX = center.x;
17368
- const centerY = center.y;
16949
+ const centerX = fabricPos.left + elementWidth / 2;
16950
+ const centerY = fabricPos.top + elementHeight / 2;
17369
16951
  const cropSetProps = {
17370
16952
  width: elementWidth,
17371
16953
  height: elementHeight,
@@ -17585,7 +17167,7 @@ const PageCanvas = react.forwardRef(
17585
17167
  y1: 0,
17586
17168
  x2: lineLen,
17587
17169
  y2: 0,
17588
- angle: fabricAngle,
17170
+ angle: element.angle ?? 0,
17589
17171
  scaleX: 1,
17590
17172
  scaleY: 1,
17591
17173
  skewX: 0,
@@ -17605,8 +17187,7 @@ const PageCanvas = react.forwardRef(
17605
17187
  if (!skipPositionUpdate && (obj instanceof fabric__namespace.FabricImage && obj.originX === "center" || obj instanceof fabric__namespace.Group && obj.__cropGroup)) {
17606
17188
  const vW = rW * effectiveScaleX;
17607
17189
  const vH = rH * effectiveScaleY;
17608
- const center = rotatedTopLeftToCenter(fabricPos.left, fabricPos.top, vW, vH, element.angle ?? 0);
17609
- posIfNotSkipped = { left: center.x, top: center.y };
17190
+ posIfNotSkipped = { left: fabricPos.left + vW / 2, top: fabricPos.top + vH / 2 };
17610
17191
  }
17611
17192
  if (element.transformMatrix && element.transformMatrix.length === 6) {
17612
17193
  if (isTextbox) {
@@ -17615,7 +17196,7 @@ const PageCanvas = react.forwardRef(
17615
17196
  width: rW,
17616
17197
  scaleX: effectiveScaleX,
17617
17198
  scaleY: effectiveScaleY,
17618
- angle: fabricAngle,
17199
+ angle: element.angle ?? 0,
17619
17200
  skewX: element.skewX ?? 0,
17620
17201
  skewY: appliedSkewY
17621
17202
  });
@@ -17624,7 +17205,7 @@ const PageCanvas = react.forwardRef(
17624
17205
  ...posIfNotSkipped,
17625
17206
  scaleX: effectiveScaleX,
17626
17207
  scaleY: effectiveScaleY,
17627
- angle: fabricAngle,
17208
+ angle: element.angle ?? 0,
17628
17209
  skewX: element.skewX ?? 0,
17629
17210
  skewY: element.skewY ?? 0
17630
17211
  });
@@ -17635,7 +17216,7 @@ const PageCanvas = react.forwardRef(
17635
17216
  obj.set({
17636
17217
  ...posIfNotSkipped,
17637
17218
  width: rW,
17638
- angle: fabricAngle,
17219
+ angle: element.angle ?? 0,
17639
17220
  skewX: element.skewX ?? 0,
17640
17221
  skewY: appliedSkewY,
17641
17222
  scaleX: effectiveScaleX * baseScaleX,
@@ -17644,7 +17225,7 @@ const PageCanvas = react.forwardRef(
17644
17225
  } else {
17645
17226
  obj.set({
17646
17227
  ...posIfNotSkipped,
17647
- angle: fabricAngle,
17228
+ angle: element.angle ?? 0,
17648
17229
  skewX: element.skewX ?? 0,
17649
17230
  skewY: element.skewY ?? 0,
17650
17231
  scaleX: effectiveScaleX * baseScaleX,
@@ -18397,14 +17978,14 @@ const PageCanvas = react.forwardRef(
18397
17978
  const pageTreeForCreate = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_f = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _f.children) ?? [];
18398
17979
  const createPos = pageTreeForCreate.length > 0 ? (() => {
18399
17980
  const node = findNodeById(pageTreeForCreate, element.id);
18400
- return node && isElement(node) ? getElementFabricPlacement(node, pageTreeForCreate, pageBoundsOptions) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
18401
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
17981
+ return node ? getAbsoluteBounds(node, pageTreeForCreate) : { left: element.left ?? 0, top: element.top ?? 0 };
17982
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
18402
17983
  img.set({
18403
17984
  left: createPos.left,
18404
17985
  top: createPos.top,
18405
17986
  scaleX: finalScaleX,
18406
17987
  scaleY: finalScaleY,
18407
- angle: createPos.angle ?? element.angle ?? 0,
17988
+ angle: element.angle ?? 0,
18408
17989
  skewX: element.skewX ?? 0,
18409
17990
  skewY: element.skewY ?? 0,
18410
17991
  flipX: element.flipX ?? false,
@@ -18491,8 +18072,8 @@ const PageCanvas = react.forwardRef(
18491
18072
  const pageTreeForCrop = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_n = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _n.children) ?? [];
18492
18073
  const createPosForCrop = pageTreeForCrop.length > 0 ? (() => {
18493
18074
  const node = findNodeById(pageTreeForCrop, element.id);
18494
- return node && isElement(node) ? getElementFabricPlacement(node, pageTreeForCrop, pageBoundsOptions) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
18495
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
18075
+ return node ? getAbsoluteBounds(node, pageTreeForCrop) : { left: element.left ?? 0, top: element.top ?? 0 };
18076
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
18496
18077
  const nodeForCreate = pageTreeForCrop.length ? findNodeById(pageTreeForCrop, element.id) : null;
18497
18078
  const createW = nodeForCreate && isElement(nodeForCreate) ? nodeForCreate.width : elementWidth;
18498
18079
  const createH = nodeForCreate && isElement(nodeForCreate) ? nodeForCreate.height : elementHeight;
@@ -18500,9 +18081,8 @@ const PageCanvas = react.forwardRef(
18500
18081
  const createSy = nodeForCreate && isElement(nodeForCreate) ? nodeForCreate.scaleY ?? 1 : element.scaleY ?? 1;
18501
18082
  const frameW = Math.max(1, Number(createW) || 200) * createSx;
18502
18083
  const frameH = Math.max(1, Number(createH) || 50) * createSy;
18503
- const createCenter = rotatedTopLeftToCenter(createPosForCrop.left, createPosForCrop.top, frameW, frameH, createPosForCrop.angle ?? element.angle ?? 0);
18504
- const createCenterX = createCenter.x;
18505
- const createCenterY = createCenter.y;
18084
+ const createCenterX = createPosForCrop.left + frameW / 2;
18085
+ const createCenterY = createPosForCrop.top + frameH / 2;
18506
18086
  const cropGroup = await createMaskedImageElement({
18507
18087
  image: img,
18508
18088
  frameW,
@@ -18515,7 +18095,7 @@ const PageCanvas = react.forwardRef(
18515
18095
  strokeWidth: 0,
18516
18096
  left: createCenterX,
18517
18097
  top: createCenterY,
18518
- angle: createPosForCrop.angle ?? element.angle ?? 0,
18098
+ angle: element.angle ?? 0,
18519
18099
  opacity: isHidden ? 0 : element.opacity ?? 1,
18520
18100
  selectable: allowSelection && !isHidden,
18521
18101
  evented: canBeEvented && !isHidden,
@@ -24905,9 +24485,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
24905
24485
  }
24906
24486
  return svgString;
24907
24487
  }
24908
- const resolvedPackageVersion = "0.5.354";
24488
+ const resolvedPackageVersion = "0.5.356";
24909
24489
  const PACKAGE_VERSION = resolvedPackageVersion;
24910
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.354";
24490
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.356";
24911
24491
  const roundParityValue = (value) => {
24912
24492
  if (typeof value !== "number") return value;
24913
24493
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -25721,7 +25301,7 @@ class PixldocsRenderer {
25721
25301
  await this.waitForCanvasScene(container, cloned, i);
25722
25302
  }
25723
25303
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
25724
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-DnoKFr-R.cjs"));
25304
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-CVOo3V8_.cjs"));
25725
25305
  const prepared = preparePagesForExport(
25726
25306
  cloned.pages,
25727
25307
  canvasWidth,
@@ -28041,7 +27621,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
28041
27621
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
28042
27622
  sanitizeSvgTreeForPdf(svgToDraw);
28043
27623
  try {
28044
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-DnoKFr-R.cjs"));
27624
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-CVOo3V8_.cjs"));
28045
27625
  try {
28046
27626
  await logTextMeasurementDiagnostic(svgToDraw);
28047
27627
  } catch {
@@ -28438,4 +28018,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
28438
28018
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
28439
28019
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
28440
28020
  exports.warmTemplateFromForm = warmTemplateFromForm;
28441
- //# sourceMappingURL=index-BUYWcO1C.cjs.map
28021
+ //# sourceMappingURL=index-CcfKFBH1.cjs.map