@pooder/kit 5.0.1 → 5.0.3
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/feature.js +87 -15
- package/.test-dist/src/image.js +28 -12
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +123 -38
- package/dist/index.mjs +123 -38
- package/package.json +1 -1
- package/src/feature.ts +96 -20
- package/src/image.ts +38 -24
package/src/feature.ts
CHANGED
|
@@ -34,6 +34,8 @@ export class FeatureTool implements Extension {
|
|
|
34
34
|
private context?: ExtensionContext;
|
|
35
35
|
private isUpdatingConfig = false;
|
|
36
36
|
private isToolActive = false;
|
|
37
|
+
private isFeatureSessionActive = false;
|
|
38
|
+
private sessionOriginalFeatures: ConstraintFeature[] | null = null;
|
|
37
39
|
private hasWorkingChanges = false;
|
|
38
40
|
private dirtyTrackerDisposable?: { dispose(): void };
|
|
39
41
|
|
|
@@ -76,6 +78,7 @@ export class FeatureTool implements Extension {
|
|
|
76
78
|
if (this.isUpdatingConfig) return;
|
|
77
79
|
|
|
78
80
|
if (e.key === "dieline.features") {
|
|
81
|
+
if (this.isFeatureSessionActive) return;
|
|
79
82
|
const next = (e.value || []) as ConstraintFeature[];
|
|
80
83
|
this.workingFeatures = this.cloneFeatures(next);
|
|
81
84
|
this.hasWorkingChanges = false;
|
|
@@ -100,6 +103,7 @@ export class FeatureTool implements Extension {
|
|
|
100
103
|
|
|
101
104
|
deactivate(context: ExtensionContext) {
|
|
102
105
|
context.eventBus.off("tool:activated", this.onToolActivated);
|
|
106
|
+
this.restoreSessionFeaturesToConfig();
|
|
103
107
|
this.dirtyTrackerDisposable?.dispose();
|
|
104
108
|
this.dirtyTrackerDisposable = undefined;
|
|
105
109
|
this.teardown();
|
|
@@ -107,8 +111,11 @@ export class FeatureTool implements Extension {
|
|
|
107
111
|
this.context = undefined;
|
|
108
112
|
}
|
|
109
113
|
|
|
110
|
-
private onToolActivated = (event: { id: string }) => {
|
|
114
|
+
private onToolActivated = (event: { id: string | null }) => {
|
|
111
115
|
this.isToolActive = event.id === this.id;
|
|
116
|
+
if (!this.isToolActive) {
|
|
117
|
+
this.restoreSessionFeaturesToConfig();
|
|
118
|
+
}
|
|
112
119
|
this.updateVisibility();
|
|
113
120
|
};
|
|
114
121
|
|
|
@@ -140,9 +147,9 @@ export class FeatureTool implements Extension {
|
|
|
140
147
|
name: "Feature",
|
|
141
148
|
interaction: "session",
|
|
142
149
|
commands: {
|
|
143
|
-
begin: "
|
|
150
|
+
begin: "beginFeatureSession",
|
|
144
151
|
commit: "completeFeatures",
|
|
145
|
-
rollback: "
|
|
152
|
+
rollback: "rollbackFeatureSession",
|
|
146
153
|
},
|
|
147
154
|
session: {
|
|
148
155
|
autoBegin: false,
|
|
@@ -151,6 +158,25 @@ export class FeatureTool implements Extension {
|
|
|
151
158
|
},
|
|
152
159
|
],
|
|
153
160
|
[ContributionPointIds.COMMANDS]: [
|
|
161
|
+
{
|
|
162
|
+
command: "beginFeatureSession",
|
|
163
|
+
title: "Begin Feature Session",
|
|
164
|
+
handler: async () => {
|
|
165
|
+
if (this.isFeatureSessionActive) {
|
|
166
|
+
return { ok: true };
|
|
167
|
+
}
|
|
168
|
+
const original = this.getCommittedFeatures();
|
|
169
|
+
this.sessionOriginalFeatures = this.cloneFeatures(original);
|
|
170
|
+
this.isFeatureSessionActive = true;
|
|
171
|
+
await this.refreshGeometry();
|
|
172
|
+
this.setWorkingFeatures(this.cloneFeatures(original));
|
|
173
|
+
this.hasWorkingChanges = false;
|
|
174
|
+
this.redraw();
|
|
175
|
+
this.emitWorkingChange();
|
|
176
|
+
this.updateCommittedFeatures([]);
|
|
177
|
+
return { ok: true };
|
|
178
|
+
},
|
|
179
|
+
},
|
|
154
180
|
{
|
|
155
181
|
command: "addFeature",
|
|
156
182
|
title: "Add Edge Feature",
|
|
@@ -203,21 +229,27 @@ export class FeatureTool implements Extension {
|
|
|
203
229
|
},
|
|
204
230
|
},
|
|
205
231
|
{
|
|
206
|
-
command: "
|
|
207
|
-
title: "
|
|
232
|
+
command: "rollbackFeatureSession",
|
|
233
|
+
title: "Rollback Feature Session",
|
|
208
234
|
handler: async () => {
|
|
209
|
-
const
|
|
210
|
-
this.
|
|
211
|
-
|
|
212
|
-
);
|
|
213
|
-
const next = (configService?.get("dieline.features", []) ||
|
|
214
|
-
[]) as ConstraintFeature[];
|
|
215
|
-
|
|
235
|
+
const original = this.cloneFeatures(
|
|
236
|
+
this.sessionOriginalFeatures || this.getCommittedFeatures(),
|
|
237
|
+
);
|
|
216
238
|
await this.refreshGeometry();
|
|
217
|
-
this.setWorkingFeatures(
|
|
239
|
+
this.setWorkingFeatures(original);
|
|
218
240
|
this.hasWorkingChanges = false;
|
|
219
241
|
this.redraw();
|
|
220
242
|
this.emitWorkingChange();
|
|
243
|
+
this.updateCommittedFeatures(original);
|
|
244
|
+
this.clearFeatureSessionState();
|
|
245
|
+
return { ok: true };
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
command: "resetWorkingFeatures",
|
|
250
|
+
title: "Reset Working Features",
|
|
251
|
+
handler: async () => {
|
|
252
|
+
await this.resetWorkingFeaturesFromSource();
|
|
221
253
|
return { ok: true };
|
|
222
254
|
},
|
|
223
255
|
},
|
|
@@ -243,6 +275,42 @@ export class FeatureTool implements Extension {
|
|
|
243
275
|
return JSON.parse(JSON.stringify(features || [])) as ConstraintFeature[];
|
|
244
276
|
}
|
|
245
277
|
|
|
278
|
+
private getConfigService(): ConfigurationService | undefined {
|
|
279
|
+
return this.context?.services.get<ConfigurationService>("ConfigurationService");
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private getCommittedFeatures(): ConstraintFeature[] {
|
|
283
|
+
const configService = this.getConfigService();
|
|
284
|
+
const committed = (configService?.get("dieline.features", []) ||
|
|
285
|
+
[]) as ConstraintFeature[];
|
|
286
|
+
return this.cloneFeatures(committed);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
private updateCommittedFeatures(next: ConstraintFeature[]) {
|
|
290
|
+
const configService = this.getConfigService();
|
|
291
|
+
if (!configService) return;
|
|
292
|
+
this.isUpdatingConfig = true;
|
|
293
|
+
try {
|
|
294
|
+
configService.update("dieline.features", next);
|
|
295
|
+
} finally {
|
|
296
|
+
this.isUpdatingConfig = false;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
private clearFeatureSessionState() {
|
|
301
|
+
this.isFeatureSessionActive = false;
|
|
302
|
+
this.sessionOriginalFeatures = null;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
private restoreSessionFeaturesToConfig() {
|
|
306
|
+
if (!this.isFeatureSessionActive) return;
|
|
307
|
+
const original = this.cloneFeatures(
|
|
308
|
+
this.sessionOriginalFeatures || this.getCommittedFeatures(),
|
|
309
|
+
);
|
|
310
|
+
this.updateCommittedFeatures(original);
|
|
311
|
+
this.clearFeatureSessionState();
|
|
312
|
+
}
|
|
313
|
+
|
|
246
314
|
private emitWorkingChange() {
|
|
247
315
|
this.context?.eventBus.emit("feature:working:change", {
|
|
248
316
|
features: this.cloneFeatures(this.workingFeatures),
|
|
@@ -261,6 +329,19 @@ export class FeatureTool implements Extension {
|
|
|
261
329
|
} catch (e) {}
|
|
262
330
|
}
|
|
263
331
|
|
|
332
|
+
private async resetWorkingFeaturesFromSource() {
|
|
333
|
+
const next = this.cloneFeatures(
|
|
334
|
+
this.isFeatureSessionActive && this.sessionOriginalFeatures
|
|
335
|
+
? this.sessionOriginalFeatures
|
|
336
|
+
: this.getCommittedFeatures(),
|
|
337
|
+
);
|
|
338
|
+
await this.refreshGeometry();
|
|
339
|
+
this.setWorkingFeatures(next);
|
|
340
|
+
this.hasWorkingChanges = false;
|
|
341
|
+
this.redraw();
|
|
342
|
+
this.emitWorkingChange();
|
|
343
|
+
}
|
|
344
|
+
|
|
264
345
|
private setWorkingFeatures(next: ConstraintFeature[]) {
|
|
265
346
|
this.workingFeatures = next;
|
|
266
347
|
}
|
|
@@ -335,13 +416,7 @@ export class FeatureTool implements Extension {
|
|
|
335
416
|
this.workingFeatures,
|
|
336
417
|
{ dielineWidth, dielineHeight },
|
|
337
418
|
(next) => {
|
|
338
|
-
this.
|
|
339
|
-
try {
|
|
340
|
-
configService.update("dieline.features", next);
|
|
341
|
-
} finally {
|
|
342
|
-
this.isUpdatingConfig = false;
|
|
343
|
-
}
|
|
344
|
-
|
|
419
|
+
this.updateCommittedFeatures(next as ConstraintFeature[]);
|
|
345
420
|
this.workingFeatures = this.cloneFeatures(next as any);
|
|
346
421
|
this.emitWorkingChange();
|
|
347
422
|
},
|
|
@@ -355,6 +430,7 @@ export class FeatureTool implements Extension {
|
|
|
355
430
|
}
|
|
356
431
|
|
|
357
432
|
this.hasWorkingChanges = false;
|
|
433
|
+
this.clearFeatureSessionState();
|
|
358
434
|
// Keep feature markers above dieline overlay after config-driven redraw.
|
|
359
435
|
this.redraw();
|
|
360
436
|
return { ok: true };
|
package/src/image.ts
CHANGED
|
@@ -148,10 +148,7 @@ export class ImageTool implements Extension {
|
|
|
148
148
|
context.eventBus.on("selection:created", this.onSelectionChanged);
|
|
149
149
|
context.eventBus.on("selection:updated", this.onSelectionChanged);
|
|
150
150
|
context.eventBus.on("selection:cleared", this.onSelectionCleared);
|
|
151
|
-
context.eventBus.on(
|
|
152
|
-
"scene:layout:change",
|
|
153
|
-
this.onSceneLayoutChanged,
|
|
154
|
-
);
|
|
151
|
+
context.eventBus.on("scene:layout:change", this.onSceneLayoutChanged);
|
|
155
152
|
|
|
156
153
|
const configService = context.services.get<ConfigurationService>(
|
|
157
154
|
"ConfigurationService",
|
|
@@ -198,10 +195,7 @@ export class ImageTool implements Extension {
|
|
|
198
195
|
context.eventBus.off("selection:created", this.onSelectionChanged);
|
|
199
196
|
context.eventBus.off("selection:updated", this.onSelectionChanged);
|
|
200
197
|
context.eventBus.off("selection:cleared", this.onSelectionCleared);
|
|
201
|
-
context.eventBus.off(
|
|
202
|
-
"scene:layout:change",
|
|
203
|
-
this.onSceneLayoutChanged,
|
|
204
|
-
);
|
|
198
|
+
context.eventBus.off("scene:layout:change", this.onSceneLayoutChanged);
|
|
205
199
|
this.dirtyTrackerDisposable?.dispose();
|
|
206
200
|
this.dirtyTrackerDisposable = undefined;
|
|
207
201
|
|
|
@@ -396,7 +390,7 @@ export class ImageTool implements Extension {
|
|
|
396
390
|
id: "image.frame.outerBackground",
|
|
397
391
|
type: "color",
|
|
398
392
|
label: "Image Frame Outer Background",
|
|
399
|
-
default: "
|
|
393
|
+
default: "#f5f5f5",
|
|
400
394
|
},
|
|
401
395
|
] as ConfigurationContribution[],
|
|
402
396
|
[ContributionPointIds.COMMANDS]: [
|
|
@@ -439,6 +433,7 @@ export class ImageTool implements Extension {
|
|
|
439
433
|
this.workingItems = this.cloneItems(this.items);
|
|
440
434
|
this.hasWorkingChanges = false;
|
|
441
435
|
this.updateImages();
|
|
436
|
+
this.emitWorkingChange();
|
|
442
437
|
},
|
|
443
438
|
},
|
|
444
439
|
{
|
|
@@ -578,6 +573,13 @@ export class ImageTool implements Extension {
|
|
|
578
573
|
return this.normalizeItems((items || []).map((i) => ({ ...i })));
|
|
579
574
|
}
|
|
580
575
|
|
|
576
|
+
private emitWorkingChange(changedId: string | null = null) {
|
|
577
|
+
this.context?.eventBus.emit("image:working:change", {
|
|
578
|
+
changedId,
|
|
579
|
+
items: this.cloneItems(this.workingItems),
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
|
|
581
583
|
private generateId(): string {
|
|
582
584
|
return Math.random().toString(36).substring(2, 9);
|
|
583
585
|
}
|
|
@@ -670,6 +672,7 @@ export class ImageTool implements Extension {
|
|
|
670
672
|
if (this.workingItems.some((existing) => existing.id === item.id)) return;
|
|
671
673
|
this.workingItems = this.cloneItems([...this.workingItems, item]);
|
|
672
674
|
this.updateImages();
|
|
675
|
+
this.emitWorkingChange(item.id);
|
|
673
676
|
}
|
|
674
677
|
|
|
675
678
|
private async updateImage(
|
|
@@ -893,11 +896,7 @@ export class ImageTool implements Extension {
|
|
|
893
896
|
"image.frame.innerBackground",
|
|
894
897
|
"rgba(0,0,0,0)",
|
|
895
898
|
) || "rgba(0,0,0,0)",
|
|
896
|
-
outerBackground:
|
|
897
|
-
this.getConfig<string>(
|
|
898
|
-
"image.frame.outerBackground",
|
|
899
|
-
"rgba(0,0,0,0.18)",
|
|
900
|
-
) || "rgba(0,0,0,0.18)",
|
|
899
|
+
outerBackground: "#f5f5f5",
|
|
901
900
|
};
|
|
902
901
|
}
|
|
903
902
|
|
|
@@ -1074,10 +1073,22 @@ export class ImageTool implements Extension {
|
|
|
1074
1073
|
const canvasH = this.canvasService.canvas.height || 0;
|
|
1075
1074
|
const visual = this.getFrameVisualConfig();
|
|
1076
1075
|
|
|
1077
|
-
const
|
|
1078
|
-
const
|
|
1079
|
-
const
|
|
1080
|
-
|
|
1076
|
+
const frameLeft = Math.max(0, Math.min(canvasW, frame.left));
|
|
1077
|
+
const frameTop = Math.max(0, Math.min(canvasH, frame.top));
|
|
1078
|
+
const frameRight = Math.max(
|
|
1079
|
+
frameLeft,
|
|
1080
|
+
Math.min(canvasW, frame.left + frame.width),
|
|
1081
|
+
);
|
|
1082
|
+
const frameBottom = Math.max(
|
|
1083
|
+
frameTop,
|
|
1084
|
+
Math.min(canvasH, frame.top + frame.height),
|
|
1085
|
+
);
|
|
1086
|
+
const visibleFrameH = Math.max(0, frameBottom - frameTop);
|
|
1087
|
+
|
|
1088
|
+
const topH = frameTop;
|
|
1089
|
+
const bottomH = Math.max(0, canvasH - frameBottom);
|
|
1090
|
+
const leftW = frameLeft;
|
|
1091
|
+
const rightW = Math.max(0, canvasW - frameRight);
|
|
1081
1092
|
|
|
1082
1093
|
const mask: RenderObjectSpec[] = [
|
|
1083
1094
|
{
|
|
@@ -1102,7 +1113,7 @@ export class ImageTool implements Extension {
|
|
|
1102
1113
|
data: { id: "image.cropMask.bottom", zIndex: 2 },
|
|
1103
1114
|
props: {
|
|
1104
1115
|
left: canvasW / 2,
|
|
1105
|
-
top:
|
|
1116
|
+
top: frameBottom + bottomH / 2,
|
|
1106
1117
|
width: canvasW,
|
|
1107
1118
|
height: bottomH,
|
|
1108
1119
|
originX: "center",
|
|
@@ -1118,9 +1129,9 @@ export class ImageTool implements Extension {
|
|
|
1118
1129
|
data: { id: "image.cropMask.left", zIndex: 3 },
|
|
1119
1130
|
props: {
|
|
1120
1131
|
left: leftW / 2,
|
|
1121
|
-
top:
|
|
1132
|
+
top: frameTop + visibleFrameH / 2,
|
|
1122
1133
|
width: leftW,
|
|
1123
|
-
height:
|
|
1134
|
+
height: visibleFrameH,
|
|
1124
1135
|
originX: "center",
|
|
1125
1136
|
originY: "center",
|
|
1126
1137
|
fill: visual.outerBackground,
|
|
@@ -1133,10 +1144,10 @@ export class ImageTool implements Extension {
|
|
|
1133
1144
|
type: "rect",
|
|
1134
1145
|
data: { id: "image.cropMask.right", zIndex: 4 },
|
|
1135
1146
|
props: {
|
|
1136
|
-
left:
|
|
1137
|
-
top:
|
|
1147
|
+
left: frameRight + rightW / 2,
|
|
1148
|
+
top: frameTop + visibleFrameH / 2,
|
|
1138
1149
|
width: rightW,
|
|
1139
|
-
height:
|
|
1150
|
+
height: visibleFrameH,
|
|
1140
1151
|
originX: "center",
|
|
1141
1152
|
originY: "center",
|
|
1142
1153
|
fill: visual.outerBackground,
|
|
@@ -1275,6 +1286,7 @@ export class ImageTool implements Extension {
|
|
|
1275
1286
|
if (this.isToolActive) {
|
|
1276
1287
|
this.updateImages();
|
|
1277
1288
|
}
|
|
1289
|
+
this.emitWorkingChange(id);
|
|
1278
1290
|
}
|
|
1279
1291
|
|
|
1280
1292
|
private async updateImageInConfig(id: string, updates: Partial<ImageItem>) {
|
|
@@ -1371,6 +1383,7 @@ export class ImageTool implements Extension {
|
|
|
1371
1383
|
this.isImageSelectionActive = true;
|
|
1372
1384
|
this.focusedImageId = id;
|
|
1373
1385
|
this.updateImages();
|
|
1386
|
+
this.emitWorkingChange(id);
|
|
1374
1387
|
}
|
|
1375
1388
|
|
|
1376
1389
|
private focusImageSelection(id: string) {
|
|
@@ -1489,6 +1502,7 @@ export class ImageTool implements Extension {
|
|
|
1489
1502
|
this.hasWorkingChanges = false;
|
|
1490
1503
|
this.workingItems = this.cloneItems(next);
|
|
1491
1504
|
this.updateConfig(next);
|
|
1505
|
+
this.emitWorkingChange(focusId);
|
|
1492
1506
|
if (focusId) {
|
|
1493
1507
|
this.focusedImageId = focusId;
|
|
1494
1508
|
this.isImageSelectionActive = true;
|