@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.
@@ -11455,17 +11455,53 @@ function applyWarpAwareSelectionBorders(selection) {
11455
11455
  k.calcOwnMatrix()
11456
11456
  ));
11457
11457
  const worldAngles = worldMatrices.map((m) => norm(fabric.util.qrDecompose(m).angle ?? 0));
11458
+ const worldPoints = [];
11459
+ for (const k of kids) {
11460
+ try {
11461
+ k.setCoords();
11462
+ } catch {
11463
+ }
11464
+ const coords = typeof k.getCoords === "function" ? k.getCoords() : null;
11465
+ if (Array.isArray(coords) && coords.length) {
11466
+ worldPoints.push(...coords.map((p) => ({ x: p.x, y: p.y })));
11467
+ continue;
11468
+ }
11469
+ const aC = k.aCoords;
11470
+ if (aC) {
11471
+ for (const key of ["tl", "tr", "br", "bl"]) {
11472
+ const p = aC[key];
11473
+ if (p) worldPoints.push({ x: p.x, y: p.y });
11474
+ }
11475
+ }
11476
+ }
11477
+ const orientedAreaForAngle = (angle) => {
11478
+ if (worldPoints.length === 0) return Number.POSITIVE_INFINITY;
11479
+ const rad = -angle * Math.PI / 180;
11480
+ const cos = Math.cos(rad), sin = Math.sin(rad);
11481
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
11482
+ for (const p of worldPoints) {
11483
+ const xr = p.x * cos - p.y * sin;
11484
+ const yr = p.x * sin + p.y * cos;
11485
+ minX = Math.min(minX, xr);
11486
+ minY = Math.min(minY, yr);
11487
+ maxX = Math.max(maxX, xr);
11488
+ maxY = Math.max(maxY, yr);
11489
+ }
11490
+ return Math.max(1, (maxX - minX) * (maxY - minY));
11491
+ };
11458
11492
  const ALL_SAME_TOL_DEG = 2;
11459
11493
  const buckets = [];
11460
11494
  for (const a of worldAngles) {
11461
11495
  const b = buckets.find((x) => angleDelta(x.angle, a) <= ALL_SAME_TOL_DEG);
11462
11496
  if (b) b.count++;
11463
- else buckets.push({ angle: a, count: 1 });
11497
+ else buckets.push({ angle: a, count: 1, area: Number.POSITIVE_INFINITY });
11464
11498
  }
11465
- buckets.sort((a, b) => b.count - a.count);
11499
+ for (const b of buckets) b.area = orientedAreaForAngle(b.angle);
11500
+ buckets.sort((a, b) => b.count - a.count || a.area - b.area || Math.abs(b.angle) - Math.abs(a.angle));
11466
11501
  const dominant = buckets[0];
11467
11502
  let targetAngle = null;
