@pixldocs/canvas-renderer 0.5.391 → 0.5.393

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.
@@ -11473,17 +11473,53 @@ function applyWarpAwareSelectionBorders(selection) {
11473
11473
  k.calcOwnMatrix()
11474
11474
  ));
11475
11475
  const worldAngles = worldMatrices.map((m) => norm(fabric__namespace.util.qrDecompose(m).angle ?? 0));
11476
+ const worldPoints = [];
11477
+ for (const k of kids) {
11478
+ try {
11479
+ k.setCoords();
11480
+ } catch {
11481
+ }
11482
+ const coords = typeof k.getCoords === "function" ? k.getCoords() : null;
11483
+ if (Array.isArray(coords) && coords.length) {
11484
+ worldPoints.push(...coords.map((p) => ({ x: p.x, y: p.y })));
11485
+ continue;
11486
+ }
11487
+ const aC = k.aCoords;
11488
+ if (aC) {
11489
+ for (const key of ["tl", "tr", "br", "bl"]) {
11490
+ const p = aC[key];
11491
+ if (p) worldPoints.push({ x: p.x, y: p.y });
11492
+ }
11493
+ }
11494
+ }
11495
+ const orientedAreaForAngle = (angle) => {
11496
+ if (worldPoints.length === 0) return Number.POSITIVE_INFINITY;
11497
+ const rad = -angle * Math.PI / 180;
11498
+ const cos = Math.cos(rad), sin = Math.sin(rad);
11499
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
11500
+ for (const p of worldPoints) {
11501
+ const xr = p.x * cos - p.y * sin;
11502
+ const yr = p.x * sin + p.y * cos;
11503
+ minX = Math.min(minX, xr);
11504
+ minY = Math.min(minY, yr);
11505
+ maxX = Math.max(maxX, xr);
11506
+ maxY = Math.max(maxY, yr);
11507
+ }
11508
+ return Math.max(1, (maxX - minX) * (maxY - minY));
11509
+ };
11476
11510
  const ALL_SAME_TOL_DEG = 2;
11477
11511
  const buckets = [];
11478
11512
  for (const a of worldAngles) {
11479
11513
  const b = buckets.find((x) => angleDelta(x.angle, a) <= ALL_SAME_TOL_DEG);
11480
11514
  if (b) b.count++;
11481
- else buckets.push({ angle: a, count: 1 });
11515
+ else buckets.push({ angle: a, count: 1, area: Number.POSITIVE_INFINITY });
11482
11516
  }
11483
- buckets.sort((a, b) => b.count - a.count);
11517
+ for (const b of buckets) b.area = orientedAreaForAngle(b.angle);
11518
+ buckets.sort((a, b) => b.count - a.count || a.area - b.area || Math.abs(b.angle) - Math.abs(a.angle));
11484
11519
  const dominant = buckets[0];
11485
11520
  let targetAngle = null;
