@pooder/kit 6.0.0 → 6.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/.test-dist/src/extensions/background/BackgroundTool.js +524 -0
- package/.test-dist/src/extensions/background/index.js +17 -0
- package/.test-dist/src/extensions/background.js +1 -1
- package/.test-dist/src/extensions/dieline/DielineTool.js +748 -0
- package/.test-dist/src/extensions/dieline/commands.js +127 -0
- package/.test-dist/src/extensions/dieline/config.js +107 -0
- package/.test-dist/src/extensions/dieline/index.js +21 -0
- package/.test-dist/src/extensions/dieline/model.js +2 -0
- package/.test-dist/src/extensions/dieline/renderer.js +2 -0
- package/.test-dist/src/extensions/dieline.js +4 -0
- package/.test-dist/src/extensions/feature/FeatureTool.js +914 -0
- package/.test-dist/src/extensions/feature/index.js +17 -0
- package/.test-dist/src/extensions/film/FilmTool.js +207 -0
- package/.test-dist/src/extensions/film/index.js +17 -0
- package/.test-dist/src/extensions/image/ImageTool.js +1499 -0
- package/.test-dist/src/extensions/image/commands.js +162 -0
- package/.test-dist/src/extensions/image/config.js +129 -0
- package/.test-dist/src/extensions/image/index.js +21 -0
- package/.test-dist/src/extensions/image/model.js +2 -0
- package/.test-dist/src/extensions/image/renderer.js +5 -0
- package/.test-dist/src/extensions/image.js +182 -7
- package/.test-dist/src/extensions/mirror/MirrorTool.js +104 -0
- package/.test-dist/src/extensions/mirror/index.js +17 -0
- package/.test-dist/src/extensions/ruler/RulerTool.js +442 -0
- package/.test-dist/src/extensions/ruler/index.js +17 -0
- package/.test-dist/src/extensions/sceneLayout.js +2 -93
- package/.test-dist/src/extensions/sceneLayoutModel.js +15 -200
- package/.test-dist/src/extensions/size/SizeTool.js +332 -0
- package/.test-dist/src/extensions/size/index.js +17 -0
- package/.test-dist/src/extensions/white-ink/WhiteInkTool.js +1003 -0
- package/.test-dist/src/extensions/white-ink/commands.js +148 -0
- package/.test-dist/src/extensions/white-ink/config.js +31 -0
- package/.test-dist/src/extensions/white-ink/index.js +21 -0
- package/.test-dist/src/extensions/white-ink/model.js +2 -0
- package/.test-dist/src/extensions/white-ink/renderer.js +5 -0
- package/.test-dist/src/services/CanvasService.js +34 -13
- package/.test-dist/src/services/SceneLayoutService.js +96 -0
- package/.test-dist/src/services/index.js +1 -0
- package/.test-dist/src/services/visibility.js +3 -0
- package/.test-dist/src/shared/constants/layers.js +25 -0
- package/.test-dist/src/shared/imaging/sourceSizeCache.js +82 -0
- package/.test-dist/src/shared/index.js +22 -0
- package/.test-dist/src/shared/runtime/sessionState.js +74 -0
- package/.test-dist/src/shared/runtime/subscriptions.js +30 -0
- package/.test-dist/src/shared/scene/frame.js +34 -0
- package/.test-dist/src/shared/scene/sceneLayoutModel.js +202 -0
- package/.test-dist/tests/run.js +118 -0
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +403 -366
- package/dist/index.d.ts +403 -366
- package/dist/index.js +5172 -4752
- package/dist/index.mjs +1410 -2027
- package/dist/tracer-PO7CRBYY.mjs +1016 -0
- package/package.json +1 -1
- package/src/extensions/{background.ts → background/BackgroundTool.ts} +33 -50
- package/src/extensions/background/index.ts +1 -0
- package/src/extensions/{dieline.ts → dieline/DielineTool.ts} +18 -218
- package/src/extensions/dieline/commands.ts +109 -0
- package/src/extensions/dieline/config.ts +106 -0
- package/src/extensions/dieline/index.ts +5 -0
- package/src/extensions/dieline/model.ts +1 -0
- package/src/extensions/dieline/renderer.ts +1 -0
- package/src/extensions/{feature.ts → feature/FeatureTool.ts} +27 -21
- package/src/extensions/feature/index.ts +1 -0
- package/src/extensions/{film.ts → film/FilmTool.ts} +36 -48
- package/src/extensions/film/index.ts +1 -0
- package/src/extensions/{image.ts → image/ImageTool.ts} +289 -335
- package/src/extensions/image/commands.ts +176 -0
- package/src/extensions/image/config.ts +128 -0
- package/src/extensions/image/index.ts +5 -0
- package/src/extensions/image/model.ts +1 -0
- package/src/extensions/image/renderer.ts +1 -0
- package/src/extensions/{mirror.ts → mirror/MirrorTool.ts} +1 -1
- package/src/extensions/mirror/index.ts +1 -0
- package/src/extensions/{ruler.ts → ruler/RulerTool.ts} +4 -5
- package/src/extensions/ruler/index.ts +1 -0
- package/src/extensions/sceneLayout.ts +1 -140
- package/src/extensions/sceneLayoutModel.ts +1 -364
- package/src/extensions/{size.ts → size/SizeTool.ts} +7 -6
- package/src/extensions/size/index.ts +1 -0
- package/src/extensions/{white-ink.ts → white-ink/WhiteInkTool.ts} +130 -317
- package/src/extensions/white-ink/commands.ts +157 -0
- package/src/extensions/white-ink/config.ts +30 -0
- package/src/extensions/white-ink/index.ts +5 -0
- package/src/extensions/white-ink/model.ts +1 -0
- package/src/extensions/white-ink/renderer.ts +1 -0
- package/src/services/CanvasService.ts +43 -12
- package/src/services/SceneLayoutService.ts +139 -0
- package/src/services/index.ts +1 -0
- package/src/services/renderSpec.ts +2 -0
- package/src/services/visibility.ts +5 -0
- package/src/shared/constants/layers.ts +23 -0
- package/src/shared/imaging/sourceSizeCache.ts +103 -0
- package/src/shared/index.ts +6 -0
- package/src/shared/runtime/sessionState.ts +105 -0
- package/src/shared/runtime/subscriptions.ts +45 -0
- package/src/shared/scene/frame.ts +46 -0
- package/src/shared/scene/sceneLayoutModel.ts +367 -0
- package/tests/run.ts +151 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createImageCommands = createImageCommands;
|
|
4
|
+
function createImageCommands(tool) {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
command: "addImage",
|
|
8
|
+
id: "addImage",
|
|
9
|
+
title: "Add Image",
|
|
10
|
+
handler: async (url, options) => {
|
|
11
|
+
const result = await tool.upsertImageEntry(url, {
|
|
12
|
+
mode: "add",
|
|
13
|
+
addOptions: options,
|
|
14
|
+
});
|
|
15
|
+
return result.id;
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
command: "upsertImage",
|
|
20
|
+
id: "upsertImage",
|
|
21
|
+
title: "Upsert Image",
|
|
22
|
+
handler: async (url, options = {}) => {
|
|
23
|
+
return await tool.upsertImageEntry(url, options);
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
command: "getWorkingImages",
|
|
28
|
+
id: "getWorkingImages",
|
|
29
|
+
title: "Get Working Images",
|
|
30
|
+
handler: () => {
|
|
31
|
+
return tool.cloneItems(tool.workingItems);
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
command: "setWorkingImage",
|
|
36
|
+
id: "setWorkingImage",
|
|
37
|
+
title: "Set Working Image",
|
|
38
|
+
handler: (id, updates) => {
|
|
39
|
+
tool.updateImageInWorking(id, updates);
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
command: "resetWorkingImages",
|
|
44
|
+
id: "resetWorkingImages",
|
|
45
|
+
title: "Reset Working Images",
|
|
46
|
+
handler: () => {
|
|
47
|
+
tool.workingItems = tool.cloneItems(tool.items);
|
|
48
|
+
tool.hasWorkingChanges = false;
|
|
49
|
+
tool.updateImages();
|
|
50
|
+
tool.emitWorkingChange();
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
command: "completeImages",
|
|
55
|
+
id: "completeImages",
|
|
56
|
+
title: "Complete Images",
|
|
57
|
+
handler: async () => {
|
|
58
|
+
return await tool.commitWorkingImagesAsCropped();
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
command: "exportUserCroppedImage",
|
|
63
|
+
id: "exportUserCroppedImage",
|
|
64
|
+
title: "Export User Cropped Image",
|
|
65
|
+
handler: async (options = {}) => {
|
|
66
|
+
return await tool.exportUserCroppedImage(options);
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
command: "fitImageToArea",
|
|
71
|
+
id: "fitImageToArea",
|
|
72
|
+
title: "Fit Image to Area",
|
|
73
|
+
handler: async (id, area) => {
|
|
74
|
+
await tool.fitImageToArea(id, area);
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
command: "fitImageToDefaultArea",
|
|
79
|
+
id: "fitImageToDefaultArea",
|
|
80
|
+
title: "Fit Image to Default Area",
|
|
81
|
+
handler: async (id) => {
|
|
82
|
+
await tool.fitImageToDefaultArea(id);
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
command: "focusImage",
|
|
87
|
+
id: "focusImage",
|
|
88
|
+
title: "Focus Image",
|
|
89
|
+
handler: (id, options = {}) => {
|
|
90
|
+
return tool.setImageFocus(id, options);
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
command: "removeImage",
|
|
95
|
+
id: "removeImage",
|
|
96
|
+
title: "Remove Image",
|
|
97
|
+
handler: (id) => {
|
|
98
|
+
const removed = tool.items.find((item) => item.id === id);
|
|
99
|
+
const next = tool.items.filter((item) => item.id !== id);
|
|
100
|
+
if (next.length !== tool.items.length) {
|
|
101
|
+
tool.purgeSourceSizeCacheForItem(removed);
|
|
102
|
+
if (tool.focusedImageId === id) {
|
|
103
|
+
tool.setImageFocus(null, {
|
|
104
|
+
syncCanvasSelection: true,
|
|
105
|
+
skipRender: true,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
tool.updateConfig(next);
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
command: "updateImage",
|
|
114
|
+
id: "updateImage",
|
|
115
|
+
title: "Update Image",
|
|
116
|
+
handler: async (id, updates, options = {}) => {
|
|
117
|
+
await tool.updateImage(id, updates, options);
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
command: "clearImages",
|
|
122
|
+
id: "clearImages",
|
|
123
|
+
title: "Clear Images",
|
|
124
|
+
handler: () => {
|
|
125
|
+
tool.sourceSizeCache.clear();
|
|
126
|
+
tool.setImageFocus(null, {
|
|
127
|
+
syncCanvasSelection: true,
|
|
128
|
+
skipRender: true,
|
|
129
|
+
});
|
|
130
|
+
tool.updateConfig([]);
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
command: "bringToFront",
|
|
135
|
+
id: "bringToFront",
|
|
136
|
+
title: "Bring Image to Front",
|
|
137
|
+
handler: (id) => {
|
|
138
|
+
const index = tool.items.findIndex((item) => item.id === id);
|
|
139
|
+
if (index !== -1 && index < tool.items.length - 1) {
|
|
140
|
+
const next = [...tool.items];
|
|
141
|
+
const [item] = next.splice(index, 1);
|
|
142
|
+
next.push(item);
|
|
143
|
+
tool.updateConfig(next);
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
command: "sendToBack",
|
|
149
|
+
id: "sendToBack",
|
|
150
|
+
title: "Send Image to Back",
|
|
151
|
+
handler: (id) => {
|
|
152
|
+
const index = tool.items.findIndex((item) => item.id === id);
|
|
153
|
+
if (index > 0) {
|
|
154
|
+
const next = [...tool.items];
|
|
155
|
+
const [item] = next.splice(index, 1);
|
|
156
|
+
next.unshift(item);
|
|
157
|
+
tool.updateConfig(next);
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createImageConfigurations = createImageConfigurations;
|
|
4
|
+
function createImageConfigurations() {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
id: "image.items",
|
|
8
|
+
type: "array",
|
|
9
|
+
label: "Images",
|
|
10
|
+
default: [],
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: "image.debug",
|
|
14
|
+
type: "boolean",
|
|
15
|
+
label: "Image Debug Log",
|
|
16
|
+
default: false,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "image.control.cornerSize",
|
|
20
|
+
type: "number",
|
|
21
|
+
label: "Image Control Corner Size",
|
|
22
|
+
min: 4,
|
|
23
|
+
max: 64,
|
|
24
|
+
step: 1,
|
|
25
|
+
default: 14,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "image.control.touchCornerSize",
|
|
29
|
+
type: "number",
|
|
30
|
+
label: "Image Control Touch Corner Size",
|
|
31
|
+
min: 8,
|
|
32
|
+
max: 96,
|
|
33
|
+
step: 1,
|
|
34
|
+
default: 24,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "image.control.cornerStyle",
|
|
38
|
+
type: "select",
|
|
39
|
+
label: "Image Control Corner Style",
|
|
40
|
+
options: ["circle", "rect"],
|
|
41
|
+
default: "circle",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "image.control.cornerColor",
|
|
45
|
+
type: "color",
|
|
46
|
+
label: "Image Control Corner Color",
|
|
47
|
+
default: "#ffffff",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "image.control.cornerStrokeColor",
|
|
51
|
+
type: "color",
|
|
52
|
+
label: "Image Control Corner Stroke Color",
|
|
53
|
+
default: "#1677ff",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "image.control.transparentCorners",
|
|
57
|
+
type: "boolean",
|
|
58
|
+
label: "Image Control Transparent Corners",
|
|
59
|
+
default: false,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "image.control.borderColor",
|
|
63
|
+
type: "color",
|
|
64
|
+
label: "Image Control Border Color",
|
|
65
|
+
default: "#1677ff",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: "image.control.borderScaleFactor",
|
|
69
|
+
type: "number",
|
|
70
|
+
label: "Image Control Border Width",
|
|
71
|
+
min: 0.5,
|
|
72
|
+
max: 8,
|
|
73
|
+
step: 0.1,
|
|
74
|
+
default: 1.5,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: "image.control.padding",
|
|
78
|
+
type: "number",
|
|
79
|
+
label: "Image Control Padding",
|
|
80
|
+
min: 0,
|
|
81
|
+
max: 64,
|
|
82
|
+
step: 1,
|
|
83
|
+
default: 0,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "image.frame.strokeColor",
|
|
87
|
+
type: "color",
|
|
88
|
+
label: "Image Frame Stroke Color",
|
|
89
|
+
default: "#808080",
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "image.frame.strokeWidth",
|
|
93
|
+
type: "number",
|
|
94
|
+
label: "Image Frame Stroke Width",
|
|
95
|
+
min: 0,
|
|
96
|
+
max: 20,
|
|
97
|
+
step: 0.5,
|
|
98
|
+
default: 2,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
id: "image.frame.strokeStyle",
|
|
102
|
+
type: "select",
|
|
103
|
+
label: "Image Frame Stroke Style",
|
|
104
|
+
options: ["solid", "dashed", "hidden"],
|
|
105
|
+
default: "dashed",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: "image.frame.dashLength",
|
|
109
|
+
type: "number",
|
|
110
|
+
label: "Image Frame Dash Length",
|
|
111
|
+
min: 1,
|
|
112
|
+
max: 40,
|
|
113
|
+
step: 1,
|
|
114
|
+
default: 8,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: "image.frame.innerBackground",
|
|
118
|
+
type: "color",
|
|
119
|
+
label: "Image Frame Inner Background",
|
|
120
|
+
default: "rgba(0,0,0,0)",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: "image.frame.outerBackground",
|
|
124
|
+
type: "color",
|
|
125
|
+
label: "Image Frame Outer Background",
|
|
126
|
+
default: "#f5f5f5",
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./ImageTool"), exports);
|
|
18
|
+
__exportStar(require("./commands"), exports);
|
|
19
|
+
__exportStar(require("./config"), exports);
|
|
20
|
+
__exportStar(require("./model"), exports);
|
|
21
|
+
__exportStar(require("./renderer"), exports);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.computeImageCoverScale = void 0;
|
|
4
|
+
var sourceSizeCache_1 = require("../../shared/imaging/sourceSizeCache");
|
|
5
|
+
Object.defineProperty(exports, "computeImageCoverScale", { enumerable: true, get: function () { return sourceSizeCache_1.getCoverScale; } });
|
|
@@ -8,6 +8,34 @@ const geometry_1 = require("./geometry");
|
|
|
8
8
|
const sceneLayoutModel_1 = require("./sceneLayoutModel");
|
|
9
9
|
const IMAGE_OBJECT_LAYER_ID = "image.user";
|
|
10
10
|
const IMAGE_OVERLAY_LAYER_ID = "image-overlay";
|
|
11
|
+
const IMAGE_DEFAULT_CONTROL_CAPABILITIES = [
|
|
12
|
+
"rotate",
|
|
13
|
+
"scale",
|
|
14
|
+
];
|
|
15
|
+
const IMAGE_CONTROL_DESCRIPTORS = [
|
|
16
|
+
{
|
|
17
|
+
key: "tl",
|
|
18
|
+
capability: "rotate",
|
|
19
|
+
create: () => new fabric_1.Control({
|
|
20
|
+
x: -0.5,
|
|
21
|
+
y: -0.5,
|
|
22
|
+
actionName: "rotate",
|
|
23
|
+
actionHandler: fabric_1.controlsUtils.rotationWithSnapping,
|
|
24
|
+
cursorStyleHandler: fabric_1.controlsUtils.rotationStyleHandler,
|
|
25
|
+
}),
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
key: "br",
|
|
29
|
+
capability: "scale",
|
|
30
|
+
create: () => new fabric_1.Control({
|
|
31
|
+
x: 0.5,
|
|
32
|
+
y: 0.5,
|
|
33
|
+
actionName: "scale",
|
|
34
|
+
actionHandler: fabric_1.controlsUtils.scalingEqually,
|
|
35
|
+
cursorStyleHandler: fabric_1.controlsUtils.scaleCursorStyleHandler,
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
];
|
|
11
39
|
class ImageTool {
|
|
12
40
|
constructor() {
|
|
13
41
|
this.id = "pooder.kit.image";
|
|
@@ -26,6 +54,7 @@ class ImageTool {
|
|
|
26
54
|
this.renderSeq = 0;
|
|
27
55
|
this.imageSpecs = [];
|
|
28
56
|
this.overlaySpecs = [];
|
|
57
|
+
this.imageControlsByCapabilityKey = new Map();
|
|
29
58
|
this.onToolActivated = (event) => {
|
|
30
59
|
const before = this.isToolActive;
|
|
31
60
|
this.syncToolActiveFromWorkbench(event.id);
|
|
@@ -183,7 +212,12 @@ class ImageTool {
|
|
|
183
212
|
this.updateImages();
|
|
184
213
|
return;
|
|
185
214
|
}
|
|
186
|
-
if (e.key.startsWith("size.") ||
|
|
215
|
+
if (e.key.startsWith("size.") ||
|
|
216
|
+
e.key.startsWith("image.frame.") ||
|
|
217
|
+
e.key.startsWith("image.control.")) {
|
|
218
|
+
if (e.key.startsWith("image.control.")) {
|
|
219
|
+
this.imageControlsByCapabilityKey.clear();
|
|
220
|
+
}
|
|
187
221
|
this.updateImages();
|
|
188
222
|
}
|
|
189
223
|
});
|
|
@@ -207,6 +241,7 @@ class ImageTool {
|
|
|
207
241
|
this.cropShapeHatchPatternKey = undefined;
|
|
208
242
|
this.imageSpecs = [];
|
|
209
243
|
this.overlaySpecs = [];
|
|
244
|
+
this.imageControlsByCapabilityKey.clear();
|
|
210
245
|
this.clearRenderedImages();
|
|
211
246
|
this.renderProducerDisposable?.dispose();
|
|
212
247
|
this.renderProducerDisposable = undefined;
|
|
@@ -228,6 +263,83 @@ class ImageTool {
|
|
|
228
263
|
isImageEditingVisible() {
|
|
229
264
|
return (this.isToolActive || this.isImageSelectionActive || !!this.focusedImageId);
|
|
230
265
|
}
|
|
266
|
+
getEnabledImageControlCapabilities() {
|
|
267
|
+
return IMAGE_DEFAULT_CONTROL_CAPABILITIES;
|
|
268
|
+
}
|
|
269
|
+
getImageControls(capabilities) {
|
|
270
|
+
const normalized = [...new Set(capabilities)].sort();
|
|
271
|
+
const cacheKey = normalized.join("|");
|
|
272
|
+
const cached = this.imageControlsByCapabilityKey.get(cacheKey);
|
|
273
|
+
if (cached) {
|
|
274
|
+
return cached;
|
|
275
|
+
}
|
|
276
|
+
const enabled = new Set(normalized);
|
|
277
|
+
const controls = {};
|
|
278
|
+
IMAGE_CONTROL_DESCRIPTORS.forEach((descriptor) => {
|
|
279
|
+
if (!enabled.has(descriptor.capability))
|
|
280
|
+
return;
|
|
281
|
+
controls[descriptor.key] = descriptor.create();
|
|
282
|
+
});
|
|
283
|
+
this.imageControlsByCapabilityKey.set(cacheKey, controls);
|
|
284
|
+
return controls;
|
|
285
|
+
}
|
|
286
|
+
getImageControlVisualConfig() {
|
|
287
|
+
const cornerSizeRaw = Number(this.getConfig("image.control.cornerSize", 14) ?? 14);
|
|
288
|
+
const touchCornerSizeRaw = Number(this.getConfig("image.control.touchCornerSize", 24) ?? 24);
|
|
289
|
+
const borderScaleFactorRaw = Number(this.getConfig("image.control.borderScaleFactor", 1.5) ?? 1.5);
|
|
290
|
+
const paddingRaw = Number(this.getConfig("image.control.padding", 0) ?? 0);
|
|
291
|
+
const cornerStyleRaw = (this.getConfig("image.control.cornerStyle", "circle") || "circle");
|
|
292
|
+
const cornerStyle = cornerStyleRaw === "rect" ? "rect" : "circle";
|
|
293
|
+
return {
|
|
294
|
+
cornerSize: Number.isFinite(cornerSizeRaw)
|
|
295
|
+
? Math.max(4, Math.min(64, cornerSizeRaw))
|
|
296
|
+
: 14,
|
|
297
|
+
touchCornerSize: Number.isFinite(touchCornerSizeRaw)
|
|
298
|
+
? Math.max(8, Math.min(96, touchCornerSizeRaw))
|
|
299
|
+
: 24,
|
|
300
|
+
cornerStyle,
|
|
301
|
+
cornerColor: this.getConfig("image.control.cornerColor", "#ffffff") ||
|
|
302
|
+
"#ffffff",
|
|
303
|
+
cornerStrokeColor: this.getConfig("image.control.cornerStrokeColor", "#1677ff") ||
|
|
304
|
+
"#1677ff",
|
|
305
|
+
transparentCorners: !!this.getConfig("image.control.transparentCorners", false),
|
|
306
|
+
borderColor: this.getConfig("image.control.borderColor", "#1677ff") ||
|
|
307
|
+
"#1677ff",
|
|
308
|
+
borderScaleFactor: Number.isFinite(borderScaleFactorRaw)
|
|
309
|
+
? Math.max(0.5, Math.min(8, borderScaleFactorRaw))
|
|
310
|
+
: 1.5,
|
|
311
|
+
padding: Number.isFinite(paddingRaw)
|
|
312
|
+
? Math.max(0, Math.min(64, paddingRaw))
|
|
313
|
+
: 0,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
applyImageObjectInteractionState(obj) {
|
|
317
|
+
if (!obj)
|
|
318
|
+
return;
|
|
319
|
+
const visible = this.isImageEditingVisible();
|
|
320
|
+
const visual = this.getImageControlVisualConfig();
|
|
321
|
+
obj.set({
|
|
322
|
+
selectable: visible,
|
|
323
|
+
evented: visible,
|
|
324
|
+
hasControls: visible,
|
|
325
|
+
hasBorders: visible,
|
|
326
|
+
lockScalingFlip: true,
|
|
327
|
+
cornerSize: visual.cornerSize,
|
|
328
|
+
touchCornerSize: visual.touchCornerSize,
|
|
329
|
+
cornerStyle: visual.cornerStyle,
|
|
330
|
+
cornerColor: visual.cornerColor,
|
|
331
|
+
cornerStrokeColor: visual.cornerStrokeColor,
|
|
332
|
+
transparentCorners: visual.transparentCorners,
|
|
333
|
+
borderColor: visual.borderColor,
|
|
334
|
+
borderScaleFactor: visual.borderScaleFactor,
|
|
335
|
+
padding: visual.padding,
|
|
336
|
+
});
|
|
337
|
+
obj.controls = this.getImageControls(this.getEnabledImageControlCapabilities());
|
|
338
|
+
obj.setCoords?.();
|
|
339
|
+
}
|
|
340
|
+
refreshImageObjectInteractionState() {
|
|
341
|
+
this.getImageObjects().forEach((obj) => this.applyImageObjectInteractionState(obj));
|
|
342
|
+
}
|
|
231
343
|
isDebugEnabled() {
|
|
232
344
|
return !!this.getConfig("image.debug", false);
|
|
233
345
|
}
|
|
@@ -271,6 +383,73 @@ class ImageTool {
|
|
|
271
383
|
label: "Image Debug Log",
|
|
272
384
|
default: false,
|
|
273
385
|
},
|
|
386
|
+
{
|
|
387
|
+
id: "image.control.cornerSize",
|
|
388
|
+
type: "number",
|
|
389
|
+
label: "Image Control Corner Size",
|
|
390
|
+
min: 4,
|
|
391
|
+
max: 64,
|
|
392
|
+
step: 1,
|
|
393
|
+
default: 14,
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
id: "image.control.touchCornerSize",
|
|
397
|
+
type: "number",
|
|
398
|
+
label: "Image Control Touch Corner Size",
|
|
399
|
+
min: 8,
|
|
400
|
+
max: 96,
|
|
401
|
+
step: 1,
|
|
402
|
+
default: 24,
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
id: "image.control.cornerStyle",
|
|
406
|
+
type: "select",
|
|
407
|
+
label: "Image Control Corner Style",
|
|
408
|
+
options: ["circle", "rect"],
|
|
409
|
+
default: "circle",
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
id: "image.control.cornerColor",
|
|
413
|
+
type: "color",
|
|
414
|
+
label: "Image Control Corner Color",
|
|
415
|
+
default: "#ffffff",
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
id: "image.control.cornerStrokeColor",
|
|
419
|
+
type: "color",
|
|
420
|
+
label: "Image Control Corner Stroke Color",
|
|
421
|
+
default: "#1677ff",
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
id: "image.control.transparentCorners",
|
|
425
|
+
type: "boolean",
|
|
426
|
+
label: "Image Control Transparent Corners",
|
|
427
|
+
default: false,
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
id: "image.control.borderColor",
|
|
431
|
+
type: "color",
|
|
432
|
+
label: "Image Control Border Color",
|
|
433
|
+
default: "#1677ff",
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
id: "image.control.borderScaleFactor",
|
|
437
|
+
type: "number",
|
|
438
|
+
label: "Image Control Border Width",
|
|
439
|
+
min: 0.5,
|
|
440
|
+
max: 8,
|
|
441
|
+
step: 0.1,
|
|
442
|
+
default: 1.5,
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
id: "image.control.padding",
|
|
446
|
+
type: "number",
|
|
447
|
+
label: "Image Control Padding",
|
|
448
|
+
min: 0,
|
|
449
|
+
max: 64,
|
|
450
|
+
step: 1,
|
|
451
|
+
default: 0,
|
|
452
|
+
},
|
|
274
453
|
{
|
|
275
454
|
id: "image.frame.strokeColor",
|
|
276
455
|
type: "color",
|
|
@@ -513,12 +692,7 @@ class ImageTool {
|
|
|
513
692
|
else {
|
|
514
693
|
const obj = this.getImageObject(id);
|
|
515
694
|
if (obj) {
|
|
516
|
-
|
|
517
|
-
selectable: true,
|
|
518
|
-
evented: true,
|
|
519
|
-
hasControls: true,
|
|
520
|
-
hasBorders: true,
|
|
521
|
-
});
|
|
695
|
+
this.applyImageObjectInteractionState(obj);
|
|
522
696
|
canvas.setActiveObject(obj);
|
|
523
697
|
}
|
|
524
698
|
}
|
|
@@ -1317,6 +1491,7 @@ class ImageTool {
|
|
|
1317
1491
|
await this.canvasService.flushRenderFromProducers();
|
|
1318
1492
|
if (seq !== this.renderSeq)
|
|
1319
1493
|
return;
|
|
1494
|
+
this.refreshImageObjectInteractionState();
|
|
1320
1495
|
renderItems.forEach((item) => {
|
|
1321
1496
|
if (!this.getImageObject(item.id))
|
|
1322
1497
|
return;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MirrorTool = void 0;
|
|
4
|
+
const core_1 = require("@pooder/core");
|
|
5
|
+
class MirrorTool {
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.id = "pooder.kit.mirror";
|
|
8
|
+
this.metadata = {
|
|
9
|
+
name: "MirrorTool",
|
|
10
|
+
};
|
|
11
|
+
this.enabled = false;
|
|
12
|
+
if (options) {
|
|
13
|
+
Object.assign(this, options);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
toJSON() {
|
|
17
|
+
return {
|
|
18
|
+
enabled: this.enabled,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
loadFromJSON(json) {
|
|
22
|
+
this.enabled = json.enabled;
|
|
23
|
+
}
|
|
24
|
+
activate(context) {
|
|
25
|
+
this.canvasService = context.services.get("CanvasService");
|
|
26
|
+
if (!this.canvasService) {
|
|
27
|
+
console.warn("CanvasService not found for MirrorTool");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const configService = context.services.get("ConfigurationService");
|
|
31
|
+
if (configService) {
|
|
32
|
+
// Load initial config
|
|
33
|
+
this.enabled = configService.get("mirror.enabled", this.enabled);
|
|
34
|
+
// Listen for changes
|
|
35
|
+
configService.onAnyChange((e) => {
|
|
36
|
+
if (e.key === "mirror.enabled") {
|
|
37
|
+
this.applyMirror(e.value);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
// Initialize with current state (if enabled was persisted)
|
|
42
|
+
if (this.enabled) {
|
|
43
|
+
this.applyMirror(true);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
deactivate(context) {
|
|
47
|
+
this.applyMirror(false);
|
|
48
|
+
this.canvasService = undefined;
|
|
49
|
+
}
|
|
50
|
+
contribute() {
|
|
51
|
+
return {
|
|
52
|
+
[core_1.ContributionPointIds.CONFIGURATIONS]: [
|
|
53
|
+
{
|
|
54
|
+
id: "mirror.enabled",
|
|
55
|
+
type: "boolean",
|
|
56
|
+
label: "Enable Mirror",
|
|
57
|
+
default: false,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
[core_1.ContributionPointIds.COMMANDS]: [
|
|
61
|
+
{
|
|
62
|
+
command: "setMirror",
|
|
63
|
+
title: "Set Mirror",
|
|
64
|
+
handler: (enabled) => {
|
|
65
|
+
this.applyMirror(enabled);
|
|
66
|
+
return true;
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
applyMirror(enabled) {
|
|
73
|
+
if (!this.canvasService)
|
|
74
|
+
return;
|
|
75
|
+
const canvas = this.canvasService.canvas;
|
|
76
|
+
if (!canvas)
|
|
77
|
+
return;
|
|
78
|
+
const width = canvas.width || 800;
|
|
79
|
+
// Fabric.js v6+ uses viewportTransform property
|
|
80
|
+
let vpt = canvas.viewportTransform || [1, 0, 0, 1, 0, 0];
|
|
81
|
+
// Create a copy to avoid mutating the reference directly before setting
|
|
82
|
+
vpt = [...vpt];
|
|
83
|
+
// If we are enabling and currently not flipped (scaleX > 0)
|
|
84
|
+
// Or disabling and currently flipped (scaleX < 0)
|
|
85
|
+
const isFlipped = vpt[0] < 0;
|
|
86
|
+
if (enabled && !isFlipped) {
|
|
87
|
+
// Flip scale X
|
|
88
|
+
vpt[0] = -vpt[0]; // Flip scale
|
|
89
|
+
vpt[4] = width - vpt[4]; // Adjust pan X
|
|
90
|
+
canvas.setViewportTransform(vpt);
|
|
91
|
+
canvas.requestRenderAll();
|
|
92
|
+
this.enabled = true;
|
|
93
|
+
}
|
|
94
|
+
else if (!enabled && isFlipped) {
|
|
95
|
+
// Restore
|
|
96
|
+
vpt[0] = -vpt[0]; // Unflip scale
|
|
97
|
+
vpt[4] = width - vpt[4]; // Restore pan X
|
|
98
|
+
canvas.setViewportTransform(vpt);
|
|
99
|
+
canvas.requestRenderAll();
|
|
100
|
+
this.enabled = false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.MirrorTool = MirrorTool;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./MirrorTool"), exports);
|