@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.
@@ -10500,105 +10500,6 @@ function bakeEdgeFade(source, fade) {
10500
10500
  }
10501
10501
  return canvas;
10502
10502
  }
10503
- const normalizeSignedAngle = (angle) => (angle % 360 + 540) % 360 - 180;
10504
- const rotatedTopLeftToCenter = (left, top, width, height, angleDeg = 0) => {
10505
- const angle = angleDeg * Math.PI / 180;
10506
- const cos = Math.cos(angle);
10507
- const sin = Math.sin(angle);
10508
- return {
10509
- x: left + width / 2 * cos - height / 2 * sin,
10510
- y: top + width / 2 * sin + height / 2 * cos
10511
- };
10512
- };
10513
- const centerToRotatedTopLeft = (centerX, centerY, width, height, angleDeg = 0) => {
10514
- const angle = angleDeg * Math.PI / 180;
10515
- const cos = Math.cos(angle);
10516
- const sin = Math.sin(angle);
10517
- return {
10518
- left: centerX - width / 2 * cos + height / 2 * sin,
10519
- top: centerY - width / 2 * sin - height / 2 * cos
10520
- };
10521
- };
10522
- const getGroupTransformFrame = (group, pageChildren, options) => {
10523
- const bounds = getNodeBounds(group, pageChildren);
10524
- const width = Math.max(1, Number(group.width ?? bounds.width) || bounds.width || 1);
10525
- const height = Math.max(1, Number(group.height ?? bounds.height) || bounds.height || 1);
10526
- return {
10527
- left: Number(group.left ?? bounds.left ?? 0) || 0,
10528
- top: Number(group.top ?? bounds.top ?? 0) || 0,
10529
- width,
10530
- height,
10531
- angle: Number(group.angle ?? 0) || 0
10532
- };
10533
- };
10534
- const getGroupLocalToParentMatrix = (group, pageChildren, options) => {
10535
- const frame = getGroupTransformFrame(group, pageChildren);
10536
- const rad = frame.angle * Math.PI / 180;
10537
- const cos = Math.cos(rad);
10538
- const sin = Math.sin(rad);
10539
- return [
10540
- cos,
10541
- sin,
10542
- -sin,
10543
- cos,
10544
- frame.left,
10545
- frame.top
10546
- ];
10547
- };
10548
- const getAncestorGroupTransform = (nodeId, pageChildren, fabric2, options) => {
10549
- let matrix = [1, 0, 0, 1, 0, 0];
10550
- let angle = 0;
10551
- const chain = [];
10552
- let currentId = nodeId;
10553
- for (let guard = 0; guard < 32; guard++) {
10554
- const parent = findParentGroup(pageChildren, currentId);
10555
- if (!parent) break;
10556
- chain.unshift(parent);
10557
- currentId = parent.id;
10558
- }
10559
- for (const group of chain) {
10560
- matrix = fabric2.util.multiplyTransformMatrices(
10561
- matrix,
10562
- getGroupLocalToParentMatrix(group, pageChildren)
10563
- );
10564
- angle += Number(group.angle ?? 0) || 0;
10565
- }
10566
- return { matrix, angle: normalizeSignedAngle(angle) };
10567
- };
10568
- const getElementFabricPlacement$1 = (element, pageChildren, fabric2, options) => {
10569
- if (!pageChildren.length) {
10570
- return { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
10571
- }
10572
- const ancestor = getAncestorGroupTransform(element.id, pageChildren, fabric2);
10573
- const point = fabric2.util.transformPoint(
10574
- new fabric2.Point(element.left ?? 0, element.top ?? 0),
10575
- ancestor.matrix
10576
- );
10577
- return {
10578
- left: point.x,
10579
- top: point.y,
10580
- angle: normalizeSignedAngle(ancestor.angle + Number(element.angle ?? 0))
10581
- };
10582
- };
10583
- const getGroupAbsoluteTransformFrame$1 = (group, pageChildren, fabric2, options) => {
10584
- const frame = getGroupTransformFrame(group, pageChildren);
10585
- const ancestor = getAncestorGroupTransform(group.id, pageChildren, fabric2);
10586
- const centerLocal = rotatedTopLeftToCenter(frame.left, frame.top, frame.width, frame.height, frame.angle);
10587
- const center = fabric2.util.transformPoint(new fabric2.Point(centerLocal.x, centerLocal.y), ancestor.matrix);
10588
- const topLeft = fabric2.util.transformPoint(new fabric2.Point(frame.left, frame.top), ancestor.matrix);
10589
- return {
10590
- left: topLeft.x,
10591
- top: topLeft.y,
10592
- width: frame.width,
10593
- height: frame.height,
10594
- centerX: center.x,
10595
- centerY: center.y,
10596
- angle: normalizeSignedAngle(ancestor.angle + frame.angle)
10597
- };
10598
- };
10599
- function preserveLogicalGroupTagDuringMove(selection, groupId) {
10600
- selection.__pixldocsGroupSelection = groupId;
10601
- }
10602
10503
  const SELECTION_PRIMARY = "hsl(217, 91%, 60%)";
10603
10504
  const SELECTION_BORDER_SCALE = 2;
10604
10505
  let ensureCanvaControlRenders = () => {
@@ -11052,18 +10953,12 @@ try {
11052
10953
  } catch (e) {
11053
10954
  }
11054
10955
  };
11055
- const wrapControlsFactory = (key) => {
11056
- if (typeof cu[key] !== "function") return;
11057
- const descriptor = Object.getOwnPropertyDescriptor(cu, key);
11058
- if (descriptor && descriptor.writable === false && !descriptor.set) return;
11059
- const original = cu[key].bind(cu);
11060
- try {
11061
- cu[key] = () => installPillRenders(original());
11062
- } catch {
11063
- }
11064
- };
11065
- wrapControlsFactory("createObjectDefaultControls");
11066
- wrapControlsFactory("createTextboxDefaultControls");
10956
+ const origObj = cu.createObjectDefaultControls.bind(cu);
10957
+ cu.createObjectDefaultControls = () => installPillRenders(origObj());
10958
+ if (typeof cu.createTextboxDefaultControls === "function") {
10959
+ const origTb = cu.createTextboxDefaultControls.bind(cu);
10960
+ cu.createTextboxDefaultControls = () => installPillRenders(origTb());
10961
+ }
11067
10962
  const wrapClassCreateControls = (Klass) => {
11068
10963
  if (!Klass || typeof Klass.createControls !== "function") return;
11069
10964
  const orig = Klass.createControls.bind(Klass);
@@ -11130,8 +11025,6 @@ const scaleUpdateNumber = (updates, source, key, factor) => {
11130
11025
  };
11131
11026
  const GROUP_TEXT_RESIZE_DEBUG_PREFIX = "[Pixldocs][group-text-corner-resize]";
11132
11027
  const GROUP_TEXT_RESIZE_DEBUG_MAX_ENTRIES = 200;
11133
- const GROUP_IMAGE_RESIZE_DEBUG_PREFIX = "[Pixldocs][group-image-side-resize]";
11134
- const GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES = 300;
11135
11028
  const isCornerResizeHandle = (handle) => handle === "tl" || handle === "tr" || handle === "bl" || handle === "br";
11136
11029
  const summarizeFabricObjectForResizeDebug = (obj) => {
11137
11030
  var _a2;
@@ -11194,43 +11087,6 @@ const logGroupTextResizeDebug = (phase, payload) => {
11194
11087
  console.log(GROUP_TEXT_RESIZE_DEBUG_PREFIX, phase, payload);
11195
11088
  }
11196
11089
  };
11197
- const isGroupResizeImageLikeObject = (obj) => {
11198
- var _a2;
11199
- return !!obj && (obj instanceof fabric.FabricImage || obj instanceof fabric.Group && (obj.__cropGroup || ((_a2 = obj._ct) == null ? void 0 : _a2.isCropGroup)));
11200
- };
11201
- const logGroupImageResizeDebug = (phase, payload) => {
11202
- if (typeof console === "undefined") return;
11203
- try {
11204
- const seen = /* @__PURE__ */ new WeakSet();
11205
- const normalize = (value) => {
11206
- if (value == null) return value;
11207
- const valueType = typeof value;
11208
- if (valueType === "number") return Number.isFinite(value) ? Math.round(value * 1e3) / 1e3 : String(value);
11209
- if (valueType === "string" || valueType === "boolean") return value;
11210
- if (valueType === "function") return `[Function ${value.name || "anonymous"}]`;
11211
- if (Array.isArray(value)) return value.map((entry) => normalize(entry));
11212
- if (valueType === "object") {
11213
- if (seen.has(value)) return "[Circular]";
11214
- seen.add(value);
11215
- if (value instanceof fabric.FabricObject) return normalize(summarizeFabricObjectForResizeDebug(value));
11216
- const output = {};
11217
- Object.entries(value).forEach(([key, entry]) => {
11218
- output[key] = normalize(entry);
11219
- });
11220
- return output;
11221
- }
11222
- return String(value);
11223
- };
11224
- const normalizedPayload = normalize(payload);
11225
- const line = `${GROUP_IMAGE_RESIZE_DEBUG_PREFIX} ${phase} ${JSON.stringify(normalizedPayload)}`;
11226
- const debugWindow = window;
11227
- debugWindow.__pixldocsGroupImageResizeLogs = Array.isArray(debugWindow.__pixldocsGroupImageResizeLogs) ? debugWindow.__pixldocsGroupImageResizeLogs.slice(-GROUP_IMAGE_RESIZE_DEBUG_MAX_ENTRIES + 1) : [];
11228
- debugWindow.__pixldocsGroupImageResizeLogs.push(line);
11229
- console.log(line);
11230
- } catch {
11231
- console.log(GROUP_IMAGE_RESIZE_DEBUG_PREFIX, phase, payload);
11232
- }
11233
- };
11234
11090
  const bakeTextboxScaleIntoTypography = (obj, sourceElement) => {
11235
11091
  const sx = Math.abs(obj.scaleX ?? 1) || 1;
11236
11092
  const sy = Math.abs(obj.scaleY ?? 1) || 1;
@@ -11304,8 +11160,6 @@ const bakeTextboxScaleIntoTypography = (obj, sourceElement) => {
11304
11160
  };
11305
11161
  return updates;
11306
11162
  };
11307
- const getElementFabricPlacement = (element, pageChildren, options) => getElementFabricPlacement$1(element, pageChildren, fabric);
11308
- const getGroupAbsoluteTransformFrame = (group, pageChildren, options) => getGroupAbsoluteTransformFrame$1(group, pageChildren, fabric);
11309
11163
  function applyWarpAwareSelectionBorders(selection) {
11310
11164
  var _a2;
11311
11165
  if (selection.__pixldocsOrigASHasBorders !== void 0) {
@@ -11314,7 +11168,6 @@ function applyWarpAwareSelectionBorders(selection) {
11314
11168
  }
11315
11169
  selection.hasBorders = true;
11316
11170
  selection.hasControls = true;
11317
- if (selection.__pixldocsGroupSelection) return;
11318
11171
  try {
11319
11172
  if (selection.__pixldocsAlignedAngle == null) {
11320
11173
  const kids = selection.getObjects();
@@ -11362,6 +11215,37 @@ function applyWarpAwareSelectionBorders(selection) {
11362
11215
  selection.setCoords();
11363
11216
  selection.dirty = true;
11364
11217
  selection.__pixldocsAlignedAngle = targetAngle;
11218
+ try {
11219
+ const kidSummary = kids.map((c) => ({
11220
+ id: c.id ?? c.__pixldocsId,
11221
+ type: c.type,
11222
+ left: c.left,
11223
+ top: c.top,
11224
+ angle: c.angle,
11225
+ scaleX: c.scaleX,
11226
+ scaleY: c.scaleY,
11227
+ originX: c.originX,
11228
+ originY: c.originY,
11229
+ width: c.width,
11230
+ height: c.height
11231
+ }));
11232
+ console.info("[Pixldocs][rot-group-image-drift] aligned-on-select", {
11233
+ targetAngle,
11234
+ selection: {
11235
+ left: selection.left,
11236
+ top: selection.top,
11237
+ angle: selection.angle,
11238
+ scaleX: selection.scaleX,
11239
+ scaleY: selection.scaleY,
11240
+ width: selection.width,
11241
+ height: selection.height,
11242
+ originX: selection.originX,
11243
+ originY: selection.originY
11244
+ },
11245
+ kids: kidSummary
11246
+ });
11247
+ } catch {
11248
+ }
11365
11249
  }
11366
11250
  }
11367
11251
  }
@@ -11441,46 +11325,10 @@ const PageCanvas = forwardRef(
11441
11325
  const [ready, setReady] = useState(false);
11442
11326
  const [unlockRequestId, setUnlockRequestId] = useState(0);
11443
11327
  const applyLogicalGroupSelectionVisualState = useCallback((selection, groupId) => {
11444
- var _a2, _b2;
11328
+ var _a2;
11445
11329
  selection.__pixldocsGroupSelection = groupId;
11446
11330
  delete selection.__pixldocsLogicalGroupIds;
11447
11331
  selection.hasBorders = true;
11448
- try {
11449
- const membersBeforeFrame = selection.getObjects();
11450
- const selectionMatrixBefore = selection.calcTransformMatrix();
11451
- const memberWorldMatrices = membersBeforeFrame.map((member) => fabric.util.multiplyTransformMatrices(
11452
- selectionMatrixBefore,
11453
- member.calcOwnMatrix()
11454
- ));
11455
- const pageChildren2 = ((_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
11456
- const groupNode = findNodeById(pageChildren2, groupId);
11457
- const groupFrame = groupNode && isGroup(groupNode) ? getGroupAbsoluteTransformFrame(groupNode, pageChildren2, pageBoundsOptions) : null;
11458
- const groupAngle = groupFrame ? groupFrame.angle : 0;
11459
- if (Number.isFinite(groupAngle)) {
11460
- selection.set({ angle: groupAngle, scaleX: 1, scaleY: 1, skewX: 0, skewY: 0 });
11461
- if (groupFrame) {
11462
- selection.setPositionByOrigin(
11463
- new fabric.Point(groupFrame.centerX, groupFrame.centerY),
11464
- "center",
11465
- "center"
11466
- );
11467
- }
11468
- const invSelectionAfter = fabric.util.invertTransform(
11469
- selection.calcTransformMatrix()
11470
- );
11471
- membersBeforeFrame.forEach((member, index) => {
11472
- const localMatrix = fabric.util.multiplyTransformMatrices(
11473
- invSelectionAfter,
11474
- memberWorldMatrices[index]
11475
- );
11476
- fabric.util.applyTransformToObject(member, localMatrix);
11477
- member.setCoords();
11478
- member.dirty = true;
11479
- });
11480
- selection.setCoords();
11481
- }
11482
- } catch {
11483
- }
11484
11332
  const members = selection.getObjects();
11485
11333
  for (const prev of suppressGroupMemberBordersRef.current) {
11486
11334
  if (members.includes(prev)) continue;
@@ -11504,7 +11352,7 @@ const PageCanvas = forwardRef(
11504
11352
  if (m.__pixldocsOrigHasControls === void 0) m.__pixldocsOrigHasControls = m.hasControls;
11505
11353
  m.hasBorders = false;
11506
11354
  m.hasControls = false;
11507
- if (m.__cropGroup || ((_b2 = m._ct) == null ? void 0 : _b2.isCropGroup)) {
11355
+ if (m.__cropGroup || ((_a2 = m._ct) == null ? void 0 : _a2.isCropGroup)) {
11508
11356
  if (m.__pixldocsOrigLockScalingX === void 0) {
11509
11357
  m.__pixldocsOrigLockScalingX = m.lockScalingX;
11510
11358
  m.__pixldocsOrigLockScalingY = m.lockScalingY;
@@ -11514,7 +11362,7 @@ const PageCanvas = forwardRef(
11514
11362
  }
11515
11363
  }
11516
11364
  applyWarpAwareSelectionBorders(selection);
11517
- }, [pageId]);
11365
+ }, []);
11518
11366
  const pageBoundsOptions = useMemo(
11519
11367
  () => ({ pageContentWidth: canvasWidth, pageContentHeight: canvasHeight }),
11520
11368
  [canvasWidth, canvasHeight]
@@ -11588,6 +11436,7 @@ const PageCanvas = forwardRef(
11588
11436
  const preserveSelectionAfterTransformIdRef = useRef(null);
11589
11437
  const groupSelectionTransformStartRef = useRef(null);
11590
11438
  const activeSelectionMoveStartRef = useRef(null);
11439
+ const sectionGroupTransientImagesRef = useRef(null);
11591
11440
  setGroupOverlayLiveBoundsRef.current = setGroupOverlayLiveBounds;
11592
11441
  const {
11593
11442
  selectElements,
@@ -12433,6 +12282,7 @@ const PageCanvas = forwardRef(
12433
12282
  fabricCanvas.__fontCleanup = fontCleanup;
12434
12283
  fabricCanvas.__isUserTransforming = false;
12435
12284
  fabricCanvas.on("mouse:down", () => {
12285
+ groupSelectionTransformStartRef.current = null;
12436
12286
  activeSelectionMoveStartRef.current = null;
12437
12287
  activeSelectionResizeHandleRef.current = null;
12438
12288
  const active = fabricCanvas.getActiveObject();
@@ -12443,7 +12293,6 @@ const PageCanvas = forwardRef(
12443
12293
  selectionLeft: rect.left,
12444
12294
  selectionTop: rect.top
12445
12295
  };
12446
- prepareGroupSelectionTransformStart(active);
12447
12296
  }
12448
12297
  if (fabricCanvas._currentTransform) {
12449
12298
  fabricCanvas.__isUserTransforming = true;
@@ -12505,8 +12354,101 @@ const PageCanvas = forwardRef(
12505
12354
  });
12506
12355
  }
12507
12356
  });
12508
- fabricCanvas.on("object:moving", () => {
12357
+ const collectSectionGroupImageDescendantObjects = (groupNode) => {
12358
+ const ids = getAllElementIds(groupNode.children ?? []);
12359
+ if (ids.length === 0) return [];
12360
+ const elementById = new Map(elementsRef.current.map((el) => [el.id, el]));
12361
+ const out = [];
12362
+ for (const id of ids) {
12363
+ const el = elementById.get(id);
12364
+ if (!el || el.type !== "image") continue;
12365
+ const obj = fabricCanvas.getObjects().find((o) => getObjectId(o) === id);
12366
+ if (obj) out.push(obj);
12367
+ }
12368
+ return out;
12369
+ };
12370
+ const ensureSectionGroupTransientSnapshot = (group) => {
12371
+ var _a2;
12372
+ if (!group || !(group instanceof fabric.Group)) return false;
12373
+ if (!group.__docuforgeSectionGroup) return false;
12374
+ const groupId = getObjectId(group);
12375
+ if (!groupId) return false;
12376
+ const existing = sectionGroupTransientImagesRef.current;
12377
+ if (existing && existing.groupId === groupId && existing.group === group) return true;
12378
+ const pageChildrenLocal = ((_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
12379
+ const node = findNodeById(pageChildrenLocal, groupId);
12380
+ if (!node || !isGroup(node)) return false;
12381
+ const images = collectSectionGroupImageDescendantObjects(node);
12382
+ const gcx = group.left ?? 0;
12383
+ const gcy = group.top ?? 0;
12384
+ const gangle = group.angle ?? 0;
12385
+ const gsx = group.scaleX ?? 1;
12386
+ const gsy = group.scaleY ?? 1;
12387
+ const rad = -gangle * Math.PI / 180;
12388
+ const cos0 = Math.cos(rad);
12389
+ const sin0 = Math.sin(rad);
12390
+ const snap = images.map((obj) => {
12391
+ const icx = obj.left ?? 0;
12392
+ const icy = obj.top ?? 0;
12393
+ const dx = icx - gcx;
12394
+ const dy = icy - gcy;
12395
+ const rx = dx * cos0 - dy * sin0;
12396
+ const ry = dx * sin0 + dy * cos0;
12397
+ return {
12398
+ obj,
12399
+ localX: gsx ? rx / gsx : rx,
12400
+ localY: gsy ? ry / gsy : ry,
12401
+ relAngle: (obj.angle ?? 0) - gangle,
12402
+ relSx: (obj.scaleX ?? 1) / (gsx || 1),
12403
+ relSy: (obj.scaleY ?? 1) / (gsy || 1)
12404
+ };
12405
+ });
12406
+ sectionGroupTransientImagesRef.current = {
12407
+ groupId,
12408
+ group,
12409
+ group0: { cx: gcx, cy: gcy, angle: gangle, sx: gsx, sy: gsy },
12410
+ images: snap
12411
+ };
12412
+ return true;
12413
+ };
12414
+ const applySectionGroupTransientTransform = () => {
12415
+ const snap = sectionGroupTransientImagesRef.current;
12416
+ if (!snap || snap.images.length === 0) return;
12417
+ const group = snap.group;
12418
+ const gcx = group.left ?? 0;
12419
+ const gcy = group.top ?? 0;
12420
+ const gangle = group.angle ?? 0;
12421
+ const gsx = group.scaleX ?? 1;
12422
+ const gsy = group.scaleY ?? 1;
12423
+ const rad = gangle * Math.PI / 180;
12424
+ const cos = Math.cos(rad);
12425
+ const sin = Math.sin(rad);
12426
+ for (const entry of snap.images) {
12427
+ const lx = entry.localX * gsx;
12428
+ const ly = entry.localY * gsy;
12429
+ const wx = lx * cos - ly * sin;
12430
+ const wy = lx * sin + ly * cos;
12431
+ entry.obj.set({
12432
+ left: gcx + wx,
12433
+ top: gcy + wy,
12434
+ angle: entry.relAngle + gangle,
12435
+ scaleX: entry.relSx * gsx,
12436
+ scaleY: entry.relSy * gsy
12437
+ });
12438
+ entry.obj.setCoords();
12439
+ entry.obj.dirty = true;
12440
+ }
12441
+ };
12442
+ const clearSectionGroupTransientSnapshot = () => {
12443
+ sectionGroupTransientImagesRef.current = null;
12444
+ };
12445
+ const maybeFollowSectionGroupTransient = (target) => {
12446
+ if (!ensureSectionGroupTransientSnapshot(target)) return;
12447
+ applySectionGroupTransientTransform();
12448
+ };
12449
+ fabricCanvas.on("object:moving", (e) => {
12509
12450
  var _a2, _b2;
12451
+ maybeFollowSectionGroupTransient((e == null ? void 0 : e.target) ?? null);
12510
12452
  fabricCanvas.__isUserTransforming = true;
12511
12453
  didTransformRef.current = true;
12512
12454
  if (drilledGroupIdRef.current) {
@@ -12548,8 +12490,9 @@ const PageCanvas = forwardRef(
12548
12490
  });
12549
12491
  }
12550
12492
  });
12551
- fabricCanvas.on("object:rotating", () => {
12493
+ fabricCanvas.on("object:rotating", (e) => {
12552
12494
  var _a2;
12495
+ maybeFollowSectionGroupTransient((e == null ? void 0 : e.target) ?? null);
12553
12496
  fabricCanvas.__isUserTransforming = true;
12554
12497
  didTransformRef.current = true;
12555
12498
  if (drilledGroupIdRef.current) {
@@ -12559,6 +12502,12 @@ const PageCanvas = forwardRef(
12559
12502
  }
12560
12503
  }
12561
12504
  });
12505
+ fabricCanvas.on("object:scaling", (e) => {
12506
+ maybeFollowSectionGroupTransient((e == null ? void 0 : e.target) ?? null);
12507
+ });
12508
+ fabricCanvas.on("mouse:up", () => {
12509
+ clearSectionGroupTransientSnapshot();
12510
+ });
12562
12511
  const syncSelectionToStore = () => {
12563
12512
  var _a2, _b2, _c, _d;
12564
12513
  if (!isActiveRef.current || isRebuildingRef.current || isSyncingSelectionToFabricRef.current || !allowSelection) return;
@@ -12945,22 +12894,16 @@ const PageCanvas = forwardRef(
12945
12894
  const pageChildren2 = ((_b2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _b2.children) ?? [];
12946
12895
  const groupNode = findNodeById(pageChildren2, groupId);
12947
12896
  if (!groupNode) return;
12948
- const groupFrame = isGroup(groupNode) ? getGroupAbsoluteTransformFrame(groupNode, pageChildren2) : null;
12949
- const groupAbs = groupFrame ?? getAbsoluteBounds(groupNode, pageChildren2);
12897
+ const groupAbs = getAbsoluteBounds(groupNode, pageChildren2);
12950
12898
  const rect = active.getBoundingRect();
12951
- const center = active.getCenterPoint();
12952
12899
  groupSelectionTransformStartRef.current = {
12953
12900
  groupId,
12954
12901
  selection: active,
12955
12902
  selectionLeft: rect.left,
12956
12903
  selectionTop: rect.top,
12957
- selectionCenterX: center.x,
12958
- selectionCenterY: center.y,
12959
12904
  groupLeft: groupAbs.left,
12960
12905
  groupTop: groupAbs.top,
12961
- groupWidth: groupAbs.width,
12962
- groupHeight: groupAbs.height,
12963
- selectionAngle: (((groupFrame == null ? void 0 : groupFrame.angle) ?? active.angle ?? 0) % 360 + 360) % 360
12906
+ selectionAngle: ((active.angle ?? 0) % 360 + 360) % 360
12964
12907
  };
12965
12908
  };
12966
12909
  const restoreGroupSelectionVisualState = (selection, groupId) => {
@@ -13294,36 +13237,9 @@ const PageCanvas = forwardRef(
13294
13237
  });
13295
13238
  };
13296
13239
  fabricCanvas.__updateDrilledGroupOutline = updateDrilledGroupOutline;
13297
- const isPointerOnSelectionControl = (selection, event) => {
13298
- var _a2;
13299
- try {
13300
- selection.setCoords();
13301
- const controls = selection.oCoords ?? ((_a2 = selection.calcOCoords) == null ? void 0 : _a2.call(selection));
13302
- const el = fabricCanvas.upperCanvasEl ?? fabricCanvas.lowerCanvasEl;
13303
- const rect = el == null ? void 0 : el.getBoundingClientRect();
13304
- if (!controls || !rect || !event) return false;
13305
- const x = Number(event.clientX) - rect.left;
13306
- const y = Number(event.clientY) - rect.top;
13307
- return Object.values(controls).some((control) => {
13308
- const pts = (control == null ? void 0 : control.touchCorner) ?? (control == null ? void 0 : control.corner);
13309
- const corners = pts ? Object.values(pts) : [];
13310
- if (!corners.length) return false;
13311
- const minX = Math.min(...corners.map((p) => p.x)) - 2;
13312
- const maxX = Math.max(...corners.map((p) => p.x)) + 2;
13313
- const minY = Math.min(...corners.map((p) => p.y)) - 2;
13314
- const maxY = Math.max(...corners.map((p) => p.y)) + 2;
13315
- return x >= minX && x <= maxX && y >= minY && y <= maxY;
13316
- });
13317
- } catch {
13318
- return false;
13319
- }
13320
- };
13321
13240
  fabricCanvas.on("mouse:down:before", (opt) => {
13322
13241
  var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
13323
13242
  const activeBeforeMouseDown = fabricCanvas.getActiveObject();
13324
- if (activeBeforeMouseDown instanceof fabric.ActiveSelection && activeBeforeMouseDown.__pixldocsGroupSelection) {
13325
- prepareGroupSelectionTransformStart(activeBeforeMouseDown);
13326
- }
13327
13243
  if (editLockRef.current) {
13328
13244
  const active = fabricCanvas.getActiveObject();
13329
13245
  if (active && (((_a2 = active._ct) == null ? void 0 : _a2.isCropGroup) || active.__cropGroup)) {
@@ -13341,8 +13257,7 @@ const PageCanvas = forwardRef(
13341
13257
  }
13342
13258
  let target = opt.target;
13343
13259
  let targetId = target ? getObjectId(target) : null;
13344
- const pointerOnActiveSelectionControl = activeBeforeMouseDown instanceof fabric.ActiveSelection ? isPointerOnSelectionControl(activeBeforeMouseDown, opt.e) : false;
13345
- if (target instanceof fabric.ActiveSelection && target.__pixldocsGroupSelection && target === fabricCanvas.getActiveObject() && !target.__corner && !pointerOnActiveSelectionControl) {
13260
+ if (target instanceof fabric.ActiveSelection && target.__pixldocsGroupSelection && target === fabricCanvas.getActiveObject()) {
13346
13261
  const child = pickChildInActiveSelectionAtPointer(target, opt.e);
13347
13262
  const childId = child ? getObjectId(child) : null;
13348
13263
  if (child && childId) {
@@ -13391,7 +13306,7 @@ const PageCanvas = forwardRef(
13391
13306
  let effectiveTargetId = targetId;
13392
13307
  const activeNowEarly = fabricCanvas.getActiveObject();
13393
13308
  const asGroupId = target instanceof fabric.ActiveSelection ? target.__pixldocsGroupSelection : void 0;
13394
- if (target instanceof fabric.ActiveSelection && asGroupId && target === activeNowEarly && !target.__corner && !pointerOnActiveSelectionControl) {
13309
+ if (target instanceof fabric.ActiveSelection && asGroupId && target === activeNowEarly) {
13395
13310
  const child = pickChildInActiveSelectionAtPointer(target, opt.e);
13396
13311
  const childId = child ? getObjectId(child) : null;
13397
13312
  if (child && childId) {
@@ -13424,7 +13339,6 @@ const PageCanvas = forwardRef(
13424
13339
  restoreGroupSelectionVisualState(selection, parent.id);
13425
13340
  fabricCanvas.setActiveObject(selection);
13426
13341
  selection.setCoords();
13427
- prepareGroupSelectionTransformStart(selection);
13428
13342
  fabricCanvas._target = selection;
13429
13343
  opt.target = selection;
13430
13344
  pendingGroupPromotionRef.current = { groupId: parent.id, selection };
@@ -13467,7 +13381,6 @@ const PageCanvas = forwardRef(
13467
13381
  restoreGroupSelectionVisualState(selection, parent.id);
13468
13382
  fabricCanvas.setActiveObject(selection);
13469
13383
  selection.setCoords();
13470
- prepareGroupSelectionTransformStart(selection);
13471
13384
  fabricCanvas._target = selection;
13472
13385
  opt.target = selection;
13473
13386
  pendingGroupPromotionRef.current = { groupId: parent.id, selection };
@@ -13736,29 +13649,34 @@ const PageCanvas = forwardRef(
13736
13649
  });
13737
13650
  const markSimpleTransform = (e) => {
13738
13651
  if (!isActiveRef.current) return;
13739
- prepareGroupSelectionTransformStart(e.target);
13740
13652
  markTransforming(e.target);
13741
13653
  };
13742
13654
  const getObjectFrameBoundsInSelection = (selection, obj, frameWidth, frameHeight) => {
13743
13655
  const w = Math.max(1, frameWidth ?? obj.width ?? 1);
13744
13656
  const h = Math.max(1, frameHeight ?? obj.height ?? 1);
13657
+ const originX = obj.originX ?? "left";
13658
+ const originY = obj.originY ?? "top";
13659
+ const localLeft = originX === "center" ? -w / 2 : originX === "right" ? -w : 0;
13660
+ const localTop = originY === "center" ? -h / 2 : originY === "bottom" ? -h : 0;
13745
13661
  const matrix = fabric.util.multiplyTransformMatrices(
13746
13662
  selection.calcTransformMatrix(),
13747
13663
  obj.calcOwnMatrix()
13748
13664
  );
13749
- const decomposed = fabric.util.qrDecompose(matrix);
13750
- const scaledW = Math.max(1, w * Math.abs(decomposed.scaleX || 1));
13751
- const scaledH = Math.max(1, h * Math.abs(decomposed.scaleY || 1));
13752
- const angleRad = (decomposed.angle ?? 0) * Math.PI / 180;
13753
- const cos = Math.cos(angleRad);
13754
- const sin = Math.sin(angleRad);
13755
- const left = decomposed.translateX - scaledW / 2 * cos + scaledH / 2 * sin;
13756
- const top = decomposed.translateY - scaledW / 2 * sin - scaledH / 2 * cos;
13665
+ const points = [
13666
+ new fabric.Point(localLeft, localTop),
13667
+ new fabric.Point(localLeft + w, localTop),
13668
+ new fabric.Point(localLeft + w, localTop + h),
13669
+ new fabric.Point(localLeft, localTop + h)
13670
+ ].map((point) => fabric.util.transformPoint(point, matrix));
13671
+ const xs = points.map((p) => p.x);
13672
+ const ys = points.map((p) => p.y);
13673
+ const left = Math.min(...xs);
13674
+ const top = Math.min(...ys);
13757
13675
  return {
13758
13676
  left,
13759
13677
  top,
13760
- width: scaledW,
13761
- height: scaledH
13678
+ width: Math.max(1, Math.max(...xs) - left),
13679
+ height: Math.max(1, Math.max(...ys) - top)
13762
13680
  };
13763
13681
  };
13764
13682
  fabricCanvas.on("object:added", (e) => {
@@ -13773,30 +13691,10 @@ const PageCanvas = forwardRef(
13773
13691
  fabricCanvas.on("selection:cleared", () => {
13774
13692
  });
13775
13693
  fabricCanvas.on("object:scaling", (e) => {
13776
- var _a2, _b2, _c, _d, _e, _f, _g, _h;
13694
+ var _a2, _b2, _c, _d, _e, _f;
13777
13695
  if (!isActiveRef.current) return;
13778
13696
  const t = e.target;
13779
13697
  if (t) lastResizeScaleTargetRef.current = t;
13780
- try {
13781
- const transformDbg = e.transform;
13782
- const cornerDbg = (transformDbg == null ? void 0 : transformDbg.corner) || "";
13783
- const children = t instanceof fabric.Group || t instanceof fabric.ActiveSelection ? t.getObjects() : [];
13784
- logGroupImageResizeDebug("scaling-entry", {
13785
- time: Math.round(performance.now()),
13786
- corner: cornerDbg,
13787
- targetType: t == null ? void 0 : t.type,
13788
- targetCtor: (_a2 = t == null ? void 0 : t.constructor) == null ? void 0 : _a2.name,
13789
- isActiveSelection: t instanceof fabric.ActiveSelection,
13790
- isGroup: t instanceof fabric.Group,
13791
- isCropGroup: !!(t && (t.__cropGroup || ((_b2 = t._ct) == null ? void 0 : _b2.isCropGroup))),
13792
- childCount: children.length,
13793
- childTypes: children.map((c) => c == null ? void 0 : c.type),
13794
- hasImageChild: children.some((c) => isGroupResizeImageLikeObject(c)),
13795
- target: t ? summarizeFabricObjectForResizeDebug(t) : null
13796
- });
13797
- } catch (err) {
13798
- console.warn("[Pixldocs][group-image-side-resize] scaling-entry log failed", err);
13799
- }
13800
13698
  prepareGroupSelectionTransformStart(t);
13801
13699
  markTransforming(t);
13802
13700
  didTransformRef.current = true;
@@ -13960,7 +13858,7 @@ const PageCanvas = forwardRef(
13960
13858
  time: Math.round(performance.now()),
13961
13859
  corner,
13962
13860
  groupSelectionId: obj.__pixldocsGroupSelection,
13963
- currentTransformAction: (_c = fabricCanvas._currentTransform) == null ? void 0 : _c.action,
13861
+ currentTransformAction: (_a2 = fabricCanvas._currentTransform) == null ? void 0 : _a2.action,
13964
13862
  selection: summarizeFabricObjectForResizeDebug(obj),
13965
13863
  textChildren: obj.getObjects().filter((child) => child instanceof fabric.Textbox).map((child) => summarizeFabricObjectForResizeDebug(child))
13966
13864
  };
@@ -13970,43 +13868,19 @@ const PageCanvas = forwardRef(
13970
13868
  const isXSide = corner === "ml" || corner === "mr";
13971
13869
  const sAxis = isXSide ? Math.abs(obj.scaleX ?? 1) : Math.abs(obj.scaleY ?? 1);
13972
13870
  if (sAxis > 1e-3) {
13973
- const hasRotatedChild = obj.getObjects().some((c) => {
13974
- const a = ((c.angle ?? 0) % 180 + 180) % 180;
13975
- return !(a < 0.5 || a > 179.5);
13976
- });
13977
- const selectionAngle = ((obj.angle ?? 0) % 180 + 180) % 180;
13978
- const isSelectionRotated = !(selectionAngle < 0.5 || selectionAngle > 179.5);
13979
- const shouldPinNonTextChildren = hasRotatedChild || isSelectionRotated;
13980
- const shouldDebugGroupImageResize = obj.getObjects().some((child) => isGroupResizeImageLikeObject(child));
13981
- if (shouldDebugGroupImageResize) {
13982
- logGroupImageResizeDebug("live-start", {
13983
- time: Math.round(performance.now()),
13984
- corner,
13985
- isXSide,
13986
- sAxis,
13987
- hasRotatedChild,
13988
- isSelectionRotated,
13989
- shouldPinNonTextChildren,
13990
- groupSelectionId: obj.__pixldocsGroupSelection,
13991
- selection: summarizeFabricObjectForResizeDebug(obj),
13992
- children: obj.getObjects().map((child) => summarizeFabricObjectForResizeDebug(child))
13993
- });
13994
- }
13995
- if ((isXSide || shouldPinNonTextChildren) && ((_d = groupShiftReflowSnapshotRef.current) == null ? void 0 : _d.selection) !== obj) {
13871
+ if (isXSide && ((_b2 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _b2.selection) !== obj) {
13996
13872
  groupShiftReflowSnapshotRef.current = null;
13997
13873
  const logicalGroupId = obj.__pixldocsGroupSelection;
13998
13874
  if (logicalGroupId) {
13999
13875
  try {
14000
13876
  const state = useEditorStore.getState();
14001
- const pageChildren2 = ((_e = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _e.children) ?? [];
13877
+ const pageChildren2 = ((_c = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
14002
13878
  const groupNode = findNodeById(pageChildren2, logicalGroupId);
14003
13879
  if (groupNode && isGroup(groupNode) && !isStackLayoutMode(groupNode.layoutMode)) {
14004
13880
  const entries = obj.getObjects().map((c) => ({
14005
13881
  obj: c,
14006
13882
  id: getObjectId(c) ?? "",
14007
- left0: c.left ?? 0,
14008
13883
  top0: c.top ?? 0,
14009
- width0: (c.width ?? 0) * Math.abs(c.scaleX ?? 1),
14010
13884
  height0: (c.height ?? 0) * Math.abs(c.scaleY ?? 1)
14011
13885
  })).filter((e2) => e2.id).sort((a, b) => a.top0 - b.top0);
14012
13886
  if (entries.length > 1) {
@@ -14029,150 +13903,78 @@ const PageCanvas = forwardRef(
14029
13903
  const asTop0 = obj.top ?? 0;
14030
13904
  const asRect0 = obj.getBoundingRect();
14031
13905
  let didReflowTextChild = false;
14032
- if (hasRotatedChild) {
14033
- if (isXSide) {
14034
- obj._set("width", asW0 * sAxis);
14035
- obj._set("scaleX", 1);
14036
- } else {
14037
- obj._set("height", asH0 * sAxis);
14038
- obj._set("scaleY", 1);
14039
- }
14040
- }
14041
- const childCounterScale = hasRotatedChild ? 1 : 1 / sAxis;
14042
- let restoredNonTextAfterLayout = false;
14043
- const restoreNonTextChildren = (pins) => {
14044
- var _a3, _b3;
14045
- if (!shouldPinNonTextChildren || ((_a3 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _a3.selection) !== obj) return;
14046
- for (const entry of groupShiftReflowSnapshotRef.current.children) {
14047
- const child = entry.obj;
14048
- if (child instanceof fabric.Textbox) continue;
14049
- if (child instanceof fabric.FabricImage || child instanceof fabric.Group && (child.__cropGroup || ((_b3 = child._ct) == null ? void 0 : _b3.isCropGroup))) {
14050
- const pin = pins == null ? void 0 : pins.get(child);
14051
- let targetLeft = hasRotatedChild && isXSide ? entry.left0 * sAxis : entry.left0;
14052
- let targetTop = hasRotatedChild && !isXSide ? entry.top0 * sAxis : entry.top0;
14053
- if (pin == null ? void 0 : pin.worldCenter) {
14054
- try {
14055
- const invSelectionMatrix = fabric.util.invertTransform(obj.calcTransformMatrix());
14056
- const localCenter = fabric.util.transformPoint(pin.worldCenter, invSelectionMatrix);
14057
- targetLeft = localCenter.x;
14058
- targetTop = localCenter.y;
14059
- } catch {
14060
- targetLeft = pin.left ?? targetLeft;
14061
- targetTop = pin.top ?? targetTop;
14062
- }
14063
- } else {
14064
- targetLeft = (pin == null ? void 0 : pin.left) ?? targetLeft;
14065
- targetTop = (pin == null ? void 0 : pin.top) ?? targetTop;
14066
- }
14067
- const beforeRestore = shouldDebugGroupImageResize ? summarizeFabricObjectForResizeDebug(child) : null;
14068
- if (Math.abs((child.left ?? 0) - targetLeft) > 0.01) child._set("left", targetLeft);
14069
- if (Math.abs((child.top ?? 0) - targetTop) > 0.01) child._set("top", targetTop);
14070
- if (isXSide) child._set("scaleX", childCounterScale);
14071
- else child._set("scaleY", childCounterScale);
14072
- child.setCoords();
14073
- child.dirty = true;
14074
- if (shouldDebugGroupImageResize) {
14075
- logGroupImageResizeDebug("restore-non-text", {
14076
- time: Math.round(performance.now()),
14077
- corner,
14078
- childId: getObjectId(child),
14079
- targetLeft,
14080
- targetTop,
14081
- pin,
14082
- before: beforeRestore,
14083
- after: summarizeFabricObjectForResizeDebug(child)
14084
- });
14085
- }
14086
- }
14087
- }
14088
- };
14089
- const projectRotatedTextPosition = (child) => {
14090
- var _a3;
14091
- if (!hasRotatedChild || ((_a3 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _a3.selection) !== obj) return;
14092
- const entry = groupShiftReflowSnapshotRef.current.children.find((candidate) => candidate.obj === child);
14093
- if (!entry) return;
14094
- if (isXSide) child._set("left", entry.left0 * sAxis);
14095
- else child._set("top", entry.top0 * sAxis);
14096
- };
14097
13906
  for (const child of obj.getObjects()) {
14098
- if (child instanceof fabric.Group && (child.__cropGroup || ((_f = child._ct) == null ? void 0 : _f.isCropGroup))) {
14099
- const beforeImageChildResize = shouldDebugGroupImageResize ? summarizeFabricObjectForResizeDebug(child) : null;
13907
+ if (child instanceof fabric.Group && (child.__cropGroup || ((_d = child._ct) == null ? void 0 : _d.isCropGroup))) {
14100
13908
  const ct = child.__cropData;
14101
- if (ct) {
13909
+ if (!ct) continue;
13910
+ if (isXSide) {
14102
13911
  if (child.__asLiveOrigW == null) {
14103
- child.__asLiveOrigW = ct.frameW ?? child.width ?? 1;
13912
+ const baseW = child.width ?? ct.frameW ?? 0;
13913
+ child.__asLiveOrigW = baseW * (child.scaleX ?? 1);
14104
13914
  }
14105
- if (child.__asLiveOrigH == null) {
14106
- child.__asLiveOrigH = ct.frameH ?? child.height ?? 1;
14107
- }
14108
- if (isXSide) {
14109
- const newW = Math.max(1, Number(child.__asLiveOrigW) * sAxis);
13915
+ const origW = child.__asLiveOrigW;
13916
+ const newW = Math.max(20, origW * sAxis);
13917
+ if (Math.abs((child.width ?? 0) - newW) > 0.5) {
14110
13918
  ct.frameW = newW;
14111
13919
  child._set("width", newW);
14112
- } else {
14113
- const newH = Math.max(1, Number(child.__asLiveOrigH) * sAxis);
13920
+ child._set("scaleX", 1 / sAxis);
13921
+ try {
13922
+ updateCoverLayout(child);
13923
+ } catch {
13924
+ }
13925
+ child.setCoords();
13926
+ child.dirty = true;
13927
+ }
13928
+ } else {
13929
+ if (child.__asLiveOrigH == null) {
13930
+ const baseH = child.height ?? ct.frameH ?? 0;
13931
+ child.__asLiveOrigH = baseH * (child.scaleY ?? 1);
13932
+ }
13933
+ const origH = child.__asLiveOrigH;
13934
+ const newH = Math.max(20, origH * sAxis);
13935
+ if (Math.abs((child.height ?? 0) - newH) > 0.5) {
14114
13936
  ct.frameH = newH;
14115
13937
  child._set("height", newH);
13938
+ child._set("scaleY", 1 / sAxis);
13939
+ try {
13940
+ updateCoverLayout(child);
13941
+ } catch {
13942
+ }
13943
+ child.setCoords();
13944
+ child.dirty = true;
14116
13945
  }
14117
- try {
14118
- updateCoverLayout(child);
14119
- } catch {
14120
- }
14121
- }
14122
- if (isXSide) child._set("scaleX", childCounterScale);
14123
- else child._set("scaleY", childCounterScale);
14124
- child.setCoords();
14125
- child.dirty = true;
14126
- if (shouldDebugGroupImageResize) {
14127
- logGroupImageResizeDebug("live-crop-child-resized", {
14128
- time: Math.round(performance.now()),
14129
- corner,
14130
- sAxis,
14131
- childCounterScale,
14132
- before: beforeImageChildResize,
14133
- after: summarizeFabricObjectForResizeDebug(child),
14134
- cropData: ct ? { frameW: ct.frameW, frameH: ct.frameH } : null
14135
- });
14136
13946
  }
14137
- didReflowTextChild = true;
14138
13947
  continue;
14139
13948
  }
14140
13949
  if (child instanceof fabric.FabricImage && !child.__cropGroup && !child.smartElementType) {
14141
- const beforeImageChildResize = shouldDebugGroupImageResize ? summarizeFabricObjectForResizeDebug(child) : null;
14142
13950
  if (isXSide) {
14143
13951
  if (child.__asLiveOrigW == null) {
14144
- child.__asLiveOrigW = (child.width ?? 0) * Math.abs(child.scaleX ?? 1);
13952
+ child.__asLiveOrigW = (child.width ?? 0) * (child.scaleX ?? 1);
13953
+ }
13954
+ const origW = child.__asLiveOrigW;
13955
+ const newW = Math.max(1, origW * sAxis);
13956
+ if (Math.abs((child.width ?? 0) - newW) > 0.5) {
13957
+ child._set("width", newW);
13958
+ child._set("scaleX", 1 / sAxis);
13959
+ child.setCoords();
13960
+ child.dirty = true;
14145
13961
  }
14146
- const newW = Math.max(1, Number(child.__asLiveOrigW) * sAxis);
14147
- child._set("width", newW);
14148
13962
  } else {
14149
13963
  if (child.__asLiveOrigH == null) {
14150
- child.__asLiveOrigH = (child.height ?? 0) * Math.abs(child.scaleY ?? 1);
13964
+ child.__asLiveOrigH = (child.height ?? 0) * (child.scaleY ?? 1);
13965
+ }
13966
+ const origH = child.__asLiveOrigH;
13967
+ const newH = Math.max(1, origH * sAxis);
13968
+ if (Math.abs((child.height ?? 0) - newH) > 0.5) {
13969
+ child._set("height", newH);
13970
+ child._set("scaleY", 1 / sAxis);
13971
+ child.setCoords();
13972
+ child.dirty = true;
14151
13973
  }
14152
- const newH = Math.max(1, Number(child.__asLiveOrigH) * sAxis);
14153
- child._set("height", newH);
14154
- }
14155
- if (isXSide) child._set("scaleX", childCounterScale);
14156
- else child._set("scaleY", childCounterScale);
14157
- child.setCoords();
14158
- child.dirty = true;
14159
- if (shouldDebugGroupImageResize) {
14160
- logGroupImageResizeDebug("live-image-child-resized", {
14161
- time: Math.round(performance.now()),
14162
- corner,
14163
- sAxis,
14164
- childCounterScale,
14165
- liveOrigW: child.__asLiveOrigW,
14166
- liveOrigH: child.__asLiveOrigH,
14167
- before: beforeImageChildResize,
14168
- after: summarizeFabricObjectForResizeDebug(child)
14169
- });
14170
13974
  }
14171
- didReflowTextChild = true;
14172
13975
  continue;
14173
13976
  }
14174
13977
  if (!(child instanceof fabric.Textbox)) continue;
14175
- projectRotatedTextPosition(child);
14176
13978
  if (isXSide) {
14177
13979
  if (child.__asLiveOrigW == null) {
14178
13980
  child.__asLiveOrigW = (child.width ?? 0) * (child.scaleX ?? 1);
@@ -14181,7 +13983,7 @@ const PageCanvas = forwardRef(
14181
13983
  const newW = Math.max(20, origW * sAxis);
14182
13984
  if (Math.abs((child.width ?? 0) - newW) > 0.5) {
14183
13985
  child._set("width", newW);
14184
- child._set("scaleX", childCounterScale);
13986
+ child._set("scaleX", 1 / sAxis);
14185
13987
  try {
14186
13988
  child.initDimensions();
14187
13989
  } catch {
@@ -14194,14 +13996,10 @@ const PageCanvas = forwardRef(
14194
13996
  if (child.__asLiveOrigH == null) {
14195
13997
  child.__asLiveOrigH = (child.height ?? 0) * (child.scaleY ?? 1);
14196
13998
  }
14197
- if (child.__asLiveOrigMinH == null) {
14198
- const m = Number(child.minBoxHeight);
14199
- if (Number.isFinite(m) && m > 0) child.__asLiveOrigMinH = m;
14200
- }
14201
13999
  const origH = child.__asLiveOrigH;
14202
14000
  const newH = Math.max(20, origH * sAxis);
14203
14001
  child.minBoxHeight = newH;
14204
- child._set("scaleY", childCounterScale);
14002
+ child._set("scaleY", 1 / sAxis);
14205
14003
  try {
14206
14004
  child.initDimensions();
14207
14005
  } catch {
@@ -14211,7 +14009,7 @@ const PageCanvas = forwardRef(
14211
14009
  didReflowTextChild = true;
14212
14010
  }
14213
14011
  }
14214
- if (isXSide && !shouldPinNonTextChildren && ((_g = groupShiftReflowSnapshotRef.current) == null ? void 0 : _g.selection) === obj) {
14012
+ if (isXSide && ((_e = groupShiftReflowSnapshotRef.current) == null ? void 0 : _e.selection) === obj) {
14215
14013
  const snap = groupShiftReflowSnapshotRef.current;
14216
14014
  const anchorEntry = snap.children[0];
14217
14015
  const anchorTopLive = anchorEntry.obj.top ?? 0;
@@ -14244,26 +14042,10 @@ const PageCanvas = forwardRef(
14244
14042
  if (cornersBefore) {
14245
14043
  fixedMidBefore = corner === "ml" ? { x: (cornersBefore.tr.x + cornersBefore.br.x) / 2, y: (cornersBefore.tr.y + cornersBefore.br.y) / 2 } : { x: (cornersBefore.tl.x + cornersBefore.bl.x) / 2, y: (cornersBefore.tl.y + cornersBefore.bl.y) / 2 };
14246
14044
  }
14247
- const nonTextPinsBeforeLayout = shouldPinNonTextChildren ? new Map(obj.getObjects().map((child) => [child, {
14248
- left: child.left ?? 0,
14249
- top: child.top ?? 0,
14250
- worldCenter: child instanceof fabric.Textbox ? void 0 : child.getCenterPoint()
14251
- }])) : void 0;
14252
14045
  try {
14253
14046
  obj.triggerLayout();
14254
14047
  } catch {
14255
14048
  }
14256
- restoreNonTextChildren(nonTextPinsBeforeLayout);
14257
- restoredNonTextAfterLayout = !!nonTextPinsBeforeLayout;
14258
- if (shouldDebugGroupImageResize) {
14259
- logGroupImageResizeDebug("after-trigger-layout", {
14260
- time: Math.round(performance.now()),
14261
- corner,
14262
- selection: summarizeFabricObjectForResizeDebug(obj),
14263
- nonTextPinsBeforeLayout,
14264
- children: obj.getObjects().map((child) => summarizeFabricObjectForResizeDebug(child))
14265
- });
14266
- }
14267
14049
  obj._set("width", asW0);
14268
14050
  obj._set("scaleX", asSx0);
14269
14051
  obj._set("scaleY", asSy0);
@@ -14289,19 +14071,9 @@ const PageCanvas = forwardRef(
14289
14071
  obj._set("left", asLeft0);
14290
14072
  obj._set("top", asTop0);
14291
14073
  }
14292
- if (!restoredNonTextAfterLayout) restoreNonTextChildren();
14293
14074
  obj._set("width", asW0);
14294
14075
  obj._set("scaleX", asSx0);
14295
14076
  obj._set("scaleY", asSy0);
14296
- if (hasRotatedChild) {
14297
- if (isXSide) {
14298
- obj._set("width", asW0 * sAxis);
14299
- obj._set("scaleX", 1);
14300
- } else {
14301
- obj._set("height", asH0 * sAxis);
14302
- obj._set("scaleY", 1);
14303
- }
14304
- }
14305
14077
  obj.setCoords();
14306
14078
  obj.dirty = true;
14307
14079
  }
@@ -14393,7 +14165,7 @@ const PageCanvas = forwardRef(
14393
14165
  setGuides(gridGuidesForScale.length ? [...scaleGuides, ...gridGuidesForScale] : scaleGuides);
14394
14166
  if (drilledGroupIdRef.current) {
14395
14167
  try {
14396
- (_h = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _h.call(fabricCanvas);
14168
+ (_f = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _f.call(fabricCanvas);
14397
14169
  } catch {
14398
14170
  }
14399
14171
  }
@@ -14484,36 +14256,44 @@ const PageCanvas = forwardRef(
14484
14256
  }
14485
14257
  });
14486
14258
  fabricCanvas.on("object:rotating", (e) => {
14487
- var _a2, _b2;
14488
- prepareGroupSelectionTransformStart(e.target);
14489
14259
  markSimpleTransform(e);
14490
14260
  didTransformRef.current = true;
14491
14261
  const tr = e.target;
14492
14262
  try {
14493
- const children = tr instanceof fabric.Group || tr instanceof fabric.ActiveSelection ? tr.getObjects() : [];
14494
- logGroupImageResizeDebug("rotating-entry", {
14495
- time: Math.round(performance.now()),
14496
- angle: tr == null ? void 0 : tr.angle,
14497
- targetType: tr == null ? void 0 : tr.type,
14498
- targetCtor: (_a2 = tr == null ? void 0 : tr.constructor) == null ? void 0 : _a2.name,
14499
- isActiveSelection: tr instanceof fabric.ActiveSelection,
14500
- isGroup: tr instanceof fabric.Group,
14501
- isCropGroup: !!(tr && (tr.__cropGroup || ((_b2 = tr._ct) == null ? void 0 : _b2.isCropGroup))),
14502
- childCount: children.length,
14503
- childTypes: children.map((c) => c == null ? void 0 : c.type),
14504
- hasImageChild: children.some((c) => isGroupResizeImageLikeObject(c)),
14505
- target: tr ? summarizeFabricObjectForResizeDebug(tr) : null,
14506
- children: children.map((c) => {
14507
- var _a3;
14508
- return {
14509
- type: c == null ? void 0 : c.type,
14510
- ctor: (_a3 = c == null ? void 0 : c.constructor) == null ? void 0 : _a3.name,
14511
- summary: summarizeFabricObjectForResizeDebug(c)
14512
- };
14513
- })
14514
- });
14515
- } catch (err) {
14516
- console.warn("[Pixldocs][group-image-side-resize] rotating-entry log failed", err);
14263
+ const t = tr;
14264
+ if (t) {
14265
+ const childSummary = (t._objects ?? []).map((c) => ({
14266
+ id: getObjectId(c),
14267
+ type: c.type,
14268
+ left: c.left,
14269
+ top: c.top,
14270
+ angle: c.angle,
14271
+ scaleX: c.scaleX,
14272
+ scaleY: c.scaleY,
14273
+ originX: c.originX,
14274
+ originY: c.originY,
14275
+ width: c.width,
14276
+ height: c.height
14277
+ }));
14278
+ console.info("[Pixldocs][rot-group-image-drift] rotating", {
14279
+ targetType: t.type,
14280
+ isAS: t instanceof fabric.ActiveSelection,
14281
+ isGroup: t instanceof fabric.Group,
14282
+ targetId: getObjectId(t),
14283
+ left: t.left,
14284
+ top: t.top,
14285
+ angle: t.angle,
14286
+ scaleX: t.scaleX,
14287
+ scaleY: t.scaleY,
14288
+ width: t.width,
14289
+ height: t.height,
14290
+ originX: t.originX,
14291
+ originY: t.originY,
14292
+ childCount: (t._objects ?? []).length,
14293
+ children: childSummary
14294
+ });
14295
+ }
14296
+ } catch {
14517
14297
  }
14518
14298
  try {
14519
14299
  const getCursor = fabricCanvas.__pixldocsGetRotateCursor;
@@ -14547,6 +14327,42 @@ const PageCanvas = forwardRef(
14547
14327
  prepareGroupSelectionTransformStart(e.target);
14548
14328
  markTransforming(e.target);
14549
14329
  didTransformRef.current = true;
14330
+ try {
14331
+ const t = e.target;
14332
+ if (t && (t.angle ?? 0) !== 0) {
14333
+ const childSummary = (t._objects ?? []).map((c) => ({
14334
+ id: getObjectId(c),
14335
+ type: c.type,
14336
+ left: c.left,
14337
+ top: c.top,
14338
+ angle: c.angle,
14339
+ scaleX: c.scaleX,
14340
+ scaleY: c.scaleY,
14341
+ originX: c.originX,
14342
+ originY: c.originY,
14343
+ width: c.width,
14344
+ height: c.height
14345
+ }));
14346
+ console.info("[Pixldocs][rot-group-image-drift] moving", {
14347
+ targetType: t.type,
14348
+ isAS: t instanceof fabric.ActiveSelection,
14349
+ isGroup: t instanceof fabric.Group,
14350
+ targetId: getObjectId(t),
14351
+ left: t.left,
14352
+ top: t.top,
14353
+ angle: t.angle,
14354
+ scaleX: t.scaleX,
14355
+ scaleY: t.scaleY,
14356
+ width: t.width,
14357
+ height: t.height,
14358
+ originX: t.originX,
14359
+ originY: t.originY,
14360
+ childCount: (t._objects ?? []).length,
14361
+ children: childSummary
14362
+ });
14363
+ }
14364
+ } catch {
14365
+ }
14550
14366
  const activeDuringMove = fabricCanvas.getActiveObject();
14551
14367
  const movingLogicalGroupId = activeDuringMove instanceof fabric.ActiveSelection ? activeDuringMove.__pixldocsGroupSelection : void 0;
14552
14368
  const pendingMoveDrill = pendingGroupDrillInRef.current;
@@ -14557,7 +14373,7 @@ const PageCanvas = forwardRef(
14557
14373
  setDrilledGroupBounds(null);
14558
14374
  drilledGroupIdRef.current = null;
14559
14375
  if (activeDuringMove instanceof fabric.ActiveSelection && groupIdToKeep) {
14560
- preserveLogicalGroupTagDuringMove(activeDuringMove, groupIdToKeep);
14376
+ restoreGroupSelectionVisualState(activeDuringMove, groupIdToKeep);
14561
14377
  }
14562
14378
  }
14563
14379
  if (e.target) e.target.__pixldocsDragMoved = true;
@@ -14610,7 +14426,7 @@ const PageCanvas = forwardRef(
14610
14426
  });
14611
14427
  let cropGroupSaveTimer = null;
14612
14428
  fabricCanvas.on("object:modified", (e) => {
14613
- var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k;
14429
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i;
14614
14430
  try {
14615
14431
  dragStarted = false;
14616
14432
  setGuides([]);
@@ -14619,43 +14435,18 @@ const PageCanvas = forwardRef(
14619
14435
  groupResizeActiveSnapRef.current = null;
14620
14436
  onDragEnd == null ? void 0 : onDragEnd();
14621
14437
  try {
14622
- const mt = e.target;
14623
- const children = mt instanceof fabric.Group || mt instanceof fabric.ActiveSelection ? mt.getObjects() : [];
14624
- logGroupImageResizeDebug("modified-entry", {
14625
- time: Math.round(performance.now()),
14626
- didTransform: didTransformRef.current,
14627
- targetType: mt == null ? void 0 : mt.type,
14628
- targetCtor: (_a2 = mt == null ? void 0 : mt.constructor) == null ? void 0 : _a2.name,
14629
- isActiveSelection: mt instanceof fabric.ActiveSelection,
14630
- isGroup: mt instanceof fabric.Group,
14631
- angle: mt == null ? void 0 : mt.angle,
14632
- childCount: children.length,
14633
- childTypes: children.map((c) => c == null ? void 0 : c.type),
14634
- hasImageChild: children.some((c) => isGroupResizeImageLikeObject(c)),
14635
- target: mt ? summarizeFabricObjectForResizeDebug(mt) : null,
14636
- children: children.map((c) => {
14637
- var _a3;
14638
- return {
14639
- type: c == null ? void 0 : c.type,
14640
- ctor: (_a3 = c == null ? void 0 : c.constructor) == null ? void 0 : _a3.name,
14641
- summary: summarizeFabricObjectForResizeDebug(c)
14642
- };
14643
- })
14644
- });
14645
- } catch (err) {
14646
- console.warn("[Pixldocs][group-image-side-resize] modified-entry log failed", err);
14647
- }
14648
- const modifiedTarget = e.target;
14649
- if (modifiedTarget instanceof fabric.ActiveSelection && modifiedTarget.getObjects().length === 0) {
14650
- didTransformRef.current = false;
14651
- groupSelectionTransformStartRef.current = null;
14652
- activeSelectionMoveStartRef.current = null;
14653
- activeSelectionResizeHandleRef.current = null;
14654
- unlockEditsSoon();
14655
- return;
14438
+ const t = e.target;
14439
+ if (t instanceof fabric.ActiveSelection) {
14440
+ for (const child of t.getObjects()) {
14441
+ delete child.__asLiveOrigW;
14442
+ delete child.__asLiveOrigH;
14443
+ }
14444
+ }
14445
+ } catch {
14656
14446
  }
14657
14447
  groupShiftReflowSnapshotRef.current = null;
14658
14448
  lockEdits();
14449
+ const modifiedTarget = e.target;
14659
14450
  const modifiedTargetId = modifiedTarget ? getObjectId(modifiedTarget) : null;
14660
14451
  const modifiedTargetElement = modifiedTargetId ? elementsRef.current.find((el) => el.id === modifiedTargetId) : null;
14661
14452
  if (modifiedTarget && (modifiedTargetElement == null ? void 0 : modifiedTargetElement.type) === "shape") {
@@ -14680,7 +14471,7 @@ const PageCanvas = forwardRef(
14680
14471
  const active = fabricCanvas.getActiveObject();
14681
14472
  const activeId = active ? getObjectId(active) : null;
14682
14473
  if (active && activeId && activeId !== "__background__" && !(active instanceof fabric.Group)) {
14683
- const pageChildrenForParent = ((_b2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _b2.children) ?? [];
14474
+ const pageChildrenForParent = ((_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
14684
14475
  const parentGroup = findParentGroup(pageChildrenForParent, activeId);
14685
14476
  if (parentGroup && isGroup(parentGroup) && parentGroup.backgroundColor) {
14686
14477
  let fabricSectionGroup = active.group && active.group instanceof fabric.Group ? active.group : null;
@@ -14762,7 +14553,7 @@ const PageCanvas = forwardRef(
14762
14553
  useEditorStore.getState().reflowStackGroupInPage(pageId, groupId);
14763
14554
  }
14764
14555
  const stateAfter = useEditorStore.getState();
14765
- const pageAfter = ((_c = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
14556
+ const pageAfter = ((_b2 = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _b2.children) ?? [];
14766
14557
  const groupNodeAfter = findNodeById(pageAfter, groupId);
14767
14558
  if (groupNodeAfter) {
14768
14559
  const abs = getAbsoluteBounds(groupNodeAfter, pageAfter);
@@ -14798,9 +14589,8 @@ const PageCanvas = forwardRef(
14798
14589
  const stateCrop = useEditorStore.getState();
14799
14590
  const pageCrop = stateCrop.canvas.pages.find((p) => p.id === pageId);
14800
14591
  const pageChildrenCrop = (pageCrop == null ? void 0 : pageCrop.children) ?? [];
14801
- const angleRad = (active.angle ?? 0) * Math.PI / 180;
14802
- const absLeft = (active.left ?? 0) - ct.frameW / 2 * Math.cos(angleRad) + ct.frameH / 2 * Math.sin(angleRad);
14803
- const absTop = (active.top ?? 0) - ct.frameW / 2 * Math.sin(angleRad) - ct.frameH / 2 * Math.cos(angleRad);
14592
+ const absLeft = (active.left ?? 0) - ct.frameW / 2;
14593
+ const absTop = (active.top ?? 0) - ct.frameH / 2;
14804
14594
  const storePosCrop = absoluteToStorePosition(absLeft, absTop, objId, pageChildrenCrop);
14805
14595
  updateElement2(objId, {
14806
14596
  width: ct.frameW,
@@ -14825,7 +14615,7 @@ const PageCanvas = forwardRef(
14825
14615
  }
14826
14616
  if (active && active instanceof fabric.Group && active.__docuforgeSectionGroup && getObjectId(active)) {
14827
14617
  const groupId = getObjectId(active);
14828
- const pageChildrenSec = ((_d = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _d.children) ?? [];
14618
+ const pageChildrenSec = ((_c = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
14829
14619
  const modifiedTarget2 = e == null ? void 0 : e.target;
14830
14620
  const resizeScaleTarget = lastResizeScaleTargetRef.current;
14831
14621
  lastResizeScaleTargetRef.current = null;
@@ -14856,7 +14646,7 @@ const PageCanvas = forwardRef(
14856
14646
  const node = findNodeById(pageChildrenSec, groupId);
14857
14647
  if (isChildModified && node && !groupMoved) {
14858
14648
  const stateAfter = useEditorStore.getState();
14859
- const pageAfter = ((_e = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _e.children) ?? [];
14649
+ const pageAfter = ((_d = stateAfter.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _d.children) ?? [];
14860
14650
  const groupNodeAfter = findNodeById(pageAfter, groupId);
14861
14651
  if (groupNodeAfter) {
14862
14652
  const abs = getAbsoluteBounds(groupNodeAfter, pageAfter);
@@ -14872,7 +14662,7 @@ const PageCanvas = forwardRef(
14872
14662
  }
14873
14663
  if (active && active instanceof fabric.Group && !(active instanceof fabric.ActiveSelection) && getObjectId(active)) {
14874
14664
  const groupId = getObjectId(active);
14875
- const pageChildren3 = ((_f = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _f.children) ?? [];
14665
+ const pageChildren3 = ((_e = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _e.children) ?? [];
14876
14666
  const w = (active.width ?? 0) * (active.scaleX ?? 1);
14877
14667
  const h = (active.height ?? 0) * (active.scaleY ?? 1);
14878
14668
  const centerX = active.left ?? 0;
@@ -14894,7 +14684,7 @@ const PageCanvas = forwardRef(
14894
14684
  }
14895
14685
  const activeObj = fabricCanvas.getActiveObject();
14896
14686
  let activeObjects = fabricCanvas.getActiveObjects();
14897
- const activeSelectionMoveStart = activeObj instanceof fabric.ActiveSelection && ((_g = activeSelectionMoveStartRef.current) == null ? void 0 : _g.selection) === activeObj ? activeSelectionMoveStartRef.current : null;
14687
+ const activeSelectionMoveStart = activeObj instanceof fabric.ActiveSelection && ((_f = activeSelectionMoveStartRef.current) == null ? void 0 : _f.selection) === activeObj ? activeSelectionMoveStartRef.current : null;
14898
14688
  const activeSelectionDelta = activeObj instanceof fabric.ActiveSelection && activeSelectionMoveStart ? (() => {
14899
14689
  const rect = activeObj.getBoundingRect();
14900
14690
  return {
@@ -14911,18 +14701,6 @@ const PageCanvas = forwardRef(
14911
14701
  const isActiveSelection = activeObj instanceof fabric.ActiveSelection || activeObjects.length > 1;
14912
14702
  const activeSelectionResizeHandle = isActiveSelection ? activeSelectionResizeHandleRef.current : null;
14913
14703
  const debugGroupTextCornerResize = activeObj instanceof fabric.ActiveSelection && isCornerResizeHandle(activeSelectionResizeHandle) && activeObjects.some((candidate) => candidate instanceof fabric.Textbox);
14914
- const debugGroupImageSideResize = activeObj instanceof fabric.ActiveSelection && (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") && activeObjects.some((candidate) => isGroupResizeImageLikeObject(candidate));
14915
- if (debugGroupImageSideResize) {
14916
- logGroupImageResizeDebug("modified-start", {
14917
- time: Math.round(performance.now()),
14918
- handle: activeSelectionResizeHandle,
14919
- target: summarizeFabricObjectForResizeDebug(modifiedTarget),
14920
- selection: summarizeFabricObjectForResizeDebug(activeObj),
14921
- activeObjectIds: activeObjects.map((candidate) => getObjectId(candidate)),
14922
- selectedStoreIds: useEditorStore.getState().canvas.selectedIds,
14923
- members: activeObjects.map((candidate) => summarizeFabricObjectForResizeDebug(candidate))
14924
- });
14925
- }
14926
14704
  if (debugGroupTextCornerResize) {
14927
14705
  logGroupTextResizeDebug("modified-start", {
14928
14706
  time: Math.round(performance.now()),
@@ -14955,14 +14733,7 @@ const PageCanvas = forwardRef(
14955
14733
  const node = findNodeById(pageChildren2, id);
14956
14734
  return !!(node && isGroup(node));
14957
14735
  });
14958
- const activeSelectionHadTransform = activeObj instanceof fabric.ActiveSelection && (Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01 || (() => {
14959
- var _a3;
14960
- const normAngle = (angle) => (angle % 360 + 360) % 360;
14961
- const startAngle = ((_a3 = groupSelectionTransformStartRef.current) == null ? void 0 : _a3.selection) === activeObj ? groupSelectionTransformStartRef.current.selectionAngle : 0;
14962
- const currentAngle = normAngle(activeObj.angle ?? 0);
14963
- const diff = Math.abs(currentAngle - normAngle(startAngle));
14964
- return Math.min(diff, 360 - diff) > 1;
14965
- })());
14736
+ const activeSelectionHadTransform = activeObj instanceof fabric.ActiveSelection && (Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01 || Math.abs((activeObj.angle ?? 0) % 360) > 0.01);
14966
14737
  if (!anyCropGroup && activeSelectionDelta && !activeSelectionHadTransform && selectedLogicalGroupIds.length > 0) {
14967
14738
  const selectedStoreIds = useEditorStore.getState().canvas.selectedIds ?? [];
14968
14739
  const groupMemberIds = /* @__PURE__ */ new Set();
@@ -15003,13 +14774,7 @@ const PageCanvas = forwardRef(
15003
14774
  return;
15004
14775
  }
15005
14776
  }
15006
- const isActiveSelectionSideResize = isActiveSelection && (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb");
15007
- const normalizeAngle = (angle) => (angle % 360 + 360) % 360;
15008
- const shortestAngleDelta = (a, b) => {
15009
- const diff = Math.abs(normalizeAngle(a) - normalizeAngle(b));
15010
- return Math.min(diff, 360 - diff);
15011
- };
15012
- if (selectedElementIds.length > 0) {
14777
+ if (selectedElementIds.length > 0 && !anyCropGroup) {
15013
14778
  const firstObj = activeObjects[0];
15014
14779
  const firstId = getObjectId(firstObj);
15015
14780
  const parentGroups = selectedElementIds.map((id) => findParentGroup(pageChildren2, id)).filter((g) => g !== null);
@@ -15032,9 +14797,9 @@ const PageCanvas = forwardRef(
15032
14797
  let movedGroupLeft = groupAbs.left;
15033
14798
  let movedGroupTop = groupAbs.top;
15034
14799
  if (activeObj instanceof fabric.ActiveSelection && (transformStart == null ? void 0 : transformStart.groupId) === groupToMove.id) {
15035
- const selectionCenter = activeObj.getCenterPoint();
15036
- movedGroupLeft = transformStart.groupLeft + (selectionCenter.x - transformStart.selectionCenterX);
15037
- movedGroupTop = transformStart.groupTop + (selectionCenter.y - transformStart.selectionCenterY);
14800
+ const selectionRect = activeObj.getBoundingRect();
14801
+ movedGroupLeft = transformStart.groupLeft + (selectionRect.left - transformStart.selectionLeft);
14802
+ movedGroupTop = transformStart.groupTop + (selectionRect.top - transformStart.selectionTop);
15038
14803
  } else if (activeObj instanceof fabric.ActiveSelection && firstId && firstObj) {
15039
14804
  const firstNode = findNodeById(pageChildren2, firstId);
15040
14805
  if (firstNode) {
@@ -15070,58 +14835,19 @@ const PageCanvas = forwardRef(
15070
14835
  }
15071
14836
  const deltaX = movedGroupLeft - groupAbs.left;
15072
14837
  const deltaY = movedGroupTop - groupAbs.top;
15073
- const hadResizeHandle = isActiveSelection && !!activeSelectionResizeHandle;
15074
- const hadScale = isActiveSelection && activeObj && (hadResizeHandle || Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01);
15075
- const startSelAngle = normalizeAngle((transformStart == null ? void 0 : transformStart.selectionAngle) ?? 0);
15076
- const currentSelAngle = isActiveSelection && activeObj ? normalizeAngle(activeObj.angle ?? 0) : 0;
15077
- const storedGroupAngle = normalizeAngle(Number(groupToMove.angle ?? 0));
15078
- const effectiveStartAngle = transformStart ? startSelAngle : storedGroupAngle;
15079
- const angleDelta = shortestAngleDelta(currentSelAngle, effectiveStartAngle);
15080
- const hadRotation = isActiveSelection && activeObj && angleDelta > 1;
15081
- if (activeGroupSelectionId === groupToMove.id && hadRotation && !hadScale && !activeSelectionResizeHandle && activeObj instanceof fabric.ActiveSelection) {
15082
- const { updateNode: updateNodeStore, commitHistory: commitHistoryStore, getCurrentElements } = useEditorStore.getState();
15083
- const center = activeObj.getCenterPoint();
15084
- const baseCenterX = (transformStart == null ? void 0 : transformStart.selectionCenterX) ?? groupAbs.left + groupAbs.width / 2;
15085
- const baseCenterY = (transformStart == null ? void 0 : transformStart.selectionCenterY) ?? groupAbs.top + groupAbs.height / 2;
15086
- const nextAbsLeft = groupAbs.left + (center.x - baseCenterX);
15087
- const nextAbsTop = groupAbs.top + (center.y - baseCenterY);
15088
- const storePos = absoluteToStorePosition(nextAbsLeft, nextAbsTop, groupToMove.id, pageChildren2);
15089
- updateNodeStore(groupToMove.id, {
15090
- left: storePos.left,
15091
- top: storePos.top,
15092
- angle: currentSelAngle
15093
- }, { recordHistory: false, skipLayoutRecalc: true });
15094
- commitHistoryStore();
15095
- restoreGroupSelectionVisualState(activeObj, groupToMove.id);
15096
- fabricCanvas.setActiveObject(activeObj);
15097
- activeObj.setCoords();
15098
- selectElements([groupToMove.id], false, false);
15099
- fabricCanvas.requestRenderAll();
15100
- elementsRef.current = getCurrentElements();
15101
- const restoreSnapshot = {
15102
- memberIds: activeObj.getObjects().map((obj) => getObjectId(obj)).filter((id) => !!id && id !== "__background__"),
15103
- groupSelectionId: groupToMove.id,
15104
- expiresAt: Date.now() + 1200
15105
- };
15106
- recentGroupSelectionRestoreRef.current = restoreSnapshot;
15107
- activeObj.getObjects().forEach((obj) => {
15108
- const objId = getObjectId(obj);
15109
- if (objId && objId !== "__background__") {
15110
- justModifiedIdsRef.current.add(objId);
15111
- modifiedIdsThisRound.add(objId);
15112
- }
15113
- });
15114
- setTimeout(() => modifiedIdsThisRound.forEach((id) => justModifiedIdsRef.current.delete(id)), 150);
15115
- groupSelectionTransformStartRef.current = null;
15116
- activeSelectionMoveStartRef.current = null;
15117
- activeSelectionResizeHandleRef.current = null;
15118
- unlockEditsSoon();
15119
- return;
15120
- }
15121
- if (!isActiveSelectionSideResize && !hadScale && !hadRotation && (Math.abs(deltaX) > 0.1 || Math.abs(deltaY) > 0.1)) {
14838
+ const hadScale = isActiveSelection && activeObj && (Math.abs((activeObj.scaleX ?? 1) - 1) > 0.01 || Math.abs((activeObj.scaleY ?? 1) - 1) > 0.01);
14839
+ const startSelAngle = (((transformStart == null ? void 0 : transformStart.selectionAngle) ?? 0) % 360 + 360) % 360;
14840
+ const currentSelAngle = isActiveSelection && activeObj ? ((activeObj.angle ?? 0) % 360 + 360) % 360 : 0;
14841
+ const angleDelta = Math.min(
14842
+ Math.abs(currentSelAngle - startSelAngle),
14843
+ 360 - Math.abs(currentSelAngle - startSelAngle)
14844
+ );
14845
+ const hadRotation = isActiveSelection && activeObj && angleDelta > 0.01;
14846
+ if (!hadScale && !hadRotation && (Math.abs(deltaX) > 0.1 || Math.abs(deltaY) > 0.1)) {
15122
14847
  const { updateNode: updateNodeStore, commitHistory: commitHistoryStore, getCurrentElements } = useEditorStore.getState();
15123
- const storePos = absoluteToStorePosition(movedGroupLeft, movedGroupTop, groupToMove.id, pageChildren2);
15124
- updateNodeStore(groupToMove.id, { left: storePos.left, top: storePos.top }, { recordHistory: false, skipLayoutRecalc: true });
14848
+ const newLeft = (groupToMove.left ?? 0) + deltaX;
14849
+ const newTop = (groupToMove.top ?? 0) + deltaY;
14850
+ updateNodeStore(groupToMove.id, { left: newLeft, top: newTop }, { recordHistory: false, skipLayoutRecalc: true });
15125
14851
  commitHistoryStore();
15126
14852
  pendingGroupDrillInRef.current = null;
15127
14853
  fabricCanvas.__activeEditingGroupId = null;
@@ -15146,8 +14872,6 @@ const PageCanvas = forwardRef(
15146
14872
  }
15147
14873
  setTimeout(() => modifiedIdsThisRound.forEach((id) => justModifiedIdsRef.current.delete(id)), 150);
15148
14874
  groupSelectionTransformStartRef.current = null;
15149
- activeSelectionMoveStartRef.current = null;
15150
- activeSelectionResizeHandleRef.current = null;
15151
14875
  const restoreSnapshot = {
15152
14876
  memberIds: targetObjects.map((obj) => getObjectId(obj)).filter((id) => !!id && id !== "__background__"),
15153
14877
  groupSelectionId,
@@ -15161,38 +14885,6 @@ const PageCanvas = forwardRef(
15161
14885
  }
15162
14886
  }
15163
14887
  const pendingCropGroupFrameBakes = [];
15164
- const logicalGroupSelectionId = activeObj instanceof fabric.ActiveSelection ? activeObj.__pixldocsGroupSelection : void 0;
15165
- const isLogicalGroupAS = !!logicalGroupSelectionId && !(activeObj == null ? void 0 : activeObj.__cropGroup) && !(activeObj == null ? void 0 : activeObj.__docuforgeSectionGroup);
15166
- const logicalGroupNodeForBake = logicalGroupSelectionId ? findNodeById(pageChildren2, logicalGroupSelectionId) : null;
15167
- const asAngleForBake = isLogicalGroupAS && activeObj ? normalizeAngle(Number(activeObj.angle ?? 0)) : 0;
15168
- const logicalGroupFinalFrame = (() => {
15169
- var _a3;
15170
- if (!isLogicalGroupAS || !logicalGroupSelectionId || !(activeObj instanceof fabric.ActiveSelection)) return null;
15171
- const baseline = ((_a3 = groupSelectionTransformStartRef.current) == null ? void 0 : _a3.groupId) === logicalGroupSelectionId ? groupSelectionTransformStartRef.current : null;
15172
- const localWidth = Math.max(1, (activeObj.width ?? (baseline == null ? void 0 : baseline.groupWidth) ?? 1) * Math.abs(activeObj.scaleX ?? 1));
15173
- const localHeight = Math.max(1, (activeObj.height ?? (baseline == null ? void 0 : baseline.groupHeight) ?? 1) * Math.abs(activeObj.scaleY ?? 1));
15174
- const center = activeObj.getCenterPoint();
15175
- const topLeft = centerToRotatedTopLeft(center.x, center.y, localWidth, localHeight, asAngleForBake);
15176
- return {
15177
- groupId: logicalGroupSelectionId,
15178
- left: topLeft.left,
15179
- top: topLeft.top,
15180
- width: localWidth,
15181
- height: localHeight,
15182
- centerX: center.x,
15183
- centerY: center.y,
15184
- angle: asAngleForBake,
15185
- matrix: fabric.util.composeMatrix({
15186
- translateX: center.x,
15187
- translateY: center.y,
15188
- angle: asAngleForBake,
15189
- scaleX: 1,
15190
- scaleY: 1,
15191
- skewX: 0,
15192
- skewY: 0
15193
- })
15194
- };
15195
- })();
15196
14888
  for (const obj of activeObjects) {
15197
14889
  const objId = getObjectId(obj);
15198
14890
  if (!objId || objId === "__background__") continue;
@@ -15238,15 +14930,16 @@ const PageCanvas = forwardRef(
15238
14930
  modifiedIdsThisRound.add(objId);
15239
14931
  let absoluteLeft;
15240
14932
  let absoluteTop;
15241
- const initialTopLeft = centerToRotatedTopLeft(
15242
- decomposed.translateX ?? (obj.left ?? 0),
15243
- decomposed.translateY ?? (obj.top ?? 0),
15244
- intrinsicWidth * Math.abs(decomposed.scaleX || 1),
15245
- intrinsicHeight * Math.abs(decomposed.scaleY || 1),
15246
- decomposed.angle ?? 0
15247
- );
15248
- absoluteLeft = initialTopLeft.left;
15249
- absoluteTop = initialTopLeft.top;
14933
+ if (isActiveSelection && activeObj) {
14934
+ const selectionMatrix = activeObj.calcTransformMatrix();
14935
+ const relativePoint = { x: obj.left ?? 0, y: obj.top ?? 0 };
14936
+ const absolutePoint = fabric.util.transformPoint(relativePoint, selectionMatrix);
14937
+ absoluteLeft = absolutePoint.x;
14938
+ absoluteTop = absolutePoint.y;
14939
+ } else {
14940
+ absoluteLeft = obj.left ?? 0;
14941
+ absoluteTop = obj.top ?? 0;
14942
+ }
15250
14943
  if (obj instanceof fabric.Group && obj.__cropGroup) {
15251
14944
  const ct = obj.__cropData;
15252
14945
  if (isActiveSelection && activeObj instanceof fabric.ActiveSelection) {
@@ -15256,22 +14949,14 @@ const PageCanvas = forwardRef(
15256
14949
  } else {
15257
14950
  const w = ((ct == null ? void 0 : ct.frameW) ?? obj.width ?? 0) * Math.abs(obj.scaleX ?? 1);
15258
14951
  const h = ((ct == null ? void 0 : ct.frameH) ?? obj.height ?? 0) * Math.abs(obj.scaleY ?? 1);
15259
- const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
15260
- absoluteLeft = (decomposed.translateX ?? absoluteLeft ?? 0) - w / 2 * Math.cos(angleRad) + h / 2 * Math.sin(angleRad);
15261
- absoluteTop = (decomposed.translateY ?? absoluteTop ?? 0) - w / 2 * Math.sin(angleRad) - h / 2 * Math.cos(angleRad);
14952
+ absoluteLeft = (absoluteLeft ?? 0) - w / 2;
14953
+ absoluteTop = (absoluteTop ?? 0) - h / 2;
15262
14954
  }
15263
14955
  } else if (obj instanceof fabric.FabricImage && (obj.originX === "center" || obj.originY === "center")) {
15264
- if (isActiveSelection && activeObj instanceof fabric.ActiveSelection) {
15265
- const frameBounds = getObjectFrameBoundsInSelection(activeObj, obj, obj.width ?? 0, obj.height ?? 0);
15266
- absoluteLeft = frameBounds.left;
15267
- absoluteTop = frameBounds.top;
15268
- } else {
15269
- const w = (obj.width ?? 0) * (obj.scaleX ?? 1);
15270
- const h = (obj.height ?? 0) * (obj.scaleY ?? 1);
15271
- const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
15272
- absoluteLeft = (decomposed.translateX ?? absoluteLeft ?? 0) - w / 2 * Math.cos(angleRad) + h / 2 * Math.sin(angleRad);
15273
- absoluteTop = (decomposed.translateY ?? absoluteTop ?? 0) - w / 2 * Math.sin(angleRad) - h / 2 * Math.cos(angleRad);
15274
- }
14956
+ const w = (obj.width ?? 0) * (obj.scaleX ?? 1);
14957
+ const h = (obj.height ?? 0) * (obj.scaleY ?? 1);
14958
+ absoluteLeft = (absoluteLeft ?? 0) - w / 2;
14959
+ absoluteTop = (absoluteTop ?? 0) - h / 2;
15275
14960
  }
15276
14961
  const preserveCornerGeometry = (sourceElement == null ? void 0 : sourceElement.type) === "shape" && (sourceElement.shapeType === "circle" || sourceElement.shapeType === "rounded-rect" || sourceElement.shapeType === "triangle");
15277
14962
  let finalWidth = intrinsicWidth;
@@ -15279,10 +14964,6 @@ const PageCanvas = forwardRef(
15279
14964
  let finalScaleX = decomposed.scaleX;
15280
14965
  let finalScaleY = decomposed.scaleY;
15281
14966
  let finalAbsoluteMatrix = absoluteMatrix;
15282
- let finalAngle = decomposed.angle;
15283
- let finalSkewX = decomposed.skewX;
15284
- let finalSkewY = decomposed.skewY;
15285
- let finalAngleFromDecomposed = true;
15286
14967
  if (obj instanceof fabric.Group && obj.__cropGroup) {
15287
14968
  const ct = obj.__cropData;
15288
14969
  if (ct) {
@@ -15299,14 +14980,12 @@ const PageCanvas = forwardRef(
15299
14980
  absoluteLeft = frameBounds.left;
15300
14981
  absoluteTop = frameBounds.top;
15301
14982
  } else {
15302
- const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
15303
- absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2 * Math.cos(angleRad) + finalHeight / 2 * Math.sin(angleRad);
15304
- absoluteTop = (decomposed.translateY ?? absoluteTop) - finalWidth / 2 * Math.sin(angleRad) - finalHeight / 2 * Math.cos(angleRad);
14983
+ absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2;
14984
+ absoluteTop = (decomposed.translateY ?? absoluteTop) - finalHeight / 2;
15305
14985
  }
15306
- const finalCenter = rotatedTopLeftToCenter(absoluteLeft, absoluteTop, finalWidth, finalHeight, decomposed.angle ?? (obj.angle ?? 0));
15307
14986
  finalAbsoluteMatrix = fabric.util.composeMatrix({
15308
- translateX: finalCenter.x,
15309
- translateY: finalCenter.y,
14987
+ translateX: absoluteLeft + finalWidth / 2,
14988
+ translateY: absoluteTop + finalHeight / 2,
15310
14989
  angle: decomposed.angle ?? (obj.angle ?? 0),
15311
14990
  scaleX: 1,
15312
14991
  scaleY: 1,
@@ -15341,12 +15020,6 @@ const PageCanvas = forwardRef(
15341
15020
  finalHeight = bakedH;
15342
15021
  finalScaleX = 1;
15343
15022
  finalScaleY = 1;
15344
- if (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") {
15345
- finalAngle = (sourceElement == null ? void 0 : sourceElement.angle) ?? obj.angle ?? decomposed.angle;
15346
- finalSkewX = (sourceElement == null ? void 0 : sourceElement.skewX) ?? obj.skewX ?? 0;
15347
- finalSkewY = (sourceElement == null ? void 0 : sourceElement.skewY) ?? obj.skewY ?? 0;
15348
- if ((sourceElement == null ? void 0 : sourceElement.angle) !== void 0 || obj.angle !== void 0) finalAngleFromDecomposed = false;
15349
- }
15350
15023
  obj.set({ scaleX: 1, scaleY: 1 });
15351
15024
  const newSrc = renderSmartElementToDataUri(sourceElement.smartElementType, sourceElement.smartProps, bakedW, bakedH);
15352
15025
  if (newSrc) {
@@ -15362,7 +15035,6 @@ const PageCanvas = forwardRef(
15362
15035
  useEditorStore.getState().updateElement(objId, { src: newSrc }, { recordHistory: false, skipLayoutRecalc: true });
15363
15036
  }
15364
15037
  } else if (isActiveSelection && (Math.abs((decomposed.scaleX ?? 1) - 1) > 1e-3 || Math.abs((decomposed.scaleY ?? 1) - 1) > 1e-3)) {
15365
- const debugImageBeforeBake = debugGroupImageSideResize ? summarizeFabricObjectForResizeDebug(obj) : null;
15366
15038
  const sx = Math.abs(decomposed.scaleX || 1);
15367
15039
  const sy = Math.abs(decomposed.scaleY || 1);
15368
15040
  const handle = activeSelectionResizeHandle;
@@ -15396,9 +15068,22 @@ const PageCanvas = forwardRef(
15396
15068
  const localScaleX = 1 / sx;
15397
15069
  const localScaleY = 1 / sy;
15398
15070
  obj.set({ scaleX: localScaleX, scaleY: localScaleY });
15399
- const selectionMatrix = (_h = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _h.call(activeObj);
15071
+ const selectionMatrix = (_g = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _g.call(activeObj);
15400
15072
  const localCenter = selectionMatrix ? fabric.util.transformPoint(preBakeCenter, fabric.util.invertTransform(selectionMatrix)) : preBakeCenter;
15401
- obj.setPositionByOrigin(localCenter, "center", "center");
15073
+ const localWidth = bakedW * localScaleX;
15074
+ const localHeight = bakedH * localScaleY;
15075
+ const isCenterOrigin = obj.originX === "center" || obj.originY === "center";
15076
+ if (isCenterOrigin) {
15077
+ obj.set({
15078
+ left: localCenter.x,
15079
+ top: localCenter.y
15080
+ });
15081
+ } else {
15082
+ obj.set({
15083
+ left: localCenter.x - localWidth / 2,
15084
+ top: localCenter.y - localHeight / 2
15085
+ });
15086
+ }
15402
15087
  }
15403
15088
  obj.dirty = true;
15404
15089
  if (activeObj) activeObj.dirty = true;
@@ -15409,63 +15094,34 @@ const PageCanvas = forwardRef(
15409
15094
  finalHeight = bakedH;
15410
15095
  finalScaleX = 1;
15411
15096
  finalScaleY = 1;
15412
- if (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") {
15413
- finalAngle = (sourceElement == null ? void 0 : sourceElement.angle) ?? obj.angle ?? decomposed.angle;
15414
- finalSkewX = (sourceElement == null ? void 0 : sourceElement.skewX) ?? obj.skewX ?? 0;
15415
- finalSkewY = (sourceElement == null ? void 0 : sourceElement.skewY) ?? obj.skewY ?? 0;
15416
- if ((sourceElement == null ? void 0 : sourceElement.angle) !== void 0 || obj.angle !== void 0) finalAngleFromDecomposed = false;
15417
- }
15418
15097
  try {
15419
- const angleRad = (finalAngle ?? 0) * Math.PI / 180;
15098
+ const angleRad = (decomposed.angle ?? 0) * Math.PI / 180;
15420
15099
  const cos = Math.cos(angleRad);
15421
15100
  const sin = Math.sin(angleRad);
15422
15101
  const hw = finalWidth / 2;
15423
15102
  const hh = finalHeight / 2;
15424
- absoluteLeft = decomposed.translateX - hw * cos + hh * sin;
15425
- absoluteTop = decomposed.translateY - hw * sin - hh * cos;
15103
+ const corners = [
15104
+ { x: -hw, y: -hh },
15105
+ { x: hw, y: -hh },
15106
+ { x: hw, y: hh },
15107
+ { x: -hw, y: hh }
15108
+ ].map((p) => ({
15109
+ x: decomposed.translateX + p.x * cos - p.y * sin,
15110
+ y: decomposed.translateY + p.x * sin + p.y * cos
15111
+ }));
15112
+ absoluteLeft = Math.min(...corners.map((p) => p.x));
15113
+ absoluteTop = Math.min(...corners.map((p) => p.y));
15426
15114
  } catch {
15427
15115
  }
15428
15116
  finalAbsoluteMatrix = fabric.util.composeMatrix({
15429
15117
  translateX: decomposed.translateX,
15430
15118
  translateY: decomposed.translateY,
15431
- angle: finalAngle ?? 0,
15119
+ angle: decomposed.angle ?? 0,
15432
15120
  scaleX: 1,
15433
15121
  scaleY: 1,
15434
- skewX: finalSkewX ?? 0,
15435
- skewY: finalSkewY ?? 0
15122
+ skewX: 0,
15123
+ skewY: 0
15436
15124
  });
15437
- if (debugGroupImageSideResize) {
15438
- logGroupImageResizeDebug("image-bake", {
15439
- time: Math.round(performance.now()),
15440
- handle: activeSelectionResizeHandle,
15441
- imageId: objId,
15442
- source: sourceElement ? {
15443
- left: sourceElement.left,
15444
- top: sourceElement.top,
15445
- width: sourceElement.width,
15446
- height: sourceElement.height,
15447
- angle: sourceElement.angle,
15448
- scaleX: sourceElement.scaleX,
15449
- scaleY: sourceElement.scaleY
15450
- } : null,
15451
- factors: { sx, sy, fx, fy, isCornerHandle },
15452
- beforeBake: debugImageBeforeBake,
15453
- afterBake: summarizeFabricObjectForResizeDebug(obj),
15454
- persistedGeometry: {
15455
- absoluteLeft,
15456
- absoluteTop,
15457
- finalWidth,
15458
- finalHeight,
15459
- finalScaleX,
15460
- finalScaleY,
15461
- finalAngle,
15462
- finalSkewX,
15463
- finalSkewY,
15464
- decomposed,
15465
- finalAbsoluteMatrix
15466
- }
15467
- });
15468
- }
15469
15125
  } else {
15470
15126
  finalWidth = intrinsicWidth;
15471
15127
  finalHeight = intrinsicHeight;
@@ -15475,33 +15131,16 @@ const PageCanvas = forwardRef(
15475
15131
  finalHeight = 0;
15476
15132
  finalScaleX = 1;
15477
15133
  finalScaleY = 1;
15478
- if (activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb") {
15479
- finalAngle = (sourceElement == null ? void 0 : sourceElement.angle) ?? obj.angle ?? decomposed.angle;
15480
- finalSkewX = (sourceElement == null ? void 0 : sourceElement.skewX) ?? obj.skewX ?? 0;
15481
- finalSkewY = (sourceElement == null ? void 0 : sourceElement.skewY) ?? obj.skewY ?? 0;
15482
- if ((sourceElement == null ? void 0 : sourceElement.angle) !== void 0 || obj.angle !== void 0) finalAngleFromDecomposed = false;
15483
- }
15484
- } else if (obj instanceof fabric.Textbox && isActiveSelection && (activeSelectionResizeHandle != null || obj.__asLiveOrigW != null || obj.__asLiveOrigH != null || Math.abs((decomposed.scaleX ?? 1) - 1) > 1e-3 || Math.abs((decomposed.scaleY ?? 1) - 1) > 1e-3)) {
15485
- const liveOrigW = obj.__asLiveOrigW;
15486
- const liveOrigH = obj.__asLiveOrigH;
15487
- const decSx = Math.abs(decomposed.scaleX || 1);
15488
- const decSy = Math.abs(decomposed.scaleY || 1);
15489
- const sx = Math.abs(decSx - 1) < 1e-3 && liveOrigW && liveOrigW > 0 ? Math.max(1e-3, (obj.width ?? liveOrigW) / liveOrigW) : decSx;
15490
- const baseHForRecover = Number(
15491
- obj.minBoxHeight ?? obj.height ?? liveOrigH ?? 1
15492
- );
15493
- const sy = Math.abs(decSy - 1) < 1e-3 && liveOrigH && liveOrigH > 0 ? Math.max(1e-3, baseHForRecover / liveOrigH) : decSy;
15134
+ } else if (obj instanceof fabric.Textbox && isActiveSelection && (Math.abs((decomposed.scaleX ?? 1) - 1) > 1e-3 || Math.abs((decomposed.scaleY ?? 1) - 1) > 1e-3)) {
15135
+ const sx = Math.abs(decomposed.scaleX || 1);
15136
+ const sy = Math.abs(decomposed.scaleY || 1);
15494
15137
  const isLikelyUniformCorner = !activeSelectionResizeHandle && Math.abs(sx - sy) < 0.01 && Math.abs(sx - 1) > 1e-3;
15495
15138
  const isCornerHandle = activeSelectionResizeHandle === "tl" || activeSelectionResizeHandle === "tr" || activeSelectionResizeHandle === "bl" || activeSelectionResizeHandle === "br" || isLikelyUniformCorner;
15496
15139
  const isHeightSideHandle = activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb";
15497
15140
  const fontScale = isCornerHandle ? Math.max(1e-3, Math.sqrt(sx * sy)) : 1;
15498
- const widthBase = liveOrigW && liveOrigW > 0 ? liveOrigW : intrinsicWidth;
15499
- const heightBase = liveOrigH && liveOrigH > 0 ? liveOrigH : intrinsicHeight;
15500
- const bakedWidth = Math.max(20, widthBase * sx);
15501
- const liveMinHOrig = obj.__asLiveOrigMinH;
15502
- const currentMinH = Number(obj.minBoxHeight ?? (sourceElement == null ? void 0 : sourceElement.minBoxHeight));
15503
- const minHBase = Number.isFinite(liveMinHOrig) && liveMinHOrig > 0 ? liveMinHOrig : liveOrigH && liveOrigH > 0 ? currentMinH / sy : currentMinH;
15504
- const nextMinH = Number.isFinite(minHBase) && minHBase > 0 ? minHBase * sy : isHeightSideHandle ? Math.max(1, heightBase * sy) : void 0;
15141
+ const bakedWidth = Math.max(20, intrinsicWidth * sx);
15142
+ const baseMinH = Number(obj.minBoxHeight ?? (sourceElement == null ? void 0 : sourceElement.minBoxHeight));
15143
+ const nextMinH = Number.isFinite(baseMinH) && baseMinH > 0 ? baseMinH * sy : isHeightSideHandle ? Math.max(1, intrinsicHeight * sy) : void 0;
15505
15144
  const bakedTextScaleUpdates = { width: bakedWidth };
15506
15145
  const debugTextBeforeBake = debugGroupTextCornerResize ? summarizeFabricObjectForResizeDebug(obj) : null;
15507
15146
  finalScaleX = 1;
@@ -15560,9 +15199,14 @@ const PageCanvas = forwardRef(
15560
15199
  const localScaleX = 1 / sx;
15561
15200
  const localScaleY = 1 / sy;
15562
15201
  obj.set({ scaleX: localScaleX, scaleY: localScaleY });
15563
- const selectionMatrix = (_i = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _i.call(activeObj);
15202
+ const selectionMatrix = (_h = activeObj == null ? void 0 : activeObj.calcTransformMatrix) == null ? void 0 : _h.call(activeObj);
15564
15203
  const localCenter = selectionMatrix ? fabric.util.transformPoint(preBakeCenter, fabric.util.invertTransform(selectionMatrix)) : preBakeCenter;
15565
- obj.setPositionByOrigin(localCenter, "center", "center");
15204
+ const localWidth = bakedWidth * localScaleX;
15205
+ const localHeight = (obj.height ?? intrinsicHeight) * localScaleY;
15206
+ obj.set({
15207
+ left: localCenter.x - localWidth / 2,
15208
+ top: localCenter.y - localHeight / 2
15209
+ });
15566
15210
  } else {
15567
15211
  obj.setPositionByOrigin(preBakeCenter, "center", "center");
15568
15212
  }
@@ -15575,23 +15219,32 @@ const PageCanvas = forwardRef(
15575
15219
  } catch {
15576
15220
  }
15577
15221
  try {
15578
- const angleRad = (finalAngle ?? 0) * Math.PI / 180;
15222
+ const angleRad = (decomposed.angle ?? 0) * Math.PI / 180;
15579
15223
  const cos = Math.cos(angleRad);
15580
15224
  const sin = Math.sin(angleRad);
15581
15225
  const hw = finalWidth / 2;
15582
15226
  const hh = finalHeight / 2;
15583
- absoluteLeft = decomposed.translateX - hw * cos + hh * sin;
15584
- absoluteTop = decomposed.translateY - hw * sin - hh * cos;
15227
+ const corners = [
15228
+ { x: -hw, y: -hh },
15229
+ { x: hw, y: -hh },
15230
+ { x: hw, y: hh },
15231
+ { x: -hw, y: hh }
15232
+ ].map((p) => ({
15233
+ x: decomposed.translateX + p.x * cos - p.y * sin,
15234
+ y: decomposed.translateY + p.x * sin + p.y * cos
15235
+ }));
15236
+ absoluteLeft = Math.min(...corners.map((p) => p.x));
15237
+ absoluteTop = Math.min(...corners.map((p) => p.y));
15585
15238
  } catch {
15586
15239
  }
15587
15240
  finalAbsoluteMatrix = fabric.util.composeMatrix({
15588
15241
  translateX: decomposed.translateX,
15589
15242
  translateY: decomposed.translateY,
15590
- angle: finalAngle ?? 0,
15243
+ angle: decomposed.angle ?? 0,
15591
15244
  scaleX: 1,
15592
15245
  scaleY: 1,
15593
- skewX: finalSkewX ?? 0,
15594
- skewY: finalSkewY ?? 0
15246
+ skewX: 0,
15247
+ skewY: 0
15595
15248
  });
15596
15249
  if (debugGroupTextCornerResize) {
15597
15250
  logGroupTextResizeDebug("text-bake", {
@@ -15646,21 +15299,7 @@ const PageCanvas = forwardRef(
15646
15299
  const state = useEditorStore.getState();
15647
15300
  const page = state.canvas.pages.find((p) => p.id === pageId);
15648
15301
  const pageChildrenForSave = (page == null ? void 0 : page.children) ?? [];
15649
- const storePos = (logicalGroupFinalFrame == null ? void 0 : logicalGroupFinalFrame.groupId) === logicalGroupSelectionId ? (() => {
15650
- const localCenter = fabric.util.transformPoint(
15651
- new fabric.Point(decomposed.translateX ?? 0, decomposed.translateY ?? 0),
15652
- fabric.util.invertTransform(logicalGroupFinalFrame.matrix)
15653
- );
15654
- const localAngle = finalAngleFromDecomposed ? ((Number(finalAngle ?? 0) - asAngleForBake) % 360 + 540) % 360 - 180 : Number(finalAngle ?? 0);
15655
- const localAngleRad = localAngle * Math.PI / 180;
15656
- return {
15657
- left: localCenter.x - finalWidth / 2 * Math.cos(localAngleRad) + finalHeight / 2 * Math.sin(localAngleRad) + logicalGroupFinalFrame.width / 2,
15658
- top: localCenter.y - finalWidth / 2 * Math.sin(localAngleRad) - finalHeight / 2 * Math.cos(localAngleRad) + logicalGroupFinalFrame.height / 2
15659
- };
15660
- })() : absoluteToStorePosition(absoluteLeft, absoluteTop, objId, pageChildrenForSave);
15661
- if (isLogicalGroupAS && finalAngleFromDecomposed && typeof finalAngle === "number") {
15662
- finalAngle = ((finalAngle - asAngleForBake) % 360 + 540) % 360 - 180;
15663
- }
15302
+ const storePos = absoluteToStorePosition(absoluteLeft, absoluteTop, objId, pageChildrenForSave);
15664
15303
  const isLineObj = obj instanceof fabric.Line;
15665
15304
  const isAutoShrinkText = (sourceElement == null ? void 0 : sourceElement.type) === "text" && sourceElement.overflowPolicy === "auto-shrink";
15666
15305
  const autoShrinkStoredHeight = isAutoShrinkText ? sourceElement.height : void 0;
@@ -15672,17 +15311,13 @@ const PageCanvas = forwardRef(
15672
15311
  // so finalWidth already reflects the new width chosen by the user.
15673
15312
  width: finalWidth,
15674
15313
  height: isLineObj ? 0 : isAutoShrinkText ? typeof autoShrinkStoredHeight === "number" ? autoShrinkStoredHeight : finalHeight : finalHeight,
15675
- angle: finalAngle,
15676
- skewX: isLineObj ? 0 : finalSkewX,
15677
- skewY: isLineObj ? 0 : finalSkewY,
15314
+ angle: decomposed.angle,
15315
+ skewX: isLineObj ? 0 : decomposed.skewX,
15316
+ skewY: isLineObj ? 0 : decomposed.skewY,
15678
15317
  scaleX: finalScaleX,
15679
- scaleY: finalScaleY
15318
+ scaleY: finalScaleY,
15319
+ transformMatrix: finalAbsoluteMatrix
15680
15320
  };
15681
- if (!isLogicalGroupAS) {
15682
- elementUpdate.transformMatrix = finalAbsoluteMatrix;
15683
- } else {
15684
- elementUpdate.transformMatrix = void 0;
15685
- }
15686
15321
  if (obj instanceof fabric.Textbox) {
15687
15322
  const bakedTextScaleUpdates = obj.__pixldocsBakedTextScaleUpdates;
15688
15323
  if (bakedTextScaleUpdates && typeof bakedTextScaleUpdates === "object") {
@@ -15713,41 +15348,10 @@ const PageCanvas = forwardRef(
15713
15348
  objectBeforeStoreWrite: summarizeFabricObjectForResizeDebug(obj)
15714
15349
  });
15715
15350
  }
15716
- if (debugGroupImageSideResize && isGroupResizeImageLikeObject(obj)) {
15717
- logGroupImageResizeDebug("store-update-image", {
15718
- time: Math.round(performance.now()),
15719
- handle: activeSelectionResizeHandle,
15720
- imageId: objId,
15721
- storePos,
15722
- elementUpdate,
15723
- objectBeforeStoreWrite: summarizeFabricObjectForResizeDebug(obj)
15724
- });
15725
- }
15726
15351
  updateElement(objId, elementUpdate, { recordHistory: false, skipLayoutRecalc: true });
15727
15352
  obj.setCoords();
15728
- delete obj.__asLiveOrigW;
15729
- delete obj.__asLiveOrigH;
15730
- delete obj.__asLiveOrigMinH;
15731
- }
15732
- if (isLogicalGroupAS && logicalGroupSelectionId && activeObj instanceof fabric.ActiveSelection) {
15733
- try {
15734
- const pageChildrenForGroup = ((_j = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _j.children) ?? [];
15735
- const groupNode = findNodeById(pageChildrenForGroup, logicalGroupSelectionId);
15736
- if (groupNode && logicalGroupFinalFrame) {
15737
- const storePosGroup = absoluteToStorePosition(logicalGroupFinalFrame.left, logicalGroupFinalFrame.top, logicalGroupSelectionId, pageChildrenForGroup);
15738
- useEditorStore.getState().updateNode(logicalGroupSelectionId, {
15739
- left: storePosGroup.left,
15740
- top: storePosGroup.top,
15741
- width: logicalGroupFinalFrame.width,
15742
- height: logicalGroupFinalFrame.height,
15743
- angle: logicalGroupFinalFrame.angle
15744
- }, { recordHistory: false, skipLayoutRecalc: true });
15745
- }
15746
- } catch (err) {
15747
- console.warn("[Pixldocs] logical-group envelope persist failed", err);
15748
- }
15749
15353
  }
15750
- const pageChildrenForReflow = ((_k = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _k.children) ?? [];
15354
+ const pageChildrenForReflow = ((_i = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _i.children) ?? [];
15751
15355
  const stackGroupsToReflow = /* @__PURE__ */ new Set();
15752
15356
  for (const id of modifiedIdsThisRound) {
15753
15357
  const parent = findParentGroup(pageChildrenForReflow, id);
@@ -15774,16 +15378,6 @@ const PageCanvas = forwardRef(
15774
15378
  renderOnAddRemove: fabricCanvas.renderOnAddRemove
15775
15379
  });
15776
15380
  }
15777
- if (debugGroupImageSideResize) {
15778
- logGroupImageResizeDebug("before-reselect", {
15779
- time: Math.round(performance.now()),
15780
- handle: activeSelectionResizeHandle,
15781
- wasGroupSel,
15782
- selection: summarizeFabricObjectForResizeDebug(activeObj),
15783
- members: membersToReselect.map((member) => summarizeFabricObjectForResizeDebug(member)),
15784
- renderOnAddRemove: fabricCanvas.renderOnAddRemove
15785
- });
15786
- }
15787
15381
  const prevRenderOnAddRemove = fabricCanvas.renderOnAddRemove;
15788
15382
  fabricCanvas.renderOnAddRemove = false;
15789
15383
  skipSelectionClearOnDiscardRef.current = true;
@@ -15798,10 +15392,9 @@ const PageCanvas = forwardRef(
15798
15392
  if (!ct) continue;
15799
15393
  ct.frameW = bake.width;
15800
15394
  ct.frameH = bake.height;
15801
- const bakeCenter = rotatedTopLeftToCenter(bake.left, bake.top, bake.width, bake.height, bake.angle);
15802
15395
  bake.obj.set({
15803
- left: bakeCenter.x,
15804
- top: bakeCenter.y,
15396
+ left: bake.left + bake.width / 2,
15397
+ top: bake.top + bake.height / 2,
15805
15398
  width: bake.width,
15806
15399
  height: bake.height,
15807
15400
  scaleX: 1,
@@ -15828,16 +15421,6 @@ const PageCanvas = forwardRef(
15828
15421
  renderOnAddRemove: fabricCanvas.renderOnAddRemove
15829
15422
  });
15830
15423
  }
15831
- if (debugGroupImageSideResize) {
15832
- logGroupImageResizeDebug("after-reselect", {
15833
- time: Math.round(performance.now()),
15834
- handle: activeSelectionResizeHandle,
15835
- wasGroupSel,
15836
- selection: summarizeFabricObjectForResizeDebug(newSel),
15837
- members: membersToReselect.map((member) => summarizeFabricObjectForResizeDebug(member)),
15838
- renderOnAddRemove: fabricCanvas.renderOnAddRemove
15839
- });
15840
- }
15841
15424
  } else if (membersToReselect.length === 1) {
15842
15425
  fabricCanvas.setActiveObject(membersToReselect[0]);
15843
15426
  }
@@ -15874,7 +15457,6 @@ const PageCanvas = forwardRef(
15874
15457
  const activeObj = fabricCanvas.getActiveObject();
15875
15458
  if (!(activeObj instanceof fabric.ActiveSelection)) return;
15876
15459
  if (skipActiveSelectionBakeOnClearRef.current) return;
15877
- if (activeObj.__pixldocsGroupSelection) return;
15878
15460
  const selectionMatrix = activeObj.calcTransformMatrix();
15879
15461
  for (const obj of deselected) {
15880
15462
  const objId = getObjectId(obj);
@@ -16344,7 +15926,7 @@ const PageCanvas = forwardRef(
16344
15926
  const nextHeight = Math.max(minVisiblePlaceholder, Number(resolvedSizeImg.height) || 50);
16345
15927
  const storePosImg = pageChildren ? (() => {
16346
15928
  const node = findNodeById(pageChildren, element.id);
16347
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
15929
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16348
15930
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16349
15931
  const elementForPlaceholder = { ...element, width: nextWidth, height: nextHeight };
16350
15932
  const placeholder = isCropGroup2 ? createImagePlaceholderForGroup(elementForPlaceholder) : createImagePlaceholder(elementForPlaceholder);
@@ -16407,14 +15989,13 @@ const PageCanvas = forwardRef(
16407
15989
  }
16408
15990
  const cropPos = pageChildren ? (() => {
16409
15991
  const node = findNodeById(pageChildren, element.id);
16410
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16411
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16412
- const cropCenter = rotatedTopLeftToCenter(cropPos.left, cropPos.top, ct.frameW ?? 0, ct.frameH ?? 0, cropPos.angle ?? element.angle ?? 0);
16413
- const cropCenterX = cropCenter.x;
16414
- const cropCenterY = cropCenter.y;
15992
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
15993
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
15994
+ const cropCenterX = cropPos.left + (ct.frameW ?? 0) / 2;
15995
+ const cropCenterY = cropPos.top + (ct.frameH ?? 0) / 2;
16415
15996
  if (element.left !== void 0) existingObj.set({ left: cropCenterX });
16416
15997
  if (element.top !== void 0) existingObj.set({ top: cropCenterY });
16417
- existingObj.set({ angle: cropPos.angle ?? element.angle ?? 0 });
15998
+ if (element.angle !== void 0) existingObj.set({ angle: element.angle });
16418
15999
  existingObj.set({
16419
16000
  flipX: element.flipX ?? false,
16420
16001
  flipY: element.flipY ?? false
@@ -16537,8 +16118,8 @@ const PageCanvas = forwardRef(
16537
16118
  if (isPlaceholderGroup) {
16538
16119
  const storePosImg = pageChildren ? (() => {
16539
16120
  const node = findNodeById(pageChildren, element.id);
16540
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16541
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16121
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16122
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
16542
16123
  const resolvedSizeImg = (pageChildren == null ? void 0 : pageChildren.length) ? getNodeBounds(element, pageChildren) : { width: typeof element.width === "number" ? element.width : 200, height: typeof element.height === "number" ? element.height : 50 };
16543
16124
  const hasExplicitSize = typeof element.width === "number" && Number.isFinite(element.width) && element.width > 0 && typeof element.height === "number" && Number.isFinite(element.height) && element.height > 0;
16544
16125
  const minVisiblePlaceholder = hasExplicitSize ? 1 : 20;
@@ -16552,7 +16133,7 @@ const PageCanvas = forwardRef(
16552
16133
  top: storePosImg.top + nextHeight / 2,
16553
16134
  originX: "center",
16554
16135
  originY: "center",
16555
- angle: storePosImg.angle ?? element.angle ?? 0,
16136
+ angle: element.angle ?? 0,
16556
16137
  opacity: isHidden ? 0 : element.opacity ?? 1,
16557
16138
  flipX: element.flipX ?? false,
16558
16139
  flipY: element.flipY ?? false,
@@ -16601,8 +16182,8 @@ const PageCanvas = forwardRef(
16601
16182
  const visibilityChanged = previousVisible !== currentVisible;
16602
16183
  const storePosForImg = pageChildren ? (() => {
16603
16184
  const node = findNodeById(pageChildren, element.id);
16604
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16605
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
16185
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16186
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
16606
16187
  const positionChanged = Math.abs((existingObj.left ?? 0) - storePosForImg.left) > 0.1 || Math.abs((existingObj.top ?? 0) - storePosForImg.top) > 0.1;
16607
16188
  if (visibilityChanged && !positionChanged || visibilityUpdateInProgressRef.current) {
16608
16189
  const isDynamicField = dynamicFieldIds.includes(element.id);
@@ -16644,7 +16225,7 @@ const PageCanvas = forwardRef(
16644
16225
  const fabricTop = existingObj.top ?? 0;
16645
16226
  const storePos = pageChildren ? (() => {
16646
16227
  const node = findNodeById(pageChildren, element.id);
16647
- return node && isElement(node) ? getElementFabricPlacement(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16228
+ return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
16648
16229
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16649
16230
  const storeLeft = storePos.left;
16650
16231
  const storeTop = storePos.top;
@@ -16771,7 +16352,7 @@ const PageCanvas = forwardRef(
16771
16352
  setObjectData(placeholder, element.id);
16772
16353
  const absPosImg = pageTree.length > 0 ? (() => {
16773
16354
  const node = findNodeById(pageTree, element.id);
16774
- return node && isElement(node) ? getElementFabricPlacement(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16355
+ return node ? getAbsoluteBounds(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16775
16356
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16776
16357
  const placeholderWidth = Number((placeholder.width ?? 0) * (placeholder.scaleX ?? 1));
16777
16358
  const placeholderHeight = Number((placeholder.height ?? 0) * (placeholder.scaleY ?? 1));
@@ -16820,7 +16401,7 @@ const PageCanvas = forwardRef(
16820
16401
  if (obj) {
16821
16402
  const absPos = pageTree.length > 0 ? (() => {
16822
16403
  const node = findNodeById(pageTree, element.id);
16823
- return node && isElement(node) ? getElementFabricPlacement(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16404
+ return node ? getAbsoluteBounds(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16824
16405
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
16825
16406
  obj.set({ left: absPos.left, top: absPos.top });
16826
16407
  obj.setCoords();
@@ -17210,7 +16791,9 @@ const PageCanvas = forwardRef(
17210
16791
  if (sameSelection && isFlatGroupSelection) {
17211
16792
  if (selectedGroupSelectionId && active instanceof fabric.ActiveSelection) {
17212
16793
  if (isPureSingleGroupSelection) {
17213
- applyLogicalGroupSelectionVisualState(active, selectedGroupSelectionId);
16794
+ active.__pixldocsGroupSelection = selectedGroupSelectionId;
16795
+ delete active.__pixldocsLogicalGroupIds;
16796
+ suppressGroupMemberBordersRef.current = active.getObjects();
17214
16797
  } else {
17215
16798
  delete active.__pixldocsGroupSelection;
17216
16799
  active.__pixldocsLogicalGroupIds = selectedGroupIds;
@@ -17250,7 +16833,8 @@ const PageCanvas = forwardRef(
17250
16833
  const selection = new fabric.ActiveSelection(toSelect, { canvas: fc });
17251
16834
  if (selectedGroupSelectionId) {
17252
16835
  if (isPureSingleGroupSelection) {
17253
- applyLogicalGroupSelectionVisualState(selection, selectedGroupSelectionId);
16836
+ selection.__pixldocsGroupSelection = selectedGroupSelectionId;
16837
+ suppressGroupMemberBordersRef.current = toSelect;
17254
16838
  } else {
17255
16839
  selection.__pixldocsLogicalGroupIds = selectedGroupIds;
17256
16840
  selection.hasBorders = true;
@@ -17308,9 +16892,8 @@ const PageCanvas = forwardRef(
17308
16892
  const currentPageTree = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_a2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _a2.children) ?? [];
17309
16893
  const fabricPos = currentPageTree.length > 0 ? (() => {
17310
16894
  const node = findNodeById(currentPageTree, element.id);
17311
- return node && isElement(node) ? getElementFabricPlacement(node, currentPageTree) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
17312
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
17313
- const fabricAngle = fabricPos.angle ?? element.angle ?? 0;
16895
+ return node ? getAbsoluteBounds(node, currentPageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
16896
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
17314
16897
  const resolvedSize = currentPageTree.length > 0 ? getNodeBounds(element, currentPageTree) : { width: typeof element.width === "number" ? element.width : 200, height: typeof element.height === "number" ? element.height : 50 };
17315
16898
  const shouldPreserveSmallSize = typeof element.width === "number" && Number.isFinite(element.width) && element.width > 0 && typeof element.height === "number" && Number.isFinite(element.height) && element.height > 0;
17316
16899
  const minVisible = shouldPreserveSmallSize ? 1 : 20;
@@ -17345,9 +16928,8 @@ const PageCanvas = forwardRef(
17345
16928
  ct.shape = clipShape === "circle" ? "circle" : clipShape === "rounded" ? "roundRect" : "rect";
17346
16929
  ct.rx = rxRatio;
17347
16930
  obj.__maintainResolution = element.maintainResolution !== false;
17348
- const center = rotatedTopLeftToCenter(fabricPos.left, fabricPos.top, elementWidth, elementHeight, element.angle ?? 0);
17349
- const centerX = center.x;
17350
- const centerY = center.y;
16931
+ const centerX = fabricPos.left + elementWidth / 2;
16932
+ const centerY = fabricPos.top + elementHeight / 2;
17351
16933
  const cropSetProps = {
17352
16934
  width: elementWidth,
17353
16935
  height: elementHeight,
@@ -17567,7 +17149,7 @@ const PageCanvas = forwardRef(
17567
17149
  y1: 0,
17568
17150
  x2: lineLen,
17569
17151
  y2: 0,
17570
- angle: fabricAngle,
17152
+ angle: element.angle ?? 0,
17571
17153
  scaleX: 1,
17572
17154
  scaleY: 1,
17573
17155
  skewX: 0,
@@ -17587,8 +17169,7 @@ const PageCanvas = forwardRef(
17587
17169
  if (!skipPositionUpdate && (obj instanceof fabric.FabricImage && obj.originX === "center" || obj instanceof fabric.Group && obj.__cropGroup)) {
17588
17170
  const vW = rW * effectiveScaleX;
17589
17171
  const vH = rH * effectiveScaleY;
17590
- const center = rotatedTopLeftToCenter(fabricPos.left, fabricPos.top, vW, vH, element.angle ?? 0);
17591
- posIfNotSkipped = { left: center.x, top: center.y };
17172
+ posIfNotSkipped = { left: fabricPos.left + vW / 2, top: fabricPos.top + vH / 2 };
17592
17173
  }
17593
17174
  if (element.transformMatrix && element.transformMatrix.length === 6) {
17594
17175
  if (isTextbox) {
@@ -17597,7 +17178,7 @@ const PageCanvas = forwardRef(
17597
17178
  width: rW,
17598
17179
  scaleX: effectiveScaleX,
17599
17180
  scaleY: effectiveScaleY,
17600
- angle: fabricAngle,
17181
+ angle: element.angle ?? 0,
17601
17182
  skewX: element.skewX ?? 0,
17602
17183
  skewY: appliedSkewY
17603
17184
  });
@@ -17606,7 +17187,7 @@ const PageCanvas = forwardRef(
17606
17187
  ...posIfNotSkipped,
17607
17188
  scaleX: effectiveScaleX,
17608
17189
  scaleY: effectiveScaleY,
17609
- angle: fabricAngle,
17190
+ angle: element.angle ?? 0,
17610
17191
  skewX: element.skewX ?? 0,
17611
17192
  skewY: element.skewY ?? 0
17612
17193
  });
@@ -17617,7 +17198,7 @@ const PageCanvas = forwardRef(
17617
17198
  obj.set({
17618
17199
  ...posIfNotSkipped,
17619
17200
  width: rW,
17620
- angle: fabricAngle,
17201
+ angle: element.angle ?? 0,
17621
17202
  skewX: element.skewX ?? 0,
17622
17203
  skewY: appliedSkewY,
17623
17204
  scaleX: effectiveScaleX * baseScaleX,
@@ -17626,7 +17207,7 @@ const PageCanvas = forwardRef(
17626
17207
  } else {
17627
17208
  obj.set({
17628
17209
  ...posIfNotSkipped,
17629
- angle: fabricAngle,
17210
+ angle: element.angle ?? 0,
17630
17211
  skewX: element.skewX ?? 0,
17631
17212
  skewY: element.skewY ?? 0,
17632
17213
  scaleX: effectiveScaleX * baseScaleX,
@@ -18379,14 +17960,14 @@ const PageCanvas = forwardRef(
18379
17960
  const pageTreeForCreate = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_f = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _f.children) ?? [];
18380
17961
  const createPos = pageTreeForCreate.length > 0 ? (() => {
18381
17962
  const node = findNodeById(pageTreeForCreate, element.id);
18382
- return node && isElement(node) ? getElementFabricPlacement(node, pageTreeForCreate, pageBoundsOptions) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
18383
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
17963
+ return node ? getAbsoluteBounds(node, pageTreeForCreate) : { left: element.left ?? 0, top: element.top ?? 0 };
17964
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
18384
17965
  img.set({
18385
17966
  left: createPos.left,
18386
17967
  top: createPos.top,
18387
17968
  scaleX: finalScaleX,
18388
17969
  scaleY: finalScaleY,
18389
- angle: createPos.angle ?? element.angle ?? 0,
17970
+ angle: element.angle ?? 0,
18390
17971
  skewX: element.skewX ?? 0,
18391
17972
  skewY: element.skewY ?? 0,
18392
17973
  flipX: element.flipX ?? false,
@@ -18473,8 +18054,8 @@ const PageCanvas = forwardRef(
18473
18054
  const pageTreeForCrop = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_n = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _n.children) ?? [];
18474
18055
  const createPosForCrop = pageTreeForCrop.length > 0 ? (() => {
18475
18056
  const node = findNodeById(pageTreeForCrop, element.id);
18476
- return node && isElement(node) ? getElementFabricPlacement(node, pageTreeForCrop, pageBoundsOptions) : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
18477
- })() : { left: element.left ?? 0, top: element.top ?? 0, angle: element.angle ?? 0 };
18057
+ return node ? getAbsoluteBounds(node, pageTreeForCrop) : { left: element.left ?? 0, top: element.top ?? 0 };
18058
+ })() : { left: element.left ?? 0, top: element.top ?? 0 };
18478
18059
  const nodeForCreate = pageTreeForCrop.length ? findNodeById(pageTreeForCrop, element.id) : null;
18479
18060
  const createW = nodeForCreate && isElement(nodeForCreate) ? nodeForCreate.width : elementWidth;
18480
18061
  const createH = nodeForCreate && isElement(nodeForCreate) ? nodeForCreate.height : elementHeight;
@@ -18482,9 +18063,8 @@ const PageCanvas = forwardRef(
18482
18063
  const createSy = nodeForCreate && isElement(nodeForCreate) ? nodeForCreate.scaleY ?? 1 : element.scaleY ?? 1;
18483
18064
  const frameW = Math.max(1, Number(createW) || 200) * createSx;
18484
18065
  const frameH = Math.max(1, Number(createH) || 50) * createSy;
18485
- const createCenter = rotatedTopLeftToCenter(createPosForCrop.left, createPosForCrop.top, frameW, frameH, createPosForCrop.angle ?? element.angle ?? 0);
18486
- const createCenterX = createCenter.x;
18487
- const createCenterY = createCenter.y;
18066
+ const createCenterX = createPosForCrop.left + frameW / 2;
18067
+ const createCenterY = createPosForCrop.top + frameH / 2;
18488
18068
  const cropGroup = await createMaskedImageElement({
18489
18069
  image: img,
18490
18070
  frameW,
@@ -18497,7 +18077,7 @@ const PageCanvas = forwardRef(
18497
18077
  strokeWidth: 0,
18498
18078
  left: createCenterX,
18499
18079
  top: createCenterY,
18500
- angle: createPosForCrop.angle ?? element.angle ?? 0,
18080
+ angle: element.angle ?? 0,
18501
18081
  opacity: isHidden ? 0 : element.opacity ?? 1,
18502
18082
  selectable: allowSelection && !isHidden,
18503
18083
  evented: canBeEvented && !isHidden,
@@ -24887,9 +24467,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
24887
24467
  }
24888
24468
  return svgString;
24889
24469
  }
24890
- const resolvedPackageVersion = "0.5.354";
24470
+ const resolvedPackageVersion = "0.5.356";
24891
24471
  const PACKAGE_VERSION = resolvedPackageVersion;
24892
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.354";
24472
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.356";
24893
24473
  const roundParityValue = (value) => {
24894
24474
  if (typeof value !== "number") return value;
24895
24475
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -25703,7 +25283,7 @@ class PixldocsRenderer {
25703
25283
  await this.waitForCanvasScene(container, cloned, i);
25704
25284
  }
25705
25285
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
25706
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-B54V1hcn.js");
25286
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-Dg5IQ77x.js");
25707
25287
  const prepared = preparePagesForExport(
25708
25288
  cloned.pages,
25709
25289
  canvasWidth,
@@ -28023,7 +27603,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
28023
27603
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
28024
27604
  sanitizeSvgTreeForPdf(svgToDraw);
28025
27605
  try {
28026
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-B54V1hcn.js");
27606
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-Dg5IQ77x.js");
28027
27607
  try {
28028
27608
  await logTextMeasurementDiagnostic(svgToDraw);
28029
27609
  } catch {
@@ -28423,4 +28003,4 @@ export {
28423
28003
  buildTeaserBlurFlatKeys as y,
28424
28004
  collectFontDescriptorsFromConfig as z
28425
28005
  };
28426
- //# sourceMappingURL=index-yEgXeiie.js.map
28006
+ //# sourceMappingURL=index-SmBKCsve.js.map