@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 +11 -0
- package/dist/index.d.mts +15 -5
- package/dist/index.d.ts +15 -5
- package/dist/index.js +148 -40
- package/dist/index.mjs +148 -40
- package/package.json +2 -2
- package/src/CanvasService.ts +89 -65
- package/src/dieline.ts +12 -22
- package/src/feature.ts +74 -31
- package/src/geometry.ts +76 -27
- package/src/image.ts +41 -0
package/dist/index.mjs
CHANGED
|
@@ -753,13 +753,16 @@ function createFeatureItem(feature, center) {
|
|
|
753
753
|
}
|
|
754
754
|
return item;
|
|
755
755
|
}
|
|
756
|
-
function
|
|
756
|
+
function getPerimeterShape(options) {
|
|
757
757
|
let mainShape = createBaseShape(options);
|
|
758
758
|
const { features } = options;
|
|
759
759
|
if (features && features.length > 0) {
|
|
760
|
+
const edgeFeatures = features.filter(
|
|
761
|
+
(f) => !f.placement || f.placement === "edge"
|
|
762
|
+
);
|
|
760
763
|
const adds = [];
|
|
761
764
|
const subtracts = [];
|
|
762
|
-
|
|
765
|
+
edgeFeatures.forEach((f) => {
|
|
763
766
|
const pos = resolveFeaturePosition(f, options);
|
|
764
767
|
const center = new paper2.Point(pos.x, pos.y);
|
|
765
768
|
const item = createFeatureItem(f, center);
|
|
@@ -798,14 +801,42 @@ function getDielineShape(options) {
|
|
|
798
801
|
}
|
|
799
802
|
return mainShape;
|
|
800
803
|
}
|
|
804
|
+
function applySurfaceFeatures(shape, features, options) {
|
|
805
|
+
const internalFeatures = features.filter((f) => f.placement === "internal");
|
|
806
|
+
if (internalFeatures.length === 0) return shape;
|
|
807
|
+
let result = shape;
|
|
808
|
+
for (const f of internalFeatures) {
|
|
809
|
+
const pos = resolveFeaturePosition(f, options);
|
|
810
|
+
const center = new paper2.Point(pos.x, pos.y);
|
|
811
|
+
const item = createFeatureItem(f, center);
|
|
812
|
+
try {
|
|
813
|
+
if (f.operation === "add") {
|
|
814
|
+
const temp = result.unite(item);
|
|
815
|
+
result.remove();
|
|
816
|
+
item.remove();
|
|
817
|
+
result = temp;
|
|
818
|
+
} else {
|
|
819
|
+
const temp = result.subtract(item);
|
|
820
|
+
result.remove();
|
|
821
|
+
item.remove();
|
|
822
|
+
result = temp;
|
|
823
|
+
}
|
|
824
|
+
} catch (e) {
|
|
825
|
+
console.error("Geometry: Failed to apply surface feature", e);
|
|
826
|
+
item.remove();
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return result;
|
|
830
|
+
}
|
|
801
831
|
function generateDielinePath(options) {
|
|
802
832
|
const paperWidth = options.canvasWidth || options.width * 2 || 2e3;
|
|
803
833
|
const paperHeight = options.canvasHeight || options.height * 2 || 2e3;
|
|
804
834
|
ensurePaper(paperWidth, paperHeight);
|
|
805
835
|
paper2.project.activeLayer.removeChildren();
|
|
806
|
-
const
|
|
807
|
-
const
|
|
808
|
-
|
|
836
|
+
const perimeter = getPerimeterShape(options);
|
|
837
|
+
const finalShape = applySurfaceFeatures(perimeter, options.features, options);
|
|
838
|
+
const pathData = finalShape.pathData;
|
|
839
|
+
finalShape.remove();
|
|
809
840
|
return pathData;
|
|
810
841
|
}
|
|
811
842
|
function generateMaskPath(options) {
|
|
@@ -816,7 +847,8 @@ function generateMaskPath(options) {
|
|
|
816
847
|
point: [0, 0],
|
|
817
848
|
size: [canvasWidth, canvasHeight]
|
|
818
849
|
});
|
|
819
|
-
const
|
|
850
|
+
const perimeter = getPerimeterShape(options);
|
|
851
|
+
const mainShape = applySurfaceFeatures(perimeter, options.features, options);
|
|
820
852
|
const finalMask = maskRect.subtract(mainShape);
|
|
821
853
|
maskRect.remove();
|
|
822
854
|
mainShape.remove();
|
|
@@ -829,8 +861,10 @@ function generateBleedZonePath(originalOptions, offsetOptions, offset) {
|
|
|
829
861
|
const paperHeight = originalOptions.canvasHeight || originalOptions.height * 2 || 2e3;
|
|
830
862
|
ensurePaper(paperWidth, paperHeight);
|
|
831
863
|
paper2.project.activeLayer.removeChildren();
|
|
832
|
-
const
|
|
833
|
-
const
|
|
864
|
+
const pOriginal = getPerimeterShape(originalOptions);
|
|
865
|
+
const shapeOriginal = applySurfaceFeatures(pOriginal, originalOptions.features, originalOptions);
|
|
866
|
+
const pOffset = getPerimeterShape(offsetOptions);
|
|
867
|
+
const shapeOffset = applySurfaceFeatures(pOffset, offsetOptions.features, offsetOptions);
|
|
834
868
|
let bleedZone;
|
|
835
869
|
if (offset > 0) {
|
|
836
870
|
bleedZone = shapeOffset.subtract(shapeOriginal);
|
|
@@ -1304,16 +1338,10 @@ var DielineTool = class {
|
|
|
1304
1338
|
radius: (f.radius || 0) * featureScale
|
|
1305
1339
|
};
|
|
1306
1340
|
});
|
|
1307
|
-
const
|
|
1308
|
-
(f) => !f.target || f.target === "original" || f.target === "both"
|
|
1309
|
-
);
|
|
1310
|
-
const offsetFeatures = absoluteFeatures.filter(
|
|
1311
|
-
(f) => f.target === "offset" || f.target === "both"
|
|
1312
|
-
);
|
|
1341
|
+
const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
|
|
1313
1342
|
const cutW = Math.max(0, visualWidth + visualOffset * 2);
|
|
1314
1343
|
const cutH = Math.max(0, visualHeight + visualOffset * 2);
|
|
1315
1344
|
const cutR = visualRadius === 0 ? 0 : Math.max(0, visualRadius + visualOffset);
|
|
1316
|
-
const maskFeatures = visualOffset !== 0 ? offsetFeatures : originalFeatures;
|
|
1317
1345
|
const maskPathData = generateMaskPath({
|
|
1318
1346
|
canvasWidth: canvasW,
|
|
1319
1347
|
canvasHeight: canvasH,
|
|
@@ -1323,7 +1351,7 @@ var DielineTool = class {
|
|
|
1323
1351
|
radius: cutR,
|
|
1324
1352
|
x: cx,
|
|
1325
1353
|
y: cy,
|
|
1326
|
-
features:
|
|
1354
|
+
features: cutFeatures,
|
|
1327
1355
|
pathData: this.state.pathData
|
|
1328
1356
|
});
|
|
1329
1357
|
const mask = new Path(maskPathData, {
|
|
@@ -1345,7 +1373,7 @@ var DielineTool = class {
|
|
|
1345
1373
|
radius: cutR,
|
|
1346
1374
|
x: cx,
|
|
1347
1375
|
y: cy,
|
|
1348
|
-
features:
|
|
1376
|
+
features: cutFeatures,
|
|
1349
1377
|
// Use same features as mask for consistency
|
|
1350
1378
|
pathData: this.state.pathData,
|
|
1351
1379
|
canvasWidth: canvasW,
|
|
@@ -1371,7 +1399,7 @@ var DielineTool = class {
|
|
|
1371
1399
|
radius: visualRadius,
|
|
1372
1400
|
x: cx,
|
|
1373
1401
|
y: cy,
|
|
1374
|
-
features:
|
|
1402
|
+
features: cutFeatures,
|
|
1375
1403
|
pathData: this.state.pathData,
|
|
1376
1404
|
canvasWidth: canvasW,
|
|
1377
1405
|
canvasHeight: canvasH
|
|
@@ -1383,7 +1411,7 @@ var DielineTool = class {
|
|
|
1383
1411
|
radius: cutR,
|
|
1384
1412
|
x: cx,
|
|
1385
1413
|
y: cy,
|
|
1386
|
-
features:
|
|
1414
|
+
features: cutFeatures,
|
|
1387
1415
|
pathData: this.state.pathData,
|
|
1388
1416
|
canvasWidth: canvasW,
|
|
1389
1417
|
canvasHeight: canvasH
|
|
@@ -1412,7 +1440,7 @@ var DielineTool = class {
|
|
|
1412
1440
|
radius: cutR,
|
|
1413
1441
|
x: cx,
|
|
1414
1442
|
y: cy,
|
|
1415
|
-
features:
|
|
1443
|
+
features: cutFeatures,
|
|
1416
1444
|
pathData: this.state.pathData,
|
|
1417
1445
|
canvasWidth: canvasW,
|
|
1418
1446
|
canvasHeight: canvasH
|
|
@@ -1436,7 +1464,7 @@ var DielineTool = class {
|
|
|
1436
1464
|
radius: visualRadius,
|
|
1437
1465
|
x: cx,
|
|
1438
1466
|
y: cy,
|
|
1439
|
-
features:
|
|
1467
|
+
features: absoluteFeatures,
|
|
1440
1468
|
pathData: this.state.pathData,
|
|
1441
1469
|
canvasWidth: canvasW,
|
|
1442
1470
|
canvasHeight: canvasH
|
|
@@ -1536,9 +1564,7 @@ var DielineTool = class {
|
|
|
1536
1564
|
radius: (f.radius || 0) * featureScale
|
|
1537
1565
|
};
|
|
1538
1566
|
});
|
|
1539
|
-
const
|
|
1540
|
-
(f) => !f.target || f.target === "original" || f.target === "both"
|
|
1541
|
-
);
|
|
1567
|
+
const cutFeatures = absoluteFeatures.filter((f) => !f.skipCut);
|
|
1542
1568
|
const generatedPathData = generateDielinePath({
|
|
1543
1569
|
shape,
|
|
1544
1570
|
width: visualWidth,
|
|
@@ -1546,7 +1572,7 @@ var DielineTool = class {
|
|
|
1546
1572
|
radius: visualRadius,
|
|
1547
1573
|
x: cx,
|
|
1548
1574
|
y: cy,
|
|
1549
|
-
features:
|
|
1575
|
+
features: cutFeatures,
|
|
1550
1576
|
pathData,
|
|
1551
1577
|
canvasWidth: canvasW,
|
|
1552
1578
|
canvasHeight: canvasH
|
|
@@ -1747,10 +1773,15 @@ var FeatureTool = class {
|
|
|
1747
1773
|
};
|
|
1748
1774
|
this.features = [];
|
|
1749
1775
|
this.isUpdatingConfig = false;
|
|
1776
|
+
this.isToolActive = false;
|
|
1750
1777
|
this.handleMoving = null;
|
|
1751
1778
|
this.handleModified = null;
|
|
1752
1779
|
this.handleDielineChange = null;
|
|
1753
1780
|
this.currentGeometry = null;
|
|
1781
|
+
this.onToolActivated = (event) => {
|
|
1782
|
+
this.isToolActive = event.id === this.id;
|
|
1783
|
+
this.updateVisibility();
|
|
1784
|
+
};
|
|
1754
1785
|
if (options) {
|
|
1755
1786
|
Object.assign(this, options);
|
|
1756
1787
|
}
|
|
@@ -1775,13 +1806,32 @@ var FeatureTool = class {
|
|
|
1775
1806
|
}
|
|
1776
1807
|
});
|
|
1777
1808
|
}
|
|
1809
|
+
context.eventBus.on("tool:activated", this.onToolActivated);
|
|
1778
1810
|
this.setup();
|
|
1779
1811
|
}
|
|
1780
1812
|
deactivate(context) {
|
|
1813
|
+
context.eventBus.off("tool:activated", this.onToolActivated);
|
|
1781
1814
|
this.teardown();
|
|
1782
1815
|
this.canvasService = void 0;
|
|
1783
1816
|
this.context = void 0;
|
|
1784
1817
|
}
|
|
1818
|
+
updateVisibility() {
|
|
1819
|
+
if (!this.canvasService) return;
|
|
1820
|
+
const canvas = this.canvasService.canvas;
|
|
1821
|
+
const markers = canvas.getObjects().filter((obj) => {
|
|
1822
|
+
var _a;
|
|
1823
|
+
return ((_a = obj.data) == null ? void 0 : _a.type) === "feature-marker";
|
|
1824
|
+
});
|
|
1825
|
+
markers.forEach((marker) => {
|
|
1826
|
+
marker.set({
|
|
1827
|
+
visible: this.isToolActive,
|
|
1828
|
+
// Or just selectable: false if we want them visible but locked
|
|
1829
|
+
selectable: this.isToolActive,
|
|
1830
|
+
evented: this.isToolActive
|
|
1831
|
+
});
|
|
1832
|
+
});
|
|
1833
|
+
canvas.requestRenderAll();
|
|
1834
|
+
}
|
|
1785
1835
|
contribute() {
|
|
1786
1836
|
return {
|
|
1787
1837
|
[ContributionPointIds4.COMMANDS]: [
|
|
@@ -1834,7 +1884,7 @@ var FeatureTool = class {
|
|
|
1834
1884
|
const newFeature = {
|
|
1835
1885
|
id: Date.now().toString(),
|
|
1836
1886
|
operation: type,
|
|
1837
|
-
|
|
1887
|
+
placement: "edge",
|
|
1838
1888
|
shape: "rect",
|
|
1839
1889
|
x: 0.5,
|
|
1840
1890
|
y: 0,
|
|
@@ -1868,6 +1918,7 @@ var FeatureTool = class {
|
|
|
1868
1918
|
groupId,
|
|
1869
1919
|
operation: "add",
|
|
1870
1920
|
shape: "circle",
|
|
1921
|
+
placement: "edge",
|
|
1871
1922
|
x: 0.5,
|
|
1872
1923
|
y: 0,
|
|
1873
1924
|
radius: lugRadius,
|
|
@@ -1879,6 +1930,7 @@ var FeatureTool = class {
|
|
|
1879
1930
|
groupId,
|
|
1880
1931
|
operation: "subtract",
|
|
1881
1932
|
shape: "circle",
|
|
1933
|
+
placement: "edge",
|
|
1882
1934
|
x: 0.5,
|
|
1883
1935
|
y: 0,
|
|
1884
1936
|
radius: holeRadius,
|
|
@@ -1895,14 +1947,6 @@ var FeatureTool = class {
|
|
|
1895
1947
|
return true;
|
|
1896
1948
|
}
|
|
1897
1949
|
getGeometryForFeature(geometry, feature) {
|
|
1898
|
-
if ((feature == null ? void 0 : feature.target) === "offset" && geometry.offset !== 0) {
|
|
1899
|
-
return {
|
|
1900
|
-
...geometry,
|
|
1901
|
-
width: geometry.width + geometry.offset * 2,
|
|
1902
|
-
height: geometry.height + geometry.offset * 2,
|
|
1903
|
-
radius: geometry.radius === 0 ? 0 : Math.max(0, geometry.radius + geometry.offset)
|
|
1904
|
-
};
|
|
1905
|
-
}
|
|
1906
1950
|
return geometry;
|
|
1907
1951
|
}
|
|
1908
1952
|
setup() {
|
|
@@ -1959,7 +2003,7 @@ var FeatureTool = class {
|
|
|
1959
2003
|
const markerStrokeWidth = (target.strokeWidth || 2) * (target.scaleX || 1);
|
|
1960
2004
|
const minDim = Math.min(target.getScaledWidth(), target.getScaledHeight());
|
|
1961
2005
|
const limit = Math.max(0, minDim / 2 - markerStrokeWidth);
|
|
1962
|
-
const snapped = this.constrainPosition(p, geometry, limit);
|
|
2006
|
+
const snapped = this.constrainPosition(p, geometry, limit, feature);
|
|
1963
2007
|
target.set({
|
|
1964
2008
|
left: snapped.x,
|
|
1965
2009
|
top: snapped.y
|
|
@@ -2043,7 +2087,17 @@ var FeatureTool = class {
|
|
|
2043
2087
|
objects.forEach((obj) => canvas.remove(obj));
|
|
2044
2088
|
this.canvasService.requestRenderAll();
|
|
2045
2089
|
}
|
|
2046
|
-
constrainPosition(p, geometry, limit) {
|
|
2090
|
+
constrainPosition(p, geometry, limit, feature) {
|
|
2091
|
+
if (feature && feature.placement === "internal") {
|
|
2092
|
+
const minX = geometry.x - geometry.width / 2;
|
|
2093
|
+
const maxX = geometry.x + geometry.width / 2;
|
|
2094
|
+
const minY = geometry.y - geometry.height / 2;
|
|
2095
|
+
const maxY = geometry.y + geometry.height / 2;
|
|
2096
|
+
return {
|
|
2097
|
+
x: Math.max(minX, Math.min(maxX, p.x)),
|
|
2098
|
+
y: Math.max(minY, Math.min(maxY, p.y))
|
|
2099
|
+
};
|
|
2100
|
+
}
|
|
2047
2101
|
const nearest = getNearestPointOnDieline({ x: p.x, y: p.y }, {
|
|
2048
2102
|
...geometry,
|
|
2049
2103
|
features: []
|
|
@@ -2168,7 +2222,9 @@ var FeatureTool = class {
|
|
|
2168
2222
|
const pos = resolveFeaturePosition(feature, geometry2);
|
|
2169
2223
|
const marker = createMarkerShape(feature, pos);
|
|
2170
2224
|
marker.set({
|
|
2171
|
-
|
|
2225
|
+
visible: this.isToolActive,
|
|
2226
|
+
selectable: this.isToolActive,
|
|
2227
|
+
evented: this.isToolActive,
|
|
2172
2228
|
hasControls: false,
|
|
2173
2229
|
hasBorders: false,
|
|
2174
2230
|
hoverCursor: "move",
|
|
@@ -2211,7 +2267,9 @@ var FeatureTool = class {
|
|
|
2211
2267
|
return createMarkerShape(feature, pos);
|
|
2212
2268
|
});
|
|
2213
2269
|
const groupObj = new Group(shapes, {
|
|
2214
|
-
|
|
2270
|
+
visible: this.isToolActive,
|
|
2271
|
+
selectable: this.isToolActive,
|
|
2272
|
+
evented: this.isToolActive,
|
|
2215
2273
|
hasControls: false,
|
|
2216
2274
|
hasBorders: false,
|
|
2217
2275
|
hoverCursor: "move",
|
|
@@ -2285,7 +2343,8 @@ var FeatureTool = class {
|
|
|
2285
2343
|
const snapped = this.constrainPosition(
|
|
2286
2344
|
new Point(marker.left, marker.top),
|
|
2287
2345
|
geometry,
|
|
2288
|
-
limit
|
|
2346
|
+
limit,
|
|
2347
|
+
feature
|
|
2289
2348
|
);
|
|
2290
2349
|
marker.set({ left: snapped.x, top: snapped.y });
|
|
2291
2350
|
marker.setCoords();
|
|
@@ -2309,6 +2368,11 @@ var ImageTool = class {
|
|
|
2309
2368
|
this.objectMap = /* @__PURE__ */ new Map();
|
|
2310
2369
|
this.loadResolvers = /* @__PURE__ */ new Map();
|
|
2311
2370
|
this.isUpdatingConfig = false;
|
|
2371
|
+
this.isToolActive = false;
|
|
2372
|
+
this.onToolActivated = (event) => {
|
|
2373
|
+
this.isToolActive = event.id === this.id;
|
|
2374
|
+
this.updateInteractivity();
|
|
2375
|
+
};
|
|
2312
2376
|
}
|
|
2313
2377
|
activate(context) {
|
|
2314
2378
|
this.context = context;
|
|
@@ -2317,6 +2381,7 @@ var ImageTool = class {
|
|
|
2317
2381
|
console.warn("CanvasService not found for ImageTool");
|
|
2318
2382
|
return;
|
|
2319
2383
|
}
|
|
2384
|
+
context.eventBus.on("tool:activated", this.onToolActivated);
|
|
2320
2385
|
const configService = context.services.get(
|
|
2321
2386
|
"ConfigurationService"
|
|
2322
2387
|
);
|
|
@@ -2334,6 +2399,7 @@ var ImageTool = class {
|
|
|
2334
2399
|
this.updateImages();
|
|
2335
2400
|
}
|
|
2336
2401
|
deactivate(context) {
|
|
2402
|
+
context.eventBus.off("tool:activated", this.onToolActivated);
|
|
2337
2403
|
if (this.canvasService) {
|
|
2338
2404
|
const layer = this.canvasService.getLayer("user");
|
|
2339
2405
|
if (layer) {
|
|
@@ -2347,6 +2413,18 @@ var ImageTool = class {
|
|
|
2347
2413
|
this.context = void 0;
|
|
2348
2414
|
}
|
|
2349
2415
|
}
|
|
2416
|
+
updateInteractivity() {
|
|
2417
|
+
var _a;
|
|
2418
|
+
this.objectMap.forEach((obj) => {
|
|
2419
|
+
obj.set({
|
|
2420
|
+
selectable: this.isToolActive,
|
|
2421
|
+
evented: this.isToolActive,
|
|
2422
|
+
hasControls: this.isToolActive,
|
|
2423
|
+
hasBorders: this.isToolActive
|
|
2424
|
+
});
|
|
2425
|
+
});
|
|
2426
|
+
(_a = this.canvasService) == null ? void 0 : _a.requestRenderAll();
|
|
2427
|
+
}
|
|
2350
2428
|
contribute() {
|
|
2351
2429
|
return {
|
|
2352
2430
|
[ContributionPointIds5.CONFIGURATIONS]: [
|
|
@@ -2534,6 +2612,14 @@ var ImageTool = class {
|
|
|
2534
2612
|
const layout = this.getLayoutInfo();
|
|
2535
2613
|
this.items.forEach((item, index) => {
|
|
2536
2614
|
let obj = this.objectMap.get(item.id);
|
|
2615
|
+
if (obj && obj.getSrc) {
|
|
2616
|
+
const currentSrc = obj.getSrc();
|
|
2617
|
+
if (currentSrc !== item.url) {
|
|
2618
|
+
layer.remove(obj);
|
|
2619
|
+
this.objectMap.delete(item.id);
|
|
2620
|
+
obj = void 0;
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2537
2623
|
if (!obj) {
|
|
2538
2624
|
this.loadImage(item, layer, layout);
|
|
2539
2625
|
} else {
|
|
@@ -2590,7 +2676,11 @@ var ImageTool = class {
|
|
|
2590
2676
|
originY: "center",
|
|
2591
2677
|
data: { id: item.id },
|
|
2592
2678
|
uniformScaling: true,
|
|
2593
|
-
lockScalingFlip: true
|
|
2679
|
+
lockScalingFlip: true,
|
|
2680
|
+
selectable: this.isToolActive,
|
|
2681
|
+
evented: this.isToolActive,
|
|
2682
|
+
hasControls: this.isToolActive,
|
|
2683
|
+
hasBorders: this.isToolActive
|
|
2594
2684
|
});
|
|
2595
2685
|
image.setControlsVisibility({
|
|
2596
2686
|
mt: false,
|
|
@@ -3447,6 +3537,24 @@ var CanvasService = class {
|
|
|
3447
3537
|
...options
|
|
3448
3538
|
});
|
|
3449
3539
|
}
|
|
3540
|
+
if (options == null ? void 0 : options.eventBus) {
|
|
3541
|
+
this.setEventBus(options.eventBus);
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
setEventBus(eventBus) {
|
|
3545
|
+
this.eventBus = eventBus;
|
|
3546
|
+
this.setupEvents();
|
|
3547
|
+
}
|
|
3548
|
+
setupEvents() {
|
|
3549
|
+
if (!this.eventBus) return;
|
|
3550
|
+
const bus = this.eventBus;
|
|
3551
|
+
const forward = (name) => (e) => bus.emit(name, e);
|
|
3552
|
+
this.canvas.on("selection:created", forward("selection:created"));
|
|
3553
|
+
this.canvas.on("selection:updated", forward("selection:updated"));
|
|
3554
|
+
this.canvas.on("selection:cleared", forward("selection:cleared"));
|
|
3555
|
+
this.canvas.on("object:modified", forward("object:modified"));
|
|
3556
|
+
this.canvas.on("object:added", forward("object:added"));
|
|
3557
|
+
this.canvas.on("object:removed", forward("object:removed"));
|
|
3450
3558
|
}
|
|
3451
3559
|
dispose() {
|
|
3452
3560
|
this.canvas.dispose();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pooder/kit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Standard plugins for Pooder editor",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"paper": "^0.12.18",
|
|
21
21
|
"fabric": "^7.0.0",
|
|
22
|
-
"@pooder/core": "
|
|
22
|
+
"@pooder/core": "2.0.0"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
25
|
"build": "tsup src/index.ts --format cjs,esm --dts",
|
package/src/CanvasService.ts
CHANGED
|
@@ -1,65 +1,89 @@
|
|
|
1
|
-
import { Canvas, Group, FabricObject } from "fabric";
|
|
2
|
-
import { Service } from "@pooder/core";
|
|
3
|
-
|
|
4
|
-
export default class CanvasService implements Service {
|
|
5
|
-
public canvas: Canvas;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
1
|
+
import { Canvas, Group, FabricObject } from "fabric";
|
|
2
|
+
import { Service, EventBus } from "@pooder/core";
|
|
3
|
+
|
|
4
|
+
export default class CanvasService implements Service {
|
|
5
|
+
public canvas: Canvas;
|
|
6
|
+
private eventBus?: EventBus;
|
|
7
|
+
|
|
8
|
+
constructor(el: HTMLCanvasElement | string | Canvas, options?: any) {
|
|
9
|
+
if (el instanceof Canvas) {
|
|
10
|
+
this.canvas = el;
|
|
11
|
+
} else {
|
|
12
|
+
this.canvas = new Canvas(el, {
|
|
13
|
+
preserveObjectStacking: true,
|
|
14
|
+
...options,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (options?.eventBus) {
|
|
19
|
+
this.setEventBus(options.eventBus);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setEventBus(eventBus: EventBus) {
|
|
24
|
+
this.eventBus = eventBus;
|
|
25
|
+
this.setupEvents();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private setupEvents() {
|
|
29
|
+
if (!this.eventBus) return;
|
|
30
|
+
const bus = this.eventBus;
|
|
31
|
+
|
|
32
|
+
const forward = (name: string) => (e: any) => bus.emit(name, e);
|
|
33
|
+
|
|
34
|
+
this.canvas.on("selection:created", forward("selection:created"));
|
|
35
|
+
this.canvas.on("selection:updated", forward("selection:updated"));
|
|
36
|
+
this.canvas.on("selection:cleared", forward("selection:cleared"));
|
|
37
|
+
this.canvas.on("object:modified", forward("object:modified"));
|
|
38
|
+
this.canvas.on("object:added", forward("object:added"));
|
|
39
|
+
this.canvas.on("object:removed", forward("object:removed"));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
dispose() {
|
|
43
|
+
this.canvas.dispose();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get a layer (Group) by its ID.
|
|
48
|
+
* We assume layers are Groups directly on the canvas with a data.id property.
|
|
49
|
+
*/
|
|
50
|
+
getLayer(id: string): Group | undefined {
|
|
51
|
+
return this.canvas.getObjects().find((obj: any) => obj.data?.id === id) as
|
|
52
|
+
| Group
|
|
53
|
+
| undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Create a layer (Group) with the given ID if it doesn't exist.
|
|
58
|
+
*/
|
|
59
|
+
createLayer(id: string, options: any = {}): Group {
|
|
60
|
+
let layer = this.getLayer(id);
|
|
61
|
+
if (!layer) {
|
|
62
|
+
const defaultOptions = {
|
|
63
|
+
selectable: false,
|
|
64
|
+
evented: false,
|
|
65
|
+
...options,
|
|
66
|
+
data: { ...options.data, id },
|
|
67
|
+
};
|
|
68
|
+
layer = new Group([], defaultOptions);
|
|
69
|
+
this.canvas.add(layer);
|
|
70
|
+
}
|
|
71
|
+
return layer;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Find an object by ID, optionally within a specific layer.
|
|
76
|
+
*/
|
|
77
|
+
getObject(id: string, layerId?: string): FabricObject | undefined {
|
|
78
|
+
if (layerId) {
|
|
79
|
+
const layer = this.getLayer(layerId);
|
|
80
|
+
if (!layer) return undefined;
|
|
81
|
+
return layer.getObjects().find((obj: any) => obj.data?.id === id);
|
|
82
|
+
}
|
|
83
|
+
return this.canvas.getObjects().find((obj: any) => obj.data?.id === id);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
requestRenderAll() {
|
|
87
|
+
this.canvas.requestRenderAll();
|
|
88
|
+
}
|
|
89
|
+
}
|