@pixldocs/canvas-renderer 0.5.451 → 0.5.453

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.
@@ -11711,13 +11711,35 @@ const angleDistanceDeg = (a, b) => {
11711
11711
  const delta = Math.abs(((a - b) % 360 + 540) % 360 - 180);
11712
11712
  return Number.isFinite(delta) ? delta : Number.POSITIVE_INFINITY;
11713
11713
  };
11714
- const normalizeMatrixForPersistedFlip = (matrix, persistedFlipX, persistedFlipY, expectedCleanAngle) => {
11714
+ const normalizeSignedAngleDeg = (angle) => {
11715
+ if (!Number.isFinite(angle)) return 0;
11716
+ const normalized = (angle % 360 + 540) % 360 - 180;
11717
+ return Math.abs(normalized) < 1e-9 ? 0 : normalized;
11718
+ };
11719
+ const resolveActiveSelectionLocalAngle = (obj, sourceElement, activeSelection) => {
11720
+ var _a2;
11721
+ const objectAngle = Number.isFinite(obj.angle) ? obj.angle ?? 0 : 0;
11722
+ const isImageLike = obj instanceof fabric__namespace.FabricImage || obj instanceof fabric__namespace.Group && (obj.__cropGroup || ((_a2 = obj._ct) == null ? void 0 : _a2.isCropGroup));
11723
+ const hasPersistedFlip = !!((sourceElement == null ? void 0 : sourceElement.flipX) || (sourceElement == null ? void 0 : sourceElement.flipY) || obj.flipX || obj.flipY);
11724
+ if (!isImageLike || !hasPersistedFlip || !Number.isFinite(sourceElement == null ? void 0 : sourceElement.angle)) {
11725
+ return normalizeSignedAngleDeg(objectAngle);
11726
+ }
11727
+ return normalizeSignedAngleDeg((sourceElement.angle ?? 0) - ((activeSelection == null ? void 0 : activeSelection.angle) ?? 0));
11728
+ };
11729
+ const resolveStableFlippedAngle = (fabricAngle, sourceAngle, hasFlip, isRotationGesture = false) => {
11730
+ const current = Number.isFinite(fabricAngle) ? fabricAngle : sourceAngle ?? 0;
11731
+ if (!hasFlip || isRotationGesture || !Number.isFinite(sourceAngle)) return current;
11732
+ const src = sourceAngle;
11733
+ const isFabricFlipEncoding = angleDistanceDeg(current, src + 180) < 2 && angleDistanceDeg(current, src) > 90;
11734
+ return isFabricFlipEncoding ? src : current;
11735
+ };
11736
+ const stripPersistedFlipForStableAngle = (matrix, persistedFlipX, persistedFlipY, expectedCleanAngle) => {
11715
11737
  if (!persistedFlipX && !persistedFlipY) return matrix;
11716
- if (!Number.isFinite(expectedCleanAngle)) return matrix;
11717
- const toggledVisual = toggleLogicalFlipInMatrix(matrix, persistedFlipX, persistedFlipY);
11718
- const cleanIfMatrixAlreadyHasFlip = fabric__namespace.util.qrDecompose(toggleLogicalFlipInMatrix(matrix, persistedFlipX, persistedFlipY)).angle ?? 0;
11719
- const cleanIfMatrixLostFlip = fabric__namespace.util.qrDecompose(matrix).angle ?? 0;
11720
- return angleDistanceDeg(cleanIfMatrixLostFlip, expectedCleanAngle) + 0.1 < angleDistanceDeg(cleanIfMatrixAlreadyHasFlip, expectedCleanAngle) ? toggledVisual : matrix;
11738
+ const toggled = toggleLogicalFlipInMatrix(matrix, persistedFlipX, persistedFlipY);
11739
+ if (!Number.isFinite(expectedCleanAngle)) return toggled;
11740
+ const asIsAngle = fabric__namespace.util.qrDecompose(matrix).angle ?? 0;
11741
+ const toggledAngle = fabric__namespace.util.qrDecompose(toggled).angle ?? 0;
11742
+ return angleDistanceDeg(toggledAngle, expectedCleanAngle) <= angleDistanceDeg(asIsAngle, expectedCleanAngle) ? toggled : matrix;
11721
11743
  };
11722
11744
  function applyWarpAwareSelectionBorders(selection) {
11723
11745
  var _a2;
@@ -14957,8 +14979,18 @@ const PageCanvas = react.forwardRef(
14957
14979
  child.__asLiveGestureKey = liveGestureKey;
14958
14980
  const childIdForAngle = getObjectId(child);
14959
14981
  const sourceChildForAngle = childIdForAngle ? elementsRef.current.find((el) => el.id === childIdForAngle) : null;
14960
- const isFlippedImageLikeChild = (child instanceof fabric__namespace.FabricImage || child instanceof fabric__namespace.Group && (child.__cropGroup || ((_m = child._ct) == null ? void 0 : _m.isCropGroup))) && !!((sourceChildForAngle == null ? void 0 : sourceChildForAngle.flipX) || (sourceChildForAngle == null ? void 0 : sourceChildForAngle.flipY)) && Number.isFinite(sourceChildForAngle == null ? void 0 : sourceChildForAngle.angle);
14961
- child.__asLiveOrigAngle = isFlippedImageLikeChild ? sourceChildForAngle.angle ?? 0 : Number.isFinite(child.angle) ? child.angle ?? 0 : 0;
14982
+ const persistedChildFlipX = (sourceChildForAngle == null ? void 0 : sourceChildForAngle.flipX) ?? child.flipX ?? false;
14983
+ const persistedChildFlipY = (sourceChildForAngle == null ? void 0 : sourceChildForAngle.flipY) ?? child.flipY ?? false;
14984
+ if (child instanceof fabric__namespace.FabricImage || child instanceof fabric__namespace.Group && (child.__cropGroup || ((_m = child._ct) == null ? void 0 : _m.isCropGroup))) {
14985
+ child.set({ flipX: persistedChildFlipX, flipY: persistedChildFlipY });
14986
+ child.__asLivePersistedFlipX = persistedChildFlipX;
14987
+ child.__asLivePersistedFlipY = persistedChildFlipY;
14988
+ }
14989
+ child.__asLiveOrigAngle = resolveActiveSelectionLocalAngle(
14990
+ child,
14991
+ sourceChildForAngle,
14992
+ obj
14993
+ );
14962
14994
  }
14963
14995
  if (child instanceof fabric__namespace.Group && (child.__cropGroup || ((_n = child._ct) == null ? void 0 : _n.isCropGroup))) {
14964
14996
  const ct = child.__cropData;
@@ -15012,6 +15044,8 @@ const PageCanvas = react.forwardRef(
15012
15044
  child._set("scaleY", decC.scaleY);
15013
15045
  child._set("skewX", decC.skewX);
15014
15046
  child._set("skewY", decC.skewY);
15047
+ child._set("flipX", child.__asLivePersistedFlipX ?? child.flipX ?? false);
15048
+ child._set("flipY", child.__asLivePersistedFlipY ?? child.flipY ?? false);
15015
15049
  } catch {
15016
15050
  }
15017
15051
  try {
@@ -15069,6 +15103,8 @@ const PageCanvas = react.forwardRef(
15069
15103
  child._set("scaleY", decI.scaleY);
15070
15104
  child._set("skewX", decI.skewX);
15071
15105
  child._set("skewY", decI.skewY);
15106
+ child._set("flipX", child.__asLivePersistedFlipX ?? child.flipX ?? false);
15107
+ child._set("flipY", child.__asLivePersistedFlipY ?? child.flipY ?? false);
15072
15108
  } catch {
15073
15109
  }
15074
15110
  child.setCoords();
@@ -15964,12 +16000,15 @@ const PageCanvas = react.forwardRef(
15964
16000
  360 - Math.abs(currentSelAngle - startSelAngle)
15965
16001
  );
15966
16002
  const hadRotation = isActiveSelection && activeObj && angleDelta > 0.01;
15967
- if (!hadScale && !hadRotation && (Math.abs(deltaX) > 0.1 || Math.abs(deltaY) > 0.1)) {
16003
+ const isMoveOnlyLogicalGroupGesture = !hadScale && !hadRotation && (Math.abs(deltaX) > 0.1 || Math.abs(deltaY) > 0.1);
16004
+ if (isMoveOnlyLogicalGroupGesture || !hadScale && !hadRotation && activeGroupSelectionId === groupToMove.id) {
15968
16005
  const { updateNode: updateNodeStore, commitHistory: commitHistoryStore, getCurrentElements } = useEditorStore.getState();
15969
- const newLeft = (groupToMove.left ?? 0) + deltaX;
15970
- const newTop = (groupToMove.top ?? 0) + deltaY;
15971
- updateNodeStore(groupToMove.id, { left: newLeft, top: newTop }, { recordHistory: false, skipLayoutRecalc: true });
15972
- commitHistoryStore();
16006
+ if (isMoveOnlyLogicalGroupGesture) {
16007
+ const newLeft = (groupToMove.left ?? 0) + deltaX;
16008
+ const newTop = (groupToMove.top ?? 0) + deltaY;
16009
+ updateNodeStore(groupToMove.id, { left: newLeft, top: newTop }, { recordHistory: false, skipLayoutRecalc: true });
16010
+ commitHistoryStore();
16011
+ }
15973
16012
  pendingGroupDrillInRef.current = null;
15974
16013
  fabricCanvas.__activeEditingGroupId = null;
15975
16014
  setDrilledGroupBounds(null);
@@ -16089,7 +16128,7 @@ const PageCanvas = react.forwardRef(
16089
16128
  if (obj instanceof fabric__namespace.Group && obj.__cropGroup) {
16090
16129
  const ct = obj.__cropData;
16091
16130
  if (ct) {
16092
- const cropChildLocalAngle = obj.__asLiveOrigAngle != null ? obj.__asLiveOrigAngle : obj.angle ?? 0;
16131
+ const cropChildLocalAngle = obj.__asLiveOrigAngle != null ? obj.__asLiveOrigAngle : resolveActiveSelectionLocalAngle(obj, sourceElement, activeObj instanceof fabric__namespace.ActiveSelection ? activeObj : null);
16093
16132
  const cropChildNormAngle = (cropChildLocalAngle % 360 + 360) % 360;
16094
16133
  const cropChildIsRotated = Math.abs(cropChildNormAngle) > 0.5 && Math.abs(cropChildNormAngle - 360) > 0.5;
16095
16134
  const cropHandle = activeSelectionResizeHandle;
@@ -16208,7 +16247,7 @@ const PageCanvas = react.forwardRef(
16208
16247
  useEditorStore.getState().updateElement(objId, { src: newSrc }, { recordHistory: false, skipLayoutRecalc: true });
16209
16248
  }
16210
16249
  } else if (isActiveSelection && (Math.abs((decomposed.scaleX ?? 1) - 1) > 1e-3 || Math.abs((decomposed.scaleY ?? 1) - 1) > 1e-3)) {
16211
- const imgChildLocalAngle = obj.__asLiveOrigAngle != null ? obj.__asLiveOrigAngle : ((sourceElement == null ? void 0 : sourceElement.flipX) || (sourceElement == null ? void 0 : sourceElement.flipY)) && Number.isFinite(sourceElement == null ? void 0 : sourceElement.angle) ? sourceElement.angle ?? 0 : obj.angle ?? 0;
16250
+ const imgChildLocalAngle = obj.__asLiveOrigAngle != null ? obj.__asLiveOrigAngle : resolveActiveSelectionLocalAngle(obj, sourceElement, activeObj instanceof fabric__namespace.ActiveSelection ? activeObj : null);
16212
16251
  const imgChildNormAngle = (imgChildLocalAngle % 360 + 360) % 360;
16213
16252
  const imgChildIsRotated = Math.abs(imgChildNormAngle) > 0.5 && Math.abs(imgChildNormAngle - 360) > 0.5;
16214
16253
  const imgHandle = activeSelectionResizeHandle;
@@ -16527,18 +16566,30 @@ const PageCanvas = react.forwardRef(
16527
16566
  const persistedFlipY = (sourceElement == null ? void 0 : sourceElement.flipY) ?? objectFlipY;
16528
16567
  const isActiveSelectionResizeGesture = activeSelectionResizeHandle === "ml" || activeSelectionResizeHandle === "mr" || activeSelectionResizeHandle === "mt" || activeSelectionResizeHandle === "mb" || activeSelectionResizeHandle === "tl" || activeSelectionResizeHandle === "tr" || activeSelectionResizeHandle === "bl" || activeSelectionResizeHandle === "br";
16529
16568
  const expectedCleanAngle = isActiveSelection && isActiveSelectionResizeGesture ? Number.isFinite(sourceElement == null ? void 0 : sourceElement.angle) ? (sourceElement == null ? void 0 : sourceElement.angle) ?? 0 : Number.isFinite(obj.angle) ? obj.angle ?? 0 : void 0 : void 0;
16530
- const normalizedFinalAbsoluteMatrix = normalizeMatrixForPersistedFlip(
16531
- toggleLogicalFlipInMatrix(
16532
- finalAbsoluteMatrix,
16533
- objectFlipX !== persistedFlipX,
16534
- objectFlipY !== persistedFlipY
16535
- ),
16569
+ const matrixWithPersistedFlipState = toggleLogicalFlipInMatrix(
16570
+ finalAbsoluteMatrix,
16571
+ objectFlipX !== persistedFlipX,
16572
+ objectFlipY !== persistedFlipY
16573
+ );
16574
+ const cleanTransformMatrix = stripPersistedFlipForStableAngle(
16575
+ matrixWithPersistedFlipState,
16536
16576
  persistedFlipX,
16537
16577
  persistedFlipY,
16538
16578
  expectedCleanAngle
16539
16579
  );
16540
- const cleanTransformMatrix = toggleLogicalFlipInMatrix(normalizedFinalAbsoluteMatrix, persistedFlipX, persistedFlipY);
16541
16580
  const persistedDecomposed = fabric__namespace.util.qrDecompose(cleanTransformMatrix);
16581
+ const hasPersistedFlipForAngle = !!(persistedFlipX || persistedFlipY);
16582
+ const isRotationGestureForStableAngle = isActiveSelection && activeObj instanceof fabric__namespace.ActiveSelection ? (() => {
16583
+ var _a3;
16584
+ const startAngle = ((_a3 = groupSelectionTransformStartRef.current) == null ? void 0 : _a3.selection) === activeObj ? groupSelectionTransformStartRef.current.selectionAngle ?? activeObj.angle ?? 0 : activeObj.angle ?? 0;
16585
+ return angleDistanceDeg(activeObj.angle ?? 0, startAngle) > 0.01;
16586
+ })() : !isActiveSelection && modifiedTarget === obj && angleDistanceDeg(obj.angle ?? 0, (sourceElement == null ? void 0 : sourceElement.angle) ?? obj.angle ?? 0) > 0.01;
16587
+ const stablePersistedAngle = resolveStableFlippedAngle(
16588
+ persistedDecomposed.angle,
16589
+ sourceElement == null ? void 0 : sourceElement.angle,
16590
+ hasPersistedFlipForAngle,
16591
+ isRotationGestureForStableAngle
16592
+ );
16542
16593
  const elementUpdate = {
16543
16594
  left: storePos.left,
16544
16595
  top: storePos.top,
@@ -16547,7 +16598,7 @@ const PageCanvas = react.forwardRef(
16547
16598
  // so finalWidth already reflects the new width chosen by the user.
16548
16599
  width: finalWidth,
16549
16600
  height: isLineObj ? 0 : isAutoShrinkText ? typeof autoShrinkStoredHeight === "number" ? autoShrinkStoredHeight : finalHeight : finalHeight,
16550
- angle: persistedDecomposed.angle,
16601
+ angle: stablePersistedAngle,
16551
16602
  skewX: isLineObj ? 0 : persistedDecomposed.skewX,
16552
16603
  skewY: isLineObj ? 0 : persistedDecomposed.skewY,
16553
16604
  scaleX: finalScaleX,
@@ -16619,7 +16670,7 @@ const PageCanvas = react.forwardRef(
16619
16670
  const isCropGroupObj = obj instanceof fabric__namespace.Group && obj.__cropGroup;
16620
16671
  const isPlainImageObj = obj instanceof fabric__namespace.FabricImage && !obj.__cropGroup && !obj.smartElementType;
16621
16672
  if (isActiveSelection && isActiveSelectionSideHandle && (isCropGroupObj || isPlainImageObj)) {
16622
- const childLocalAngleSrc = obj.__asLiveOrigAngle != null ? obj.__asLiveOrigAngle : ((sourceElement == null ? void 0 : sourceElement.flipX) || (sourceElement == null ? void 0 : sourceElement.flipY)) && Number.isFinite(sourceElement == null ? void 0 : sourceElement.angle) ? sourceElement.angle ?? 0 : Number.isFinite(sourceElement == null ? void 0 : sourceElement.angle) ? sourceElement.angle ?? 0 : obj.angle ?? 0;
16673
+ const childLocalAngleSrc = obj.__asLiveOrigAngle != null ? obj.__asLiveOrigAngle : resolveActiveSelectionLocalAngle(obj, sourceElement, activeObj instanceof fabric__namespace.ActiveSelection ? activeObj : null);
16623
16674
  const normAng = (childLocalAngleSrc % 360 + 360) % 360;
16624
16675
  const isRotatedImg = Math.min(normAng, 360 - normAng) > 0.5;
16625
16676
  if (isRotatedImg && activeObj instanceof fabric__namespace.ActiveSelection) {
@@ -16858,6 +16909,8 @@ const PageCanvas = react.forwardRef(
16858
16909
  delete child.__asLiveParentWorldAngle;
16859
16910
  delete child.__asLiveFinalW;
16860
16911
  delete child.__asLiveFinalH;
16912
+ delete child.__asLivePersistedFlipX;
16913
+ delete child.__asLivePersistedFlipY;
16861
16914
  }
16862
16915
  }
16863
16916
  } catch {
@@ -25961,9 +26014,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
25961
26014
  }
25962
26015
  return svgString;
25963
26016
  }
25964
- const resolvedPackageVersion = "0.5.451";
26017
+ const resolvedPackageVersion = "0.5.453";
25965
26018
  const PACKAGE_VERSION = resolvedPackageVersion;
25966
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.451";
26019
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.453";
25967
26020
  const roundParityValue = (value) => {
25968
26021
  if (typeof value !== "number") return value;
25969
26022
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -26777,7 +26830,7 @@ class PixldocsRenderer {
26777
26830
  await this.waitForCanvasScene(container, cloned, i);
26778
26831
  }
26779
26832
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
26780
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-a8L9h6E3.cjs"));
26833
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-B4XYT84_.cjs"));
26781
26834
  const prepared = preparePagesForExport(
26782
26835
  cloned.pages,
26783
26836
  canvasWidth,
@@ -29097,7 +29150,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
29097
29150
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
29098
29151
  sanitizeSvgTreeForPdf(svgToDraw);
29099
29152
  try {
29100
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-a8L9h6E3.cjs"));
29153
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-B4XYT84_.cjs"));
29101
29154
  try {
29102
29155
  await logTextMeasurementDiagnostic(svgToDraw);
29103
29156
  } catch {
@@ -29494,4 +29547,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
29494
29547
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
29495
29548
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
29496
29549
  exports.warmTemplateFromForm = warmTemplateFromForm;
29497
- //# sourceMappingURL=index-xHv8_Y1M.cjs.map
29550
+ //# sourceMappingURL=index-B8LHS1IK.cjs.map