@pixldocs/canvas-renderer 0.5.492 → 0.5.494

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.
@@ -2059,12 +2059,17 @@ const useEditorStore = zustand.create((set, get) => ({
2059
2059
  toggleElementLock: (id) => set((state) => {
2060
2060
  const currentPage = getCurrentPageFromCanvas(state.canvas);
2061
2061
  const node = findNodeById(currentPage.children, id);
2062
- if (!node || isGroup(node)) return {};
2062
+ if (!node) return {};
2063
+ const wasLocked = !!node.locked || node.selectable === false;
2064
+ const nextLocked = !wasLocked;
2063
2065
  const nextCanvas = updateCurrentPageChildren(
2064
2066
  state.canvas,
2065
2067
  (children) => updateNodeInTree(children, id, {
2066
- selectable: !node.selectable,
2067
- evented: !node.evented
2068
+ locked: nextLocked,
2069
+ // Keep legacy selectable/evented in sync with the canonical flag so
2070
+ // fabricObjectCreators (which also honors selectable === false)
2071
+ // stays consistent for elements loaded from older configs.
2072
+ ...isGroup(node) ? {} : { selectable: !nextLocked, evented: !nextLocked }
2068
2073
  })
2069
2074
  );
2070
2075
  const committed = commitFromState(state, nextCanvas);
@@ -12247,7 +12252,7 @@ const PageCanvas = react.forwardRef(
12247
12252
  var _a2;
12248
12253
  const fc = fabricRef.current;
12249
12254
  const groupId = snapshot == null ? void 0 : snapshot.groupSelectionId;
12250
- if (!fc || !groupId || snapshot.memberIds.length < 2 || editingTextIdRef.current) return;
12255
+ if (!fc || !snapshot || snapshot.memberIds.length < 2 || editingTextIdRef.current) return;
12251
12256
  const members = snapshot.memberIds.map((id) => fc.getObjects().find((o) => getObjectId(o) === id)).filter((o) => !!o);
12252
12257
  if (members.length < 2) return;
12253
12258
  const activeBeforeRestore = fc.getActiveObject();
@@ -12256,7 +12261,7 @@ const PageCanvas = react.forwardRef(
12256
12261
  const sameMembers = activeMembers.length === members.length && members.every((member) => activeMembers.includes(member));
12257
12262
  const sameGroup = activeBeforeRestore.__pixldocsGroupSelection === groupId;
12258
12263
  const alreadyAligned = activeBeforeRestore.__pixldocsAlignedAngle != null;
12259
- if (sameMembers && sameGroup && alreadyAligned) {
12264
+ if (sameMembers && (!groupId || sameGroup && alreadyAligned)) {
12260
12265
  ensureCanvaControlRenders(activeBeforeRestore);
12261
12266
  return;
12262
12267
  }
@@ -12265,7 +12270,7 @@ const PageCanvas = react.forwardRef(
12265
12270
  try {
12266
12271
  const active = activeBeforeRestore;
12267
12272
  const selection = active instanceof fabric__namespace.ActiveSelection && members.every((member) => active.getObjects().includes(member)) ? active : new fabric__namespace.ActiveSelection(members, { canvas: fc });
12268
- applyLogicalGroupSelectionVisualState(selection, groupId);
12273
+ if (groupId) applyLogicalGroupSelectionVisualState(selection, groupId);
12269
12274
  ensureCanvaControlRenders(selection);
12270
12275
  fc.setActiveObject(selection);
12271
12276
  try {
@@ -12312,7 +12317,53 @@ const PageCanvas = react.forwardRef(
12312
12317
  }, [selectedIds]);
12313
12318
  react.useEffect(() => {
12314
12319
  const fc = fabricRef.current;
12315
- if (!fc || !isActive || !currentPage) return;
12320
+ if (!fc || !isEditorMode || !currentPage) return;
12321
+ const lockedIds = /* @__PURE__ */ new Set();
12322
+ const walk = (nodes, parentLocked) => {
12323
+ for (const n of nodes) {
12324
+ const nodeLocked = !!n.locked || n.selectable === false;
12325
+ const eff = parentLocked || nodeLocked;
12326
+ if (eff) lockedIds.add(n.id);
12327
+ if (isGroup(n)) walk(n.children ?? [], eff);
12328
+ }
12329
+ };
12330
+ walk(currentPage.children ?? [], false);
12331
+ fc.getObjects().forEach((o) => {
12332
+ const id = getObjectId(o);
12333
+ if (!id || id === "__background__") return;
12334
+ const locked = lockedIds.has(id);
12335
+ o.set({
12336
+ lockMovementX: locked,
12337
+ lockMovementY: locked,
12338
+ lockScalingX: locked,
12339
+ lockScalingY: locked,
12340
+ lockRotation: locked,
12341
+ lockSkewingX: locked,
12342
+ lockSkewingY: locked,
12343
+ hoverCursor: locked ? "not-allowed" : void 0
12344
+ });
12345
+ });
12346
+ fc.requestRenderAll();
12347
+ }, [currentPage == null ? void 0 : currentPage.children, isEditorMode, elements]);
12348
+ react.useEffect(() => {
12349
+ const fc = fabricRef.current;
12350
+ if (!fc || !currentPage) return;
12351
+ if (!isActive) {
12352
+ try {
12353
+ fc.__activeEditingGroupId = null;
12354
+ drilledGroupIdRef.current = null;
12355
+ setDrilledGroupBounds(null);
12356
+ preserveActiveSelectionAfterTransformRef.current = null;
12357
+ recentGroupSelectionRestoreRef.current = null;
12358
+ if (fc.getActiveObject()) {
12359
+ fc.discardActiveObject();
12360
+ }
12361
+ clearCanvasActiveVisuals(fc);
12362
+ fc.requestRenderAll();
12363
+ } catch {
12364
+ }
12365
+ return;
12366
+ }
12316
12367
  const pageChildren2 = currentPage.children ?? [];
12317
12368
  const hasMissingSelection = selectedIds.some((id) => !findNodeById(pageChildren2, id));
12318
12369
  const activeEditingGroupId = fc.__activeEditingGroupId ?? null;
@@ -13759,7 +13810,7 @@ const PageCanvas = react.forwardRef(
13759
13810
  syncLockedRef.current = false;
13760
13811
  }
13761
13812
  const preservedGroupSelection = preserveActiveSelectionAfterTransformRef.current;
13762
- const shouldRestoreGroupSelection = !!((preservedGroupSelection == null ? void 0 : preservedGroupSelection.groupSelectionId) && (!preservedGroupSelection.expiresAt || preservedGroupSelection.expiresAt > Date.now()));
13813
+ const shouldRestoreGroupSelection = !!(preservedGroupSelection && preservedGroupSelection.memberIds.length >= 2 && (!preservedGroupSelection.expiresAt || preservedGroupSelection.expiresAt > Date.now()));
13763
13814
  if (skipSelectionClearOnDiscardRef.current) {
13764
13815
  skipSelectionClearOnDiscardRef.current = false;
13765
13816
  return;
@@ -14013,9 +14064,13 @@ const PageCanvas = react.forwardRef(
14013
14064
  suppressBordersForObjects(memberObjects);
14014
14065
  };
14015
14066
  const restorePreservedGroupSelectionSoon = (snapshot = preserveActiveSelectionAfterTransformRef.current) => {
14016
- if (!(snapshot == null ? void 0 : snapshot.groupSelectionId) || snapshot.memberIds.length < 2) return;
14067
+ if (!snapshot || snapshot.memberIds.length < 2) return;
14017
14068
  const groupId = snapshot.groupSelectionId;
14018
- selectElements([groupId], false, false);
14069
+ if (groupId) {
14070
+ selectElements([groupId], false, false);
14071
+ } else {
14072
+ selectElements(snapshot.memberIds, false, false);
14073
+ }
14019
14074
  requestAnimationFrame(() => {
14020
14075
  setTimeout(() => {
14021
14076
  if (!isActiveRef.current) return;
@@ -14025,7 +14080,7 @@ const PageCanvas = react.forwardRef(
14025
14080
  const sameMembers = activeIds.length === snapshot.memberIds.length && snapshot.memberIds.every((id) => activeIds.includes(id));
14026
14081
  const sameGroup = active.__pixldocsGroupSelection === snapshot.groupSelectionId;
14027
14082
  const alreadyAligned = active.__pixldocsAlignedAngle != null;
14028
- if (sameMembers && sameGroup && alreadyAligned) {
14083
+ if (sameMembers && (!groupId || sameGroup && alreadyAligned)) {
14029
14084
  ensureCanvaControlRenders(active);
14030
14085
  return;
14031
14086
  }
@@ -17138,6 +17193,10 @@ const PageCanvas = react.forwardRef(
17138
17193
  const innerImg = ct == null ? void 0 : ct._img;
17139
17194
  const innerSrc = ((_a2 = innerImg == null ? void 0 : innerImg.getSrc) == null ? void 0 : _a2.call(innerImg)) || ((_b2 = innerImg == null ? void 0 : innerImg._originalElement) == null ? void 0 : _b2.src) || (innerImg == null ? void 0 : innerImg.src) || "";
17140
17195
  const isPlaceholder = !innerSrc || innerSrc === EMPTY_IMAGE_PLACEHOLDER_DATA_URL;
17196
+ const activatedAt = cropGroupActivatedAtRef.current.get(target) ?? 0;
17197
+ if (Date.now() - activatedAt < 400) {
17198
+ return;
17199
+ }
17141
17200
  const targetId = getObjectId(target);
17142
17201
  const pageChildrenForCrop = ((_c2 = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _c2.children) ?? [];
17143
17202
  const parentForCrop = targetId ? findParentGroup(pageChildrenForCrop, targetId) : null;
@@ -17154,10 +17213,6 @@ const PageCanvas = react.forwardRef(
17154
17213
  }
17155
17214
  return;
17156
17215
  }
17157
- const activatedAt = cropGroupActivatedAtRef.current.get(target) ?? 0;
17158
- if (Date.now() - activatedAt < 400) {
17159
- return;
17160
- }
17161
17216
  }
17162
17217
  if (innerImg && !isPlaceholder && !isCropGroupInCropMode(target)) {
17163
17218
  enterCropMode(target);
@@ -17423,7 +17478,8 @@ const PageCanvas = react.forwardRef(
17423
17478
  }
17424
17479
  return memberIds.length > 0 ? { ...rawActiveSelectionSnapshot, memberIds, groupSelectionId } : null;
17425
17480
  })() : null;
17426
- if (syncTriggeredByPanelRef.current && !transformSelectionId && !shouldSkipUpdates2 && !isTransforming2) {
17481
+ const hasFreshPreservedActiveSelection = !!(activeSelectionSnapshot && activeSelectionSnapshot.memberIds.length >= 2 && preserveActiveSelectionAfterTransformRef.current && (!preserveActiveSelectionAfterTransformRef.current.expiresAt || preserveActiveSelectionAfterTransformRef.current.expiresAt > Date.now()));
17482
+ if (syncTriggeredByPanelRef.current && !transformSelectionId && !hasFreshPreservedActiveSelection && !shouldSkipUpdates2 && !isTransforming2) {
17427
17483
  const activeObj = fc.getActiveObject();
17428
17484
  const activeObjId = activeObj ? getObjectId(activeObj) : null;
17429
17485
  const isTextBeingEdited = activeObjId && editingTextIdRef.current === activeObjId;
@@ -17439,7 +17495,7 @@ const PageCanvas = react.forwardRef(
17439
17495
  currentFabricObjects.set(id, obj);
17440
17496
  }
17441
17497
  });
17442
- const skipRestoreSelection = syncTriggeredByPanelRef.current && !transformSelectionId;
17498
+ const skipRestoreSelection = syncTriggeredByPanelRef.current && !transformSelectionId && !hasFreshPreservedActiveSelection;
17443
17499
  const activeId = transformSelectionId || (activeBeforeSync ? getObjectId(activeBeforeSync) : null);
17444
17500
  const activeStillOnCanvas = activeBeforeSync && fc.getObjects().includes(activeBeforeSync);
17445
17501
  const replacementById = !activeStillOnCanvas && activeId ? fc.getObjects().find((o) => getObjectId(o) === activeId) ?? null : null;
@@ -18282,6 +18338,11 @@ const PageCanvas = react.forwardRef(
18282
18338
  const recentGroupRestore = recentGroupSelectionRestoreRef.current;
18283
18339
  if ((recentGroupRestore == null ? void 0 : recentGroupRestore.groupSelectionId) && recentGroupRestore.expiresAt > Date.now()) {
18284
18340
  restoreGroupSelectionSnapshot(recentGroupRestore);
18341
+ } else {
18342
+ const preservedActiveSelectionRestore = preserveActiveSelectionAfterTransformRef.current;
18343
+ if (preservedActiveSelectionRestore && preservedActiveSelectionRestore.memberIds.length >= 2 && (!preservedActiveSelectionRestore.expiresAt || preservedActiveSelectionRestore.expiresAt > Date.now())) {
18344
+ restoreGroupSelectionSnapshot(preservedActiveSelectionRestore);
18345
+ }
18285
18346
  }
18286
18347
  preserveSelectionAfterTransformIdRef.current = null;
18287
18348
  preserveActiveSelectionAfterTransformRef.current = null;
@@ -26520,9 +26581,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
26520
26581
  }
26521
26582
  return svgString;
26522
26583
  }
26523
- const resolvedPackageVersion = "0.5.492";
26584
+ const resolvedPackageVersion = "0.5.494";
26524
26585
  const PACKAGE_VERSION = resolvedPackageVersion;
26525
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.492";
26586
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.494";
26526
26587
  const roundParityValue = (value) => {
26527
26588
  if (typeof value !== "number") return value;
26528
26589
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -27336,7 +27397,7 @@ class PixldocsRenderer {
27336
27397
  await this.waitForCanvasScene(container, cloned, i);
27337
27398
  }
27338
27399
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
27339
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-PMQQ8BkR.cjs"));
27400
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BkAhiIFX.cjs"));
27340
27401
  const prepared = preparePagesForExport(
27341
27402
  cloned.pages,
27342
27403
  canvasWidth,
@@ -29656,7 +29717,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
29656
29717
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
29657
29718
  sanitizeSvgTreeForPdf(svgToDraw);
29658
29719
  try {
29659
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-PMQQ8BkR.cjs"));
29720
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BkAhiIFX.cjs"));
29660
29721
  try {
29661
29722
  await logTextMeasurementDiagnostic(svgToDraw);
29662
29723
  } catch {
@@ -29970,4 +30031,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
29970
30031
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
29971
30032
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
29972
30033
  exports.warmTemplateFromForm = warmTemplateFromForm;
29973
- //# sourceMappingURL=index-CoJw0tIl.cjs.map
30034
+ //# sourceMappingURL=index-CCMdTuIr.cjs.map