@pooder/kit 3.0.0 → 3.1.0

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.
package/dist/index.mjs CHANGED
@@ -432,6 +432,65 @@ var Coordinate = class {
432
432
 
433
433
  // src/geometry.ts
434
434
  import paper from "paper";
435
+ function resolveHolePosition(hole, geometry, canvasSize) {
436
+ if (hole.anchor) {
437
+ const { x, y, width, height } = geometry;
438
+ let bx = x;
439
+ let by = y;
440
+ const left = x - width / 2;
441
+ const right = x + width / 2;
442
+ const top = y - height / 2;
443
+ const bottom = y + height / 2;
444
+ switch (hole.anchor) {
445
+ case "top-left":
446
+ bx = left;
447
+ by = top;
448
+ break;
449
+ case "top-center":
450
+ bx = x;
451
+ by = top;
452
+ break;
453
+ case "top-right":
454
+ bx = right;
455
+ by = top;
456
+ break;
457
+ case "center-left":
458
+ bx = left;
459
+ by = y;
460
+ break;
461
+ case "center":
462
+ bx = x;
463
+ by = y;
464
+ break;
465
+ case "center-right":
466
+ bx = right;
467
+ by = y;
468
+ break;
469
+ case "bottom-left":
470
+ bx = left;
471
+ by = bottom;
472
+ break;
473
+ case "bottom-center":
474
+ bx = x;
475
+ by = bottom;
476
+ break;
477
+ case "bottom-right":
478
+ bx = right;
479
+ by = bottom;
480
+ break;
481
+ }
482
+ return {
483
+ x: bx + (hole.offsetX || 0),
484
+ y: by + (hole.offsetY || 0)
485
+ };
486
+ } else if (hole.x !== void 0 && hole.y !== void 0) {
487
+ return {
488
+ x: hole.x * canvasSize.width,
489
+ y: hole.y * canvasSize.height
490
+ };
491
+ }
492
+ return { x: 0, y: 0 };
493
+ }
435
494
  function ensurePaper(width, height) {
436
495
  if (!paper.project) {
437
496
  paper.setup(new paper.Size(width, height));
@@ -793,65 +852,6 @@ var DielineTool = class {
793
852
  }
794
853
  ],
795
854
  [ContributionPointIds2.COMMANDS]: [
796
- {
797
- command: "reset",
798
- title: "Reset Dieline",
799
- handler: () => {
800
- this.shape = "rect";
801
- this.width = 300;
802
- this.height = 300;
803
- this.radius = 0;
804
- this.offset = 0;
805
- this.style = "solid";
806
- this.insideColor = "rgba(0,0,0,0)";
807
- this.outsideColor = "#ffffff";
808
- this.showBleedLines = true;
809
- this.holes = [];
810
- this.pathData = void 0;
811
- this.updateDieline();
812
- return true;
813
- }
814
- },
815
- {
816
- command: "setDimensions",
817
- title: "Set Dimensions",
818
- handler: (width, height) => {
819
- if (this.width === width && this.height === height) return true;
820
- this.width = width;
821
- this.height = height;
822
- this.updateDieline();
823
- return true;
824
- }
825
- },
826
- {
827
- command: "setShape",
828
- title: "Set Shape",
829
- handler: (shape) => {
830
- if (this.shape === shape) return true;
831
- this.shape = shape;
832
- this.updateDieline();
833
- return true;
834
- }
835
- },
836
- {
837
- command: "setBleed",
838
- title: "Set Bleed",
839
- handler: (bleed) => {
840
- if (this.offset === bleed) return true;
841
- this.offset = bleed;
842
- this.updateDieline();
843
- return true;
844
- }
845
- },
846
- {
847
- command: "setHoles",
848
- title: "Set Holes",
849
- handler: (holes) => {
850
- this.holes = holes;
851
- this.updateDieline(false);
852
- return true;
853
- }
854
- },
855
855
  {
856
856
  command: "getGeometry",
857
857
  title: "Get Geometry",
@@ -870,16 +870,21 @@ var DielineTool = class {
870
870
  command: "detectEdge",
871
871
  title: "Detect Edge from Image",
872
872
  handler: async (imageUrl, options) => {
873
+ var _a;
873
874
  try {
874
875
  const pathData = await ImageTracer.trace(imageUrl, options);
875
876
  const bounds = getPathBounds(pathData);
876
877
  const currentMax = Math.max(this.width, this.height);
877
878
  const scale = currentMax / Math.max(bounds.width, bounds.height);
878
- this.width = bounds.width * scale;
879
- this.height = bounds.height * scale;
880
- this.shape = "custom";
881
- this.pathData = pathData;
882
- this.updateDieline();
879
+ const newWidth = bounds.width * scale;
880
+ const newHeight = bounds.height * scale;
881
+ const configService = (_a = this.context) == null ? void 0 : _a.services.get("ConfigurationService");
882
+ if (configService) {
883
+ configService.update("dieline.width", newWidth);
884
+ configService.update("dieline.height", newHeight);
885
+ configService.update("dieline.shape", "custom");
886
+ configService.update("dieline.pathData", pathData);
887
+ }
883
888
  return pathData;
884
889
  } catch (e) {
885
890
  console.error("Edge detection failed", e);
@@ -939,6 +944,7 @@ var DielineTool = class {
939
944
  return new Pattern({ source: canvas, repetition: "repeat" });
940
945
  }
941
946
  updateDieline(emitEvent = true) {
947
+ var _a, _b;
942
948
  if (!this.canvasService) return;
943
949
  const layer = this.getLayer();
944
950
  if (!layer) return;
@@ -957,23 +963,31 @@ var DielineTool = class {
957
963
  let { width, height } = this;
958
964
  const canvasW = this.canvasService.canvas.width || 800;
959
965
  const canvasH = this.canvasService.canvas.height || 600;
966
+ let visualWidth = width;
967
+ let visualHeight = height;
960
968
  if (borderLength && borderLength > 0) {
961
- width = Math.max(0, canvasW - borderLength * 2);
962
- height = Math.max(0, canvasH - borderLength * 2);
969
+ visualWidth = Math.max(0, canvasW - borderLength * 2);
970
+ visualHeight = Math.max(0, canvasH - borderLength * 2);
963
971
  }
964
- const normalizedPos = position != null ? position : { x: 0.5, y: 0.5 };
965
- const cx = Coordinate.toAbsolute(normalizedPos.x, canvasW);
966
- const cy = Coordinate.toAbsolute(normalizedPos.y, canvasH);
972
+ const cx = Coordinate.toAbsolute((_a = position == null ? void 0 : position.x) != null ? _a : 0.5, canvasW);
973
+ const cy = Coordinate.toAbsolute((_b = position == null ? void 0 : position.y) != null ? _b : 0.5, canvasH);
967
974
  layer.remove(...layer.getObjects());
975
+ const geometryForHoles = {
976
+ x: cx,
977
+ y: cy,
978
+ width: visualWidth,
979
+ height: visualHeight
980
+ };
968
981
  const absoluteHoles = (holes || []).map((h) => {
969
- const p = Coordinate.denormalizePoint(
970
- { x: h.x, y: h.y },
982
+ const pos = resolveHolePosition(
983
+ h,
984
+ geometryForHoles,
971
985
  { width: canvasW, height: canvasH }
972
986
  );
973
987
  return {
974
988
  ...h,
975
- x: p.x,
976
- y: p.y
989
+ x: pos.x,
990
+ y: pos.y
977
991
  };
978
992
  });
979
993
  const cutW = Math.max(0, width + offset * 2);
@@ -1158,14 +1172,15 @@ var DielineTool = class {
1158
1172
  const cx = Coordinate.toAbsolute((_a = position == null ? void 0 : position.x) != null ? _a : 0.5, canvasW);
1159
1173
  const cy = Coordinate.toAbsolute((_b = position == null ? void 0 : position.y) != null ? _b : 0.5, canvasH);
1160
1174
  const absoluteHoles = (holes || []).map((h) => {
1161
- const p = Coordinate.denormalizePoint(
1162
- { x: h.x, y: h.y },
1175
+ const pos = resolveHolePosition(
1176
+ h,
1177
+ { x: cx, y: cy, width, height },
1163
1178
  { width: canvasW, height: canvasH }
1164
1179
  );
1165
1180
  return {
1166
1181
  ...h,
1167
- x: p.x,
1168
- y: p.y
1182
+ x: pos.x,
1183
+ y: pos.y
1169
1184
  };
1170
1185
  });
1171
1186
  const pathData = generateDielinePath({
@@ -1406,9 +1421,6 @@ var HoleTool = class {
1406
1421
  this.metadata = {
1407
1422
  name: "HoleTool"
1408
1423
  };
1409
- this.innerRadius = 15;
1410
- this.outerRadius = 25;
1411
- this.style = "solid";
1412
1424
  this.holes = [];
1413
1425
  this.constraintTarget = "bleed";
1414
1426
  this.isUpdatingConfig = false;
@@ -1432,53 +1444,20 @@ var HoleTool = class {
1432
1444
  "ConfigurationService"
1433
1445
  );
1434
1446
  if (configService) {
1435
- this.innerRadius = configService.get(
1436
- "hole.innerRadius",
1437
- this.innerRadius
1438
- );
1439
- this.outerRadius = configService.get(
1440
- "hole.outerRadius",
1441
- this.outerRadius
1442
- );
1443
- this.style = configService.get("hole.style", this.style);
1444
1447
  this.constraintTarget = configService.get(
1445
1448
  "hole.constraintTarget",
1446
1449
  this.constraintTarget
1447
1450
  );
1448
- const dielineHoles = configService.get("dieline.holes", []);
1449
- if (this.canvasService) {
1450
- const { width, height } = this.canvasService.canvas;
1451
- this.holes = dielineHoles.map((h) => {
1452
- const p = Coordinate.denormalizePoint(h, {
1453
- width: width || 800,
1454
- height: height || 600
1455
- });
1456
- return { x: p.x, y: p.y };
1457
- });
1458
- }
1451
+ this.holes = configService.get("dieline.holes", []);
1459
1452
  configService.onAnyChange((e) => {
1460
1453
  if (this.isUpdatingConfig) return;
1461
- if (e.key.startsWith("hole.")) {
1462
- const prop = e.key.split(".")[1];
1463
- if (prop && prop in this) {
1464
- this[prop] = e.value;
1465
- this.redraw();
1466
- this.syncHolesToDieline();
1467
- }
1454
+ if (e.key === "hole.constraintTarget") {
1455
+ this.constraintTarget = e.value;
1456
+ this.enforceConstraints();
1468
1457
  }
1469
1458
  if (e.key === "dieline.holes") {
1470
- const holes = e.value || [];
1471
- if (this.canvasService) {
1472
- const { width, height } = this.canvasService.canvas;
1473
- this.holes = holes.map((h) => {
1474
- const p = Coordinate.denormalizePoint(h, {
1475
- width: width || 800,
1476
- height: height || 600
1477
- });
1478
- return { x: p.x, y: p.y };
1479
- });
1480
- this.redraw();
1481
- }
1459
+ this.holes = e.value || [];
1460
+ this.redraw();
1482
1461
  }
1483
1462
  });
1484
1463
  }
@@ -1492,29 +1471,6 @@ var HoleTool = class {
1492
1471
  contribute() {
1493
1472
  return {
1494
1473
  [ContributionPointIds4.CONFIGURATIONS]: [
1495
- {
1496
- id: "hole.innerRadius",
1497
- type: "number",
1498
- label: "Inner Radius",
1499
- min: 1,
1500
- max: 100,
1501
- default: 15
1502
- },
1503
- {
1504
- id: "hole.outerRadius",
1505
- type: "number",
1506
- label: "Outer Radius",
1507
- min: 1,
1508
- max: 100,
1509
- default: 25
1510
- },
1511
- {
1512
- id: "hole.style",
1513
- type: "select",
1514
- label: "Line Style",
1515
- options: ["solid", "dashed"],
1516
- default: "solid"
1517
- },
1518
1474
  {
1519
1475
  id: "hole.constraintTarget",
1520
1476
  type: "select",
@@ -1528,6 +1484,7 @@ var HoleTool = class {
1528
1484
  command: "resetHoles",
1529
1485
  title: "Reset Holes",
1530
1486
  handler: () => {
1487
+ var _a;
1531
1488
  if (!this.canvasService) return false;
1532
1489
  let defaultPos = { x: this.canvasService.canvas.width / 2, y: 50 };
1533
1490
  if (this.currentGeometry) {
@@ -1538,12 +1495,24 @@ var HoleTool = class {
1538
1495
  holes: []
1539
1496
  });
1540
1497
  }
1541
- this.innerRadius = 15;
1542
- this.outerRadius = 25;
1543
- this.style = "solid";
1544
- this.holes = [defaultPos];
1545
- this.redraw();
1546
- this.syncHolesToDieline();
1498
+ const { width, height } = this.canvasService.canvas;
1499
+ const normalizedHole = Coordinate.normalizePoint(defaultPos, {
1500
+ width: width || 800,
1501
+ height: height || 600
1502
+ });
1503
+ const configService = (_a = this.context) == null ? void 0 : _a.services.get(
1504
+ "ConfigurationService"
1505
+ );
1506
+ if (configService) {
1507
+ configService.update("dieline.holes", [
1508
+ {
1509
+ x: normalizedHole.x,
1510
+ y: normalizedHole.y,
1511
+ innerRadius: 15,
1512
+ outerRadius: 25
1513
+ }
1514
+ ]);
1515
+ }
1547
1516
  return true;
1548
1517
  }
1549
1518
  },
@@ -1551,10 +1520,29 @@ var HoleTool = class {
1551
1520
  command: "addHole",
1552
1521
  title: "Add Hole",
1553
1522
  handler: (x, y) => {
1554
- if (!this.holes) this.holes = [];
1555
- this.holes.push({ x, y });
1556
- this.redraw();
1557
- this.syncHolesToDieline();
1523
+ var _a, _b, _c;
1524
+ if (!this.canvasService) return false;
1525
+ const { width, height } = this.canvasService.canvas;
1526
+ const normalizedHole = Coordinate.normalizePoint(
1527
+ { x, y },
1528
+ { width: width || 800, height: height || 600 }
1529
+ );
1530
+ const configService = (_a = this.context) == null ? void 0 : _a.services.get(
1531
+ "ConfigurationService"
1532
+ );
1533
+ if (configService) {
1534
+ const currentHoles = configService.get("dieline.holes", []);
1535
+ const lastHole = currentHoles[currentHoles.length - 1];
1536
+ const innerRadius = (_b = lastHole == null ? void 0 : lastHole.innerRadius) != null ? _b : 15;
1537
+ const outerRadius = (_c = lastHole == null ? void 0 : lastHole.outerRadius) != null ? _c : 25;
1538
+ const newHole = {
1539
+ x: normalizedHole.x,
1540
+ y: normalizedHole.y,
1541
+ innerRadius,
1542
+ outerRadius
1543
+ };
1544
+ configService.update("dieline.holes", [...currentHoles, newHole]);
1545
+ }
1558
1546
  return true;
1559
1547
  }
1560
1548
  },
@@ -1562,9 +1550,13 @@ var HoleTool = class {
1562
1550
  command: "clearHoles",
1563
1551
  title: "Clear Holes",
1564
1552
  handler: () => {
1565
- this.holes = [];
1566
- this.redraw();
1567
- this.syncHolesToDieline();
1553
+ var _a;
1554
+ const configService = (_a = this.context) == null ? void 0 : _a.services.get(
1555
+ "ConfigurationService"
1556
+ );
1557
+ if (configService) {
1558
+ configService.update("dieline.holes", []);
1559
+ }
1568
1560
  return true;
1569
1561
  }
1570
1562
  }
@@ -1605,10 +1597,12 @@ var HoleTool = class {
1605
1597
  }
1606
1598
  if (!this.handleMoving) {
1607
1599
  this.handleMoving = (e) => {
1608
- var _a;
1600
+ var _a, _b, _c, _d, _e;
1609
1601
  const target = e.target;
1610
1602
  if (!target || ((_a = target.data) == null ? void 0 : _a.type) !== "hole-marker") return;
1611
1603
  if (!this.currentGeometry) return;
1604
+ const index = (_c = (_b = target.data) == null ? void 0 : _b.index) != null ? _c : -1;
1605
+ const holeData = this.holes[index];
1612
1606
  const effectiveOffset = this.constraintTarget === "original" ? 0 : this.currentGeometry.offset;
1613
1607
  const constraintGeometry = {
1614
1608
  ...this.currentGeometry,
@@ -1620,7 +1614,12 @@ var HoleTool = class {
1620
1614
  radius: Math.max(0, this.currentGeometry.radius + effectiveOffset)
1621
1615
  };
1622
1616
  const p = new Point(target.left, target.top);
1623
- const newPos = this.calculateConstrainedPosition(p, constraintGeometry);
1617
+ const newPos = this.calculateConstrainedPosition(
1618
+ p,
1619
+ constraintGeometry,
1620
+ (_d = holeData == null ? void 0 : holeData.innerRadius) != null ? _d : 15,
1621
+ (_e = holeData == null ? void 0 : holeData.outerRadius) != null ? _e : 25
1622
+ );
1624
1623
  target.set({
1625
1624
  left: newPos.x,
1626
1625
  top: newPos.y
@@ -1641,19 +1640,6 @@ var HoleTool = class {
1641
1640
  }
1642
1641
  initializeHoles() {
1643
1642
  if (!this.canvasService) return;
1644
- if (!this.holes || this.holes.length === 0) {
1645
- let defaultPos = { x: this.canvasService.canvas.width / 2, y: 50 };
1646
- if (this.currentGeometry) {
1647
- const g = this.currentGeometry;
1648
- const topCenter = { x: g.x, y: g.y - g.height / 2 };
1649
- const snapped = getNearestPointOnDieline(topCenter, {
1650
- ...g,
1651
- holes: []
1652
- });
1653
- defaultPos = snapped;
1654
- }
1655
- this.holes = [defaultPos];
1656
- }
1657
1643
  this.redraw();
1658
1644
  this.syncHolesToDieline();
1659
1645
  }
@@ -1697,32 +1683,98 @@ var HoleTool = class {
1697
1683
  var _a;
1698
1684
  return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker";
1699
1685
  });
1700
- const holes = objects.map((obj) => ({ x: obj.left, y: obj.top }));
1701
- this.holes = holes;
1686
+ objects.sort(
1687
+ (a, b) => {
1688
+ var _a, _b, _c, _d;
1689
+ return ((_b = (_a = a.data) == null ? void 0 : _a.index) != null ? _b : 0) - ((_d = (_c = b.data) == null ? void 0 : _c.index) != null ? _d : 0);
1690
+ }
1691
+ );
1692
+ const newHoles = objects.map((obj, i) => {
1693
+ var _a, _b;
1694
+ const original = this.holes[i];
1695
+ const newAbsX = obj.left;
1696
+ const newAbsY = obj.top;
1697
+ if (original && original.anchor && this.currentGeometry) {
1698
+ const { x, y, width: width2, height: height2 } = this.currentGeometry;
1699
+ let bx = x;
1700
+ let by = y;
1701
+ const left = x - width2 / 2;
1702
+ const right = x + width2 / 2;
1703
+ const top = y - height2 / 2;
1704
+ const bottom = y + height2 / 2;
1705
+ switch (original.anchor) {
1706
+ case "top-left":
1707
+ bx = left;
1708
+ by = top;
1709
+ break;
1710
+ case "top-center":
1711
+ bx = x;
1712
+ by = top;
1713
+ break;
1714
+ case "top-right":
1715
+ bx = right;
1716
+ by = top;
1717
+ break;
1718
+ case "center-left":
1719
+ bx = left;
1720
+ by = y;
1721
+ break;
1722
+ case "center":
1723
+ bx = x;
1724
+ by = y;
1725
+ break;
1726
+ case "center-right":
1727
+ bx = right;
1728
+ by = y;
1729
+ break;
1730
+ case "bottom-left":
1731
+ bx = left;
1732
+ by = bottom;
1733
+ break;
1734
+ case "bottom-center":
1735
+ bx = x;
1736
+ by = bottom;
1737
+ break;
1738
+ case "bottom-right":
1739
+ bx = right;
1740
+ by = bottom;
1741
+ break;
1742
+ }
1743
+ return {
1744
+ ...original,
1745
+ offsetX: newAbsX - bx,
1746
+ offsetY: newAbsY - by,
1747
+ // Clear direct coordinates if we use anchor
1748
+ x: void 0,
1749
+ y: void 0
1750
+ };
1751
+ }
1752
+ const { width, height } = this.canvasService.canvas;
1753
+ const p = Coordinate.normalizePoint(
1754
+ { x: newAbsX, y: newAbsY },
1755
+ { width: width || 800, height: height || 600 }
1756
+ );
1757
+ return {
1758
+ ...original,
1759
+ x: p.x,
1760
+ y: p.y,
1761
+ // Ensure radii are preserved
1762
+ innerRadius: (_a = original == null ? void 0 : original.innerRadius) != null ? _a : 15,
1763
+ outerRadius: (_b = original == null ? void 0 : original.outerRadius) != null ? _b : 25
1764
+ };
1765
+ });
1766
+ this.holes = newHoles;
1702
1767
  this.syncHolesToDieline();
1703
1768
  }
1704
1769
  syncHolesToDieline() {
1705
1770
  if (!this.context || !this.canvasService) return;
1706
- const { holes, innerRadius, outerRadius } = this;
1707
- const currentHoles = holes || [];
1708
- const width = this.canvasService.canvas.width || 800;
1709
- const height = this.canvasService.canvas.height || 600;
1710
1771
  const configService = this.context.services.get(
1711
1772
  "ConfigurationService"
1712
1773
  );
1713
1774
  if (configService) {
1714
1775
  this.isUpdatingConfig = true;
1715
1776
  try {
1716
- const normalizedHoles = currentHoles.map((h) => {
1717
- const p = Coordinate.normalizePoint(h, { width, height });
1718
- return {
1719
- x: p.x,
1720
- y: p.y,
1721
- innerRadius,
1722
- outerRadius
1723
- };
1724
- });
1725
- configService.update("dieline.holes", normalizedHoles);
1777
+ configService.update("dieline.holes", this.holes);
1726
1778
  } finally {
1727
1779
  this.isUpdatingConfig = false;
1728
1780
  }
@@ -1731,19 +1783,31 @@ var HoleTool = class {
1731
1783
  redraw() {
1732
1784
  if (!this.canvasService) return;
1733
1785
  const canvas = this.canvasService.canvas;
1786
+ const { width, height } = canvas;
1734
1787
  const existing = canvas.getObjects().filter((obj) => {
1735
1788
  var _a;
1736
1789
  return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker";
1737
1790
  });
1738
1791
  existing.forEach((obj) => canvas.remove(obj));
1739
- const { innerRadius, outerRadius, style, holes } = this;
1792
+ const holes = this.holes;
1740
1793
  if (!holes || holes.length === 0) {
1741
1794
  this.canvasService.requestRenderAll();
1742
1795
  return;
1743
1796
  }
1797
+ const geometry = this.currentGeometry || {
1798
+ x: (width || 800) / 2,
1799
+ y: (height || 600) / 2,
1800
+ width: width || 800,
1801
+ height: height || 600
1802
+ };
1744
1803
  holes.forEach((hole, index) => {
1804
+ const pos = resolveHolePosition(
1805
+ hole,
1806
+ geometry,
1807
+ { width: width || 800, height: height || 600 }
1808
+ );
1745
1809
  const innerCircle = new Circle({
1746
- radius: innerRadius,
1810
+ radius: hole.innerRadius,
1747
1811
  fill: "transparent",
1748
1812
  stroke: "red",
1749
1813
  strokeWidth: 2,
@@ -1751,17 +1815,17 @@ var HoleTool = class {
1751
1815
  originY: "center"
1752
1816
  });
1753
1817
  const outerCircle = new Circle({
1754
- radius: outerRadius,
1818
+ radius: hole.outerRadius,
1755
1819
  fill: "transparent",
1756
1820
  stroke: "#666",
1757
1821
  strokeWidth: 1,
1758
- strokeDashArray: style === "dashed" ? [5, 5] : void 0,
1822
+ strokeDashArray: [5, 5],
1759
1823
  originX: "center",
1760
1824
  originY: "center"
1761
1825
  });
1762
1826
  const holeGroup = new Group([outerCircle, innerCircle], {
1763
- left: hole.x,
1764
- top: hole.y,
1827
+ left: pos.x,
1828
+ top: pos.y,
1765
1829
  originX: "center",
1766
1830
  originY: "center",
1767
1831
  selectable: true,
@@ -1806,9 +1870,6 @@ var HoleTool = class {
1806
1870
  enforceConstraints() {
1807
1871
  const geometry = this.currentGeometry;
1808
1872
  if (!geometry || !this.canvasService) {
1809
- console.log(
1810
- "[HoleTool] Skipping enforceConstraints: No geometry or canvas service"
1811
- );
1812
1873
  return false;
1813
1874
  }
1814
1875
  const effectiveOffset = this.constraintTarget === "original" ? 0 : geometry.offset;
@@ -1822,9 +1883,6 @@ var HoleTool = class {
1822
1883
  var _a;
1823
1884
  return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker";
1824
1885
  });
1825
- console.log(
1826
- `[HoleTool] Enforcing constraints on ${objects.length} markers`
1827
- );
1828
1886
  let changed = false;
1829
1887
  objects.sort(
1830
1888
  (a, b) => {
@@ -1833,16 +1891,17 @@ var HoleTool = class {
1833
1891
  }
1834
1892
  );
1835
1893
  const newHoles = [];
1836
- objects.forEach((obj) => {
1894
+ objects.forEach((obj, i) => {
1895
+ var _a, _b;
1837
1896
  const currentPos = new Point(obj.left, obj.top);
1897
+ const holeData = this.holes[i];
1838
1898
  const newPos = this.calculateConstrainedPosition(
1839
1899
  currentPos,
1840
- constraintGeometry
1900
+ constraintGeometry,
1901
+ (_a = holeData == null ? void 0 : holeData.innerRadius) != null ? _a : 15,
1902
+ (_b = holeData == null ? void 0 : holeData.outerRadius) != null ? _b : 25
1841
1903
  );
1842
1904
  if (currentPos.distanceFrom(newPos) > 0.1) {
1843
- console.log(
1844
- `[HoleTool] Moving hole from (${currentPos.x}, ${currentPos.y}) to (${newPos.x}, ${newPos.y})`
1845
- );
1846
1905
  obj.set({
1847
1906
  left: newPos.x,
1848
1907
  top: newPos.y
@@ -1850,16 +1909,14 @@ var HoleTool = class {
1850
1909
  obj.setCoords();
1851
1910
  changed = true;
1852
1911
  }
1853
- newHoles.push({ x: obj.left, y: obj.top });
1854
1912
  });
1855
1913
  if (changed) {
1856
- this.holes = newHoles;
1857
- this.canvasService.requestRenderAll();
1914
+ this.syncHolesFromCanvas();
1858
1915
  return true;
1859
1916
  }
1860
1917
  return false;
1861
1918
  }
1862
- calculateConstrainedPosition(p, g) {
1919
+ calculateConstrainedPosition(p, g, innerRadius, outerRadius) {
1863
1920
  const options = {
1864
1921
  ...g,
1865
1922
  holes: []
@@ -1873,7 +1930,6 @@ var HoleTool = class {
1873
1930
  const dist = p.distanceFrom(nearestP);
1874
1931
  const v = p.subtract(nearestP);
1875
1932
  const center = new Point(g.x, g.y);
1876
- const centerToNearest = nearestP.subtract(center);
1877
1933
  const distToCenter = p.distanceFrom(center);
1878
1934
  const nearestDistToCenter = nearestP.distanceFrom(center);
1879
1935
  let signedDist = dist;
@@ -1882,9 +1938,9 @@ var HoleTool = class {
1882
1938
  }
1883
1939
  let clampedDist = signedDist;
1884
1940
  if (signedDist > 0) {
1885
- clampedDist = Math.min(signedDist, this.innerRadius);
1941
+ clampedDist = Math.min(signedDist, innerRadius);
1886
1942
  } else {
1887
- clampedDist = Math.max(signedDist, -this.outerRadius);
1943
+ clampedDist = Math.max(signedDist, -outerRadius);
1888
1944
  }
1889
1945
  if (dist < 1e-3) return nearestP;
1890
1946
  const scale = Math.abs(clampedDist) / (dist || 1);