@pooder/kit 3.5.0 → 4.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
@@ -793,13 +793,16 @@ function createFeatureItem(feature, center) {
793
793
  }
794
794
  return item;
795
795
  }
796
- function getDielineShape(options) {
796
+ function getPerimeterShape(options) {
797
797
  let mainShape = createBaseShape(options);
798
798
  const { features } = options;
799
799
  if (features && features.length > 0) {
800
+ const edgeFeatures = features.filter(
801
+ (f) => !f.placement || f.placement === "edge"
802
+ );
800
803
  const adds = [];
801
804
  const subtracts = [];
802
- features.forEach((f) => {
805
+ edgeFeatures.forEach((f) => {
803
806
  const pos = resolveFeaturePosition(f, options);
804
807
  const center = new import_paper2.default.Point(pos.x, pos.y);
805
808
  const item = createFeatureItem(f, center);
@@ -838,14 +841,42 @@ function getDielineShape(options) {
838
841
  }
839
842
  return mainShape;
840
843
  }
844
+ function applySurfaceFeatures(shape, features, options) {
845
+ const internalFeatures = features.filter((f) => f.placement === "internal");
846
+ if (internalFeatures.length === 0) return shape;
847
+ let result = shape;
848
+ for (const f of internalFeatures) {
849
+ const pos = resolveFeaturePosition(f, options);
850
+ const center = new import_paper2.default.Point(pos.x, pos.y);
851
+ const item = createFeatureItem(f, center);
852
+ try {
853
+ if (f.operation === "add") {
854
+ const temp = result.unite(item);
855
+ result.remove();
856
+ item.remove();
857
+ result = temp;
858
+ } else {
859
+ const temp = result.subtract(item);
860
+ result.remove();
861
+ item.remove();
862
+ result = temp;
863
+ }
864
+ } catch (e) {
865
+ console.error("Geometry: Failed to apply surface feature", e);
866
+ item.remove();
867
+ }
868
+ }
869
+ return result;
870
+ }
841
871
  function generateDielinePath(options) {
842
872
  const paperWidth = options.canvasWidth || options.width * 2 || 2e3;
843
873
  const paperHeight = options.canvasHeight || options.height * 2 || 2e3;
844
874
  ensurePaper(paperWidth, paperHeight);
845
875
  import_paper2.default.project.activeLayer.removeChildren();
846
- const mainShape = getDielineShape(options);
847
- const pathData = mainShape.pathData;
848
- mainShape.remove();
876
+ const perimeter = getPerimeterShape(options);
877
+ const finalShape = applySurfaceFeatures(perimeter, options.features, options);
878
+ const pathData = finalShape.pathData;
879
+ finalShape.remove();
849
880
  return pathData;
850
881
  }
851
882
  function generateMaskPath(options) {
@@ -856,7 +887,8 @@ function generateMaskPath(options) {
856
887
  point: [0, 0],
857
888
  size: [canvasWidth, canvasHeight]
858
889
  });
859
- const mainShape = getDielineShape(options);
890
+ const perimeter = getPerimeterShape(options);
891
+ const mainShape = applySurfaceFeatures(perimeter, options.features, options);
860
892
  const finalMask = maskRect.subtract(mainShape);
861
893
  maskRect.remove();
862
894
  mainShape.remove();
@@ -869,8 +901,10 @@ function generateBleedZonePath(originalOptions, offsetOptions, offset) {
869
901
  const paperHeight = originalOptions.canvasHeight || originalOptions.height * 2 || 2e3;
870
902
  ensurePaper(paperWidth, paperHeight);
871
903
  import_paper2.default.project.activeLayer.removeChildren();
872
- const shapeOriginal = getDielineShape(originalOptions);
873
- const shapeOffset = getDielineShape(offsetOptions);
904
+ const pOriginal = getPerimeterShape(originalOptions);
905
+ const shapeOriginal = applySurfaceFeatures(pOriginal, originalOptions.features, originalOptions);
906
+ const pOffset = getPerimeterShape(offsetOptions);
907
+ const shapeOffset = applySurfaceFeatures(pOffset, offsetOptions.features, offsetOptions);
874
908
  let bleedZone;
875
909
  if (offset > 0) {
876
910
  bleedZone = shapeOffset.subtract(shapeOriginal);
@@ -906,6 +940,105 @@ function getPathBounds(pathData) {
906
940
  };
907
941
  }
908
942
 
943
+ // src/constraints.ts
944
+ var ConstraintRegistry = class {
945
+ static register(type, handler) {
946
+ this.handlers.set(type, handler);
947
+ }
948
+ static apply(x, y, feature, context) {
949
+ if (!feature.constraints || !feature.constraints.type) {
950
+ return { x, y };
951
+ }
952
+ const handler = this.handlers.get(feature.constraints.type);
953
+ if (handler) {
954
+ return handler(x, y, feature, context);
955
+ }
956
+ return { x, y };
957
+ }
958
+ };
959
+ ConstraintRegistry.handlers = /* @__PURE__ */ new Map();
960
+ var edgeConstraint = (x, y, feature, context) => {
961
+ var _a;
962
+ const { dielineWidth, dielineHeight } = context;
963
+ const params = ((_a = feature.constraints) == null ? void 0 : _a.params) || {};
964
+ const allowedEdges = params.allowedEdges || [
965
+ "top",
966
+ "bottom",
967
+ "left",
968
+ "right"
969
+ ];
970
+ const confine = params.confine || false;
971
+ const offset = params.offset || 0;
972
+ const distances = [];
973
+ if (allowedEdges.includes("top"))
974
+ distances.push({ edge: "top", dist: y * dielineHeight });
975
+ if (allowedEdges.includes("bottom"))
976
+ distances.push({ edge: "bottom", dist: (1 - y) * dielineHeight });
977
+ if (allowedEdges.includes("left"))
978
+ distances.push({ edge: "left", dist: x * dielineWidth });
979
+ if (allowedEdges.includes("right"))
980
+ distances.push({ edge: "right", dist: (1 - x) * dielineWidth });
981
+ if (distances.length === 0) return { x, y };
982
+ distances.sort((a, b) => a.dist - b.dist);
983
+ const nearest = distances[0].edge;
984
+ let newX = x;
985
+ let newY = y;
986
+ const fw = feature.width || 0;
987
+ const fh = feature.height || 0;
988
+ switch (nearest) {
989
+ case "top":
990
+ newY = 0 + offset / dielineHeight;
991
+ if (confine) {
992
+ const minX = fw / 2 / dielineWidth;
993
+ const maxX = 1 - minX;
994
+ newX = Math.max(minX, Math.min(newX, maxX));
995
+ }
996
+ break;
997
+ case "bottom":
998
+ newY = 1 - offset / dielineHeight;
999
+ if (confine) {
1000
+ const minX = fw / 2 / dielineWidth;
1001
+ const maxX = 1 - minX;
1002
+ newX = Math.max(minX, Math.min(newX, maxX));
1003
+ }
1004
+ break;
1005
+ case "left":
1006
+ newX = 0 + offset / dielineWidth;
1007
+ if (confine) {
1008
+ const minY = fh / 2 / dielineHeight;
1009
+ const maxY = 1 - minY;
1010
+ newY = Math.max(minY, Math.min(newY, maxY));
1011
+ }
1012
+ break;
1013
+ case "right":
1014
+ newX = 1 - offset / dielineWidth;
1015
+ if (confine) {
1016
+ const minY = fh / 2 / dielineHeight;
1017
+ const maxY = 1 - minY;
1018
+ newY = Math.max(minY, Math.min(newY, maxY));
1019
+ }
1020
+ break;
1021
+ }
1022
+ return { x: newX, y: newY };
1023
+ };
1024
+ var internalConstraint = (x, y, feature, context) => {
1025
+ var _a;
1026
+ const { dielineWidth, dielineHeight } = context;
1027
+ const params = ((_a = feature.constraints) == null ? void 0 : _a.params) || {};
1028
+ const margin = params.margin || 0;
1029
+ const fw = feature.width || 0;
1030
+ const fh = feature.height || 0;
1031
+ const minX = (margin + fw / 2) / dielineWidth;
1032
+ const maxX = 1 - (margin + fw / 2) / dielineWidth;
1033
+ const minY = (margin + fh / 2) / dielineHeight;
1034
+ const maxY = 1 - (margin + fh / 2) / dielineHeight;
1035
+ const clampedX = minX > maxX ? 0.5 : Math.max(minX, Math.min(x, maxX));
1036
+ const clampedY = minY > maxY ? 0.5 : Math.max(minY, Math.min(y, maxY));
1037
+ return { x: clampedX, y: clampedY };
1038
+ };
1039
+ ConstraintRegistry.register("edge", edgeConstraint);
1040
+ ConstraintRegistry.register("internal", internalConstraint);
1041
+
909
1042
  // src/dieline.ts
910
1043
  var DielineTool = class {
911
1044
  constructor(options) {
@@ -1200,6 +1333,37 @@ var DielineTool = class {
1200
1333
  }
1201
1334
  ],
1202
1335
  [import_core2.ContributionPointIds.COMMANDS]: [
1336
+ {
1337
+ command: "updateFeaturePosition",
1338
+ title: "Update Feature Position",
1339
+ handler: (groupId, x, y) => {
1340
+ var _a;
1341
+ const configService = (_a = this.context) == null ? void 0 : _a.services.get(
1342
+ "ConfigurationService"
1343
+ );
1344
+ if (!configService) return;
1345
+ const features = configService.get("dieline.features") || [];
1346
+ const dielineWidth = configService.get("dieline.width") || 500;
1347
+ const dielineHeight = configService.get("dieline.height") || 500;
1348
+ let changed = false;
1349
+ const newFeatures = features.map((f) => {
1350
+ if (f.groupId === groupId) {
1351
+ const constrained = ConstraintRegistry.apply(x, y, f, {
1352
+ dielineWidth,
1353
+ dielineHeight
1354
+ });
1355
+ if (f.x !== constrained.x || f.y !== constrained.y) {
1356
+ changed = true;
1357
+ return { ...f, x: constrained.x, y: constrained.y };
1358
+ }
1359
+ }
1360
+ return f;
1361
+ });
1362
+ if (changed) {
1363
+ configService.update("dieline.features", newFeatures);
1364
+ }
1365
+ }
1366
+ },
1203
1367
  {
1204
1368
  command: "getGeometry",
1205
1369
  title: "Get Geometry",
@@ -1344,16 +1508,10 @@ var DielineTool = class {
1344
1508
  radius: (f.radius || 0) * featureScale
1345
1509
  };
1346
1510
  });
1347
- const originalFeatures = absoluteFeatures.filter(
1348
- (f) => !f.target || f.target === "original" || f.target === "both"
1349
- );
1350
- const offsetFeatures = absoluteFeatures.filter(
1351
- (f) => f.target === "offset" || f.target === "both"
1352
- );
1511
+ const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
1353
1512
  const cutW = Math.max(0, visualWidth + visualOffset * 2);
1354
1513
  const cutH = Math.max(0, visualHeight + visualOffset * 2);
1355
1514
  const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
1356
- const maskFeatures = visualOffset !== 0 ? offsetFeatures : originalFeatures;
1357
1515
  const maskPathData = generateMaskPath({
1358
1516
  canvasWidth: canvasW,
1359
1517
  canvasHeight: canvasH,
@@ -1363,7 +1521,7 @@ var DielineTool = class {
1363
1521
  radius: cutR,
1364
1522
  x: cx,
1365
1523
  y: cy,
1366
- features: maskFeatures,
1524
+ features: cutFeatures,
1367
1525
  pathData: this.state.pathData
1368
1526
  });
1369
1527
  const mask = new import_fabric2.Path(maskPathData, {
@@ -1385,7 +1543,7 @@ var DielineTool = class {
1385
1543
  radius: cutR,
1386
1544
  x: cx,
1387
1545
  y: cy,
1388
- features: maskFeatures,
1546
+ features: cutFeatures,
1389
1547
  // Use same features as mask for consistency
1390
1548
  pathData: this.state.pathData,
1391
1549
  canvasWidth: canvasW,
@@ -1411,7 +1569,7 @@ var DielineTool = class {
1411
1569
  radius: visualRadius,
1412
1570
  x: cx,
1413
1571
  y: cy,
1414
- features: originalFeatures,
1572
+ features: cutFeatures,
1415
1573
  pathData: this.state.pathData,
1416
1574
  canvasWidth: canvasW,
1417
1575
  canvasHeight: canvasH
@@ -1423,7 +1581,7 @@ var DielineTool = class {
1423
1581
  radius: cutR,
1424
1582
  x: cx,
1425
1583
  y: cy,
1426
- features: offsetFeatures,
1584
+ features: cutFeatures,
1427
1585
  pathData: this.state.pathData,
1428
1586
  canvasWidth: canvasW,
1429
1587
  canvasHeight: canvasH
@@ -1452,7 +1610,7 @@ var DielineTool = class {
1452
1610
  radius: cutR,
1453
1611
  x: cx,
1454
1612
  y: cy,
1455
- features: offsetFeatures,
1613
+ features: cutFeatures,
1456
1614
  pathData: this.state.pathData,
1457
1615
  canvasWidth: canvasW,
1458
1616
  canvasHeight: canvasH
@@ -1476,7 +1634,7 @@ var DielineTool = class {
1476
1634
  radius: visualRadius,
1477
1635
  x: cx,
1478
1636
  y: cy,
1479
- features: originalFeatures,
1637
+ features: absoluteFeatures,
1480
1638
  pathData: this.state.pathData,
1481
1639
  canvasWidth: canvasW,
1482
1640
  canvasHeight: canvasH
@@ -1576,9 +1734,7 @@ var DielineTool = class {
1576
1734
  radius: (f.radius || 0) * featureScale
1577
1735
  };
1578
1736
  });
1579
- const originalFeatures = absoluteFeatures.filter(
1580
- (f) => !f.target || f.target === "original" || f.target === "both"
1581
- );
1737
+ const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
1582
1738
  const generatedPathData = generateDielinePath({
1583
1739
  shape,
1584
1740
  width: visualWidth,
@@ -1586,7 +1742,7 @@ var DielineTool = class {
1586
1742
  radius: visualRadius,
1587
1743
  x: cx,
1588
1744
  y: cy,
1589
- features: originalFeatures,
1745
+ features: cutFeatures,
1590
1746
  pathData,
1591
1747
  canvasWidth: canvasW,
1592
1748
  canvasHeight: canvasH
@@ -1783,10 +1939,15 @@ var FeatureTool = class {
1783
1939
  };
1784
1940
  this.features = [];
1785
1941
  this.isUpdatingConfig = false;
1942
+ this.isToolActive = false;
1786
1943
  this.handleMoving = null;
1787
1944
  this.handleModified = null;
1788
1945
  this.handleDielineChange = null;
1789
1946
  this.currentGeometry = null;
1947
+ this.onToolActivated = (event) => {
1948
+ this.isToolActive = event.id === this.id;
1949
+ this.updateVisibility();
1950
+ };
1790
1951
  if (options) {
1791
1952
  Object.assign(this, options);
1792
1953
  }
@@ -1811,13 +1972,32 @@ var FeatureTool = class {
1811
1972
  }
1812
1973
  });
1813
1974
  }
1975
+ context.eventBus.on("tool:activated", this.onToolActivated);
1814
1976
  this.setup();
1815
1977
  }
1816
1978
  deactivate(context) {
1979
+ context.eventBus.off("tool:activated", this.onToolActivated);
1817
1980
  this.teardown();
1818
1981
  this.canvasService = void 0;
1819
1982
  this.context = void 0;
1820
1983
  }
1984
+ updateVisibility() {
1985
+ if (!this.canvasService) return;
1986
+ const canvas = this.canvasService.canvas;
1987
+ const markers = canvas.getObjects().filter((obj) => {
1988
+ var _a;
1989
+ return ((_a = obj.data) == null ? void 0 : _a.type) === "feature-marker";
1990
+ });
1991
+ markers.forEach((marker) => {
1992
+ marker.set({
1993
+ visible: this.isToolActive,
1994
+ // Or just selectable: false if we want them visible but locked
1995
+ selectable: this.isToolActive,
1996
+ evented: this.isToolActive
1997
+ });
1998
+ });
1999
+ canvas.requestRenderAll();
2000
+ }
1821
2001
  contribute() {
1822
2002
  return {
1823
2003
  [import_core4.ContributionPointIds.COMMANDS]: [
@@ -1870,7 +2050,7 @@ var FeatureTool = class {
1870
2050
  const newFeature = {
1871
2051
  id: Date.now().toString(),
1872
2052
  operation: type,
1873
- target: "original",
2053
+ placement: "edge",
1874
2054
  shape: "rect",
1875
2055
  x: 0.5,
1876
2056
  y: 0,
@@ -1904,6 +2084,7 @@ var FeatureTool = class {
1904
2084
  groupId,
1905
2085
  operation: "add",
1906
2086
  shape: "circle",
2087
+ placement: "edge",
1907
2088
  x: 0.5,
1908
2089
  y: 0,
1909
2090
  radius: lugRadius,
@@ -1915,6 +2096,7 @@ var FeatureTool = class {
1915
2096
  groupId,
1916
2097
  operation: "subtract",
1917
2098
  shape: "circle",
2099
+ placement: "edge",
1918
2100
  x: 0.5,
1919
2101
  y: 0,
1920
2102
  radius: holeRadius,
@@ -1931,14 +2113,6 @@ var FeatureTool = class {
1931
2113
  return true;
1932
2114
  }
1933
2115
  getGeometryForFeature(geometry, feature) {
1934
- if ((feature == null ? void 0 : feature.target) === "offset" && geometry.offset !== 0) {
1935
- return {
1936
- ...geometry,
1937
- width: geometry.width + geometry.offset * 2,
1938
- height: geometry.height + geometry.offset * 2,
1939
- radius: geometry.radius === 0 ? 0 : Math.max(0, geometry.radius + geometry.offset)
1940
- };
1941
- }
1942
2116
  return geometry;
1943
2117
  }
1944
2118
  setup() {
@@ -1995,7 +2169,7 @@ var FeatureTool = class {
1995
2169
  const markerStrokeWidth = (target.strokeWidth || 2) * (target.scaleX || 1);
1996
2170
  const minDim = Math.min(target.getScaledWidth(), target.getScaledHeight());
1997
2171
  const limit = Math.max(0, minDim / 2 - markerStrokeWidth);
1998
- const snapped = this.constrainPosition(p, geometry, limit);
2172
+ const snapped = this.constrainPosition(p, geometry, limit, feature);
1999
2173
  target.set({
2000
2174
  left: snapped.x,
2001
2175
  top: snapped.y
@@ -2079,7 +2253,34 @@ var FeatureTool = class {
2079
2253
  objects.forEach((obj) => canvas.remove(obj));
2080
2254
  this.canvasService.requestRenderAll();
2081
2255
  }
2082
- constrainPosition(p, geometry, limit) {
2256
+ constrainPosition(p, geometry, limit, feature) {
2257
+ if (feature && feature.constraints) {
2258
+ const minX = geometry.x - geometry.width / 2;
2259
+ const minY = geometry.y - geometry.height / 2;
2260
+ const nx = geometry.width > 0 ? (p.x - minX) / geometry.width : 0.5;
2261
+ const ny = geometry.height > 0 ? (p.y - minY) / geometry.height : 0.5;
2262
+ const scale2 = geometry.scale || 1;
2263
+ const dielineWidth = geometry.width / scale2;
2264
+ const dielineHeight = geometry.height / scale2;
2265
+ const constrained = ConstraintRegistry.apply(nx, ny, feature, {
2266
+ dielineWidth,
2267
+ dielineHeight
2268
+ });
2269
+ return {
2270
+ x: minX + constrained.x * geometry.width,
2271
+ y: minY + constrained.y * geometry.height
2272
+ };
2273
+ }
2274
+ if (feature && feature.placement === "internal") {
2275
+ const minX = geometry.x - geometry.width / 2;
2276
+ const maxX = geometry.x + geometry.width / 2;
2277
+ const minY = geometry.y - geometry.height / 2;
2278
+ const maxY = geometry.y + geometry.height / 2;
2279
+ return {
2280
+ x: Math.max(minX, Math.min(maxX, p.x)),
2281
+ y: Math.max(minY, Math.min(maxY, p.y))
2282
+ };
2283
+ }
2083
2284
  const nearest = getNearestPointOnDieline({ x: p.x, y: p.y }, {
2084
2285
  ...geometry,
2085
2286
  features: []
@@ -2204,7 +2405,9 @@ var FeatureTool = class {
2204
2405
  const pos = resolveFeaturePosition(feature, geometry2);
2205
2406
  const marker = createMarkerShape(feature, pos);
2206
2407
  marker.set({
2207
- selectable: true,
2408
+ visible: this.isToolActive,
2409
+ selectable: this.isToolActive,
2410
+ evented: this.isToolActive,
2208
2411
  hasControls: false,
2209
2412
  hasBorders: false,
2210
2413
  hoverCursor: "move",
@@ -2247,7 +2450,9 @@ var FeatureTool = class {
2247
2450
  return createMarkerShape(feature, pos);
2248
2451
  });
2249
2452
  const groupObj = new import_fabric4.Group(shapes, {
2250
- selectable: true,
2453
+ visible: this.isToolActive,
2454
+ selectable: this.isToolActive,
2455
+ evented: this.isToolActive,
2251
2456
  hasControls: false,
2252
2457
  hasBorders: false,
2253
2458
  hoverCursor: "move",
@@ -2321,7 +2526,8 @@ var FeatureTool = class {
2321
2526
  const snapped = this.constrainPosition(
2322
2527
  new import_fabric4.Point(marker.left, marker.top),
2323
2528
  geometry,
2324
- limit
2529
+ limit,
2530
+ feature
2325
2531
  );
2326
2532
  marker.set({ left: snapped.x, top: snapped.y });
2327
2533
  marker.setCoords();
@@ -2343,6 +2549,11 @@ var ImageTool = class {
2343
2549
  this.objectMap = /* @__PURE__ */ new Map();
2344
2550
  this.loadResolvers = /* @__PURE__ */ new Map();
2345
2551
  this.isUpdatingConfig = false;
2552
+ this.isToolActive = false;
2553
+ this.onToolActivated = (event) => {
2554
+ this.isToolActive = event.id === this.id;
2555
+ this.updateInteractivity();
2556
+ };
2346
2557
  }
2347
2558
  activate(context) {
2348
2559
  this.context = context;
@@ -2351,6 +2562,7 @@ var ImageTool = class {
2351
2562
  console.warn("CanvasService not found for ImageTool");
2352
2563
  return;
2353
2564
  }
2565
+ context.eventBus.on("tool:activated", this.onToolActivated);
2354
2566
  const configService = context.services.get(
2355
2567
  "ConfigurationService"
2356
2568
  );
@@ -2368,6 +2580,7 @@ var ImageTool = class {
2368
2580
  this.updateImages();
2369
2581
  }
2370
2582
  deactivate(context) {
2583
+ context.eventBus.off("tool:activated", this.onToolActivated);
2371
2584
  if (this.canvasService) {
2372
2585
  const layer = this.canvasService.getLayer("user");
2373
2586
  if (layer) {
@@ -2381,6 +2594,18 @@ var ImageTool = class {
2381
2594
  this.context = void 0;
2382
2595
  }
2383
2596
  }
2597
+ updateInteractivity() {
2598
+ var _a;
2599
+ this.objectMap.forEach((obj) => {
2600
+ obj.set({
2601
+ selectable: this.isToolActive,
2602
+ evented: this.isToolActive,
2603
+ hasControls: this.isToolActive,
2604
+ hasBorders: this.isToolActive
2605
+ });
2606
+ });
2607
+ (_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
2608
+ }
2384
2609
  contribute() {
2385
2610
  return {
2386
2611
  [import_core5.ContributionPointIds.CONFIGURATIONS]: [
@@ -2568,6 +2793,14 @@ var ImageTool = class {
2568
2793
  const layout = this.getLayoutInfo();
2569
2794
  this.items.forEach((item, index) => {
2570
2795
  let obj = this.objectMap.get(item.id);
2796
+ if (obj && obj.getSrc) {
2797
+ const currentSrc = obj.getSrc();
2798
+ if (currentSrc !== item.url) {
2799
+ layer.remove(obj);
2800
+ this.objectMap.delete(item.id);
2801
+ obj = void 0;
2802
+ }
2803
+ }
2571
2804
  if (!obj) {
2572
2805
  this.loadImage(item, layer, layout);
2573
2806
  } else {
@@ -2624,7 +2857,11 @@ var ImageTool = class {
2624
2857
  originY: "center",
2625
2858
  data: { id: item.id },
2626
2859
  uniformScaling: true,
2627
- lockScalingFlip: true
2860
+ lockScalingFlip: true,
2861
+ selectable: this.isToolActive,
2862
+ evented: this.isToolActive,
2863
+ hasControls: this.isToolActive,
2864
+ hasBorders: this.isToolActive
2628
2865
  });
2629
2866
  image.setControlsVisibility({
2630
2867
  mt: false,
@@ -3475,6 +3712,24 @@ var CanvasService = class {
3475
3712
  ...options
3476
3713
  });
3477
3714
  }
3715
+ if (options == null ? void 0 : options.eventBus) {
3716
+ this.setEventBus(options.eventBus);
3717
+ }
3718
+ }
3719
+ setEventBus(eventBus) {
3720
+ this.eventBus = eventBus;
3721
+ this.setupEvents();
3722
+ }
3723
+ setupEvents() {
3724
+ if (!this.eventBus) return;
3725
+ const bus = this.eventBus;
3726
+ const forward = (name) => (e) => bus.emit(name, e);
3727
+ this.canvas.on("selection:created", forward("selection:created"));
3728
+ this.canvas.on("selection:updated", forward("selection:updated"));
3729
+ this.canvas.on("selection:cleared", forward("selection:cleared"));
3730
+ this.canvas.on("object:modified", forward("object:modified"));
3731
+ this.canvas.on("object:added", forward("object:added"));
3732
+ this.canvas.on("object:removed", forward("object:removed"));
3478
3733
  }
3479
3734
  dispose() {
3480
3735
  this.canvas.dispose();