@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.
@@ -1550,7 +1550,7 @@ const useEditorStore = zustand.create((set, get) => ({
1550
1550
  }
1551
1551
  let nextCanvas = updateCurrentPageChildren(state.canvas, () => nextChildren);
1552
1552
  nextCanvas.selectedIds = state.canvas.selectedIds.filter(
1553
- (id) => !ids.includes(id) && !prunedGroupIds.has(id)
1553
+ (id) => !allDeletedIds.has(id) && !prunedGroupIds.has(id)
1554
1554
  );
1555
1555
  if (nextCanvas.themeConfig) {
1556
1556
  const remainingProps = nextCanvas.themeConfig.properties.filter((p) => !allDeletedIds.has(p.elementId));
@@ -11305,6 +11305,41 @@ const PageCanvas = react.forwardRef(
11305
11305
  const [groupResizeState, setGroupResizeState] = react.useState(null);
11306
11306
  const [groupOverlayLiveBounds, setGroupOverlayLiveBounds] = react.useState(null);
11307
11307
  const setGroupOverlayLiveBoundsRef = react.useRef(setGroupOverlayLiveBounds);
11308
+ const restoreSuppressedGroupMemberVisuals = react.useCallback(() => {
11309
+ const list = suppressGroupMemberBordersRef.current;
11310
+ if (!list || list.length === 0) return;
11311
+ for (const member of list) {
11312
+ const origBorders = member.__pixldocsOrigHasBorders;
11313
+ const origControls = member.__pixldocsOrigHasControls;
11314
+ const origLockX = member.__pixldocsOrigLockScalingX;
11315
+ if (origBorders !== void 0) member.hasBorders = origBorders;
11316
+ else member.hasBorders = true;
11317
+ if (origControls !== void 0) member.hasControls = origControls;
11318
+ else member.hasControls = true;
11319
+ if (origLockX !== void 0) {
11320
+ member.lockScalingX = origLockX;
11321
+ member.lockScalingY = member.__pixldocsOrigLockScalingY;
11322
+ }
11323
+ delete member.__pixldocsOrigHasBorders;
11324
+ delete member.__pixldocsOrigHasControls;
11325
+ delete member.__pixldocsOrigLockScalingX;
11326
+ delete member.__pixldocsOrigLockScalingY;
11327
+ }
11328
+ suppressGroupMemberBordersRef.current = [];
11329
+ }, []);
11330
+ const clearCanvasActiveVisuals = react.useCallback((fc) => {
11331
+ setGroupOverlayLiveBoundsRef.current(null);
11332
+ restoreSuppressedGroupMemberVisuals();
11333
+ try {
11334
+ fc.discardActiveObject();
11335
+ const topContext = fc.contextTop;
11336
+ if (topContext && typeof fc.clearContext === "function") {
11337
+ fc.clearContext(topContext);
11338
+ }
11339
+ fc.requestRenderAll();
11340
+ } catch {
11341
+ }
11342
+ }, [restoreSuppressedGroupMemberVisuals]);
11308
11343
  const skipSelectionClearOnDiscardRef = react.useRef(false);
11309
11344
  const skipActiveSelectionBakeOnClearRef = react.useRef(false);
11310
11345
  const preserveEditingScopeOnSelectionClearRef = react.useRef(false);
@@ -11331,6 +11366,7 @@ const PageCanvas = react.forwardRef(
11331
11366
  const lastTextEditDimensionsRef = react.useRef(null);
11332
11367
  const lastResizeScaleTargetRef = react.useRef(null);
11333
11368
  const activeSelectionResizeHandleRef = react.useRef(null);
11369
+ const groupShiftReflowSnapshotRef = react.useRef(null);
11334
11370
  const preserveSelectionAfterTransformIdRef = react.useRef(null);
11335
11371
  const groupSelectionTransformStartRef = react.useRef(null);
11336
11372
  const activeSelectionMoveStartRef = react.useRef(null);
@@ -11393,6 +11429,34 @@ const PageCanvas = react.forwardRef(
11393
11429
  react.useEffect(() => {
11394
11430
  selectedIdsRef.current = selectedIds;
11395
11431
  }, [selectedIds]);
11432
+ react.useEffect(() => {
11433
+ const fc = fabricRef.current;
11434
+ if (!fc || !isActive || !currentPage) return;
11435
+ const pageChildren2 = currentPage.children ?? [];
11436
+ const hasMissingSelection = selectedIds.some((id) => !findNodeById(pageChildren2, id));
11437
+ const activeEditingGroupId = fc.__activeEditingGroupId ?? null;
11438
+ const activeEditingGroupMissing = !!activeEditingGroupId && !findNodeById(pageChildren2, activeEditingGroupId);
11439
+ const drilledGroupMissing = !!drilledGroupIdRef.current && !findNodeById(pageChildren2, drilledGroupIdRef.current);
11440
+ const hasGroupEditContext = !!activeEditingGroupId || !!drilledGroupIdRef.current;
11441
+ if (selectedIds.length === 0 && !hasGroupEditContext || hasMissingSelection || activeEditingGroupMissing || drilledGroupMissing) {
11442
+ fc.__activeEditingGroupId = null;
11443
+ drilledGroupIdRef.current = null;
11444
+ setDrilledGroupBounds(null);
11445
+ preserveActiveSelectionAfterTransformRef.current = null;
11446
+ recentGroupSelectionRestoreRef.current = null;
11447
+ clearCanvasActiveVisuals(fc);
11448
+ } else if (hasGroupEditContext) {
11449
+ requestAnimationFrame(() => {
11450
+ var _a2;
11451
+ if (fabricRef.current !== fc) return;
11452
+ try {
11453
+ (_a2 = fc.__updateDrilledGroupOutline) == null ? void 0 : _a2.call(fc);
11454
+ } catch {
11455
+ }
11456
+ fc.requestRenderAll();
11457
+ });
11458
+ }
11459
+ }, [selectedIds, currentPage, isActive, clearCanvasActiveVisuals]);
11396
11460
  react.useEffect(() => {
11397
11461
  isActiveRef.current = isActive;
11398
11462
  if (isEditorMode && isActive && fabricRef.current) ;
@@ -13460,7 +13524,7 @@ const PageCanvas = react.forwardRef(
13460
13524
  fabricCanvas.on("selection:cleared", () => {
13461
13525
  });
13462
13526
  fabricCanvas.on("object:scaling", (e) => {
13463
- var _a2, _b2, _c;
13527
+ var _a2, _b2, _c, _d, _e, _f;
13464
13528
  if (!isActiveRef.current) return;
13465
13529
  const t = e.target;
13466
13530
  if (t) lastResizeScaleTargetRef.current = t;
@@ -13637,6 +13701,33 @@ const PageCanvas = react.forwardRef(
13637
13701
  const isXSide = corner === "ml" || corner === "mr";
13638
13702
  const sAxis = isXSide ? Math.abs(obj.scaleX ?? 1) : Math.abs(obj.scaleY ?? 1);
13639
13703
  if (sAxis > 1e-3) {
13704
+ if (isXSide && ((_b2 = groupShiftReflowSnapshotRef.current) == null ? void 0 : _b2.selection) !== obj) {
13705
+ groupShiftReflowSnapshotRef.current = null;
13706
+ const logicalGroupId = obj.__pixldocsGroupSelection;
13707
+ if (logicalGroupId) {
13708
+ try {
13709
+ const state = useEditorStore.getState();
13710
+ const pageChildren2 = ((_c = state.canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c.children) ?? [];
13711
+ const groupNode = findNodeById(pageChildren2, logicalGroupId);
13712
+ if (groupNode && isGroup(groupNode) && !isStackLayoutMode(groupNode.layoutMode)) {
13713
+ const entries = obj.getObjects().map((c) => ({
13714
+ obj: c,
13715
+ id: getObjectId(c) ?? "",
13716
+ top0: c.top ?? 0,
13717
+ height0: (c.height ?? 0) * Math.abs(c.scaleY ?? 1)
13718
+ })).filter((e2) => e2.id).sort((a, b) => a.top0 - b.top0);
13719
+ if (entries.length > 1) {
13720
+ const gaps = [];
13721
+ for (let i = 1; i < entries.length; i++) {
13722
+ gaps.push(Math.max(0, entries[i].top0 - (entries[i - 1].top0 + entries[i - 1].height0)));
13723
+ }
13724
+ groupShiftReflowSnapshotRef.current = { selection: obj, groupId: logicalGroupId, children: entries, gaps };
13725
+ }
13726
+ }
13727
+ } catch {
13728
+ }
13729
+ }
13730
+ }
13640
13731
  const asW0 = obj.width ?? 0;
13641
13732
  const asH0 = obj.height ?? 0;
13642
13733
  const asSx0 = obj.scaleX ?? 1;
@@ -13646,7 +13737,7 @@ const PageCanvas = react.forwardRef(
13646
13737
  const asRect0 = obj.getBoundingRect();
13647
13738
  let didReflowTextChild = false;
13648
13739
  for (const child of obj.getObjects()) {
13649
- if (child instanceof fabric__namespace.Group && (child.__cropGroup || ((_b2 = child._ct) == null ? void 0 : _b2.isCropGroup))) {
13740
+ if (child instanceof fabric__namespace.Group && (child.__cropGroup || ((_d = child._ct) == null ? void 0 : _d.isCropGroup))) {
13650
13741
  const ct = child.__cropData;
13651
13742
  if (!ct) continue;
13652
13743
  if (isXSide) {
@@ -13751,6 +13842,31 @@ const PageCanvas = react.forwardRef(
13751
13842
  didReflowTextChild = true;
13752
13843
  }
13753
13844
  }
13845
+ if (isXSide && ((_e = groupShiftReflowSnapshotRef.current) == null ? void 0 : _e.selection) === obj) {
13846
+ const snap = groupShiftReflowSnapshotRef.current;
13847
+ let prevBottom = -Infinity;
13848
+ let didShift = false;
13849
+ for (let i = 0; i < snap.children.length; i++) {
13850
+ const entry = snap.children[i];
13851
+ const c = entry.obj;
13852
+ let liveH;
13853
+ if (c instanceof fabric__namespace.Textbox) {
13854
+ liveH = c.height ?? entry.height0;
13855
+ } else {
13856
+ liveH = (c.height ?? entry.height0) * Math.abs(c.scaleY ?? 1);
13857
+ }
13858
+ const gap = i === 0 ? 0 : snap.gaps[i - 1];
13859
+ const targetTop = i === 0 ? entry.top0 : Math.max(entry.top0, prevBottom + gap);
13860
+ if (Math.abs((c.top ?? 0) - targetTop) > 0.5) {
13861
+ c._set("top", targetTop);
13862
+ c.setCoords();
13863
+ c.dirty = true;
13864
+ didShift = true;
13865
+ }
13866
+ prevBottom = targetTop + liveH;
13867
+ }
13868
+ if (didShift) didReflowTextChild = true;
13869
+ }
13754
13870
  if (isXSide && didReflowTextChild && typeof obj.triggerLayout === "function") {
13755
13871
  try {
13756
13872
  obj.triggerLayout();
@@ -13864,7 +13980,7 @@ const PageCanvas = react.forwardRef(
13864
13980
  setGuides(gridGuidesForScale.length ? [...scaleGuides, ...gridGuidesForScale] : scaleGuides);
13865
13981
  if (drilledGroupIdRef.current) {
13866
13982
  try {
13867
- (_c = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _c.call(fabricCanvas);
13983
+ (_f = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _f.call(fabricCanvas);
13868
13984
  } catch {
13869
13985
  }
13870
13986
  }
@@ -14071,6 +14187,7 @@ const PageCanvas = react.forwardRef(
14071
14187
  }
14072
14188
  } catch {
14073
14189
  }
14190
+ groupShiftReflowSnapshotRef.current = null;
14074
14191
  lockEdits();
14075
14192
  const modifiedTarget = e.target;
14076
14193
  const modifiedTargetId = modifiedTarget ? getObjectId(modifiedTarget) : null;
@@ -15294,7 +15411,7 @@ const PageCanvas = react.forwardRef(
15294
15411
  visibilityUpdateInProgressRef.current = false;
15295
15412
  }
15296
15413
  doSyncRef.current = () => {
15297
- var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j;
15414
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k;
15298
15415
  const shouldSkipUpdates2 = syncLockedRef.current || editLockRef.current;
15299
15416
  const state = useEditorStore.getState();
15300
15417
  const elementsToSync = elements;
@@ -15319,10 +15436,20 @@ const PageCanvas = react.forwardRef(
15319
15436
  const activeBeforeSync = fc.getActiveObject();
15320
15437
  const transformSelectionId = preserveSelectionAfterTransformIdRef.current;
15321
15438
  const isTransforming2 = !!fc._currentTransform;
15322
- const activeSelectionSnapshot = activeBeforeSync instanceof fabric__namespace.ActiveSelection ? {
15439
+ const rawActiveSelectionSnapshot = activeBeforeSync instanceof fabric__namespace.ActiveSelection ? {
15323
15440
  memberIds: activeBeforeSync.getObjects().map((o) => getObjectId(o)).filter((id) => !!id && id !== "__background__"),
15324
15441
  groupSelectionId: activeBeforeSync.__pixldocsGroupSelection
15325
15442
  } : preserveActiveSelectionAfterTransformRef.current;
15443
+ const activeSelectionSnapshot = rawActiveSelectionSnapshot ? (() => {
15444
+ let memberIds = rawActiveSelectionSnapshot.memberIds.filter((id) => allElementIds.has(id));
15445
+ const groupSelectionId = rawActiveSelectionSnapshot.groupSelectionId;
15446
+ if (groupSelectionId) {
15447
+ const groupNode = findNodeById(pageTree, groupSelectionId);
15448
+ if (!groupNode || !isGroup(groupNode)) return null;
15449
+ memberIds = getAllElementIds(groupNode.children ?? []).filter((id) => allElementIds.has(id));
15450
+ }
15451
+ return memberIds.length > 0 ? { ...rawActiveSelectionSnapshot, memberIds, groupSelectionId } : null;
15452
+ })() : null;
15326
15453
  if (syncTriggeredByPanelRef.current && !transformSelectionId && !shouldSkipUpdates2 && !isTransforming2) {
15327
15454
  const activeObj = fc.getActiveObject();
15328
15455
  const activeObjId = activeObj ? getObjectId(activeObj) : null;
@@ -16116,6 +16243,12 @@ const PageCanvas = react.forwardRef(
16116
16243
  }
16117
16244
  }
16118
16245
  }
16246
+ if (fc.__activeEditingGroupId) {
16247
+ try {
16248
+ (_k = fc.__updateDrilledGroupOutline) == null ? void 0 : _k.call(fc);
16249
+ } catch {
16250
+ }
16251
+ }
16119
16252
  const recentGroupRestore = recentGroupSelectionRestoreRef.current;
16120
16253
  if ((recentGroupRestore == null ? void 0 : recentGroupRestore.groupSelectionId) && recentGroupRestore.expiresAt > Date.now()) {
16121
16254
  restoreGroupSelectionSnapshot(recentGroupRestore);
@@ -24043,9 +24176,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
24043
24176
  }
24044
24177
  return svgString;
24045
24178
  }
24046
- const resolvedPackageVersion = "0.5.301";
24179
+ const resolvedPackageVersion = "0.5.303";
24047
24180
  const PACKAGE_VERSION = resolvedPackageVersion;
24048
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.301";
24181
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.303";
24049
24182
  const roundParityValue = (value) => {
24050
24183
  if (typeof value !== "number") return value;
24051
24184
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -24859,7 +24992,7 @@ class PixldocsRenderer {
24859
24992
  await this.waitForCanvasScene(container, cloned, i);
24860
24993
  }
24861
24994
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
24862
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-hHMDys-j.cjs"));
24995
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BWWx6ATR.cjs"));
24863
24996
  const prepared = preparePagesForExport(
24864
24997
  cloned.pages,
24865
24998
  canvasWidth,
@@ -27179,7 +27312,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
27179
27312
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
27180
27313
  sanitizeSvgTreeForPdf(svgToDraw);
27181
27314
  try {
27182
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-hHMDys-j.cjs"));
27315
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BWWx6ATR.cjs"));
27183
27316
  try {
27184
27317
  await logTextMeasurementDiagnostic(svgToDraw);
27185
27318
  } catch {
@@ -27576,4 +27709,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
27576
27709
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
27577
27710
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
27578
27711
  exports.warmTemplateFromForm = warmTemplateFromForm;
27579
- //# sourceMappingURL=index-BUG1_dx7.cjs.map
27712
+ //# sourceMappingURL=index-RzHOtjZi.cjs.map