@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.js CHANGED
@@ -472,6 +472,65 @@ var Coordinate = class {
472
472
 
473
473
  // src/geometry.ts
474
474
  var import_paper = __toESM(require("paper"));
475
+ function resolveHolePosition(hole, geometry, canvasSize) {
476
+ if (hole.anchor) {
477
+ const { x, y, width, height } = geometry;
478
+ let bx = x;
479
+ let by = y;
480
+ const left = x - width / 2;
481
+ const right = x + width / 2;
482
+ const top = y - height / 2;
483
+ const bottom = y + height / 2;
484
+ switch (hole.anchor) {
485
+ case "top-left":
486
+ bx = left;
487
+ by = top;
488
+ break;
489
+ case "top-center":
490
+ bx = x;
491
+ by = top;
492
+ break;
493
+ case "top-right":
494
+ bx = right;
495
+ by = top;
496
+ break;
497
+ case "center-left":
498
+ bx = left;
499
+ by = y;
500
+ break;
501
+ case "center":
502
+ bx = x;
503
+ by = y;
504
+ break;
505
+ case "center-right":
506
+ bx = right;
507
+ by = y;
508
+ break;
509
+ case "bottom-left":
510
+ bx = left;
511
+ by = bottom;
512
+ break;
513
+ case "bottom-center":
514
+ bx = x;
515
+ by = bottom;
516
+ break;
517
+ case "bottom-right":
518
+ bx = right;
519
+ by = bottom;
520
+ break;
521
+ }
522
+ return {
523
+ x: bx + (hole.offsetX || 0),
524
+ y: by + (hole.offsetY || 0)
525
+ };
526
+ } else if (hole.x !== void 0 && hole.y !== void 0) {
527
+ return {
528
+ x: hole.x * canvasSize.width,
529
+ y: hole.y * canvasSize.height
530
+ };
531
+ }
532
+ return { x: 0, y: 0 };
533
+ }
475
534
  function ensurePaper(width, height) {
476
535
  if (!import_paper.default.project) {
477
536
  import_paper.default.setup(new import_paper.default.Size(width, height));
@@ -833,65 +892,6 @@ var DielineTool = class {
833
892
  }
834
893
  ],
835
894
  [import_core2.ContributionPointIds.COMMANDS]: [
836
- {
837
- command: "reset",
838
- title: "Reset Dieline",
839
- handler: () => {
840
- this.shape = "rect";
841
- this.width = 300;
842
- this.height = 300;
843
- this.radius = 0;
844
- this.offset = 0;
845
- this.style = "solid";
846
- this.insideColor = "rgba(0,0,0,0)";
847
- this.outsideColor = "#ffffff";
848
- this.showBleedLines = true;
849
- this.holes = [];
850
- this.pathData = void 0;
851
- this.updateDieline();
852
- return true;
853
- }
854
- },
855
- {
856
- command: "setDimensions",
857
- title: "Set Dimensions",
858
- handler: (width, height) => {
859
- if (this.width === width && this.height === height) return true;
860
- this.width = width;
861
- this.height = height;
862
- this.updateDieline();
863
- return true;
864
- }
865
- },
866
- {
867
- command: "setShape",
868
- title: "Set Shape",
869
- handler: (shape) => {
870
- if (this.shape === shape) return true;
871
- this.shape = shape;
872
- this.updateDieline();
873
- return true;
874
- }
875
- },
876
- {
877
- command: "setBleed",
878
- title: "Set Bleed",
879
- handler: (bleed) => {
880
- if (this.offset === bleed) return true;
881
- this.offset = bleed;
882
- this.updateDieline();
883
- return true;
884
- }
885
- },
886
- {
887
- command: "setHoles",
888
- title: "Set Holes",
889
- handler: (holes) => {
890
- this.holes = holes;
891
- this.updateDieline(false);
892
- return true;
893
- }
894
- },
895
895
  {
896
896
  command: "getGeometry",
897
897
  title: "Get Geometry",
@@ -910,16 +910,21 @@ var DielineTool = class {
910
910
  command: "detectEdge",
911
911
  title: "Detect Edge from Image",
912
912
  handler: async (imageUrl, options) => {
913
+ var _a;
913
914
  try {
914
915
  const pathData = await ImageTracer.trace(imageUrl, options);
915
916
  const bounds = getPathBounds(pathData);
916
917
  const currentMax = Math.max(this.width, this.height);
917
918
  const scale = currentMax / Math.max(bounds.width, bounds.height);
918
- this.width = bounds.width * scale;
919
- this.height = bounds.height * scale;
920
- this.shape = "custom";
921
- this.pathData = pathData;
922
- this.updateDieline();
919
+ const newWidth = bounds.width * scale;
920
+ const newHeight = bounds.height * scale;
921
+ const configService = (_a = this.context) == null ? void 0 : _a.services.get("ConfigurationService");
922
+ if (configService) {
923
+ configService.update("dieline.width", newWidth);
924
+ configService.update("dieline.height", newHeight);
925
+ configService.update("dieline.shape", "custom");
926
+ configService.update("dieline.pathData", pathData);
927
+ }
923
928
  return pathData;
924
929
  } catch (e) {
925
930
  console.error("Edge detection failed", e);
@@ -979,6 +984,7 @@ var DielineTool = class {
979
984
  return new import_fabric2.Pattern({ source: canvas, repetition: "repeat" });
980
985
  }
981
986
  updateDieline(emitEvent = true) {
987
+ var _a, _b;
982
988
  if (!this.canvasService) return;
983
989
  const layer = this.getLayer();
984
990
  if (!layer) return;
@@ -997,23 +1003,31 @@ var DielineTool = class {
997
1003
  let { width, height } = this;
998
1004
  const canvasW = this.canvasService.canvas.width || 800;
999
1005
  const canvasH = this.canvasService.canvas.height || 600;
1006
+ let visualWidth = width;
1007
+ let visualHeight = height;
1000
1008
  if (borderLength && borderLength > 0) {
1001
- width = Math.max(0, canvasW - borderLength * 2);
1002
- height = Math.max(0, canvasH - borderLength * 2);
1009
+ visualWidth = Math.max(0, canvasW - borderLength * 2);
1010
+ visualHeight = Math.max(0, canvasH - borderLength * 2);
1003
1011
  }
1004
- const normalizedPos = position != null ? position : { x: 0.5, y: 0.5 };
1005
- const cx = Coordinate.toAbsolute(normalizedPos.x, canvasW);
1006
- const cy = Coordinate.toAbsolute(normalizedPos.y, canvasH);
1012
+ const cx = Coordinate.toAbsolute((_a = position == null ? void 0 : position.x) != null ? _a : 0.5, canvasW);
1013
+ const cy = Coordinate.toAbsolute((_b = position == null ? void 0 : position.y) != null ? _b : 0.5, canvasH);
1007
1014
  layer.remove(...layer.getObjects());
1015
+ const geometryForHoles = {
1016
+ x: cx,
1017
+ y: cy,
1018
+ width: visualWidth,
1019
+ height: visualHeight
1020
+ };
1008
1021
  const absoluteHoles = (holes || []).map((h) => {
1009
- const p = Coordinate.denormalizePoint(
1010
- { x: h.x, y: h.y },
1022
+ const pos = resolveHolePosition(
1023
+ h,
1024
+ geometryForHoles,
1011
1025
  { width: canvasW, height: canvasH }
1012
1026
  );
1013
1027
  return {
1014
1028
  ...h,
1015
- x: p.x,
1016
- y: p.y
1029
+ x: pos.x,
1030
+ y: pos.y
1017
1031
  };
1018
1032
  });
1019
1033
  const cutW = Math.max(0, width + offset * 2);
@@ -1198,14 +1212,15 @@ var DielineTool = class {
1198
1212
  const cx = Coordinate.toAbsolute((_a = position == null ? void 0 : position.x) != null ? _a : 0.5, canvasW);
1199
1213
  const cy = Coordinate.toAbsolute((_b = position == null ? void 0 : position.y) != null ? _b : 0.5, canvasH);
1200
1214
  const absoluteHoles = (holes || []).map((h) => {
1201
- const p = Coordinate.denormalizePoint(
1202
- { x: h.x, y: h.y },
1215
+ const pos = resolveHolePosition(
1216
+ h,
1217
+ { x: cx, y: cy, width, height },
1203
1218
  { width: canvasW, height: canvasH }
1204
1219
  );
1205
1220
  return {
1206
1221
  ...h,
1207
- x: p.x,
1208
- y: p.y
1222
+ x: pos.x,
1223
+ y: pos.y
1209
1224
  };
1210
1225
  });
1211
1226
  const pathData = generateDielinePath({
@@ -1442,9 +1457,6 @@ var HoleTool = class {
1442
1457
  this.metadata = {
1443
1458
  name: "HoleTool"
1444
1459
  };
1445
- this.innerRadius = 15;
1446
- this.outerRadius = 25;
1447
- this.style = "solid";
1448
1460
  this.holes = [];
1449
1461
  this.constraintTarget = "bleed";
1450
1462
  this.isUpdatingConfig = false;
@@ -1468,53 +1480,20 @@ var HoleTool = class {
1468
1480
  "ConfigurationService"
1469
1481
  );
1470
1482
  if (configService) {
1471
- this.innerRadius = configService.get(
1472
- "hole.innerRadius",
1473
- this.innerRadius
1474
- );
1475
- this.outerRadius = configService.get(
1476
- "hole.outerRadius",
1477
- this.outerRadius
1478
- );
1479
- this.style = configService.get("hole.style", this.style);
1480
1483
  this.constraintTarget = configService.get(
1481
1484
  "hole.constraintTarget",
1482
1485
  this.constraintTarget
1483
1486
  );
1484
- const dielineHoles = configService.get("dieline.holes", []);
1485
- if (this.canvasService) {
1486
- const { width, height } = this.canvasService.canvas;
1487
- this.holes = dielineHoles.map((h) => {
1488
- const p = Coordinate.denormalizePoint(h, {
1489
- width: width || 800,
1490
- height: height || 600
1491
- });
1492
- return { x: p.x, y: p.y };
1493
- });
1494
- }
1487
+ this.holes = configService.get("dieline.holes", []);
1495
1488
  configService.onAnyChange((e) => {
1496
1489
  if (this.isUpdatingConfig) return;
1497
- if (e.key.startsWith("hole.")) {
1498
- const prop = e.key.split(".")[1];
1499
- if (prop && prop in this) {
1500
- this[prop] = e.value;
1501
- this.redraw();
1502
- this.syncHolesToDieline();
1503
- }
1490
+ if (e.key === "hole.constraintTarget") {
1491
+ this.constraintTarget = e.value;
1492
+ this.enforceConstraints();
1504
1493
  }
1505
1494
  if (e.key === "dieline.holes") {
1506
- const holes = e.value || [];
1507
- if (this.canvasService) {
1508
- const { width, height } = this.canvasService.canvas;
1509
- this.holes = holes.map((h) => {
1510
- const p = Coordinate.denormalizePoint(h, {
1511
- width: width || 800,
1512
- height: height || 600
1513
- });
1514
- return { x: p.x, y: p.y };
1515
- });
1516
- this.redraw();
1517
- }
1495
+ this.holes = e.value || [];
1496
+ this.redraw();
1518
1497
  }
1519
1498
  });
1520
1499
  }
@@ -1528,29 +1507,6 @@ var HoleTool = class {
1528
1507
  contribute() {
1529
1508
  return {
1530
1509
  [import_core4.ContributionPointIds.CONFIGURATIONS]: [
1531
- {
1532
- id: "hole.innerRadius",
1533
- type: "number",
1534
- label: "Inner Radius",
1535
- min: 1,
1536
- max: 100,
1537
- default: 15
1538
- },
1539
- {
1540
- id: "hole.outerRadius",
1541
- type: "number",
1542
- label: "Outer Radius",
1543
- min: 1,
1544
- max: 100,
1545
- default: 25
1546
- },
1547
- {
1548
- id: "hole.style",
1549
- type: "select",
1550
- label: "Line Style",
1551
- options: ["solid", "dashed"],
1552
- default: "solid"
1553
- },
1554
1510
  {
1555
1511
  id: "hole.constraintTarget",
1556
1512
  type: "select",
@@ -1564,6 +1520,7 @@ var HoleTool = class {
1564
1520
  command: "resetHoles",
1565
1521
  title: "Reset Holes",
1566
1522
  handler: () => {
1523
+ var _a;
1567
1524
  if (!this.canvasService) return false;
1568
1525
  let defaultPos = { x: this.canvasService.canvas.width / 2, y: 50 };
1569
1526
  if (this.currentGeometry) {
@@ -1574,12 +1531,24 @@ var HoleTool = class {
1574
1531
  holes: []
1575
1532
  });
1576
1533
  }
1577
- this.innerRadius = 15;
1578
- this.outerRadius = 25;
1579
- this.style = "solid";
1580
- this.holes = [defaultPos];
1581
- this.redraw();
1582
- this.syncHolesToDieline();
1534
+ const { width, height } = this.canvasService.canvas;
1535
+ const normalizedHole = Coordinate.normalizePoint(defaultPos, {
1536
+ width: width || 800,
1537
+ height: height || 600
1538
+ });
1539
+ const configService = (_a = this.context) == null ? void 0 : _a.services.get(
1540
+ "ConfigurationService"
1541
+ );
1542
+ if (configService) {
1543
+ configService.update("dieline.holes", [
1544
+ {
1545
+ x: normalizedHole.x,
1546
+ y: normalizedHole.y,
1547
+ innerRadius: 15,
1548
+ outerRadius: 25
1549
+ }
1550
+ ]);
1551
+ }
1583
1552
  return true;
1584
1553
  }
1585
1554
  },
@@ -1587,10 +1556,29 @@ var HoleTool = class {
1587
1556
  command: "addHole",
1588
1557
  title: "Add Hole",
1589
1558
  handler: (x, y) => {
1590
- if (!this.holes) this.holes = [];
1591
- this.holes.push({ x, y });
1592
- this.redraw();
1593
- this.syncHolesToDieline();
1559
+ var _a, _b, _c;
1560
+ if (!this.canvasService) return false;
1561
+ const { width, height } = this.canvasService.canvas;
1562
+ const normalizedHole = Coordinate.normalizePoint(
1563
+ { x, y },
1564
+ { width: width || 800, height: height || 600 }
1565
+ );
1566
+ const configService = (_a = this.context) == null ? void 0 : _a.services.get(
1567
+ "ConfigurationService"
1568
+ );
1569
+ if (configService) {
1570
+ const currentHoles = configService.get("dieline.holes", []);
1571
+ const lastHole = currentHoles[currentHoles.length - 1];
1572
+ const innerRadius = (_b = lastHole == null ? void 0 : lastHole.innerRadius) != null ? _b : 15;
1573
+ const outerRadius = (_c = lastHole == null ? void 0 : lastHole.outerRadius) != null ? _c : 25;
1574
+ const newHole = {
1575
+ x: normalizedHole.x,
1576
+ y: normalizedHole.y,
1577
+ innerRadius,
1578
+ outerRadius
1579
+ };
1580
+ configService.update("dieline.holes", [...currentHoles, newHole]);
1581
+ }
1594
1582
  return true;
1595
1583
  }
1596
1584
  },
@@ -1598,9 +1586,13 @@ var HoleTool = class {
1598
1586
  command: "clearHoles",
1599
1587
  title: "Clear Holes",
1600
1588
  handler: () => {
1601
- this.holes = [];
1602
- this.redraw();
1603
- this.syncHolesToDieline();
1589
+ var _a;
1590
+ const configService = (_a = this.context) == null ? void 0 : _a.services.get(
1591
+ "ConfigurationService"
1592
+ );
1593
+ if (configService) {
1594
+ configService.update("dieline.holes", []);
1595
+ }
1604
1596
  return true;
1605
1597
  }
1606
1598
  }
@@ -1641,10 +1633,12 @@ var HoleTool = class {
1641
1633
  }
1642
1634
  if (!this.handleMoving) {
1643
1635
  this.handleMoving = (e) => {
1644
- var _a;
1636
+ var _a, _b, _c, _d, _e;
1645
1637
  const target = e.target;
1646
1638
  if (!target || ((_a = target.data) == null ? void 0 : _a.type) !== "hole-marker") return;
1647
1639
  if (!this.currentGeometry) return;
1640
+ const index = (_c = (_b = target.data) == null ? void 0 : _b.index) != null ? _c : -1;
1641
+ const holeData = this.holes[index];
1648
1642
  const effectiveOffset = this.constraintTarget === "original" ? 0 : this.currentGeometry.offset;
1649
1643
  const constraintGeometry = {
1650
1644
  ...this.currentGeometry,
@@ -1656,7 +1650,12 @@ var HoleTool = class {
1656
1650
  radius: Math.max(0, this.currentGeometry.radius + effectiveOffset)
1657
1651
  };
1658
1652
  const p = new import_fabric4.Point(target.left, target.top);
1659
- const newPos = this.calculateConstrainedPosition(p, constraintGeometry);
1653
+ const newPos = this.calculateConstrainedPosition(
1654
+ p,
1655
+ constraintGeometry,
1656
+ (_d = holeData == null ? void 0 : holeData.innerRadius) != null ? _d : 15,
1657
+ (_e = holeData == null ? void 0 : holeData.outerRadius) != null ? _e : 25
1658
+ );
1660
1659
  target.set({
1661
1660
  left: newPos.x,
1662
1661
  top: newPos.y
@@ -1677,19 +1676,6 @@ var HoleTool = class {
1677
1676
  }
1678
1677
  initializeHoles() {
1679
1678
  if (!this.canvasService) return;
1680
- if (!this.holes || this.holes.length === 0) {
1681
- let defaultPos = { x: this.canvasService.canvas.width / 2, y: 50 };
1682
- if (this.currentGeometry) {
1683
- const g = this.currentGeometry;
1684
- const topCenter = { x: g.x, y: g.y - g.height / 2 };
1685
- const snapped = getNearestPointOnDieline(topCenter, {
1686
- ...g,
1687
- holes: []
1688
- });
1689
- defaultPos = snapped;
1690
- }
1691
- this.holes = [defaultPos];
1692
- }
1693
1679
  this.redraw();
1694
1680
  this.syncHolesToDieline();
1695
1681
  }
@@ -1733,32 +1719,98 @@ var HoleTool = class {
1733
1719
  var _a;
1734
1720
  return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker";
1735
1721
  });
1736
- const holes = objects.map((obj) => ({ x: obj.left, y: obj.top }));
1737
- this.holes = holes;
1722
+ objects.sort(
1723
+ (a, b) => {
1724
+ var _a, _b, _c, _d;
1725
+ 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);
1726
+ }
1727
+ );
1728
+ const newHoles = objects.map((obj, i) => {
1729
+ var _a, _b;
1730
+ const original = this.holes[i];
1731
+ const newAbsX = obj.left;
1732
+ const newAbsY = obj.top;
1733
+ if (original && original.anchor && this.currentGeometry) {
1734
+ const { x, y, width: width2, height: height2 } = this.currentGeometry;
1735
+ let bx = x;
1736
+ let by = y;
1737
+ const left = x - width2 / 2;
1738
+ const right = x + width2 / 2;
1739
+ const top = y - height2 / 2;
1740
+ const bottom = y + height2 / 2;
1741
+ switch (original.anchor) {
1742
+ case "top-left":
1743
+ bx = left;
1744
+ by = top;
1745
+ break;
1746
+ case "top-center":
1747
+ bx = x;
1748
+ by = top;
1749
+ break;
1750
+ case "top-right":
1751
+ bx = right;
1752
+ by = top;
1753
+ break;
1754
+ case "center-left":
1755
+ bx = left;
1756
+ by = y;
1757
+ break;
1758
+ case "center":
1759
+ bx = x;
1760
+ by = y;
1761
+ break;
1762
+ case "center-right":
1763
+ bx = right;
1764
+ by = y;
1765
+ break;
1766
+ case "bottom-left":
1767
+ bx = left;
1768
+ by = bottom;
1769
+ break;
1770
+ case "bottom-center":
1771
+ bx = x;
1772
+ by = bottom;
1773
+ break;
1774
+ case "bottom-right":
1775
+ bx = right;
1776
+ by = bottom;
1777
+ break;
1778
+ }
1779
+ return {
1780
+ ...original,
1781
+ offsetX: newAbsX - bx,
1782
+ offsetY: newAbsY - by,
1783
+ // Clear direct coordinates if we use anchor
1784
+ x: void 0,
1785
+ y: void 0
1786
+ };
1787
+ }
1788
+ const { width, height } = this.canvasService.canvas;
1789
+ const p = Coordinate.normalizePoint(
1790
+ { x: newAbsX, y: newAbsY },
1791
+ { width: width || 800, height: height || 600 }
1792
+ );
1793
+ return {
1794
+ ...original,
1795
+ x: p.x,
1796
+ y: p.y,
1797
+ // Ensure radii are preserved
1798
+ innerRadius: (_a = original == null ? void 0 : original.innerRadius) != null ? _a : 15,
1799
+ outerRadius: (_b = original == null ? void 0 : original.outerRadius) != null ? _b : 25
1800
+ };
1801
+ });
1802
+ this.holes = newHoles;
1738
1803
  this.syncHolesToDieline();
1739
1804
  }
1740
1805
  syncHolesToDieline() {
1741
1806
  if (!this.context || !this.canvasService) return;
1742
- const { holes, innerRadius, outerRadius } = this;
1743
- const currentHoles = holes || [];
1744
- const width = this.canvasService.canvas.width || 800;
1745
- const height = this.canvasService.canvas.height || 600;
1746
1807
  const configService = this.context.services.get(
1747
1808
  "ConfigurationService"
1748
1809
  );
1749
1810
  if (configService) {
1750
1811
  this.isUpdatingConfig = true;
1751
1812
  try {
1752
- const normalizedHoles = currentHoles.map((h) => {
1753
- const p = Coordinate.normalizePoint(h, { width, height });
1754
- return {
1755
- x: p.x,
1756
- y: p.y,
1757
- innerRadius,
1758
- outerRadius
1759
- };
1760
- });
1761
- configService.update("dieline.holes", normalizedHoles);
1813
+ configService.update("dieline.holes", this.holes);
1762
1814
  } finally {
1763
1815
  this.isUpdatingConfig = false;
1764
1816
  }
@@ -1767,19 +1819,31 @@ var HoleTool = class {
1767
1819
  redraw() {
1768
1820
  if (!this.canvasService) return;
1769
1821
  const canvas = this.canvasService.canvas;
1822
+ const { width, height } = canvas;
1770
1823
  const existing = canvas.getObjects().filter((obj) => {
1771
1824
  var _a;
1772
1825
  return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker";
1773
1826
  });
1774
1827
  existing.forEach((obj) => canvas.remove(obj));
1775
- const { innerRadius, outerRadius, style, holes } = this;
1828
+ const holes = this.holes;
1776
1829
  if (!holes || holes.length === 0) {
1777
1830
  this.canvasService.requestRenderAll();
1778
1831
  return;
1779
1832
  }
1833
+ const geometry = this.currentGeometry || {
1834
+ x: (width || 800) / 2,
1835
+ y: (height || 600) / 2,
1836
+ width: width || 800,
1837
+ height: height || 600
1838
+ };
1780
1839
  holes.forEach((hole, index) => {
1840
+ const pos = resolveHolePosition(
1841
+ hole,
1842
+ geometry,
1843
+ { width: width || 800, height: height || 600 }
1844
+ );
1781
1845
  const innerCircle = new import_fabric4.Circle({
1782
- radius: innerRadius,
1846
+ radius: hole.innerRadius,
1783
1847
  fill: "transparent",
1784
1848
  stroke: "red",
1785
1849
  strokeWidth: 2,
@@ -1787,17 +1851,17 @@ var HoleTool = class {
1787
1851
  originY: "center"
1788
1852
  });
1789
1853
  const outerCircle = new import_fabric4.Circle({
1790
- radius: outerRadius,
1854
+ radius: hole.outerRadius,
1791
1855
  fill: "transparent",
1792
1856
  stroke: "#666",
1793
1857
  strokeWidth: 1,
1794
- strokeDashArray: style === "dashed" ? [5, 5] : void 0,
1858
+ strokeDashArray: [5, 5],
1795
1859
  originX: "center",
1796
1860
  originY: "center"
1797
1861
  });
1798
1862
  const holeGroup = new import_fabric4.Group([outerCircle, innerCircle], {
1799
- left: hole.x,
1800
- top: hole.y,
1863
+ left: pos.x,
1864
+ top: pos.y,
1801
1865
  originX: "center",
1802
1866
  originY: "center",
1803
1867
  selectable: true,
@@ -1842,9 +1906,6 @@ var HoleTool = class {
1842
1906
  enforceConstraints() {
1843
1907
  const geometry = this.currentGeometry;
1844
1908
  if (!geometry || !this.canvasService) {
1845
- console.log(
1846
- "[HoleTool] Skipping enforceConstraints: No geometry or canvas service"
1847
- );
1848
1909
  return false;
1849
1910
  }
1850
1911
  const effectiveOffset = this.constraintTarget === "original" ? 0 : geometry.offset;
@@ -1858,9 +1919,6 @@ var HoleTool = class {
1858
1919
  var _a;
1859
1920
  return ((_a = obj.data) == null ? void 0 : _a.type) === "hole-marker";
1860
1921
  });
1861
- console.log(
1862
- `[HoleTool] Enforcing constraints on ${objects.length} markers`
1863
- );
1864
1922
  let changed = false;
1865
1923
  objects.sort(
1866
1924
  (a, b) => {
@@ -1869,16 +1927,17 @@ var HoleTool = class {
1869
1927
  }
1870
1928
  );
1871
1929
  const newHoles = [];
1872
- objects.forEach((obj) => {
1930
+ objects.forEach((obj, i) => {
1931
+ var _a, _b;
1873
1932
  const currentPos = new import_fabric4.Point(obj.left, obj.top);
1933
+ const holeData = this.holes[i];
1874
1934
  const newPos = this.calculateConstrainedPosition(
1875
1935
  currentPos,
1876
- constraintGeometry
1936
+ constraintGeometry,
1937
+ (_a = holeData == null ? void 0 : holeData.innerRadius) != null ? _a : 15,
1938
+ (_b = holeData == null ? void 0 : holeData.outerRadius) != null ? _b : 25
1877
1939
  );
1878
1940
  if (currentPos.distanceFrom(newPos) > 0.1) {
1879
- console.log(
1880
- `[HoleTool] Moving hole from (${currentPos.x}, ${currentPos.y}) to (${newPos.x}, ${newPos.y})`
1881
- );
1882
1941
  obj.set({
1883
1942
  left: newPos.x,
1884
1943
  top: newPos.y
@@ -1886,16 +1945,14 @@ var HoleTool = class {
1886
1945
  obj.setCoords();
1887
1946
  changed = true;
1888
1947
  }
1889
- newHoles.push({ x: obj.left, y: obj.top });
1890
1948
  });
1891
1949
  if (changed) {
1892
- this.holes = newHoles;
1893
- this.canvasService.requestRenderAll();
1950
+ this.syncHolesFromCanvas();
1894
1951
  return true;
1895
1952
  }
1896
1953
  return false;
1897
1954
  }
1898
- calculateConstrainedPosition(p, g) {
1955
+ calculateConstrainedPosition(p, g, innerRadius, outerRadius) {
1899
1956
  const options = {
1900
1957
  ...g,
1901
1958
  holes: []
@@ -1909,7 +1966,6 @@ var HoleTool = class {
1909
1966
  const dist = p.distanceFrom(nearestP);
1910
1967
  const v = p.subtract(nearestP);
1911
1968
  const center = new import_fabric4.Point(g.x, g.y);
1912
- const centerToNearest = nearestP.subtract(center);
1913
1969
  const distToCenter = p.distanceFrom(center);
1914
1970
  const nearestDistToCenter = nearestP.distanceFrom(center);
1915
1971
  let signedDist = dist;
@@ -1918,9 +1974,9 @@ var HoleTool = class {
1918
1974
  }
1919
1975
  let clampedDist = signedDist;
1920
1976
  if (signedDist > 0) {
1921
- clampedDist = Math.min(signedDist, this.innerRadius);
1977
+ clampedDist = Math.min(signedDist, innerRadius);
1922
1978
  } else {
1923
- clampedDist = Math.max(signedDist, -this.outerRadius);
1979
+ clampedDist = Math.max(signedDist, -outerRadius);
1924
1980
  }
1925
1981
  if (dist < 1e-3) return nearestP;
1926
1982
  const scale = Math.abs(clampedDist) / (dist || 1);