@pixldocs/canvas-renderer 0.5.270 → 0.5.272

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.
@@ -12722,7 +12722,9 @@ const PageCanvas = react.forwardRef(
12722
12722
  const selection = new fabric__namespace.ActiveSelection(members, { canvas: fc });
12723
12723
  restoreGroupSelectionVisualState(selection, groupId);
12724
12724
  fc.setActiveObject(selection);
12725
- selection.setCoords();
12725
+ if (!selection.getObjects().every((obj) => !(obj instanceof fabric__namespace.Group))) {
12726
+ selection.setCoords();
12727
+ }
12726
12728
  fc.requestRenderAll();
12727
12729
  } finally {
12728
12730
  requestAnimationFrame(() => {
@@ -13906,7 +13908,7 @@ const PageCanvas = react.forwardRef(
13906
13908
  });
13907
13909
  let cropGroupSaveTimer = null;
13908
13910
  fabricCanvas.on("object:modified", (e) => {
13909
- var _a2, _b2, _c, _d, _e, _f, _g;
13911
+ var _a2, _b2, _c, _d, _e, _f, _g, _h;
13910
13912
  try {
13911
13913
  dragStarted = false;
13912
13914
  setGuides([]);
@@ -14322,6 +14324,7 @@ const PageCanvas = react.forwardRef(
14322
14324
  drilledGroupIdRef.current = null;
14323
14325
  const groupSelectionId = (isActiveSelection && activeObj instanceof fabric__namespace.ActiveSelection ? activeObj.__pixldocsGroupSelection : void 0) ?? groupToMove.id;
14324
14326
  const targetObjects = isActiveSelection && activeObj instanceof fabric__namespace.ActiveSelection ? activeObj.getObjects() : activeObjects;
14327
+ let preservedGroupMemberIds = targetObjects.map((obj) => getObjectId(obj)).filter((id) => !!id && id !== "__background__");
14325
14328
  if (groupSelectionId && activeObj instanceof fabric__namespace.ActiveSelection) {
14326
14329
  try {
14327
14330
  skipSelectionClearOnDiscardRef.current = true;
@@ -14334,15 +14337,35 @@ const PageCanvas = react.forwardRef(
14334
14337
  }
14335
14338
  } catch {
14336
14339
  }
14337
- const bakedSelection = targetObjects.length > 1 ? new fabric__namespace.ActiveSelection(targetObjects, { canvas: fabricCanvas }) : activeObj;
14340
+ const pageAfterMove = ((_g = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _g.children) ?? [];
14341
+ const groupAfterMove = findNodeById(pageAfterMove, groupToMove.id);
14342
+ const memberIdsAfterMove = groupAfterMove && isGroup(groupAfterMove) ? getAllElementIds(groupAfterMove.children ?? []) : targetObjects.map((obj) => getObjectId(obj)).filter((id) => !!id && id !== "__background__");
14343
+ preservedGroupMemberIds = memberIdsAfterMove;
14344
+ const reselectionObjects = memberIdsAfterMove.map((id) => targetObjects.find((obj) => getObjectId(obj) === id) ?? fabricCanvas.getObjects().find((obj) => getObjectId(obj) === id)).filter((obj) => !!obj);
14345
+ for (const obj of reselectionObjects) {
14346
+ const id = getObjectId(obj);
14347
+ const node = id ? findNodeById(pageAfterMove, id) : null;
14348
+ if (!node) continue;
14349
+ const abs = getAbsoluteBounds(node, pageAfterMove, pageBoundsOptions);
14350
+ const bounds = getNodeBounds(node, pageAfterMove, pageBoundsOptions);
14351
+ if (obj instanceof fabric__namespace.Group && obj.__cropGroup || obj instanceof fabric__namespace.FabricImage && (obj.originX === "center" || obj.originY === "center")) {
14352
+ obj.set({ left: abs.left + Math.max(1, bounds.width) / 2, top: abs.top + Math.max(1, bounds.height) / 2 });
14353
+ } else {
14354
+ obj.set({ left: abs.left, top: abs.top });
14355
+ }
14356
+ obj.setCoords();
14357
+ }
14358
+ const bakedSelection = reselectionObjects.length > 1 ? new fabric__namespace.ActiveSelection(reselectionObjects, { canvas: fabricCanvas }) : activeObj;
14338
14359
  restoreGroupSelectionVisualState(bakedSelection, groupSelectionId);
14339
14360
  fabricCanvas.setActiveObject(bakedSelection);
14340
- bakedSelection.setCoords();
14361
+ if (!(bakedSelection instanceof fabric__namespace.ActiveSelection && bakedSelection.getObjects().every((obj) => !(obj instanceof fabric__namespace.Group)))) {
14362
+ bakedSelection.setCoords();
14363
+ }
14341
14364
  }
14342
14365
  selectElements([groupSelectionId], false, false);
14343
14366
  fabricCanvas.requestRenderAll();
14344
14367
  elementsRef.current = getCurrentElements();
14345
- for (const obj of targetObjects) {
14368
+ for (const obj of targetObjects.length ? targetObjects : activeObjects) {
14346
14369
  const objId = getObjectId(obj);
14347
14370
  if (objId && objId !== "__background__") {
14348
14371
  justModifiedIdsRef.current.add(objId);
@@ -14352,7 +14375,7 @@ const PageCanvas = react.forwardRef(
14352
14375
  setTimeout(() => modifiedIdsThisRound.forEach((id) => justModifiedIdsRef.current.delete(id)), 150);
14353
14376
  groupSelectionTransformStartRef.current = null;
14354
14377
  restorePreservedGroupSelectionSoon({
14355
- memberIds: targetObjects.map((obj) => getObjectId(obj)).filter((id) => !!id && id !== "__background__"),
14378
+ memberIds: preservedGroupMemberIds,
14356
14379
  groupSelectionId
14357
14380
  });
14358
14381
  unlockEditsSoon();
@@ -14616,7 +14639,7 @@ const PageCanvas = react.forwardRef(
14616
14639
  updateElement(objId, elementUpdate, { recordHistory: false, skipLayoutRecalc: true });
14617
14640
  obj.setCoords();
14618
14641
  }
14619
- const pageChildrenForReflow = ((_g = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _g.children) ?? [];
14642
+ const pageChildrenForReflow = ((_h = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _h.children) ?? [];
14620
14643
  const stackGroupsToReflow = /* @__PURE__ */ new Set();
14621
14644
  for (const id of modifiedIdsThisRound) {
14622
14645
  const parent = findParentGroup(pageChildrenForReflow, id);
@@ -15119,9 +15142,42 @@ const PageCanvas = react.forwardRef(
15119
15142
  };
15120
15143
  fc.add(sectionGroup);
15121
15144
  }
15145
+ const getActiveSelectionContainingObject = (obj) => {
15146
+ const active = fc.getActiveObject();
15147
+ return active instanceof fabric__namespace.ActiveSelection && active.getObjects().includes(obj) ? active : null;
15148
+ };
15149
+ const shouldPreserveActiveSelectionMemberPosition = (obj) => {
15150
+ if (syncTriggeredByPanelRef.current) return false;
15151
+ const activeSelection = getActiveSelectionContainingObject(obj);
15152
+ if (!activeSelection) return false;
15153
+ const logicalActiveSelection = activeSelection;
15154
+ const logicalGroupId = logicalActiveSelection.__pixldocsGroupSelection;
15155
+ const logicalGroupIds = logicalActiveSelection.__pixldocsLogicalGroupIds;
15156
+ if (logicalGroupId || Array.isArray(logicalGroupIds)) return true;
15157
+ const id = getObjectId(obj);
15158
+ const preserved = preserveActiveSelectionAfterTransformRef.current;
15159
+ return !!(id && (preserved == null ? void 0 : preserved.memberIds.includes(id)) && (!preserved.expiresAt || preserved.expiresAt > Date.now()));
15160
+ };
15161
+ const getObjectSyncComparePosition = (obj) => {
15162
+ const activeSelection = getActiveSelectionContainingObject(obj);
15163
+ if (!activeSelection) return { left: obj.left ?? 0, top: obj.top ?? 0 };
15164
+ const point = fabric__namespace.util.transformPoint({ x: obj.left ?? 0, y: obj.top ?? 0 }, activeSelection.calcTransformMatrix());
15165
+ let left = point.x;
15166
+ let top = point.y;
15167
+ const cropObj = obj;
15168
+ if (obj instanceof fabric__namespace.Group && cropObj.__cropGroup) {
15169
+ const ct = cropObj.__cropData;
15170
+ left -= ((ct == null ? void 0 : ct.frameW) ?? obj.width ?? 0) * Math.abs(obj.scaleX ?? 1) / 2;
15171
+ top -= ((ct == null ? void 0 : ct.frameH) ?? obj.height ?? 0) * Math.abs(obj.scaleY ?? 1) / 2;
15172
+ } else if (obj instanceof fabric__namespace.FabricImage && (obj.originX === "center" || obj.originY === "center")) {
15173
+ left -= (obj.width ?? 0) * Math.abs(obj.scaleX ?? 1) / 2;
15174
+ top -= (obj.height ?? 0) * Math.abs(obj.scaleY ?? 1) / 2;
15175
+ }
15176
+ return { left, top };
15177
+ };
15122
15178
  for (const element of elementsToSync) {
15123
15179
  if (sectionDescendantIds.has(element.id)) continue;
15124
- let existingObj = currentFabricObjects.get(element.id);
15180
+ const existingObj = currentFabricObjects.get(element.id);
15125
15181
  const isHidden = !element.visible;
15126
15182
  if (existingObj) {
15127
15183
  const isBeingTransformed = transformingIdsRef.current.has(element.id);
@@ -15415,7 +15471,9 @@ const PageCanvas = react.forwardRef(
15415
15471
  const node = findNodeById(pageTree, element.id);
15416
15472
  return node ? getAbsoluteBounds(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
15417
15473
  })() : { left: element.left ?? 0, top: element.top ?? 0 };
15418
- const positionChanged = Math.abs((existingObj.left ?? 0) - storePosForImg.left) > 0.1 || Math.abs((existingObj.top ?? 0) - storePosForImg.top) > 0.1;
15474
+ const comparePosForImg = getObjectSyncComparePosition(existingObj);
15475
+ const preserveSelectionMemberPosition = shouldPreserveActiveSelectionMemberPosition(existingObj);
15476
+ const positionChanged = !preserveSelectionMemberPosition && (Math.abs(comparePosForImg.left - storePosForImg.left) > 0.1 || Math.abs(comparePosForImg.top - storePosForImg.top) > 0.1);
15419
15477
  if (visibilityChanged && !positionChanged || visibilityUpdateInProgressRef.current) {
15420
15478
  const isDynamicField = dynamicFieldIds.includes(element.id);
15421
15479
  const canBeEvented = isEditorMode || isPreviewMode && isDynamicField;
@@ -15430,7 +15488,7 @@ const PageCanvas = react.forwardRef(
15430
15488
  previousVisibilityRef.current.set(element.id, currentVisible);
15431
15489
  } else {
15432
15490
  if (!visibilityUpdateInProgressRef.current) {
15433
- updateFabricObject(existingObj, element, wasJustModified);
15491
+ updateFabricObject(existingObj, element, wasJustModified || preserveSelectionMemberPosition);
15434
15492
  }
15435
15493
  const isDynamicField = dynamicFieldIds.includes(element.id);
15436
15494
  const canBeEvented = isEditorMode || isPreviewMode && isDynamicField;
@@ -15452,8 +15510,9 @@ const PageCanvas = react.forwardRef(
15452
15510
  if (!isBeingTransformed && !isBeingTextEdited && !shouldSkipUpdates2) {
15453
15511
  previousVisibilityRef.current.get(element.id) ?? true;
15454
15512
  const currentVisible = element.visible !== false;
15455
- const fabricLeft = existingObj.left ?? 0;
15456
- const fabricTop = existingObj.top ?? 0;
15513
+ const comparePos = getObjectSyncComparePosition(existingObj);
15514
+ const fabricLeft = comparePos.left;
15515
+ const fabricTop = comparePos.top;
15457
15516
  const storePos = pageTree.length ? (() => {
15458
15517
  const node = findNodeById(pageTree, element.id);
15459
15518
  return node ? getAbsoluteBounds(node, pageTree) : { left: element.left ?? 0, top: element.top ?? 0 };
@@ -15462,7 +15521,8 @@ const PageCanvas = react.forwardRef(
15462
15521
  const storeTop = storePos.top;
15463
15522
  const deltaX = Math.abs(fabricLeft - storeLeft);
15464
15523
  const deltaY = Math.abs(fabricTop - storeTop);
15465
- let positionChanged = deltaX > 0.1 || deltaY > 0.1;
15524
+ const preserveSelectionMemberPosition = shouldPreserveActiveSelectionMemberPosition(existingObj);
15525
+ let positionChanged = !preserveSelectionMemberPosition && (deltaX > 0.1 || deltaY > 0.1);
15466
15526
  const activeObj = fc.getActiveObject();
15467
15527
  const isInActiveSelection = activeObj && (activeObj instanceof fabric__namespace.ActiveSelection ? activeObj.getObjects().includes(existingObj) : activeObj === existingObj);
15468
15528
  const isInSelectedIds = selectedIdsFromStore.has(element.id);
@@ -15514,7 +15574,7 @@ const PageCanvas = react.forwardRef(
15514
15574
  });
15515
15575
  previousVisibilityRef.current.set(element.id, currentVisible);
15516
15576
  } else {
15517
- const skipPositionBecauseSelection = isSelected && (deltaX > 0.1 || deltaY > 0.1) && (wasJustModified || isBeingTransformed);
15577
+ const skipPositionBecauseSelection = preserveSelectionMemberPosition || isSelected && (deltaX > 0.1 || deltaY > 0.1) && (wasJustModified || isBeingTransformed);
15518
15578
  const anyChange = positionChanged || otherPropsChanged || forceApplyFromPanel;
15519
15579
  if (!visibilityUpdateInProgressRef.current) {
15520
15580
  if (anyChange && !skipPositionBecauseSelection) {
@@ -23696,9 +23756,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
23696
23756
  }
23697
23757
  return svgString;
23698
23758
  }
23699
- const resolvedPackageVersion = "0.5.270";
23759
+ const resolvedPackageVersion = "0.5.272";
23700
23760
  const PACKAGE_VERSION = resolvedPackageVersion;
23701
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.270";
23761
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.272";
23702
23762
  const roundParityValue = (value) => {
23703
23763
  if (typeof value !== "number") return value;
23704
23764
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -24512,7 +24572,7 @@ class PixldocsRenderer {
24512
24572
  await this.waitForCanvasScene(container, cloned, i);
24513
24573
  }
24514
24574
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
24515
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BpHyRyQS.cjs"));
24575
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-CdiLpR0-.cjs"));
24516
24576
  const prepared = preparePagesForExport(
24517
24577
  cloned.pages,
24518
24578
  canvasWidth,
@@ -26832,7 +26892,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
26832
26892
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
26833
26893
  sanitizeSvgTreeForPdf(svgToDraw);
26834
26894
  try {
26835
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BpHyRyQS.cjs"));
26895
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-CdiLpR0-.cjs"));
26836
26896
  try {
26837
26897
  await logTextMeasurementDiagnostic(svgToDraw);
26838
26898
  } catch {
@@ -27229,4 +27289,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
27229
27289
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
27230
27290
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
27231
27291
  exports.warmTemplateFromForm = warmTemplateFromForm;
27232
- //# sourceMappingURL=index-CLq3CdA3.cjs.map
27292
+ //# sourceMappingURL=index-BYfp_ae9.cjs.map