@pooder/kit 3.5.0 → 4.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @pooder/kit
2
2
 
3
+ ## 4.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - Virtual Features
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @pooder/core@2.0.0
13
+
3
14
  ## 3.5.0
4
15
 
5
16
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Extension, ExtensionContext, ContributionPointIds, ConfigurationContribution, CommandContribution, Service } from '@pooder/core';
1
+ import { Extension, ExtensionContext, ContributionPointIds, ConfigurationContribution, CommandContribution, Service, EventBus } from '@pooder/core';
2
2
  import { Canvas, Group, FabricObject } from 'fabric';
3
3
 
4
4
  declare class BackgroundTool implements Extension {
@@ -27,7 +27,7 @@ type Unit = "px" | "mm" | "cm" | "in";
27
27
 
28
28
  type FeatureOperation = "add" | "subtract";
29
29
  type FeatureShape = "rect" | "circle";
30
- interface EdgeFeature {
30
+ interface DielineFeature {
31
31
  id: string;
32
32
  groupId?: string;
33
33
  operation: FeatureOperation;
@@ -38,9 +38,10 @@ interface EdgeFeature {
38
38
  height?: number;
39
39
  radius?: number;
40
40
  rotation?: number;
41
- target?: "original" | "offset" | "both";
41
+ placement?: "edge" | "internal";
42
42
  color?: string;
43
43
  strokeDash?: number[];
44
+ skipCut?: boolean;
44
45
  }
45
46
 
46
47
  interface DielineGeometry {
@@ -76,7 +77,7 @@ interface DielineState {
76
77
  insideColor: string;
77
78
  outsideColor: string;
78
79
  showBleedLines: boolean;
79
- features: EdgeFeature[];
80
+ features: DielineFeature[];
80
81
  pathData?: string;
81
82
  }
82
83
  declare class DielineTool implements Extension {
@@ -135,15 +136,18 @@ declare class FeatureTool implements Extension {
135
136
  private canvasService?;
136
137
  private context?;
137
138
  private isUpdatingConfig;
139
+ private isToolActive;
138
140
  private handleMoving;
139
141
  private handleModified;
140
142
  private handleDielineChange;
141
143
  private currentGeometry;
142
144
  constructor(options?: Partial<{
143
- features: EdgeFeature[];
145
+ features: DielineFeature[];
144
146
  }>);
145
147
  activate(context: ExtensionContext): void;
146
148
  deactivate(context: ExtensionContext): void;
149
+ private onToolActivated;
150
+ private updateVisibility;
147
151
  contribute(): {
148
152
  [ContributionPointIds.COMMANDS]: CommandContribution[];
149
153
  };
@@ -178,8 +182,11 @@ declare class ImageTool implements Extension {
178
182
  private canvasService?;
179
183
  private context?;
180
184
  private isUpdatingConfig;
185
+ private isToolActive;
181
186
  activate(context: ExtensionContext): void;
182
187
  deactivate(context: ExtensionContext): void;
188
+ private onToolActivated;
189
+ private updateInteractivity;
183
190
  contribute(): {
184
191
  [ContributionPointIds.CONFIGURATIONS]: ConfigurationContribution[];
185
192
  [ContributionPointIds.COMMANDS]: CommandContribution[];
@@ -288,7 +295,10 @@ declare class MirrorTool implements Extension {
288
295
 
289
296
  declare class CanvasService implements Service {
290
297
  canvas: Canvas;
298
+ private eventBus?;
291
299
  constructor(el: HTMLCanvasElement | string | Canvas, options?: any);
300
+ setEventBus(eventBus: EventBus): void;
301
+ private setupEvents;
292
302
  dispose(): void;
293
303
  /**
294
304
  * Get a layer (Group) by its ID.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Extension, ExtensionContext, ContributionPointIds, ConfigurationContribution, CommandContribution, Service } from '@pooder/core';
1
+ import { Extension, ExtensionContext, ContributionPointIds, ConfigurationContribution, CommandContribution, Service, EventBus } from '@pooder/core';
2
2
  import { Canvas, Group, FabricObject } from 'fabric';
3
3
 
4
4
  declare class BackgroundTool implements Extension {
@@ -27,7 +27,7 @@ type Unit = "px" | "mm" | "cm" | "in";
27
27
 
28
28
  type FeatureOperation = "add" | "subtract";
29
29
  type FeatureShape = "rect" | "circle";
30
- interface EdgeFeature {
30
+ interface DielineFeature {
31
31
  id: string;
32
32
  groupId?: string;
33
33
  operation: FeatureOperation;
@@ -38,9 +38,10 @@ interface EdgeFeature {
38
38
  height?: number;
39
39
  radius?: number;
40
40
  rotation?: number;
41
- target?: "original" | "offset" | "both";
41
+ placement?: "edge" | "internal";
42
42
  color?: string;
43
43
  strokeDash?: number[];
44
+ skipCut?: boolean;
44
45
  }
45
46
 
46
47
  interface DielineGeometry {
@@ -76,7 +77,7 @@ interface DielineState {
76
77
  insideColor: string;
77
78
  outsideColor: string;
78
79
  showBleedLines: boolean;
79
- features: EdgeFeature[];
80
+ features: DielineFeature[];
80
81
  pathData?: string;
81
82
  }
82
83
  declare class DielineTool implements Extension {
@@ -135,15 +136,18 @@ declare class FeatureTool implements Extension {
135
136
  private canvasService?;
136
137
  private context?;
137
138
  private isUpdatingConfig;
139
+ private isToolActive;
138
140
  private handleMoving;
139
141
  private handleModified;
140
142
  private handleDielineChange;
141
143
  private currentGeometry;
142
144
  constructor(options?: Partial<{
143
- features: EdgeFeature[];
145
+ features: DielineFeature[];
144
146
  }>);
145
147
  activate(context: ExtensionContext): void;
146
148
  deactivate(context: ExtensionContext): void;
149
+ private onToolActivated;
150
+ private updateVisibility;
147
151
  contribute(): {
148
152
  [ContributionPointIds.COMMANDS]: CommandContribution[];
149
153
  };
@@ -178,8 +182,11 @@ declare class ImageTool implements Extension {
178
182
  private canvasService?;
179
183
  private context?;
180
184
  private isUpdatingConfig;
185
+ private isToolActive;
181
186
  activate(context: ExtensionContext): void;
182
187
  deactivate(context: ExtensionContext): void;
188
+ private onToolActivated;
189
+ private updateInteractivity;
183
190
  contribute(): {
184
191
  [ContributionPointIds.CONFIGURATIONS]: ConfigurationContribution[];
185
192
  [ContributionPointIds.COMMANDS]: CommandContribution[];
@@ -288,7 +295,10 @@ declare class MirrorTool implements Extension {
288
295
 
289
296
  declare class CanvasService implements Service {
290
297
  canvas: Canvas;
298
+ private eventBus?;
291
299
  constructor(el: HTMLCanvasElement | string | Canvas, options?: any);
300
+ setEventBus(eventBus: EventBus): void;
301
+ private setupEvents;
292
302
  dispose(): void;
293
303
  /**
294
304
  * Get a layer (Group) by its ID.
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);
@@ -1344,16 +1378,10 @@ var DielineTool = class {
1344
1378
  radius: (f.radius || 0) * featureScale
1345
1379
  };
1346
1380
  });
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
- );
1381
+ const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
1353
1382
  const cutW = Math.max(0, visualWidth + visualOffset * 2);
1354
1383
  const cutH = Math.max(0, visualHeight + visualOffset * 2);
1355
1384
  const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
1356
- const maskFeatures = visualOffset !== 0 ? offsetFeatures : originalFeatures;
1357
1385
  const maskPathData = generateMaskPath({
1358
1386
  canvasWidth: canvasW,
1359
1387
  canvasHeight: canvasH,
@@ -1363,7 +1391,7 @@ var DielineTool = class {
1363
1391
  radius: cutR,
1364
1392
  x: cx,
1365
1393
  y: cy,
1366
- features: maskFeatures,
1394
+ features: cutFeatures,
1367
1395
  pathData: this.state.pathData
1368
1396
  });
1369
1397
  const mask = new import_fabric2.Path(maskPathData, {
@@ -1385,7 +1413,7 @@ var DielineTool = class {
1385
1413
  radius: cutR,
1386
1414
  x: cx,
1387
1415
  y: cy,
1388
- features: maskFeatures,
1416
+ features: cutFeatures,
1389
1417
  // Use same features as mask for consistency
1390
1418
  pathData: this.state.pathData,
1391
1419
  canvasWidth: canvasW,
@@ -1411,7 +1439,7 @@ var DielineTool = class {
1411
1439
  radius: visualRadius,
1412
1440
  x: cx,
1413
1441
  y: cy,
1414
- features: originalFeatures,
1442
+ features: cutFeatures,
1415
1443
  pathData: this.state.pathData,
1416
1444
  canvasWidth: canvasW,
1417
1445
  canvasHeight: canvasH
@@ -1423,7 +1451,7 @@ var DielineTool = class {
1423
1451
  radius: cutR,
1424
1452
  x: cx,
1425
1453
  y: cy,
1426
- features: offsetFeatures,
1454
+ features: cutFeatures,
1427
1455
  pathData: this.state.pathData,
1428
1456
  canvasWidth: canvasW,
1429
1457
  canvasHeight: canvasH
@@ -1452,7 +1480,7 @@ var DielineTool = class {
1452
1480
  radius: cutR,
1453
1481
  x: cx,
1454
1482
  y: cy,
1455
- features: offsetFeatures,
1483
+ features: cutFeatures,
1456
1484
  pathData: this.state.pathData,
1457
1485
  canvasWidth: canvasW,
1458
1486
  canvasHeight: canvasH
@@ -1476,7 +1504,7 @@ var DielineTool = class {
1476
1504
  radius: visualRadius,
1477
1505
  x: cx,
1478
1506
  y: cy,
1479
- features: originalFeatures,
1507
+ features: absoluteFeatures,
1480
1508
  pathData: this.state.pathData,
1481
1509
  canvasWidth: canvasW,
1482
1510
  canvasHeight: canvasH
@@ -1576,9 +1604,7 @@ var DielineTool = class {
1576
1604
  radius: (f.radius || 0) * featureScale
1577
1605
  };
1578
1606
  });
1579
- const originalFeatures = absoluteFeatures.filter(
1580
- (f) => !f.target || f.target === "original" || f.target === "both"
1581
- );
1607
+ const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
1582
1608
  const generatedPathData = generateDielinePath({
1583
1609
  shape,
1584
1610
  width: visualWidth,
@@ -1586,7 +1612,7 @@ var DielineTool = class {
1586
1612
  radius: visualRadius,
1587
1613
  x: cx,
1588
1614
  y: cy,
1589
- features: originalFeatures,
1615
+ features: cutFeatures,
1590
1616
  pathData,
1591
1617
  canvasWidth: canvasW,
1592
1618
  canvasHeight: canvasH
@@ -1783,10 +1809,15 @@ var FeatureTool = class {
1783
1809
  };
1784
1810
  this.features = [];
1785
1811
  this.isUpdatingConfig = false;
1812
+ this.isToolActive = false;
1786
1813
  this.handleMoving = null;
1787
1814
  this.handleModified = null;
1788
1815
  this.handleDielineChange = null;
1789
1816
  this.currentGeometry = null;
1817
+ this.onToolActivated = (event) => {
1818
+ this.isToolActive = event.id === this.id;
1819
+ this.updateVisibility();
1820
+ };
1790
1821
  if (options) {
1791
1822
  Object.assign(this, options);
1792
1823
  }
@@ -1811,13 +1842,32 @@ var FeatureTool = class {
1811
1842
  }
1812
1843
  });
1813
1844
  }
1845
+ context.eventBus.on("tool:activated", this.onToolActivated);
1814
1846
  this.setup();
1815
1847
  }
1816
1848
  deactivate(context) {
1849
+ context.eventBus.off("tool:activated", this.onToolActivated);
1817
1850
  this.teardown();
1818
1851
  this.canvasService = void 0;
1819
1852
  this.context = void 0;
1820
1853
  }
1854
+ updateVisibility() {
1855
+ if (!this.canvasService) return;
1856
+ const canvas = this.canvasService.canvas;
1857
+ const markers = canvas.getObjects().filter((obj) => {
1858
+ var _a;
1859
+ return ((_a = obj.data) == null ? void 0 : _a.type) === "feature-marker";
1860
+ });
1861
+ markers.forEach((marker) => {
1862
+ marker.set({
1863
+ visible: this.isToolActive,
1864
+ // Or just selectable: false if we want them visible but locked
1865
+ selectable: this.isToolActive,
1866
+ evented: this.isToolActive
1867
+ });
1868
+ });
1869
+ canvas.requestRenderAll();
1870
+ }
1821
1871
  contribute() {
1822
1872
  return {
1823
1873
  [import_core4.ContributionPointIds.COMMANDS]: [
@@ -1870,7 +1920,7 @@ var FeatureTool = class {
1870
1920
  const newFeature = {
1871
1921
  id: Date.now().toString(),
1872
1922
  operation: type,
1873
- target: "original",
1923
+ placement: "edge",
1874
1924
  shape: "rect",
1875
1925
  x: 0.5,
1876
1926
  y: 0,
@@ -1904,6 +1954,7 @@ var FeatureTool = class {
1904
1954
  groupId,
1905
1955
  operation: "add",
1906
1956
  shape: "circle",
1957
+ placement: "edge",
1907
1958
  x: 0.5,
1908
1959
  y: 0,
1909
1960
  radius: lugRadius,
@@ -1915,6 +1966,7 @@ var FeatureTool = class {
1915
1966
  groupId,
1916
1967
  operation: "subtract",
1917
1968
  shape: "circle",
1969
+ placement: "edge",
1918
1970
  x: 0.5,
1919
1971
  y: 0,
1920
1972
  radius: holeRadius,
@@ -1931,14 +1983,6 @@ var FeatureTool = class {
1931
1983
  return true;
1932
1984
  }
1933
1985
  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
1986
  return geometry;
1943
1987
  }
1944
1988
  setup() {
@@ -1995,7 +2039,7 @@ var FeatureTool = class {
1995
2039
  const markerStrokeWidth = (target.strokeWidth || 2) * (target.scaleX || 1);
1996
2040
  const minDim = Math.min(target.getScaledWidth(), target.getScaledHeight());
1997
2041
  const limit = Math.max(0, minDim / 2 - markerStrokeWidth);
1998
- const snapped = this.constrainPosition(p, geometry, limit);
2042
+ const snapped = this.constrainPosition(p, geometry, limit, feature);
1999
2043
  target.set({
2000
2044
  left: snapped.x,
2001
2045
  top: snapped.y
@@ -2079,7 +2123,17 @@ var FeatureTool = class {
2079
2123
  objects.forEach((obj) => canvas.remove(obj));
2080
2124
  this.canvasService.requestRenderAll();
2081
2125
  }
2082
- constrainPosition(p, geometry, limit) {
2126
+ constrainPosition(p, geometry, limit, feature) {
2127
+ if (feature && feature.placement === "internal") {
2128
+ const minX = geometry.x - geometry.width / 2;
2129
+ const maxX = geometry.x + geometry.width / 2;
2130
+ const minY = geometry.y - geometry.height / 2;
2131
+ const maxY = geometry.y + geometry.height / 2;
2132
+ return {
2133
+ x: Math.max(minX, Math.min(maxX, p.x)),
2134
+ y: Math.max(minY, Math.min(maxY, p.y))
2135
+ };
2136
+ }
2083
2137
  const nearest = getNearestPointOnDieline({ x: p.x, y: p.y }, {
2084
2138
  ...geometry,
2085
2139
  features: []
@@ -2204,7 +2258,9 @@ var FeatureTool = class {
2204
2258
  const pos = resolveFeaturePosition(feature, geometry2);
2205
2259
  const marker = createMarkerShape(feature, pos);
2206
2260
  marker.set({
2207
- selectable: true,
2261
+ visible: this.isToolActive,
2262
+ selectable: this.isToolActive,
2263
+ evented: this.isToolActive,
2208
2264
  hasControls: false,
2209
2265
  hasBorders: false,
2210
2266
  hoverCursor: "move",
@@ -2247,7 +2303,9 @@ var FeatureTool = class {
2247
2303
  return createMarkerShape(feature, pos);
2248
2304
  });
2249
2305
  const groupObj = new import_fabric4.Group(shapes, {
2250
- selectable: true,
2306
+ visible: this.isToolActive,
2307
+ selectable: this.isToolActive,
2308
+ evented: this.isToolActive,
2251
2309
  hasControls: false,
2252
2310
  hasBorders: false,
2253
2311
  hoverCursor: "move",
@@ -2321,7 +2379,8 @@ var FeatureTool = class {
2321
2379
  const snapped = this.constrainPosition(
2322
2380
  new import_fabric4.Point(marker.left, marker.top),
2323
2381
  geometry,
2324
- limit
2382
+ limit,
2383
+ feature
2325
2384
  );
2326
2385
  marker.set({ left: snapped.x, top: snapped.y });
2327
2386
  marker.setCoords();
@@ -2343,6 +2402,11 @@ var ImageTool = class {
2343
2402
  this.objectMap = /* @__PURE__ */ new Map();
2344
2403
  this.loadResolvers = /* @__PURE__ */ new Map();
2345
2404
  this.isUpdatingConfig = false;
2405
+ this.isToolActive = false;
2406
+ this.onToolActivated = (event) => {
2407
+ this.isToolActive = event.id === this.id;
2408
+ this.updateInteractivity();
2409
+ };
2346
2410
  }
2347
2411
  activate(context) {
2348
2412
  this.context = context;
@@ -2351,6 +2415,7 @@ var ImageTool = class {
2351
2415
  console.warn("CanvasService not found for ImageTool");
2352
2416
  return;
2353
2417
  }
2418
+ context.eventBus.on("tool:activated", this.onToolActivated);
2354
2419
  const configService = context.services.get(
2355
2420
  "ConfigurationService"
2356
2421
  );
@@ -2368,6 +2433,7 @@ var ImageTool = class {
2368
2433
  this.updateImages();
2369
2434
  }
2370
2435
  deactivate(context) {
2436
+ context.eventBus.off("tool:activated", this.onToolActivated);
2371
2437
  if (this.canvasService) {
2372
2438
  const layer = this.canvasService.getLayer("user");
2373
2439
  if (layer) {
@@ -2381,6 +2447,18 @@ var ImageTool = class {
2381
2447
  this.context = void 0;
2382
2448
  }
2383
2449
  }
2450
+ updateInteractivity() {
2451
+ var _a;
2452
+ this.objectMap.forEach((obj) => {
2453
+ obj.set({
2454
+ selectable: this.isToolActive,
2455
+ evented: this.isToolActive,
2456
+ hasControls: this.isToolActive,
2457
+ hasBorders: this.isToolActive
2458
+ });
2459
+ });
2460
+ (_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
2461
+ }
2384
2462
  contribute() {
2385
2463
  return {
2386
2464
  [import_core5.ContributionPointIds.CONFIGURATIONS]: [
@@ -2568,6 +2646,14 @@ var ImageTool = class {
2568
2646
  const layout = this.getLayoutInfo();
2569
2647
  this.items.forEach((item, index) => {
2570
2648
  let obj = this.objectMap.get(item.id);
2649
+ if (obj && obj.getSrc) {
2650
+ const currentSrc = obj.getSrc();
2651
+ if (currentSrc !== item.url) {
2652
+ layer.remove(obj);
2653
+ this.objectMap.delete(item.id);
2654
+ obj = void 0;
2655
+ }
2656
+ }
2571
2657
  if (!obj) {
2572
2658
  this.loadImage(item, layer, layout);
2573
2659
  } else {
@@ -2624,7 +2710,11 @@ var ImageTool = class {
2624
2710
  originY: "center",
2625
2711
  data: { id: item.id },
2626
2712
  uniformScaling: true,
2627
- lockScalingFlip: true
2713
+ lockScalingFlip: true,
2714
+ selectable: this.isToolActive,
2715
+ evented: this.isToolActive,
2716
+ hasControls: this.isToolActive,
2717
+ hasBorders: this.isToolActive
2628
2718
  });
2629
2719
  image.setControlsVisibility({
2630
2720
  mt: false,
@@ -3475,6 +3565,24 @@ var CanvasService = class {
3475
3565
  ...options
3476
3566
  });
3477
3567
  }
3568
+ if (options == null ? void 0 : options.eventBus) {
3569
+ this.setEventBus(options.eventBus);
3570
+ }
3571
+ }
3572
+ setEventBus(eventBus) {
3573
+ this.eventBus = eventBus;
3574
+ this.setupEvents();
3575
+ }
3576
+ setupEvents() {
3577
+ if (!this.eventBus) return;
3578
+ const bus = this.eventBus;
3579
+ const forward = (name) => (e) => bus.emit(name, e);
3580
+ this.canvas.on("selection:created", forward("selection:created"));
3581
+ this.canvas.on("selection:updated", forward("selection:updated"));
3582
+ this.canvas.on("selection:cleared", forward("selection:cleared"));
3583
+ this.canvas.on("object:modified", forward("object:modified"));
3584
+ this.canvas.on("object:added", forward("object:added"));
3585
+ this.canvas.on("object:removed", forward("object:removed"));
3478
3586
  }
3479
3587
  dispose() {
3480
3588
  this.canvas.dispose();