@pixldocs/canvas-renderer 0.5.244 → 0.5.246

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.
@@ -11120,7 +11120,9 @@ const PageCanvas = react.forwardRef(
11120
11120
  const isSyncingSelectionToFabricRef = react.useRef(false);
11121
11121
  const suppressGroupMemberBordersRef = react.useRef([]);
11122
11122
  const editingTextIdRef = react.useRef(null);
11123
- const pendingTextEditOnUpRef = react.useRef(null);
11123
+ const selectAllTextOnEditingEnterRef = react.useRef(null);
11124
+ const suppressedTextEditObjectsRef = react.useRef([]);
11125
+ const suppressTextDoubleClickUntilRef = react.useRef(0);
11124
11126
  const syncLockedRef = react.useRef(false);
11125
11127
  const editLockRef = react.useRef(false);
11126
11128
  const editLockCountRef = react.useRef(0);
@@ -11138,6 +11140,8 @@ const PageCanvas = react.forwardRef(
11138
11140
  const [guides, setGuides] = react.useState([]);
11139
11141
  const [gridResizeLabel, setGridResizeLabel] = react.useState(null);
11140
11142
  const [hoverBounds, setHoverBounds] = react.useState(null);
11143
+ const [drilledGroupBounds, setDrilledGroupBounds] = react.useState(null);
11144
+ const drilledGroupIdRef = react.useRef(null);
11141
11145
  const [rotationLabel, setRotationLabel] = react.useState(null);
11142
11146
  const [sizeLabel, setSizeLabel] = react.useState(null);
11143
11147
  const [ready, setReady] = react.useState(false);
@@ -11827,6 +11831,44 @@ const PageCanvas = react.forwardRef(
11827
11831
  });
11828
11832
  fabricCanvas.hoverCursor = "default";
11829
11833
  fabricCanvas.moveCursor = "move";
11834
+ const suppressTextEditForClick = (textbox) => {
11835
+ if (!textbox) return;
11836
+ textbox.selected = false;
11837
+ textbox.__lastSelected = false;
11838
+ textbox.__corner = void 0;
11839
+ textbox.__pixldocsSuppressNextEdit = true;
11840
+ suppressTextDoubleClickUntilRef.current = Date.now() + 350;
11841
+ if (!suppressedTextEditObjectsRef.current.some((entry) => entry.textbox === textbox)) {
11842
+ suppressedTextEditObjectsRef.current.push({ textbox, editable: textbox.editable });
11843
+ }
11844
+ textbox.editable = false;
11845
+ };
11846
+ const restoreSuppressedTextEditObjects = () => {
11847
+ const entries = suppressedTextEditObjectsRef.current.splice(0);
11848
+ for (const { textbox, editable } of entries) {
11849
+ try {
11850
+ textbox.editable = editable;
11851
+ delete textbox.__pixldocsSuppressNextEdit;
11852
+ } catch {
11853
+ }
11854
+ }
11855
+ };
11856
+ const restoreSuppressedTextEditObjectsSoon = () => {
11857
+ requestAnimationFrame(() => {
11858
+ restoreSuppressedTextEditObjects();
11859
+ });
11860
+ };
11861
+ const selectAllActiveTextbox = (textbox) => {
11862
+ var _a2;
11863
+ try {
11864
+ textbox.selectAll();
11865
+ } catch {
11866
+ const len = ((_a2 = textbox.text) == null ? void 0 : _a2.length) ?? 0;
11867
+ textbox.selectionStart = 0;
11868
+ textbox.selectionEnd = len;
11869
+ }
11870
+ fabricCanvas.requestRenderAll();
11871
+ };
11830
11872
  if (!allowSelection) {
11831
11873
  fabricCanvas.selection = false;
11832
11874
  fabricCanvas.on("selection:created", () => {
@@ -12005,16 +12047,29 @@ const PageCanvas = react.forwardRef(
12005
12047
  }
12006
12048
  });
12007
12049
  fabricCanvas.on("object:scaling", () => {
12050
+ var _a2;
12008
12051
  fabricCanvas.__isUserTransforming = true;
12052
+ if (drilledGroupIdRef.current) {
12053
+ try {
12054
+ (_a2 = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _a2.call(fabricCanvas);
12055
+ } catch {
12056
+ }
12057
+ }
12009
12058
  });
12010
12059
  fabricCanvas.on("object:moving", () => {
12011
- var _a2;
12060
+ var _a2, _b2;
12012
12061
  fabricCanvas.__isUserTransforming = true;
12013
12062
  didTransformRef.current = true;
12063
+ if (drilledGroupIdRef.current) {
12064
+ try {
12065
+ (_a2 = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _a2.call(fabricCanvas);
12066
+ } catch {
12067
+ }
12068
+ }
12014
12069
  const active = fabricCanvas.getActiveObject();
12015
12070
  if (!active) return;
12016
12071
  const state = useEditorStore.getState();
12017
- const canvasPage = (_a2 = state.canvas.pages) == null ? void 0 : _a2.find((p) => p.id === pageId);
12072
+ const canvasPage = (_b2 = state.canvas.pages) == null ? void 0 : _b2.find((p) => p.id === pageId);
12018
12073
  const children = (canvasPage == null ? void 0 : canvasPage.children) ?? [];
12019
12074
  if (!canvasPage) return;
12020
12075
  const ids = state.canvas.selectedIds ?? [];
@@ -12045,8 +12100,15 @@ const PageCanvas = react.forwardRef(
12045
12100
  }
12046
12101
  });
12047
12102
  fabricCanvas.on("object:rotating", () => {
12103
+ var _a2;
12048
12104
  fabricCanvas.__isUserTransforming = true;
12049
12105
  didTransformRef.current = true;
12106
+ if (drilledGroupIdRef.current) {
12107
+ try {
12108
+ (_a2 = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _a2.call(fabricCanvas);
12109
+ } catch {
12110
+ }
12111
+ }
12050
12112
  });
12051
12113
  const syncSelectionToStore = () => {
12052
12114
  var _a2, _b2, _c, _d;
@@ -12257,7 +12319,7 @@ const PageCanvas = react.forwardRef(
12257
12319
  }
12258
12320
  });
12259
12321
  fabricCanvas.on("mouse:dblclick", (opt) => {
12260
- var _a2, _b2;
12322
+ var _a2, _b2, _c;
12261
12323
  const target = opt == null ? void 0 : opt.target;
12262
12324
  if (!target) return;
12263
12325
  if (target.isEditing) return;
@@ -12352,6 +12414,10 @@ const PageCanvas = react.forwardRef(
12352
12414
  }
12353
12415
  const selectedId = selectionIdx < 0 ? childId : chain[selectionIdx].id;
12354
12416
  selectElements([selectedId], false, false);
12417
+ try {
12418
+ (_c = fabricCanvas.__updateDrilledGroupOutline) == null ? void 0 : _c.call(fabricCanvas);
12419
+ } catch {
12420
+ }
12355
12421
  });
12356
12422
  fabricCanvas.on("selection:cleared", () => {
12357
12423
  if (!isActiveRef.current || isRebuildingRef.current || !allowSelection) return;
@@ -12359,6 +12425,8 @@ const PageCanvas = react.forwardRef(
12359
12425
  groupBoundsResizingRef.current = false;
12360
12426
  if (!preserveEditingScopeOnSelectionClearRef.current) {
12361
12427
  fabricCanvas.__activeEditingGroupId = null;
12428
+ setDrilledGroupBounds(null);
12429
+ drilledGroupIdRef.current = null;
12362
12430
  }
12363
12431
  const preservedGroupSelection = preserveActiveSelectionAfterTransformRef.current;
12364
12432
  const shouldRestoreGroupSelection = !!((preservedGroupSelection == null ? void 0 : preservedGroupSelection.groupSelectionId) && (!preservedGroupSelection.expiresAt || preservedGroupSelection.expiresAt > Date.now()));
@@ -12762,8 +12830,35 @@ const PageCanvas = react.forwardRef(
12762
12830
  }
12763
12831
  return pick;
12764
12832
  };
12833
+ const updateDrilledGroupOutline = () => {
12834
+ const gid = fabricCanvas.__activeEditingGroupId ?? null;
12835
+ drilledGroupIdRef.current = gid;
12836
+ if (!gid) {
12837
+ setDrilledGroupBounds(null);
12838
+ return;
12839
+ }
12840
+ const pageNow = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId);
12841
+ const node = pageNow ? findNodeById(pageNow.children ?? [], gid) : null;
12842
+ if (!node || !isGroup(node) || node.backgroundColor) {
12843
+ setDrilledGroupBounds(null);
12844
+ return;
12845
+ }
12846
+ const b = groupFabricUnionBBox(node);
12847
+ if (!b) {
12848
+ setDrilledGroupBounds(null);
12849
+ return;
12850
+ }
12851
+ setDrilledGroupBounds({
12852
+ left: b.left,
12853
+ top: b.top,
12854
+ width: b.right - b.left,
12855
+ height: b.bottom - b.top
12856
+ });
12857
+ };
12858
+ fabricCanvas.__updateDrilledGroupOutline = updateDrilledGroupOutline;
12765
12859
  fabricCanvas.on("mouse:down:before", (opt) => {
12766
12860
  var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
12861
+ const activeBeforeMouseDown = fabricCanvas.getActiveObject();
12767
12862
  if (editLockRef.current) {
12768
12863
  const active = fabricCanvas.getActiveObject();
12769
12864
  if (active && (((_a2 = active._ct) == null ? void 0 : _a2.isCropGroup) || active.__cropGroup)) {
@@ -12789,6 +12884,9 @@ const PageCanvas = react.forwardRef(
12789
12884
  targetId = childId;
12790
12885
  }
12791
12886
  }
12887
+ if (target instanceof fabric__namespace.Textbox && targetId && targetId !== "__background__" && activeBeforeMouseDown === target && !target.isEditing && !target.__corner && !isMultiSelectModifier(opt.e)) {
12888
+ selectAllTextOnEditingEnterRef.current = targetId;
12889
+ }
12792
12890
  const activeEditingGroupId = fabricCanvas.__activeEditingGroupId ?? null;
12793
12891
  const pageNow = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId);
12794
12892
  const childrenNow = (pageNow == null ? void 0 : pageNow.children) ?? [];
@@ -12896,7 +12994,15 @@ const PageCanvas = react.forwardRef(
12896
12994
  opt.target = effectiveTarget;
12897
12995
  pendingGroupPromotionRef.current = null;
12898
12996
  pendingGroupDrillInRef.current = { groupId: drillGroup.id, childId: effectiveTargetId, target: effectiveTarget };
12997
+ if (effectiveTarget instanceof fabric__namespace.Textbox) {
12998
+ suppressTextEditForClick(effectiveTarget);
12999
+ } else {
13000
+ effectiveTarget.selected = false;
13001
+ effectiveTarget.__lastSelected = false;
13002
+ effectiveTarget.__corner = void 0;
13003
+ }
12899
13004
  selectElements([effectiveTargetId], false, false);
13005
+ updateDrilledGroupOutline();
12900
13006
  fabricCanvas.requestRenderAll();
12901
13007
  }
12902
13008
  } else if (!target || targetId === "__background__") {
@@ -13037,7 +13143,6 @@ const PageCanvas = react.forwardRef(
13037
13143
  lockEdits();
13038
13144
  }
13039
13145
  const o = fabricCanvas.getActiveObject();
13040
- pendingTextEditOnUpRef.current = null;
13041
13146
  if (!o) return;
13042
13147
  o.__lockScaleDuringCrop = false;
13043
13148
  });
@@ -13064,6 +13169,13 @@ const PageCanvas = react.forwardRef(
13064
13169
  (_b2 = (_a2 = pendingDrillIn.target).set) == null ? void 0 : _b2.call(_a2, { selectable: true, evented: true, hasBorders: true, hasControls: true });
13065
13170
  fabricCanvas.setActiveObject(pendingDrillIn.target);
13066
13171
  pendingDrillIn.target.setCoords();
13172
+ if (pendingDrillIn.target instanceof fabric__namespace.Textbox) {
13173
+ suppressTextEditForClick(pendingDrillIn.target);
13174
+ } else {
13175
+ pendingDrillIn.target.selected = false;
13176
+ pendingDrillIn.target.__lastSelected = false;
13177
+ pendingDrillIn.target.__corner = void 0;
13178
+ }
13067
13179
  fabricCanvas.requestRenderAll();
13068
13180
  } finally {
13069
13181
  requestAnimationFrame(() => {
@@ -13071,6 +13183,7 @@ const PageCanvas = react.forwardRef(
13071
13183
  });
13072
13184
  }
13073
13185
  selectElements([pendingDrillIn.childId], false, false);
13186
+ updateDrilledGroupOutline();
13074
13187
  }
13075
13188
  }
13076
13189
  const pendingPromotion = pendingGroupPromotionRef.current;
@@ -13135,6 +13248,7 @@ const PageCanvas = react.forwardRef(
13135
13248
  syncLockedRef.current = false;
13136
13249
  }, 0);
13137
13250
  unlockEditsSoon();
13251
+ restoreSuppressedTextEditObjectsSoon();
13138
13252
  if (allowDynamicFieldClick && onDynamicFieldClick && e.target) {
13139
13253
  const clickedId = getObjectId(e.target);
13140
13254
  if (clickedId && dynamicFieldIds.includes(clickedId)) {
@@ -14421,6 +14535,9 @@ const PageCanvas = react.forwardRef(
14421
14535
  else if (active instanceof fabric__namespace.ActiveSelection && active.getObjects().length === 1 && active.getObjects()[0] instanceof fabric__namespace.Textbox) target = active.getObjects()[0];
14422
14536
  }
14423
14537
  if (target && target instanceof fabric__namespace.Textbox) {
14538
+ if (Date.now() < suppressTextDoubleClickUntilRef.current || target.__pixldocsSuppressNextEdit) {
14539
+ return;
14540
+ }
14424
14541
  const elementId = getObjectId(target);
14425
14542
  if (target.__formattingEnabled === true || target.editable === false) {
14426
14543
  sonner.toast.info("Inline formatting is on — edit the text in the right panel.", {
@@ -14437,7 +14554,21 @@ const PageCanvas = react.forwardRef(
14437
14554
  const target = e.target;
14438
14555
  if (target && target instanceof fabric__namespace.Textbox) {
14439
14556
  const elementId = getObjectId(target);
14557
+ if (target.__pixldocsSuppressNextEdit) {
14558
+ try {
14559
+ target.exitEditing();
14560
+ } catch {
14561
+ }
14562
+ editingTextIdRef.current = null;
14563
+ setEditingText(false);
14564
+ fabricCanvas.requestRenderAll();
14565
+ return;
14566
+ }
14440
14567
  editingTextIdRef.current = elementId || null;
14568
+ if (elementId && selectAllTextOnEditingEnterRef.current === elementId) {
14569
+ selectAllTextOnEditingEnterRef.current = null;
14570
+ selectAllActiveTextbox(target);
14571
+ }
14441
14572
  setEditingText(true);
14442
14573
  }
14443
14574
  });
@@ -17199,6 +17330,28 @@ const PageCanvas = react.forwardRef(
17199
17330
  )
17200
17331
  }
17201
17332
  ),
17333
+ drilledGroupBounds && /* @__PURE__ */ jsxRuntime.jsx(
17334
+ "svg",
17335
+ {
17336
+ className: "absolute inset-0 pointer-events-none",
17337
+ style: { width: scaledWidth, height: scaledHeight },
17338
+ viewBox: `0 0 ${canvasWidth} ${canvasHeight}`,
17339
+ children: /* @__PURE__ */ jsxRuntime.jsx(
17340
+ "rect",
17341
+ {
17342
+ x: drilledGroupBounds.left,
17343
+ y: drilledGroupBounds.top,
17344
+ width: drilledGroupBounds.width,
17345
+ height: drilledGroupBounds.height,
17346
+ fill: "none",
17347
+ stroke: "rgba(100, 116, 139, 0.7)",
17348
+ strokeWidth: 1,
17349
+ strokeDasharray: "4 4",
17350
+ vectorEffect: "non-scaling-stroke"
17351
+ }
17352
+ )
17353
+ }
17354
+ ),
17202
17355
  canvas.projectSettings.showGrid && (() => {
17203
17356
  const ps = canvas.projectSettings;
17204
17357
  const gx = Math.max(1, ps.gridSizeX ?? ps.gridSize ?? 0);
@@ -23310,9 +23463,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
23310
23463
  }
23311
23464
  return svgString;
23312
23465
  }
23313
- const resolvedPackageVersion = "0.5.244";
23466
+ const resolvedPackageVersion = "0.5.246";
23314
23467
  const PACKAGE_VERSION = resolvedPackageVersion;
23315
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.244";
23468
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.246";
23316
23469
  const roundParityValue = (value) => {
23317
23470
  if (typeof value !== "number") return value;
23318
23471
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -24126,7 +24279,7 @@ class PixldocsRenderer {
24126
24279
  await this.waitForCanvasScene(container, cloned, i);
24127
24280
  }
24128
24281
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
24129
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BUlPzdRT.cjs"));
24282
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-g3JJf7fm.cjs"));
24130
24283
  const prepared = preparePagesForExport(
24131
24284
  cloned.pages,
24132
24285
  canvasWidth,
@@ -26446,7 +26599,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
26446
26599
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
26447
26600
  sanitizeSvgTreeForPdf(svgToDraw);
26448
26601
  try {
26449
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BUlPzdRT.cjs"));
26602
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-g3JJf7fm.cjs"));
26450
26603
  try {
26451
26604
  await logTextMeasurementDiagnostic(svgToDraw);
26452
26605
  } catch {
@@ -26843,4 +26996,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
26843
26996
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
26844
26997
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
26845
26998
  exports.warmTemplateFromForm = warmTemplateFromForm;
26846
- //# sourceMappingURL=index-Bu8x_hs7.cjs.map
26999
+ //# sourceMappingURL=index-DtQblfr0.cjs.map