@pixldocs/canvas-renderer 0.5.330 → 0.5.332

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.
@@ -11160,6 +11160,15 @@ const bakeTextboxScaleIntoTypography = (obj, sourceElement) => {
11160
11160
  };
11161
11161
  return updates;
11162
11162
  };
11163
+ const rotatedTopLeftToCenter = (left, top, width, height, angleDeg = 0) => {
11164
+ const angle = angleDeg * Math.PI / 180;
11165
+ const cos = Math.cos(angle);
11166
+ const sin = Math.sin(angle);
11167
+ return {
11168
+ x: left + width / 2 * cos - height / 2 * sin,
11169
+ y: top + width / 2 * sin + height / 2 * cos
11170
+ };
11171
+ };
11163
11172
  function applyWarpAwareSelectionBorders(selection) {
11164
11173
  var _a2;
11165
11174
  if (selection.__pixldocsOrigASHasBorders !== void 0) {
@@ -13522,29 +13531,23 @@ const PageCanvas = forwardRef(
13522
13531
  const getObjectFrameBoundsInSelection = (selection, obj, frameWidth, frameHeight) => {
13523
13532
  const w = Math.max(1, frameWidth ?? obj.width ?? 1);
13524
13533
  const h = Math.max(1, frameHeight ?? obj.height ?? 1);
13525
- const originX = obj.originX ?? "left";
13526
- const originY = obj.originY ?? "top";
13527
- const localLeft = originX === "center" ? -w / 2 : originX === "right" ? -w : 0;
13528
- const localTop = originY === "center" ? -h / 2 : originY === "bottom" ? -h : 0;
13529
13534
  const matrix = fabric.util.multiplyTransformMatrices(
13530
13535
  selection.calcTransformMatrix(),
13531
13536
  obj.calcOwnMatrix()
13532
13537
  );
13533
- const points = [
13534
- new fabric.Point(localLeft, localTop),
13535
- new fabric.Point(localLeft + w, localTop),
13536
- new fabric.Point(localLeft + w, localTop + h),
13537
- new fabric.Point(localLeft, localTop + h)
13538
- ].map((point) => fabric.util.transformPoint(point, matrix));
13539
- const xs = points.map((p) => p.x);
13540
- const ys = points.map((p) => p.y);
13541
- const left = Math.min(...xs);
13542
- const top = Math.min(...ys);
13538
+ const decomposed = fabric.util.qrDecompose(matrix);
13539
+ const scaledW = Math.max(1, w * Math.abs(decomposed.scaleX || 1));
13540
+ const scaledH = Math.max(1, h * Math.abs(decomposed.scaleY || 1));
13541
+ const angleRad = (decomposed.angle ?? 0) * Math.PI / 180;
13542
+ const cos = Math.cos(angleRad);
13543
+ const sin = Math.sin(angleRad);
13544
+ const left = decomposed.translateX - scaledW / 2 * cos + scaledH / 2 * sin;
13545
+ const top = decomposed.translateY - scaledW / 2 * sin - scaledH / 2 * cos;
13543
13546
  return {
13544
13547
  left,
13545
13548
  top,
13546
- width: Math.max(1, Math.max(...xs) - left),
13547
- height: Math.max(1, Math.max(...ys) - top)
13549
+ width: scaledW,
13550
+ height: scaledH
13548
13551
  };
13549
13552
  };
13550
13553
  fabricCanvas.on("object:added", (e) => {
@@ -13740,7 +13743,10 @@ const PageCanvas = forwardRef(
13740
13743
  const a = ((c.angle ?? 0) % 180 + 180) % 180;
13741
13744
  return !(a < 0.5 || a > 179.5);
13742
13745
  });
13743
- if ((isXSide || hasRotatedChild) && ((_b2 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _b2.selection) !== obj) {
13746
+ const selectionAngle = ((obj.angle ?? 0) % 180 + 180) % 180;
13747
+ const isSelectionRotated = !(selectionAngle < 0.5 || selectionAngle > 179.5);
13748
+ const shouldPinNonTextChildren = hasRotatedChild || isSelectionRotated;
13749
+ if ((isXSide || shouldPinNonTextChildren) && ((_b2 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _b2.selection) !== obj) {
13744
13750
  groupShiftReflowSnapshotRef.current = null;
13745
13751
  const logicalGroupId = obj.__pixldocsGroupSelection;
13746
13752
  if (logicalGroupId) {
@@ -13787,16 +13793,31 @@ const PageCanvas = forwardRef(
13787
13793
  }
13788
13794
  }
13789
13795
  const childCounterScale = hasRotatedChild ? 1 : 1 / sAxis;
13796
+ let restoredNonTextAfterLayout = false;
13790
13797
  const restoreNonTextChildren = (pins) => {
13791
13798
  var _a3, _b3;
13792
- if (!hasRotatedChild || ((_a3 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _a3.selection) !== obj) return;
13799
+ if (!shouldPinNonTextChildren || ((_a3 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _a3.selection) !== obj) return;
13793
13800
  for (const entry of groupShiftReflowSnapshotRef.current.children) {
13794
13801
  const child = entry.obj;
13795
13802
  if (child instanceof fabric.Textbox) continue;
13796
13803
  if (child instanceof fabric.FabricImage || child instanceof fabric.Group && (child.__cropGroup || ((_b3 = child._ct) == null ? void 0 : _b3.isCropGroup))) {
13797
13804
  const pin = pins == null ? void 0 : pins.get(child);
13798
- const targetLeft = (pin == null ? void 0 : pin.left) ?? (isXSide ? entry.left0 * sAxis : entry.left0);
13799
- const targetTop = (pin == null ? void 0 : pin.top) ?? (isXSide ? entry.top0 : entry.top0 * sAxis);
13805
+ let targetLeft = hasRotatedChild && isXSide ? entry.left0 * sAxis : entry.left0;
13806
+ let targetTop = hasRotatedChild && !isXSide ? entry.top0 * sAxis : entry.top0;
13807
+ if (pin == null ? void 0 : pin.worldCenter) {
13808
+ try {
13809
+ const invSelectionMatrix = fabric.util.invertTransform(obj.calcTransformMatrix());
13810
+ const localCenter = fabric.util.transformPoint(pin.worldCenter, invSelectionMatrix);
13811
+ targetLeft = localCenter.x;
13812
+ targetTop = localCenter.y;
13813
+ } catch {
13814
+ targetLeft = pin.left ?? targetLeft;
13815
+ targetTop = pin.top ?? targetTop;
13816
+ }
13817
+ } else {
13818
+ targetLeft = (pin == null ? void 0 : pin.left) ?? targetLeft;
13819
+ targetTop = (pin == null ? void 0 : pin.top) ?? targetTop;
13820
+ }
13800
13821
  if (Math.abs((child.left ?? 0) - targetLeft) > 0.01) child._set("left", targetLeft);
13801
13822
  if (Math.abs((child.top ?? 0) - targetTop) > 0.01) child._set("top", targetTop);
13802
13823
  if (isXSide) child._set("scaleX", childCounterScale);
@@ -13816,17 +13837,54 @@ const PageCanvas = forwardRef(
13816
13837
  };
13817
13838
  for (const child of obj.getObjects()) {
13818
13839
  if (child instanceof fabric.Group && (child.__cropGroup || ((_d = child._ct) == null ? void 0 : _d.isCropGroup))) {
13840
+ const ct = child.__cropData;
13841
+ if (ct) {
13842
+ if (child.__asLiveOrigW == null) {
13843
+ child.__asLiveOrigW = ct.frameW ?? child.width ?? 1;
13844
+ }
13845
+ if (child.__asLiveOrigH == null) {
13846
+ child.__asLiveOrigH = ct.frameH ?? child.height ?? 1;
13847
+ }
13848
+ if (isXSide) {
13849
+ const newW = Math.max(1, Number(child.__asLiveOrigW) * sAxis);
13850
+ ct.frameW = newW;
13851
+ child._set("width", newW);
13852
+ } else {
13853
+ const newH = Math.max(1, Number(child.__asLiveOrigH) * sAxis);
13854
+ ct.frameH = newH;
13855
+ child._set("height", newH);
13856
+ }
13857
+ try {
13858
+ updateCoverLayout(child);
13859
+ } catch {
13860
+ }
13861
+ }
13819
13862
  if (isXSide) child._set("scaleX", childCounterScale);
13820
13863
  else child._set("scaleY", childCounterScale);
13821
13864
  child.setCoords();
13822
13865
  child.dirty = true;
13866
+ didReflowTextChild = true;
13823
13867
  continue;
13824
13868
  }
13825
13869
  if (child instanceof fabric.FabricImage && !child.__cropGroup && !child.smartElementType) {
13870
+ if (isXSide) {
13871
+ if (child.__asLiveOrigW == null) {
13872
+ child.__asLiveOrigW = (child.width ?? 0) * Math.abs(child.scaleX ?? 1);
13873
+ }
13874
+ const newW = Math.max(1, Number(child.__asLiveOrigW) * sAxis);
13875
+ child._set("width", newW);
13876
+ } else {
13877
+ if (child.__asLiveOrigH == null) {
13878
+ child.__asLiveOrigH = (child.height ?? 0) * Math.abs(child.scaleY ?? 1);
13879
+ }
13880
+ const newH = Math.max(1, Number(child.__asLiveOrigH) * sAxis);
13881
+ child._set("height", newH);
13882
+ }
13826
13883
  if (isXSide) child._set("scaleX", childCounterScale);
13827
13884
  else child._set("scaleY", childCounterScale);
13828
13885
  child.setCoords();
13829
13886
  child.dirty = true;
13887
+ didReflowTextChild = true;
13830
13888
  continue;
13831
13889
  }
13832
13890
  if (!(child instanceof fabric.Textbox)) continue;
@@ -13865,7 +13923,7 @@ const PageCanvas = forwardRef(
13865
13923
  didReflowTextChild = true;
13866
13924
  }
13867
13925
  }
13868
- if (isXSide && ((_e = groupShiftReflowSnapshotRef.current) == null ? void 0 : _e.selection) === obj) {
13926
+ if (isXSide && !shouldPinNonTextChildren && ((_e = groupShiftReflowSnapshotRef.current) == null ? void 0 : _e.selection) === obj) {
13869
13927
  const snap = groupShiftReflowSnapshotRef.current;
13870
13928
  const anchorEntry = snap.children[0];
13871
13929
  const anchorTopLive = anchorEntry.obj.top ?? 0;
@@ -13898,12 +13956,17 @@ const PageCanvas = forwardRef(
13898
13956
  if (cornersBefore) {
13899
13957
  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 };
13900
13958
  }
13901
- const nonTextPinsBeforeLayout = hasRotatedChild ? new Map(obj.getObjects().map((child) => [child, { left: child.left ?? 0, top: child.top ?? 0 }])) : void 0;
13959
+ const nonTextPinsBeforeLayout = shouldPinNonTextChildren ? new Map(obj.getObjects().map((child) => [child, {
13960
+ left: child.left ?? 0,
13961
+ top: child.top ?? 0,
13962
+ worldCenter: child instanceof fabric.Textbox ? void 0 : child.getCenterPoint()
13963
+ }])) : void 0;
13902
13964
  try {
13903
13965
  obj.triggerLayout();
13904
13966
  } catch {
13905
13967
  }
13906
13968
  restoreNonTextChildren(nonTextPinsBeforeLayout);
13969
+ restoredNonTextAfterLayout = !!nonTextPinsBeforeLayout;
13907
13970
  obj._set("width", asW0);
13908
13971
  obj._set("scaleX", asSx0);
13909
13972
  obj._set("scaleY", asSy0);
@@ -13929,7 +13992,7 @@ const PageCanvas = forwardRef(
13929
13992
  obj._set("left", asLeft0);
13930
13993
  obj._set("top", asTop0);
13931
13994
  }
13932
- restoreNonTextChildren();
13995
+ if (!restoredNonTextAfterLayout) restoreNonTextChildren();
13933
13996
  obj._set("width", asW0);
13934
13997
  obj._set("scaleX", asSx0);
13935
13998
  obj._set("scaleY", asSy0);
@@ -14385,8 +14448,9 @@ const PageCanvas = forwardRef(
14385
14448
  const stateCrop = useEditorStore.getState();
14386
14449
  const pageCrop = stateCrop.canvas.pages.find((p) => p.id === pageId);
14387
14450
  const pageChildrenCrop = (pageCrop == null ? void 0 : pageCrop.children) ?? [];
14388
- const absLeft = (active.left ?? 0) - ct.frameW / 2;
14389
- const absTop = (active.top ?? 0) - ct.frameH / 2;
14451
+ const angleRad = (active.angle ?? 0) * Math.PI / 180;
14452
+ const absLeft = (active.left ?? 0) - ct.frameW / 2 * Math.cos(angleRad) + ct.frameH / 2 * Math.sin(angleRad);
14453
+ const absTop = (active.top ?? 0) - ct.frameW / 2 * Math.sin(angleRad) - ct.frameH / 2 * Math.cos(angleRad);
14390
14454
  const storePosCrop = absoluteToStorePosition(absLeft, absTop, objId, pageChildrenCrop);
14391
14455
  updateElement2(objId, {
14392
14456
  width: ct.frameW,
@@ -14747,14 +14811,22 @@ const PageCanvas = forwardRef(
14747
14811
  } else {
14748
14812
  const w = ((ct == null ? void 0 : ct.frameW) ?? obj.width ?? 0) * Math.abs(obj.scaleX ?? 1);
14749
14813
  const h = ((ct == null ? void 0 : ct.frameH) ?? obj.height ?? 0) * Math.abs(obj.scaleY ?? 1);
14750
- absoluteLeft = (absoluteLeft ?? 0) - w / 2;
14751
- absoluteTop = (absoluteTop ?? 0) - h / 2;
14814
+ const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
14815
+ absoluteLeft = (decomposed.translateX ?? absoluteLeft ?? 0) - w / 2 * Math.cos(angleRad) + h / 2 * Math.sin(angleRad);
14816
+ absoluteTop = (decomposed.translateY ?? absoluteTop ?? 0) - w / 2 * Math.sin(angleRad) - h / 2 * Math.cos(angleRad);
14752
14817
  }
14753
14818
  } else if (obj instanceof fabric.FabricImage && (obj.originX === "center" || obj.originY === "center")) {
14754
- const w = (obj.width ?? 0) * (obj.scaleX ?? 1);
14755
- const h = (obj.height ?? 0) * (obj.scaleY ?? 1);
14756
- absoluteLeft = (absoluteLeft ?? 0) - w / 2;
14757
- absoluteTop = (absoluteTop ?? 0) - h / 2;
14819
+ if (isActiveSelection && activeObj instanceof fabric.ActiveSelection) {
14820
+ const frameBounds = getObjectFrameBoundsInSelection(activeObj, obj, obj.width ?? 0, obj.height ?? 0);
14821
+ absoluteLeft = frameBounds.left;
14822
+ absoluteTop = frameBounds.top;
14823
+ } else {
14824
+ const w = (obj.width ?? 0) * (obj.scaleX ?? 1);
14825
+ const h = (obj.height ?? 0) * (obj.scaleY ?? 1);
14826
+ const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
14827
+ absoluteLeft = (decomposed.translateX ?? absoluteLeft ?? 0) - w / 2 * Math.cos(angleRad) + h / 2 * Math.sin(angleRad);
14828
+ absoluteTop = (decomposed.translateY ?? absoluteTop ?? 0) - w / 2 * Math.sin(angleRad) - h / 2 * Math.cos(angleRad);
14829
+ }
14758
14830
  }
14759
14831
  const preserveCornerGeometry = (sourceElement == null ? void 0 : sourceElement.type) === "shape" && (sourceElement.shapeType === "circle" || sourceElement.shapeType === "rounded-rect" || sourceElement.shapeType === "triangle");
14760
14832
  let finalWidth = intrinsicWidth;
@@ -14781,12 +14853,14 @@ const PageCanvas = forwardRef(
14781
14853
  absoluteLeft = frameBounds.left;
14782
14854
  absoluteTop = frameBounds.top;
14783
14855
  } else {
14784
- absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2;
14785
- absoluteTop = (decomposed.translateY ?? absoluteTop) - finalHeight / 2;
14856
+ const angleRad = (decomposed.angle ?? obj.angle ?? 0) * Math.PI / 180;
14857
+ absoluteLeft = (decomposed.translateX ?? absoluteLeft) - finalWidth / 2 * Math.cos(angleRad) + finalHeight / 2 * Math.sin(angleRad);
14858
+ absoluteTop = (decomposed.translateY ?? absoluteTop) - finalWidth / 2 * Math.sin(angleRad) - finalHeight / 2 * Math.cos(angleRad);
14786
14859
  }
14860
+ const finalCenter = rotatedTopLeftToCenter(absoluteLeft, absoluteTop, finalWidth, finalHeight, decomposed.angle ?? (obj.angle ?? 0));
14787
14861
  finalAbsoluteMatrix = fabric.util.composeMatrix({
14788
- translateX: absoluteLeft + finalWidth / 2,
14789
- translateY: absoluteTop + finalHeight / 2,
14862
+ translateX: finalCenter.x,
14863
+ translateY: finalCenter.y,
14790
14864
  angle: decomposed.angle ?? (obj.angle ?? 0),
14791
14865
  scaleX: 1,
14792
14866
  scaleY: 1,
@@ -15172,9 +15246,10 @@ const PageCanvas = forwardRef(
15172
15246
  if (!ct) continue;
15173
15247
  ct.frameW = bake.width;
15174
15248
  ct.frameH = bake.height;
15249
+ const bakeCenter = rotatedTopLeftToCenter(bake.left, bake.top, bake.width, bake.height, bake.angle);
15175
15250
  bake.obj.set({
15176
- left: bake.left + bake.width / 2,
15177
- top: bake.top + bake.height / 2,
15251
+ left: bakeCenter.x,
15252
+ top: bakeCenter.y,
15178
15253
  width: bake.width,
15179
15254
  height: bake.height,
15180
15255
  scaleX: 1,
@@ -15771,8 +15846,9 @@ const PageCanvas = forwardRef(
15771
15846
  const node = findNodeById(pageChildren, element.id);
15772
15847
  return node ? getAbsoluteBounds(node, pageChildren) : { left: element.left ?? 0, top: element.top ?? 0 };
15773
15848
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
15774
- const cropCenterX = cropPos.left + (ct.frameW ?? 0) / 2;
15775
- const cropCenterY = cropPos.top + (ct.frameH ?? 0) / 2;
15849
+ const cropCenter = rotatedTopLeftToCenter(cropPos.left, cropPos.top, ct.frameW ?? 0, ct.frameH ?? 0, element.angle ?? 0);
15850
+ const cropCenterX = cropCenter.x;
15851
+ const cropCenterY = cropCenter.y;
15776
15852
  if (element.left !== void 0) existingObj.set({ left: cropCenterX });
15777
15853
  if (element.top !== void 0) existingObj.set({ top: cropCenterY });
15778
15854
  if (element.angle !== void 0) existingObj.set({ angle: element.angle });
@@ -16708,8 +16784,9 @@ const PageCanvas = forwardRef(
16708
16784
  ct.shape = clipShape === "circle" ? "circle" : clipShape === "rounded" ? "roundRect" : "rect";
16709
16785
  ct.rx = rxRatio;
16710
16786
  obj.__maintainResolution = element.maintainResolution !== false;
16711
- const centerX = fabricPos.left + elementWidth / 2;
16712
- const centerY = fabricPos.top + elementHeight / 2;
16787
+ const center = rotatedTopLeftToCenter(fabricPos.left, fabricPos.top, elementWidth, elementHeight, element.angle ?? 0);
16788
+ const centerX = center.x;
16789
+ const centerY = center.y;
16713
16790
  const cropSetProps = {
16714
16791
  width: elementWidth,
16715
16792
  height: elementHeight,
@@ -16949,7 +17026,8 @@ const PageCanvas = forwardRef(
16949
17026
  if (!skipPositionUpdate && (obj instanceof fabric.FabricImage && obj.originX === "center" || obj instanceof fabric.Group && obj.__cropGroup)) {
16950
17027
  const vW = rW * effectiveScaleX;
16951
17028
  const vH = rH * effectiveScaleY;
16952
- posIfNotSkipped = { left: fabricPos.left + vW / 2, top: fabricPos.top + vH / 2 };
17029
+ const center = rotatedTopLeftToCenter(fabricPos.left, fabricPos.top, vW, vH, element.angle ?? 0);
17030
+ posIfNotSkipped = { left: center.x, top: center.y };
16953
17031
  }
16954
17032
  if (element.transformMatrix && element.transformMatrix.length === 6) {
16955
17033
  if (isTextbox) {
@@ -24247,9 +24325,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
24247
24325
  }
24248
24326
  return svgString;
24249
24327
  }
24250
- const resolvedPackageVersion = "0.5.330";
24328
+ const resolvedPackageVersion = "0.5.332";
24251
24329
  const PACKAGE_VERSION = resolvedPackageVersion;
24252
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.330";
24330
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.332";
24253
24331
  const roundParityValue = (value) => {
24254
24332
  if (typeof value !== "number") return value;
24255
24333
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -25063,7 +25141,7 @@ class PixldocsRenderer {
25063
25141
  await this.waitForCanvasScene(container, cloned, i);
25064
25142
  }
25065
25143
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
25066
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-BIkOnJF2.js");
25144
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-BE-V6kqQ.js");
25067
25145
  const prepared = preparePagesForExport(
25068
25146
  cloned.pages,
25069
25147
  canvasWidth,
@@ -27383,7 +27461,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
27383
27461
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
27384
27462
  sanitizeSvgTreeForPdf(svgToDraw);
27385
27463
  try {
27386
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-BIkOnJF2.js");
27464
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-BE-V6kqQ.js");
27387
27465
  try {
27388
27466
  await logTextMeasurementDiagnostic(svgToDraw);
27389
27467
  } catch {
@@ -27783,4 +27861,4 @@ export {
27783
27861
  buildTeaserBlurFlatKeys as y,
27784
27862
  collectFontDescriptorsFromConfig as z
27785
27863
  };
27786
- //# sourceMappingURL=index-B6Ucv-_d.js.map
27864
+ //# sourceMappingURL=index-xMYBX3BX.js.map