11468
- if (dominant && Math.abs(dominant.angle) > 0.5 && (kids.length === 1 || dominant.count >= 2 || dominant.count === kids.length)) {
11503
+ const isLogicalGroupSelection = !!selection.__pixldocsGroupSelection;
11504
+ if (dominant && Math.abs(dominant.angle) > 0.5 && (isLogicalGroupSelection || kids.length === 1 || dominant.count >= 2 || dominant.count === kids.length)) {
11469
11505
  targetAngle = dominant.angle;
11470
11506
  }
11471
11507
  if (targetAngle != null) {
@@ -13519,7 +13555,7 @@ const PageCanvas = forwardRef(
13519
13555
  return { left: minX, top: minY, right: maxX, bottom: maxY };
13520
13556
  };
13521
13557
  const groupFabricOrientedBBox = (g) => {
13522
- var _a2;
13558
+ var _a2, _b2;
13523
13559
  const memberIds = new Set(getAllElementIds(g.children ?? []));
13524
13560
  if (memberIds.size === 0) return null;
13525
13561
  const members = [];
@@ -13528,25 +13564,56 @@ const PageCanvas = forwardRef(
13528
13564
  if (oid && memberIds.has(oid)) members.push(o);
13529
13565
  }
13530
13566
  if (members.length === 0) return null;
13531
- const TOL = 0.5;
13567
+ const TOL = 2;
13568
+ const norm = (a) => {
13569
+ const n = (a % 360 + 360) % 360;
13570
+ return n > 180 ? n - 360 : n;
13571
+ };
13572
+ const angleDelta = (a, b) => {
13573
+ const d = Math.abs(norm(a) - norm(b));
13574
+ return Math.min(d, 360 - d);
13575
+ };
13576
+ const worldPoints = [];
13577
+ for (const m of members) {
13578
+ (_a2 = m.setCoords) == null ? void 0 : _a2.call(m);
13579
+ const aC = m.aCoords;
13580
+ if (!aC) continue;
13581
+ for (const k of ["tl", "tr", "br", "bl"]) {
13582
+ const p = aC[k];
13583
+ if (p) worldPoints.push({ x: p.x, y: p.y });
13584
+ }
13585
+ }
13586
+ const orientedAreaForAngle = (angle) => {
13587
+ if (worldPoints.length === 0) return Number.POSITIVE_INFINITY;
13588
+ const r = -angle * Math.PI / 180;
13589
+ const c = Math.cos(r), s = Math.sin(r);
13590
+ let nX = Infinity, nY = Infinity, xX = -Infinity, xY = -Infinity;
13591
+ for (const p of worldPoints) {
13592
+ const xr = p.x * c - p.y * s;
13593
+ const yr = p.x * s + p.y * c;
13594
+ if (xr < nX) nX = xr;
13595
+ if (yr < nY) nY = yr;
13596
+ if (xr > xX) xX = xr;
13597
+ if (yr > xY) xY = yr;
13598
+ }
13599
+ return Math.max(1, (xX - nX) * (xY - nY));
13600
+ };
13532
13601
  const buckets = [];
13533
13602
  for (const m of members) {
13534
- const a = ((m.angle ?? 0) % 360 + 360) % 360;
13535
- const b = buckets.find((x) => {
13536
- const d = Math.min(Math.abs(x.angle - a), 360 - Math.abs(x.angle - a));
13537
- return d <= TOL;
13538
- });
13603
+ const a = norm(m.angle ?? 0);
13604
+ const b = buckets.find((x) => angleDelta(x.angle, a) <= TOL);
13539
13605
  if (b) b.count++;
13540
- else buckets.push({ angle: a, count: 1 });
13606
+ else buckets.push({ angle: a, count: 1, area: Number.POSITIVE_INFINITY });
13541
13607
  }
13542
- buckets.sort((a, b) => b.count - a.count);
13608
+ for (const b of buckets) b.area = orientedAreaForAngle(b.angle);
13609
+ buckets.sort((a, b) => b.count - a.count || a.area - b.area || Math.abs(b.angle) - Math.abs(a.angle));
13543
13610
  const a0 = buckets[0].angle;
13544
13611
  const rad = -a0 * Math.PI / 180;
13545
13612
  const cos = Math.cos(rad), sin = Math.sin(rad);
13546
13613
  let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
13547
13614
  let found = false;
13548
13615
  for (const m of members) {
13549
- (_a2 = m.setCoords) == null ? void 0 : _a2.call(m);
13616
+ (_b2 = m.setCoords) == null ? void 0 : _b2.call(m);
13550
13617
  const aC = m.aCoords;
13551
13618
  if (!aC) continue;
13552
13619
  for (const k of ["tl", "tr", "br", "bl"]) {
@@ -25030,9 +25097,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
25030
25097
  }
25031
25098
  return svgString;
25032
25099
  }
25033
- const resolvedPackageVersion = "0.5.391";
25100
+ const resolvedPackageVersion = "0.5.393";
25034
25101
  const PACKAGE_VERSION = resolvedPackageVersion;
25035
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.391";
25102
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.393";
25036
25103
  const roundParityValue = (value) => {
25037
25104
  if (typeof value !== "number") return value;
25038
25105
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -25846,7 +25913,7 @@ class PixldocsRenderer {
25846
25913
  await this.waitForCanvasScene(container, cloned, i);
25847
25914
  }
25848
25915
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
25849
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-C8_CSDHY.js");
25916
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-DBJQBWsb.js");
25850
25917
  const prepared = preparePagesForExport(
25851
25918
  cloned.pages,
25852
25919
  canvasWidth,
@@ -28166,7 +28233,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
28166
28233
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
28167
28234
  sanitizeSvgTreeForPdf(svgToDraw);
28168
28235
  try {
28169
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-C8_CSDHY.js");
28236
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-DBJQBWsb.js");
28170
28237
  try {
28171
28238
  await logTextMeasurementDiagnostic(svgToDraw);
28172
28239
  } catch {
@@ -28566,4 +28633,4 @@ export {
28566
28633
  buildTeaserBlurFlatKeys as y,
28567
28634
  collectFontDescriptorsFromConfig as z
28568
28635
  };
28569
- //# sourceMappingURL=index-Cx-Z8HWW.js.map
28636
+ //# sourceMappingURL=index-CaUhUYZP.js.map