@pooder/kit 6.1.1 → 6.2.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 +177 -5
- package/.test-dist/src/extensions/constraintUtils.js +44 -0
- package/.test-dist/src/extensions/dieline/DielineTool.js +30 -400
- package/.test-dist/src/extensions/dieline/featureResolution.js +29 -0
- package/.test-dist/src/extensions/dieline/model.js +83 -0
- package/.test-dist/src/extensions/dieline/renderBuilder.js +211 -0
- package/.test-dist/src/extensions/feature/FeatureTool.js +136 -42
- package/.test-dist/src/extensions/image/ImageTool.js +281 -25
- package/.test-dist/src/shared/constants/layers.js +3 -1
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +58 -6
- package/dist/index.d.ts +58 -6
- package/dist/index.js +989 -518
- package/dist/index.mjs +1014 -545
- package/package.json +1 -1
- package/src/extensions/background/BackgroundTool.ts +264 -4
- package/src/extensions/dieline/DielineTool.ts +38 -539
- package/src/extensions/dieline/model.ts +165 -1
- package/src/extensions/dieline/renderBuilder.ts +275 -0
- package/src/extensions/feature/FeatureTool.ts +167 -44
- package/src/extensions/image/ImageTool.ts +385 -29
- package/src/shared/constants/layers.ts +2 -0
|
@@ -22,7 +22,7 @@ const DEFAULT_BACKGROUND_CONFIG = {
|
|
|
22
22
|
order: 0,
|
|
23
23
|
enabled: true,
|
|
24
24
|
exportable: false,
|
|
25
|
-
color: "#
|
|
25
|
+
color: "#eee",
|
|
26
26
|
},
|
|
27
27
|
],
|
|
28
28
|
};
|
|
@@ -45,6 +45,22 @@ function normalizeFitMode(value, fallback) {
|
|
|
45
45
|
}
|
|
46
46
|
return fallback;
|
|
47
47
|
}
|
|
48
|
+
function normalizeRegionUnit(value, fallback) {
|
|
49
|
+
if (value === "px" || value === "normalized") {
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
return fallback;
|
|
53
|
+
}
|
|
54
|
+
function normalizeRegistrationFrame(value, fallback) {
|
|
55
|
+
if (value === "trim" ||
|
|
56
|
+
value === "cut" ||
|
|
57
|
+
value === "bleed" ||
|
|
58
|
+
value === "focus" ||
|
|
59
|
+
value === "viewport") {
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
return fallback;
|
|
63
|
+
}
|
|
48
64
|
function normalizeAnchor(value, fallback) {
|
|
49
65
|
if (typeof value !== "string")
|
|
50
66
|
return fallback;
|
|
@@ -57,6 +73,64 @@ function normalizeOrder(value, fallback) {
|
|
|
57
73
|
return fallback;
|
|
58
74
|
return numeric;
|
|
59
75
|
}
|
|
76
|
+
function normalizeRegionValue(value, fallback) {
|
|
77
|
+
const numeric = Number(value);
|
|
78
|
+
return Number.isFinite(numeric) ? numeric : fallback;
|
|
79
|
+
}
|
|
80
|
+
function normalizeRegistrationRegion(raw, fallback) {
|
|
81
|
+
if (!raw || typeof raw !== "object") {
|
|
82
|
+
return fallback ? { ...fallback } : undefined;
|
|
83
|
+
}
|
|
84
|
+
const input = raw;
|
|
85
|
+
const base = fallback || {
|
|
86
|
+
left: 0,
|
|
87
|
+
top: 0,
|
|
88
|
+
width: 1,
|
|
89
|
+
height: 1,
|
|
90
|
+
unit: "normalized",
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
left: normalizeRegionValue(input.left, base.left),
|
|
94
|
+
top: normalizeRegionValue(input.top, base.top),
|
|
95
|
+
width: normalizeRegionValue(input.width, base.width),
|
|
96
|
+
height: normalizeRegionValue(input.height, base.height),
|
|
97
|
+
unit: normalizeRegionUnit(input.unit, base.unit),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function normalizeRegistration(raw, fallback) {
|
|
101
|
+
if (!raw || typeof raw !== "object") {
|
|
102
|
+
return fallback
|
|
103
|
+
? {
|
|
104
|
+
sourceRegion: fallback.sourceRegion
|
|
105
|
+
? { ...fallback.sourceRegion }
|
|
106
|
+
: undefined,
|
|
107
|
+
targetFrame: fallback.targetFrame,
|
|
108
|
+
fit: fallback.fit,
|
|
109
|
+
}
|
|
110
|
+
: undefined;
|
|
111
|
+
}
|
|
112
|
+
const input = raw;
|
|
113
|
+
const normalized = {
|
|
114
|
+
sourceRegion: normalizeRegistrationRegion(input.sourceRegion, fallback?.sourceRegion),
|
|
115
|
+
targetFrame: normalizeRegistrationFrame(input.targetFrame, fallback?.targetFrame || "trim"),
|
|
116
|
+
fit: normalizeFitMode(input.fit, fallback?.fit || "stretch"),
|
|
117
|
+
};
|
|
118
|
+
if (!normalized.sourceRegion) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
return normalized;
|
|
122
|
+
}
|
|
123
|
+
function cloneRegistration(registration) {
|
|
124
|
+
if (!registration)
|
|
125
|
+
return undefined;
|
|
126
|
+
return {
|
|
127
|
+
sourceRegion: registration.sourceRegion
|
|
128
|
+
? { ...registration.sourceRegion }
|
|
129
|
+
: undefined,
|
|
130
|
+
targetFrame: registration.targetFrame,
|
|
131
|
+
fit: registration.fit,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
60
134
|
function normalizeLayer(raw, index, fallback) {
|
|
61
135
|
const fallbackLayer = fallback || {
|
|
62
136
|
id: `layer-${index + 1}`,
|
|
@@ -70,7 +144,10 @@ function normalizeLayer(raw, index, fallback) {
|
|
|
70
144
|
src: "",
|
|
71
145
|
};
|
|
72
146
|
if (!raw || typeof raw !== "object") {
|
|
73
|
-
return {
|
|
147
|
+
return {
|
|
148
|
+
...fallbackLayer,
|
|
149
|
+
registration: cloneRegistration(fallbackLayer.registration),
|
|
150
|
+
};
|
|
74
151
|
}
|
|
75
152
|
const input = raw;
|
|
76
153
|
const kind = normalizeLayerKind(input.kind, fallbackLayer.kind);
|
|
@@ -103,6 +180,9 @@ function normalizeLayer(raw, index, fallback) {
|
|
|
103
180
|
? fallbackLayer.src
|
|
104
181
|
: ""
|
|
105
182
|
: undefined,
|
|
183
|
+
registration: kind === "image"
|
|
184
|
+
? normalizeRegistration(input.registration, fallbackLayer.registration)
|
|
185
|
+
: undefined,
|
|
106
186
|
};
|
|
107
187
|
}
|
|
108
188
|
function normalizeConfig(raw) {
|
|
@@ -136,7 +216,10 @@ function normalizeConfig(raw) {
|
|
|
136
216
|
function cloneConfig(config) {
|
|
137
217
|
return {
|
|
138
218
|
version: config.version,
|
|
139
|
-
layers: (config.layers || []).map((layer) => ({
|
|
219
|
+
layers: (config.layers || []).map((layer) => ({
|
|
220
|
+
...layer,
|
|
221
|
+
registration: cloneRegistration(layer.registration),
|
|
222
|
+
})),
|
|
140
223
|
};
|
|
141
224
|
}
|
|
142
225
|
function mergeConfig(base, patch) {
|
|
@@ -353,6 +436,41 @@ class BackgroundTool {
|
|
|
353
436
|
height: layout.trimRect.height,
|
|
354
437
|
};
|
|
355
438
|
}
|
|
439
|
+
resolveTargetFrameRect(frame) {
|
|
440
|
+
if (frame === "viewport") {
|
|
441
|
+
return this.getViewportRect();
|
|
442
|
+
}
|
|
443
|
+
const layout = this.resolveSceneLayout();
|
|
444
|
+
if (!layout) {
|
|
445
|
+
return frame === "focus" ? this.getViewportRect() : null;
|
|
446
|
+
}
|
|
447
|
+
switch (frame) {
|
|
448
|
+
case "trim":
|
|
449
|
+
case "focus":
|
|
450
|
+
return {
|
|
451
|
+
left: layout.trimRect.left,
|
|
452
|
+
top: layout.trimRect.top,
|
|
453
|
+
width: layout.trimRect.width,
|
|
454
|
+
height: layout.trimRect.height,
|
|
455
|
+
};
|
|
456
|
+
case "cut":
|
|
457
|
+
return {
|
|
458
|
+
left: layout.cutRect.left,
|
|
459
|
+
top: layout.cutRect.top,
|
|
460
|
+
width: layout.cutRect.width,
|
|
461
|
+
height: layout.cutRect.height,
|
|
462
|
+
};
|
|
463
|
+
case "bleed":
|
|
464
|
+
return {
|
|
465
|
+
left: layout.bleedRect.left,
|
|
466
|
+
top: layout.bleedRect.top,
|
|
467
|
+
width: layout.bleedRect.width,
|
|
468
|
+
height: layout.bleedRect.height,
|
|
469
|
+
};
|
|
470
|
+
default:
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
356
474
|
resolveAnchorRect(anchor) {
|
|
357
475
|
if (anchor === "focus") {
|
|
358
476
|
return this.resolveFocusRect() || this.getViewportRect();
|
|
@@ -387,6 +505,60 @@ class BackgroundTool {
|
|
|
387
505
|
scaleY: scale,
|
|
388
506
|
};
|
|
389
507
|
}
|
|
508
|
+
resolveRegistrationRegion(region, sourceSize) {
|
|
509
|
+
const sourceWidth = Math.max(1, Number(sourceSize.width || 0));
|
|
510
|
+
const sourceHeight = Math.max(1, Number(sourceSize.height || 0));
|
|
511
|
+
const width = region.unit === "normalized" ? region.width * sourceWidth : region.width;
|
|
512
|
+
const height = region.unit === "normalized"
|
|
513
|
+
? region.height * sourceHeight
|
|
514
|
+
: region.height;
|
|
515
|
+
const left = region.unit === "normalized" ? region.left * sourceWidth : region.left;
|
|
516
|
+
const top = region.unit === "normalized" ? region.top * sourceHeight : region.top;
|
|
517
|
+
if (!Number.isFinite(left) ||
|
|
518
|
+
!Number.isFinite(top) ||
|
|
519
|
+
!Number.isFinite(width) ||
|
|
520
|
+
!Number.isFinite(height) ||
|
|
521
|
+
width <= 0 ||
|
|
522
|
+
height <= 0) {
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
return { left, top, width, height };
|
|
526
|
+
}
|
|
527
|
+
resolveRegistrationPlacement(layer, sourceSize) {
|
|
528
|
+
const registration = layer.registration;
|
|
529
|
+
if (!registration?.sourceRegion)
|
|
530
|
+
return null;
|
|
531
|
+
const targetRect = this.resolveTargetFrameRect(registration.targetFrame || "trim");
|
|
532
|
+
if (!targetRect)
|
|
533
|
+
return null;
|
|
534
|
+
const sourceRegion = this.resolveRegistrationRegion(registration.sourceRegion, sourceSize);
|
|
535
|
+
if (!sourceRegion)
|
|
536
|
+
return null;
|
|
537
|
+
const fit = registration.fit || "stretch";
|
|
538
|
+
const baseScaleX = targetRect.width / sourceRegion.width;
|
|
539
|
+
const baseScaleY = targetRect.height / sourceRegion.height;
|
|
540
|
+
if (fit === "stretch") {
|
|
541
|
+
return {
|
|
542
|
+
left: targetRect.left - sourceRegion.left * baseScaleX,
|
|
543
|
+
top: targetRect.top - sourceRegion.top * baseScaleY,
|
|
544
|
+
scaleX: baseScaleX,
|
|
545
|
+
scaleY: baseScaleY,
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
const uniformScale = fit === "contain"
|
|
549
|
+
? Math.min(baseScaleX, baseScaleY)
|
|
550
|
+
: Math.max(baseScaleX, baseScaleY);
|
|
551
|
+
const alignedWidth = sourceRegion.width * uniformScale;
|
|
552
|
+
const alignedHeight = sourceRegion.height * uniformScale;
|
|
553
|
+
const offsetLeft = targetRect.left + (targetRect.width - alignedWidth) / 2;
|
|
554
|
+
const offsetTop = targetRect.top + (targetRect.height - alignedHeight) / 2;
|
|
555
|
+
return {
|
|
556
|
+
left: offsetLeft - sourceRegion.left * uniformScale,
|
|
557
|
+
top: offsetTop - sourceRegion.top * uniformScale,
|
|
558
|
+
scaleX: uniformScale,
|
|
559
|
+
scaleY: uniformScale,
|
|
560
|
+
};
|
|
561
|
+
}
|
|
390
562
|
buildColorLayerSpec(layer) {
|
|
391
563
|
const rect = this.resolveAnchorRect(layer.anchor);
|
|
392
564
|
return {
|
|
@@ -422,8 +594,8 @@ class BackgroundTool {
|
|
|
422
594
|
const sourceSize = this.sourceSizeCache.getSourceSize(src);
|
|
423
595
|
if (!sourceSize)
|
|
424
596
|
return [];
|
|
425
|
-
const
|
|
426
|
-
|
|
597
|
+
const placement = this.resolveRegistrationPlacement(layer, sourceSize) ||
|
|
598
|
+
this.resolveImagePlacement(this.resolveAnchorRect(layer.anchor), sourceSize, layer.fit);
|
|
427
599
|
return [
|
|
428
600
|
{
|
|
429
601
|
id: `background.layer.${layer.id}.image`,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPathConstraintProbePoint = getPathConstraintProbePoint;
|
|
4
|
+
function getPathConstraintProbePoint(args) {
|
|
5
|
+
const { x, y, geometry, feature } = args;
|
|
6
|
+
const minX = geometry.x - geometry.width / 2;
|
|
7
|
+
const minY = geometry.y - geometry.height / 2;
|
|
8
|
+
const maxX = minX + geometry.width;
|
|
9
|
+
const maxY = minY + geometry.height;
|
|
10
|
+
const absX = minX + x * geometry.width;
|
|
11
|
+
const absY = minY + y * geometry.height;
|
|
12
|
+
const minEdgeDistance = Math.min(x, 1 - x, y, 1 - y);
|
|
13
|
+
const isAnchoredToBoundary = x <= 0 || x >= 1 || y <= 0 || y >= 1 || minEdgeDistance <= 1e-6;
|
|
14
|
+
if (!isAnchoredToBoundary) {
|
|
15
|
+
return { x: absX, y: absY };
|
|
16
|
+
}
|
|
17
|
+
const clampedX = Math.max(0, Math.min(1, x));
|
|
18
|
+
const clampedY = Math.max(0, Math.min(1, y));
|
|
19
|
+
const halfFeatureExtent = feature?.shape === "circle"
|
|
20
|
+
? Math.max(0, feature?.radius || 0)
|
|
21
|
+
: Math.max(0, (feature?.width || 0) / 2, (feature?.height || 0) / 2);
|
|
22
|
+
const outsidePad = Math.max(1e-3, halfFeatureExtent, Math.min(geometry.width, geometry.height) * 0.02);
|
|
23
|
+
let probeX = minX + clampedX * geometry.width;
|
|
24
|
+
let probeY = minY + clampedY * geometry.height;
|
|
25
|
+
const distances = [
|
|
26
|
+
{ edge: "top", dist: Math.abs(y) },
|
|
27
|
+
{ edge: "bottom", dist: Math.abs(1 - y) },
|
|
28
|
+
{ edge: "left", dist: Math.abs(x) },
|
|
29
|
+
{ edge: "right", dist: Math.abs(1 - x) },
|
|
30
|
+
];
|
|
31
|
+
const nearestDist = Math.min(...distances.map((entry) => entry.dist));
|
|
32
|
+
const activeEdges = distances
|
|
33
|
+
.filter((entry) => Math.abs(entry.dist - nearestDist) <= 1e-6)
|
|
34
|
+
.map((entry) => entry.edge);
|
|
35
|
+
if (activeEdges.includes("top"))
|
|
36
|
+
probeY = minY - outsidePad;
|
|
37
|
+
if (activeEdges.includes("bottom"))
|
|
38
|
+
probeY = maxY + outsidePad;
|
|
39
|
+
if (activeEdges.includes("left"))
|
|
40
|
+
probeX = minX - outsidePad;
|
|
41
|
+
if (activeEdges.includes("right"))
|
|
42
|
+
probeX = maxX + outsidePad;
|
|
43
|
+
return { x: probeX, y: probeY };
|
|
44
|
+
}
|