@pixldocs/canvas-renderer 0.5.301 → 0.5.303

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.
@@ -1532,7 +1532,7 @@ const useEditorStore = create((set, get) => ({
1532
1532
  }
1533
1533
  let nextCanvas = updateCurrentPageChildren(state.canvas, () => nextChildren);
1534
1534
  nextCanvas.selectedIds = state.canvas.selectedIds.filter(
1535
- (id) => !ids.includes(id) && !prunedGroupIds.has(id)
1535
+ (id) => !allDeletedIds.has(id) && !prunedGroupIds.has(id)
1536
1536
  );
1537
1537
  if (nextCanvas.themeConfig) {
1538
1538
  const remainingProps = nextCanvas.themeConfig.properties.filter((p) => !allDeletedIds.has(p.elementId));
@@ -11287,6 +11287,41 @@ const PageCanvas = forwardRef(
11287
11287
  const [groupResizeState, setGroupResizeState] = useState(null);
11288
11288
  const [groupOverlayLiveBounds, setGroupOverlayLiveBounds] = useState(null);
11289
11289
  const setGroupOverlayLiveBoundsRef = useRef(setGroupOverlayLiveBounds);
11290
+ const restoreSuppressedGroupMemberVisuals = useCallback(() => {
11291
+ const list = suppressGroupMemberBordersRef.current;
11292
+ if (!list || list.length === 0) return;
11293
+ for (const member of list) {
11294
+ const origBorders = member.__pixldocsOrigHasBorders;
11295
+ const origControls = member.__pixldocsOrigHasControls;
11296
+ const origLockX = member.__pixldocsOrigLockScalingX;
11297
+ if (origBorders !== void 0) member.hasBorders = origBorders;
11298
+ else member.hasBorders = true;
11299
+ if (origControls !== void 0) member.hasControls = origControls;
11300
+ else member.hasControls = true;
11301
+ if (origLockX !== void 0) {
11302
+ member.lockScalingX = origLockX;
11303
+ member.lockScalingY = member.__pixldocsOrigLockScalingY;
11304
+ }
11305
+ delete member.__pixldocsOrigHasBorders;
11306
+ delete member.__pixldocsOrigHasControls;
11307
+ delete member.__pixldocsOrigLockScalingX;
11308
+ delete member.__pixldocsOrigLockScalingY;
11309
+ }
11310
+ suppressGroupMemberBordersRef.current = [];
11311
+ }, []);
11312
+ const clearCanvasActiveVisuals = useCallback((fc) => {
11313
+ setGroupOverlayLiveBoundsRef.current(null);
11314
+ restoreSuppressedGroupMemberVisuals();
11315
+ try {
11316
+ fc.discardActiveObject();
11317
+ const topContext = fc.contextTop;
11318
+ if (topContext && typeof fc.clearContext === "function") {
11319
+ fc.clearContext(topContext);
11320
+ }
11321
+ fc.requestRenderAll();
11322
+ } catch {
11323
+ }
11324
+ }, [restoreSuppressedGroupMemberVisuals]);
11290
11325
  const skipSelectionClearOnDiscardRef = useRef(false);
11291
11326
  const skipActiveSelectionBakeOnClearRef = useRef(false);
11292
11327
  const preserveEditingScopeOnSelectionClearRef = useRef(false);
@@ -11313,6 +11348,7 @@ const PageCanvas = forwardRef(
11313
11348
  const lastTextEditDimensionsRef = useRef(null);
11314
11349
  const lastResizeScaleTargetRef = useRef(null);
11315
11350
  const activeSelectionResizeHandleRef = useRef(null);
11351
+ const groupShiftReflowSnapshotRef = useRef(null);
11316
11352
  const preserveSelectionAfterTransformIdRef = useRef(null);
11317
11353
  const groupSelectionTransformStartRef = useRef(null);
11318
11354
  const activeSelectionMoveStartRef = useRef(null);
@@ -11375,6 +11411,34 @@ const PageCanvas = forwardRef(
11375
11411
  useEffect(() => {
11376
11412
  selectedIdsRef.current = selectedIds;
11377
11413
  }, [selectedIds]);
11414
+ useEffect(() => {
11415
+ const fc = fabricRef.current;
11416
+ if (!fc || !isActive || !currentPage) return;
11417
+ const pageChildren2 = currentPage.children ?? [];
11418
+ const hasMissingSelection = selectedIds.some((id) => !findNodeById(pageChildren2, id));
11419
+ const activeEditingGroupId = fc.__activeEditingGroupId ?? null;
11420
+ const activeEditingGroupMissing = !!activeEditingGroupId && !findNodeById(pageChildren2, activeEditingGroupId);
11421
+ const drilledGroupMissing = !!drilledGroupIdRef.current && !findNodeById(pageChildren2, drilledGroupIdRef.current);
11422
+ const hasGroupEditContext = !!activeEditingGroupId || !!drilledGroupIdRef.current;
11423
+ if (selectedIds.length === 0 && !hasGroupEditContext || hasMissingSelection || activeEditingGroupMissing || drilledGroupMissing) {
11424
+ fc.__activeEditingGroupId = null;
11425
+ drilledGroupIdRef.current = null;
11426
+ setDrilledGroupBounds(null);
11427
+ preserveActiveSelectionAfterTransformRef.current = null;
11428
+ recentGroupSelectionRestoreRef.current = null;
11429
+ clearCanvasActiveVisuals(fc);
11430
+ } else if (hasGroupEditContext) {
11431
+ requestAnimationFrame(() => {
11432
+ var _a2;
11433
+ if (fabricRef.current !== fc) return;
11434
+ try {
11435
+ (_a2 = fc.__updateDrilledGroupOutline) == null ? void 0 : _a2.call(fc);
11436
+ } catch {
11437
+ }
11438
+ fc.requestRenderAll();
11439
+ });
11440
+ }
11441
+ }, [selectedIds, currentPage, isActive, clearCanvasActiveVisuals]);
11378
11442
  useEffect(() => {
11379
11443
  isActiveRef.current = isActive;
11380
11444
  if (isEditorMode && isActive && fabricRef.current) ;
@@ -13442,7 +13506,7 @@ const PageCanvas = forwardRef(
13442
13506
  fabricCanvas.on("selection:cleared", () => {
13443
13507
  });
13444
13508
  fabricCanvas.on("object:scaling", (e) => {
13445
- var _a2, _b2, _c;
13509
+ var _a2, _b2, _c, _d, _e, _f;
13446
13510
  if (!isActiveRef.current) return;
13447
13511
  const t = e.target;
13448
13512
  if (t) lastResizeScaleTargetRef.current = t;
@@ -13619,6 +13683,33 @@ const PageCanvas = forwardRef(
13619
13683
  const isXSide = corner === "ml" || corner === "mr";
13620
13684
  const sAxis = isXSide ? Math.abs(obj.scaleX ?? 1) : Math.abs(obj.scaleY ?? 1);
13621
13685
  if (sAxis > 1e-3) {
13686
+ if (isXSide && ((_b2 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _b2.selection) !== obj) {
13687
+ groupShiftReflowSnapshotRef.current = null;
13688
+ const logicalGroupId = obj.__pixldocsGroupSelection;
13689
+ if (logicalGroupId) {
13690
+ try {
13691
+ const state = useEditorStore.getState();
13692
+ const pageChildren2 = ((_c = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
13693
+ const groupNode = findNodeById(pageChildren2, logicalGroupId);
13694
+ if (groupNode && isGroup(groupNode) && !isStackLayoutMode(groupNode.layoutMode)) {
13695
+ const entries = obj.getObjects().map((c) => ({
13696
+ obj: c,
13697
+ id: getObjectId(c) ?? "",
13698
+ top0: c.top ?? 0,
13699
+ height0: (c.height ?? 0) * Math.abs(c.scaleY ?? 1)
13700
+ })).filter((e2) => e2.id).sort((a, b) => a.top0 - b.top0);
13701
+ if (entries.length > 1) {
13702
+ const gaps = [];
13703
+ for (let i = 1; i < entries.length; i++) {
13704
+ gaps.push(Math.max(0, entries[i].top0 - (entries[i - 1].top0 + entries[i - 1].height0)));
13705
+ }
13706
+ groupShiftReflowSnapshotRef.current = { selection: obj, groupId: logicalGroupId, children: entries, gaps };
13707
+ }
13708
+ }
13709
+ } catch {
13710
+ }
13711
+ }
13712
+ }
13622
13713
  const asW0 = obj.width ?? 0;
13623
13714
  const asH0 = obj.height ?? 0;
13624
13715
  const asSx0 = obj.scaleX ?? 1;
@@ -13628,7 +13719,7 @@ const PageCanvas = forwardRef(
13628
13719
  const asRect0 = obj.getBoundingRect();
13629
13720
  let didReflowTextChild = false;
13630
13721
  for (const child of obj.getObjects()) {
13631
- if (child instanceof fabric.Group && (child.__cropGroup || ((_b2 = child._ct) == null ? void 0 : _b2.isCropGroup))) {
13722
+ if (child instanceof fabric.Group && (child.__cropGroup || ((_d = child._ct) == null ? void 0 : _d.isCropGroup))) {
13632
13723
  const ct = child.__cropData;
13633
13724
  if (!ct) continue;
13634
13725
  if (isXSide) {
@@ -13733,6 +13824,31 @@ const PageCanvas = forwardRef(
13733
13824
  didReflowTextChild = true;
13734
13825
  }
13735
13826
  }
13827
+ if (isXSide && ((_e = groupShiftReflowSnapshotRef.current) == null ? void 0 : _e.selection) === obj) {
13828
+ const snap = groupShiftReflowSnapshotRef.current;
13829
+ let prevBottom = -Infinity;
13830
+ let didShift = false;
13831
+ for (let i = 0; i < snap.children.length; i++) {
13832
+ const entry = snap.children[i];
13833
+ const c = entry.obj;
13834
+ let liveH;
13835
+ if (c instanceof fabric.Textbox) {
13836
+ liveH = c.height ?? entry.height0;
13837
+ } else {
13838
+ liveH = (c.height ?? entry.height0) * Math.abs(c.scaleY ?? 1);
13839
+ }
13840
+ const gap = i === 0 ? 0 : snap.gaps[i - 1];
13841
+ const targetTop = i === 0 ? entry.top0 : Math.max(entry.top0, prevBottom + gap);
13842
+ if (Math.abs((c.top ?? 0) - targetTop) > 0.5) {
13843
+ c._set("top", targetTop);
13844
+ c.setCoords();
13845
+ c.dirty = true;
13846
+ didShift = true;
13847
+ }
13848
+ prevBottom = targetTop + liveH;
13849
+ }
13850
+ if (didShift) didReflowTextChild = true;
13851
+ }
13736
13852
  if (isXSide && didReflowTextChild && typeof obj.triggerLayout === "function") {
13737
13853
  try {
13738
13854
  obj.triggerLayout();
@@ -13846,7 +13962,7 @@ const PageCanvas = forwardRef(
13846
13962
  setGuides(gridGuidesForScale.length ? [...scaleGuides, ...gridGuidesForScale] : scaleGuides);
13847
13963
  if (drilledGroupIdRef.current) {
13848
13964
  try {
13849
- (_c = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _c.call(fabricCanvas);
13965
+ (_f = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _f.call(fabricCanvas);
13850
13966
  } catch {
13851
13967
  }
13852
13968
  }
@@ -14053,6 +14169,7 @@ const PageCanvas = forwardRef(
14053
14169
  }
14054
14170
  } catch {
14055
14171
  }
14172
+ groupShiftReflowSnapshotRef.current = null;
14056
14173
  lockEdits();
14057
14174
  const modifiedTarget = e.target;
14058
14175
  const modifiedTargetId = modifiedTarget ? getObjectId(modifiedTarget) : null;
@@ -15276,7 +15393,7 @@ const PageCanvas = forwardRef(
15276
15393
  visibilityUpdateInProgressRef.current = false;
15277
15394
  }
15278
15395
  doSyncRef.current = () => {
15279
- var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j;
15396
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k;
15280
15397
  const shouldSkipUpdates2 = syncLockedRef.current || editLockRef.current;
15281
15398
  const state = useEditorStore.getState();
15282
15399
  const elementsToSync = elements;
@@ -15301,10 +15418,20 @@ const PageCanvas = forwardRef(
15301
15418
  const activeBeforeSync = fc.getActiveObject();
15302
15419
  const transformSelectionId = preserveSelectionAfterTransformIdRef.current;
15303
15420
  const isTransforming2 = !!fc._currentTransform;
15304
- const activeSelectionSnapshot = activeBeforeSync instanceof fabric.ActiveSelection ? {
15421
+ const rawActiveSelectionSnapshot = activeBeforeSync instanceof fabric.ActiveSelection ? {
15305
15422
  memberIds: activeBeforeSync.getObjects().map((o) => getObjectId(o)).filter((id) => !!id && id !== "__background__"),
15306
15423
  groupSelectionId: activeBeforeSync.__pixldocsGroupSelection
15307
15424
  } : preserveActiveSelectionAfterTransformRef.current;
15425
+ const activeSelectionSnapshot = rawActiveSelectionSnapshot ? (() => {
15426
+ let memberIds = rawActiveSelectionSnapshot.memberIds.filter((id) => allElementIds.has(id));
15427
+ const groupSelectionId = rawActiveSelectionSnapshot.groupSelectionId;
15428
+ if (groupSelectionId) {
15429
+ const groupNode = findNodeById(pageTree, groupSelectionId);
15430
+ if (!groupNode || !isGroup(groupNode)) return null;
15431
+ memberIds = getAllElementIds(groupNode.children ?? []).filter((id) => allElementIds.has(id));
15432
+ }
15433
+ return memberIds.length > 0 ? { ...rawActiveSelectionSnapshot, memberIds, groupSelectionId } : null;
15434
+ })() : null;
15308
15435
  if (syncTriggeredByPanelRef.current && !transformSelectionId && !shouldSkipUpdates2 && !isTransforming2) {
15309
15436
  const activeObj = fc.getActiveObject();
15310
15437
  const activeObjId = activeObj ? getObjectId(activeObj) : null;
@@ -16098,6 +16225,12 @@ const PageCanvas = forwardRef(
16098
16225
  }
16099
16226
  }
16100
16227
  }
16228
+ if (fc.__activeEditingGroupId) {
16229
+ try {
16230
+ (_k = fc.__updateDrilledGroupOutline) == null ? void 0 : _k.call(fc);
16231
+ } catch {
16232
+ }
16233
+ }
16101
16234
  const recentGroupRestore = recentGroupSelectionRestoreRef.current;
16102
16235
  if ((recentGroupRestore == null ? void 0 : recentGroupRestore.groupSelectionId) && recentGroupRestore.expiresAt > Date.now()) {
16103
16236
  restoreGroupSelectionSnapshot(recentGroupRestore);
@@ -24025,9 +24158,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
24025
24158
  }
24026
24159
  return svgString;
24027
24160
  }
24028
- const resolvedPackageVersion = "0.5.301";
24161
+ const resolvedPackageVersion = "0.5.303";
24029
24162
  const PACKAGE_VERSION = resolvedPackageVersion;
24030
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.301";
24163
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.303";
24031
24164
  const roundParityValue = (value) => {
24032
24165
  if (typeof value !== "number") return value;
24033
24166
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -24841,7 +24974,7 @@ class PixldocsRenderer {
24841
24974
  await this.waitForCanvasScene(container, cloned, i);
24842
24975
  }
24843
24976
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
24844
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-wfJpS8kd.js");
24977
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-DlOAYoOr.js");
24845
24978
  const prepared = preparePagesForExport(
24846
24979
  cloned.pages,
24847
24980
  canvasWidth,
@@ -27161,7 +27294,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
27161
27294
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
27162
27295
  sanitizeSvgTreeForPdf(svgToDraw);
27163
27296
  try {
27164
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-wfJpS8kd.js");
27297
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-DlOAYoOr.js");
27165
27298
  try {
27166
27299
  await logTextMeasurementDiagnostic(svgToDraw);
27167
27300
  } catch {
@@ -27561,4 +27694,4 @@ export {
27561
27694
  buildTeaserBlurFlatKeys as y,
27562
27695
  collectFontDescriptorsFromConfig as z
27563
27696
  };
27564
- //# sourceMappingURL=index-CUodp3G_.js.map
27697
+ //# sourceMappingURL=index-BZNOM2c8.js.map