11486
- if (dominant && Math.abs(dominant.angle) > 0.5 && (kids.length === 1 || dominant.count >= 2 || dominant.count === kids.length)) {
11521
+ const isLogicalGroupSelection = !!selection.__pixldocsGroupSelection;
11522
+ if (dominant && Math.abs(dominant.angle) > 0.5 && (isLogicalGroupSelection || kids.length === 1 || dominant.count >= 2 || dominant.count === kids.length)) {
11487
11523
  targetAngle = dominant.angle;
11488
11524
  }
11489
11525
  if (targetAngle != null) {
@@ -13537,7 +13573,7 @@ const PageCanvas = react.forwardRef(
13537
13573
  return { left: minX, top: minY, right: maxX, bottom: maxY };
13538
13574
  };
13539
13575
  const groupFabricOrientedBBox = (g) => {
13540
- var _a2;
13576
+ var _a2, _b2;
13541
13577
  const memberIds = new Set(getAllElementIds(g.children ?? []));
13542
13578
  if (memberIds.size === 0) return null;
13543
13579
  const members = [];
@@ -13546,25 +13582,56 @@ const PageCanvas = react.forwardRef(
13546
13582
  if (oid && memberIds.has(oid)) members.push(o);
13547
13583
  }
13548
13584
  if (members.length === 0) return null;
13549
- const TOL = 0.5;
13585
+ const TOL = 2;
13586
+ const norm = (a) => {
13587
+ const n = (a % 360 + 360) % 360;
13588
+ return n > 180 ? n - 360 : n;
13589
+ };
13590
+ const angleDelta = (a, b) => {
13591
+ const d = Math.abs(norm(a) - norm(b));
13592
+ return Math.min(d, 360 - d);
13593
+ };
13594
+ const worldPoints = [];
13595
+ for (const m of members) {
13596
+ (_a2 = m.setCoords) == null ? void 0 : _a2.call(m);
13597
+ const aC = m.aCoords;
13598
+ if (!aC) continue;
13599
+ for (const k of ["tl", "tr", "br", "bl"]) {
13600
+ const p = aC[k];
13601
+ if (p) worldPoints.push({ x: p.x, y: p.y });
13602
+ }
13603
+ }
13604
+ const orientedAreaForAngle = (angle) => {
13605
+ if (worldPoints.length === 0) return Number.POSITIVE_INFINITY;
13606
+ const r = -angle * Math.PI / 180;
13607
+ const c = Math.cos(r), s = Math.sin(r);
13608
+ let nX = Infinity, nY = Infinity, xX = -Infinity, xY = -Infinity;
13609
+ for (const p of worldPoints) {
13610
+ const xr = p.x * c - p.y * s;
13611
+ const yr = p.x * s + p.y * c;
13612
+ if (xr < nX) nX = xr;
13613
+ if (yr < nY) nY = yr;
13614
+ if (xr > xX) xX = xr;
13615
+ if (yr > xY) xY = yr;
13616
+ }
13617
+ return Math.max(1, (xX - nX) * (xY - nY));
13618
+ };
13550
13619
  const buckets = [];
13551
13620
  for (const m of members) {
13552
- const a = ((m.angle ?? 0) % 360 + 360) % 360;
13553
- const b = buckets.find((x) => {
13554
- const d = Math.min(Math.abs(x.angle - a), 360 - Math.abs(x.angle - a));
13555
- return d <= TOL;
13556
- });
13621
+ const a = norm(m.angle ?? 0);
13622
+ const b = buckets.find((x) => angleDelta(x.angle, a) <= TOL);
13557
13623
  if (b) b.count++;
13558
- else buckets.push({ angle: a, count: 1 });
13624
+ else buckets.push({ angle: a, count: 1, area: Number.POSITIVE_INFINITY });
13559
13625
  }
13560
- buckets.sort((a, b) => b.count - a.count);
13626
+ for (const b of buckets) b.area = orientedAreaForAngle(b.angle);
13627
+ buckets.sort((a, b) => b.count - a.count || a.area - b.area || Math.abs(b.angle) - Math.abs(a.angle));
13561
13628
  const a0 = buckets[0].angle;
13562
13629
  const rad = -a0 * Math.PI / 180;
13563
13630
  const cos = Math.cos(rad), sin = Math.sin(rad);
13564
13631
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
13565
13632
  let found = false;
13566
13633
  for (const m of members) {
13567
- (_a2 = m.setCoords) == null ? void 0 : _a2.call(m);
13634
+ (_b2 = m.setCoords) == null ? void 0 : _b2.call(m);
13568
13635
  const aC = m.aCoords;
13569
13636
  if (!aC) continue;
13570
13637
  for (const k of ["tl", "tr", "br", "bl"]) {
@@ -25048,9 +25115,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
25048
25115
  }
25049
25116
  return svgString;
25050
25117
  }
25051
- const resolvedPackageVersion = "0.5.391";
25118
+ const resolvedPackageVersion = "0.5.393";
25052
25119
  const PACKAGE_VERSION = resolvedPackageVersion;
25053
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.391";
25120
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.393";
25054
25121
  const roundParityValue = (value) => {
25055
25122
  if (typeof value !== "number") return value;
25056
25123
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -25864,7 +25931,7 @@ class PixldocsRenderer {
25864
25931
  await this.waitForCanvasScene(container, cloned, i);
25865
25932
  }
25866
25933
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
25867
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-B8BF2GBZ.cjs"));
25934
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BWhYgu3c.cjs"));
25868
25935
  const prepared = preparePagesForExport(
25869
25936
  cloned.pages,
25870
25937
  canvasWidth,
@@ -28184,7 +28251,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
28184
28251
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
28185
28252
  sanitizeSvgTreeForPdf(svgToDraw);
28186
28253
  try {
28187
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-B8BF2GBZ.cjs"));
28254
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BWhYgu3c.cjs"));
28188
28255
  try {
28189
28256
  await logTextMeasurementDiagnostic(svgToDraw);
28190
28257
  } catch {
@@ -28581,4 +28648,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
28581
28648
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
28582
28649
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
28583
28650
  exports.warmTemplateFromForm = warmTemplateFromForm;
28584
- //# sourceMappingURL=index-C5CC51On.cjs.map
28651
+ //# sourceMappingURL=index-B0Ej1RxQ.cjs.map