@pooder/kit 4.0.0 → 4.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.
Files changed (44) hide show
  1. package/.test-dist/src/CanvasService.js +83 -0
  2. package/.test-dist/src/ViewportSystem.js +75 -0
  3. package/.test-dist/src/background.js +203 -0
  4. package/.test-dist/src/constraints.js +153 -0
  5. package/.test-dist/src/coordinate.js +74 -0
  6. package/.test-dist/src/dieline.js +758 -0
  7. package/.test-dist/src/feature.js +687 -0
  8. package/.test-dist/src/featureComplete.js +31 -0
  9. package/.test-dist/src/featureDraft.js +31 -0
  10. package/.test-dist/src/film.js +167 -0
  11. package/.test-dist/src/geometry.js +292 -0
  12. package/.test-dist/src/image.js +421 -0
  13. package/.test-dist/src/index.js +31 -0
  14. package/.test-dist/src/mirror.js +104 -0
  15. package/.test-dist/src/ruler.js +383 -0
  16. package/.test-dist/src/tracer.js +448 -0
  17. package/.test-dist/src/units.js +30 -0
  18. package/.test-dist/src/white-ink.js +310 -0
  19. package/.test-dist/tests/run.js +60 -0
  20. package/CHANGELOG.md +12 -0
  21. package/dist/index.d.mts +54 -5
  22. package/dist/index.d.ts +54 -5
  23. package/dist/index.js +584 -190
  24. package/dist/index.mjs +581 -189
  25. package/package.json +3 -2
  26. package/src/CanvasService.ts +7 -0
  27. package/src/ViewportSystem.ts +92 -0
  28. package/src/background.ts +230 -230
  29. package/src/constraints.ts +207 -0
  30. package/src/coordinate.ts +106 -106
  31. package/src/dieline.ts +194 -75
  32. package/src/feature.ts +239 -147
  33. package/src/featureComplete.ts +45 -0
  34. package/src/film.ts +194 -194
  35. package/src/geometry.ts +4 -0
  36. package/src/image.ts +512 -512
  37. package/src/index.ts +1 -0
  38. package/src/mirror.ts +128 -128
  39. package/src/ruler.ts +508 -500
  40. package/src/tracer.ts +570 -570
  41. package/src/units.ts +27 -0
  42. package/src/white-ink.ts +373 -373
  43. package/tests/run.ts +81 -0
  44. package/tsconfig.test.json +15 -0
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WhiteInkTool = void 0;
4
+ const core_1 = require("@pooder/core");
5
+ const fabric_1 = require("fabric");
6
+ class WhiteInkTool {
7
+ constructor(options) {
8
+ this.id = "pooder.kit.white-ink";
9
+ this.metadata = {
10
+ name: "WhiteInkTool",
11
+ };
12
+ this.customMask = "";
13
+ this.opacity = 1;
14
+ this.enableClip = false;
15
+ this._loadingUrl = null;
16
+ if (options) {
17
+ Object.assign(this, options);
18
+ }
19
+ }
20
+ activate(context) {
21
+ this.canvasService = context.services.get("CanvasService");
22
+ if (!this.canvasService) {
23
+ console.warn("CanvasService not found for WhiteInkTool");
24
+ return;
25
+ }
26
+ const configService = context.services.get("ConfigurationService");
27
+ if (configService) {
28
+ // Load initial config
29
+ this.customMask = configService.get("whiteInk.customMask", this.customMask);
30
+ this.opacity = configService.get("whiteInk.opacity", this.opacity);
31
+ this.enableClip = configService.get("whiteInk.enableClip", this.enableClip);
32
+ // Listen for changes
33
+ configService.onAnyChange((e) => {
34
+ if (e.key.startsWith("whiteInk.")) {
35
+ const prop = e.key.split(".")[1];
36
+ console.log(`[WhiteInkTool] Config change detected: ${e.key} -> ${e.value}`);
37
+ if (prop && prop in this) {
38
+ this[prop] = e.value;
39
+ this.updateWhiteInk();
40
+ }
41
+ }
42
+ });
43
+ }
44
+ this.setup();
45
+ this.updateWhiteInk();
46
+ }
47
+ deactivate(context) {
48
+ this.teardown();
49
+ this.canvasService = undefined;
50
+ }
51
+ contribute() {
52
+ return {
53
+ [core_1.ContributionPointIds.CONFIGURATIONS]: [
54
+ {
55
+ id: "whiteInk.customMask",
56
+ type: "string",
57
+ label: "Custom Mask URL",
58
+ default: "",
59
+ },
60
+ {
61
+ id: "whiteInk.opacity",
62
+ type: "number",
63
+ label: "Opacity",
64
+ min: 0,
65
+ max: 1,
66
+ step: 0.01,
67
+ default: 1,
68
+ },
69
+ {
70
+ id: "whiteInk.enableClip",
71
+ type: "boolean",
72
+ label: "Enable Clip",
73
+ default: false,
74
+ },
75
+ ],
76
+ [core_1.ContributionPointIds.COMMANDS]: [
77
+ {
78
+ command: "setWhiteInkImage",
79
+ title: "Set White Ink Image",
80
+ handler: (customMask, opacity, enableClip = true) => {
81
+ if (this.customMask === customMask &&
82
+ this.opacity === opacity &&
83
+ this.enableClip === enableClip)
84
+ return true;
85
+ this.customMask = customMask;
86
+ this.opacity = opacity;
87
+ this.enableClip = enableClip;
88
+ this.updateWhiteInk();
89
+ return true;
90
+ },
91
+ },
92
+ ],
93
+ };
94
+ }
95
+ setup() {
96
+ if (!this.canvasService)
97
+ return;
98
+ const canvas = this.canvasService.canvas;
99
+ let userLayer = this.canvasService.getLayer("user");
100
+ if (!userLayer) {
101
+ userLayer = this.canvasService.createLayer("user", {
102
+ width: canvas.width,
103
+ height: canvas.height,
104
+ left: 0,
105
+ top: 0,
106
+ originX: "left",
107
+ originY: "top",
108
+ selectable: false,
109
+ evented: true,
110
+ subTargetCheck: true,
111
+ interactive: true,
112
+ });
113
+ canvas.add(userLayer);
114
+ }
115
+ if (!this.syncHandler) {
116
+ this.syncHandler = (e) => {
117
+ const target = e.target;
118
+ if (target && target.data?.id === "user-image") {
119
+ this.syncWithUserImage();
120
+ }
121
+ };
122
+ canvas.on("object:moving", this.syncHandler);
123
+ canvas.on("object:scaling", this.syncHandler);
124
+ canvas.on("object:rotating", this.syncHandler);
125
+ canvas.on("object:modified", this.syncHandler);
126
+ }
127
+ }
128
+ teardown() {
129
+ if (!this.canvasService)
130
+ return;
131
+ const canvas = this.canvasService.canvas;
132
+ if (this.syncHandler) {
133
+ canvas.off("object:moving", this.syncHandler);
134
+ canvas.off("object:scaling", this.syncHandler);
135
+ canvas.off("object:rotating", this.syncHandler);
136
+ canvas.off("object:modified", this.syncHandler);
137
+ this.syncHandler = undefined;
138
+ }
139
+ const layer = this.canvasService.getLayer("user");
140
+ if (layer) {
141
+ const whiteInk = this.canvasService.getObject("white-ink", "user");
142
+ if (whiteInk) {
143
+ layer.remove(whiteInk);
144
+ }
145
+ }
146
+ const userImage = this.canvasService.getObject("user-image", "user");
147
+ if (userImage && userImage.clipPath) {
148
+ userImage.set({ clipPath: undefined });
149
+ }
150
+ this.canvasService.requestRenderAll();
151
+ }
152
+ updateWhiteInk() {
153
+ if (!this.canvasService)
154
+ return;
155
+ const { customMask, opacity, enableClip } = this;
156
+ const layer = this.canvasService.getLayer("user");
157
+ if (!layer) {
158
+ console.warn("[WhiteInkTool] User layer not found");
159
+ return;
160
+ }
161
+ const whiteInk = this.canvasService.getObject("white-ink", "user");
162
+ const userImage = this.canvasService.getObject("user-image", "user");
163
+ if (!customMask) {
164
+ if (whiteInk) {
165
+ layer.remove(whiteInk);
166
+ }
167
+ if (userImage && userImage.clipPath) {
168
+ userImage.set({ clipPath: undefined });
169
+ }
170
+ layer.dirty = true;
171
+ this.canvasService.requestRenderAll();
172
+ return;
173
+ }
174
+ // Check if we need to load/reload white ink backing
175
+ if (whiteInk) {
176
+ const currentSrc = whiteInk.getSrc?.() || whiteInk._element?.src;
177
+ if (currentSrc !== customMask) {
178
+ this.loadWhiteInk(layer, customMask, opacity, enableClip, whiteInk);
179
+ }
180
+ else {
181
+ if (whiteInk.opacity !== opacity) {
182
+ whiteInk.set({ opacity });
183
+ layer.dirty = true;
184
+ this.canvasService.requestRenderAll();
185
+ }
186
+ }
187
+ }
188
+ else {
189
+ this.loadWhiteInk(layer, customMask, opacity, enableClip);
190
+ }
191
+ // Handle Clip Path Toggle
192
+ if (userImage) {
193
+ if (enableClip) {
194
+ if (!userImage.clipPath) {
195
+ this.applyClipPath(customMask);
196
+ }
197
+ }
198
+ else {
199
+ if (userImage.clipPath) {
200
+ userImage.set({ clipPath: undefined });
201
+ layer.dirty = true;
202
+ this.canvasService.requestRenderAll();
203
+ }
204
+ }
205
+ }
206
+ }
207
+ loadWhiteInk(layer, url, opacity, enableClip, oldImage) {
208
+ if (!this.canvasService)
209
+ return;
210
+ if (this._loadingUrl === url)
211
+ return;
212
+ this._loadingUrl = url;
213
+ fabric_1.FabricImage.fromURL(url, { crossOrigin: "anonymous" })
214
+ .then((image) => {
215
+ if (this._loadingUrl !== url)
216
+ return;
217
+ this._loadingUrl = null;
218
+ if (oldImage) {
219
+ layer.remove(oldImage);
220
+ }
221
+ image.filters?.push(new fabric_1.filters.BlendColor({
222
+ color: "#FFFFFF",
223
+ mode: "add",
224
+ }));
225
+ image.applyFilters();
226
+ image.set({
227
+ opacity,
228
+ selectable: false,
229
+ evented: false,
230
+ data: {
231
+ id: "white-ink",
232
+ },
233
+ });
234
+ // Add to layer
235
+ layer.add(image);
236
+ // Ensure white-ink is behind user-image
237
+ const userImage = this.canvasService.getObject("user-image", "user");
238
+ if (userImage) {
239
+ // Re-adding moves it to the top of the stack
240
+ layer.remove(userImage);
241
+ layer.add(userImage);
242
+ }
243
+ // Apply clip path to user-image if enabled
244
+ if (enableClip) {
245
+ this.applyClipPath(url);
246
+ }
247
+ else if (userImage) {
248
+ userImage.set({ clipPath: undefined });
249
+ }
250
+ // Sync position immediately
251
+ this.syncWithUserImage();
252
+ layer.dirty = true;
253
+ this.canvasService.requestRenderAll();
254
+ })
255
+ .catch((err) => {
256
+ console.error("Failed to load white ink mask", url, err);
257
+ this._loadingUrl = null;
258
+ });
259
+ }
260
+ applyClipPath(url) {
261
+ if (!this.canvasService)
262
+ return;
263
+ const userImage = this.canvasService.getObject("user-image", "user");
264
+ if (!userImage)
265
+ return;
266
+ fabric_1.FabricImage.fromURL(url, { crossOrigin: "anonymous" })
267
+ .then((maskImage) => {
268
+ // Configure clipPath
269
+ maskImage.set({
270
+ originX: "center",
271
+ originY: "center",
272
+ left: 0,
273
+ top: 0,
274
+ // Scale to fit userImage if dimensions differ
275
+ scaleX: userImage.width / maskImage.width,
276
+ scaleY: userImage.height / maskImage.height,
277
+ });
278
+ userImage.set({ clipPath: maskImage });
279
+ const layer = this.canvasService.getLayer("user");
280
+ if (layer)
281
+ layer.dirty = true;
282
+ this.canvasService.requestRenderAll();
283
+ })
284
+ .catch((err) => {
285
+ console.error("Failed to load clip path", url, err);
286
+ });
287
+ }
288
+ syncWithUserImage() {
289
+ if (!this.canvasService)
290
+ return;
291
+ const userImage = this.canvasService.getObject("user-image", "user");
292
+ const whiteInk = this.canvasService.getObject("white-ink", "user");
293
+ if (userImage && whiteInk) {
294
+ whiteInk.set({
295
+ left: userImage.left,
296
+ top: userImage.top,
297
+ scaleX: userImage.scaleX,
298
+ scaleY: userImage.scaleY,
299
+ angle: userImage.angle,
300
+ skewX: userImage.skewX,
301
+ skewY: userImage.skewY,
302
+ flipX: userImage.flipX,
303
+ flipY: userImage.flipY,
304
+ originX: userImage.originX,
305
+ originY: userImage.originY,
306
+ });
307
+ }
308
+ }
309
+ }
310
+ exports.WhiteInkTool = WhiteInkTool;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const constraints_1 = require("../src/constraints");
4
+ const featureComplete_1 = require("../src/featureComplete");
5
+ function assert(condition, message) {
6
+ if (!condition)
7
+ throw new Error(message);
8
+ }
9
+ function closeTo(a, b, eps = 1e-6) {
10
+ return Math.abs(a - b) <= eps;
11
+ }
12
+ function testTangentBottom() {
13
+ const feature = {
14
+ id: "stand",
15
+ operation: "add",
16
+ shape: "rect",
17
+ x: 0.5,
18
+ y: 0.2,
19
+ width: 40,
20
+ height: 20,
21
+ constraints: { type: "tangent-bottom", params: { gap: 0 } },
22
+ };
23
+ const out = constraints_1.ConstraintRegistry.apply(feature.x, feature.y, feature, {
24
+ dielineWidth: 100,
25
+ dielineHeight: 100,
26
+ });
27
+ assert(closeTo(out.y, 1.1), `tangent-bottom y expected 1.1, got ${out.y}`);
28
+ assert(closeTo(out.x, 0.5), `tangent-bottom x expected 0.5, got ${out.x}`);
29
+ }
30
+ function testCompleteFeaturesStrict() {
31
+ const updates = [];
32
+ const illegal = {
33
+ id: "stand",
34
+ operation: "add",
35
+ shape: "rect",
36
+ x: 0.5,
37
+ y: 0.5,
38
+ width: 40,
39
+ height: 20,
40
+ constraints: { type: "tangent-bottom", params: { gap: 0 } },
41
+ };
42
+ const failed = (0, featureComplete_1.completeFeaturesStrict)([illegal], { dielineWidth: 100, dielineHeight: 100 }, (next) => updates.push({ key: "dieline.features", value: next }));
43
+ assert(failed.ok === false, "completeFeatures should fail for illegal features");
44
+ assert(updates.length === 0, "illegal draft should not update configuration");
45
+ const legal = {
46
+ ...illegal,
47
+ y: 1.1,
48
+ };
49
+ const ok = (0, featureComplete_1.completeFeaturesStrict)([legal], { dielineWidth: 100, dielineHeight: 100 }, (next) => updates.push({ key: "dieline.features", value: next }));
50
+ assert(ok.ok === true, "completeFeatures should succeed for legal features");
51
+ assert(updates.length === 1, "legal draft should update configuration once");
52
+ assert(updates[0].key === "dieline.features", "should update dieline.features");
53
+ assert(closeTo(updates[0].value[0].y, 1.1), "saved feature y should remain 1.1");
54
+ }
55
+ function main() {
56
+ testTangentBottom();
57
+ testCompleteFeaturesStrict();
58
+ console.log("ok");
59
+ }
60
+ main();
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @pooder/kit
2
2
 
3
+ ## 4.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - viewport system, constraints and features
8
+
9
+ ## 4.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Restriction strategy
14
+
3
15
  ## 4.0.0
4
16
 
5
17
  ### Major Changes
package/dist/index.d.mts CHANGED
@@ -23,7 +23,22 @@ declare class BackgroundTool implements Extension {
23
23
  private updateBackground;
24
24
  }
25
25
 
26
+ interface Point {
27
+ x: number;
28
+ y: number;
29
+ }
30
+ interface Size {
31
+ width: number;
32
+ height: number;
33
+ }
26
34
  type Unit = "px" | "mm" | "cm" | "in";
35
+ interface Layout {
36
+ scale: number;
37
+ offsetX: number;
38
+ offsetY: number;
39
+ width: number;
40
+ height: number;
41
+ }
27
42
 
28
43
  type FeatureOperation = "add" | "subtract";
29
44
  type FeatureShape = "rect" | "circle";
@@ -42,11 +57,16 @@ interface DielineFeature {
42
57
  color?: string;
43
58
  strokeDash?: number[];
44
59
  skipCut?: boolean;
60
+ constraints?: {
61
+ type: string;
62
+ params?: any;
63
+ };
45
64
  }
46
65
 
47
66
  interface DielineGeometry {
48
67
  shape: "rect" | "circle" | "ellipse" | "custom";
49
- unit: Unit;
68
+ unit: "mm";
69
+ displayUnit: Unit;
50
70
  x: number;
51
71
  y: number;
52
72
  width: number;
@@ -65,7 +85,7 @@ interface LineStyle {
65
85
  style: "solid" | "dashed" | "hidden";
66
86
  }
67
87
  interface DielineState {
68
- unit: Unit;
88
+ displayUnit: Unit;
69
89
  shape: "rect" | "circle" | "ellipse" | "custom";
70
90
  width: number;
71
91
  height: number;
@@ -132,7 +152,7 @@ declare class FeatureTool implements Extension {
132
152
  metadata: {
133
153
  name: string;
134
154
  };
135
- private features;
155
+ private workingFeatures;
136
156
  private canvasService?;
137
157
  private context?;
138
158
  private isUpdatingConfig;
@@ -151,6 +171,12 @@ declare class FeatureTool implements Extension {
151
171
  contribute(): {
152
172
  [ContributionPointIds.COMMANDS]: CommandContribution[];
153
173
  };
174
+ private cloneFeatures;
175
+ private emitWorkingChange;
176
+ private refreshGeometry;
177
+ private setWorkingFeatures;
178
+ private updateWorkingGroupPosition;
179
+ private completeFeatures;
154
180
  private addFeature;
155
181
  private addDoubleLayerHole;
156
182
  private getGeometryForFeature;
@@ -245,7 +271,7 @@ declare class RulerTool implements Extension {
245
271
  private fontSize;
246
272
  private dielineWidth;
247
273
  private dielineHeight;
248
- private dielineUnit;
274
+ private dielineDisplayUnit;
249
275
  private dielinePadding;
250
276
  private dielineOffset;
251
277
  private canvasService?;
@@ -293,8 +319,31 @@ declare class MirrorTool implements Extension {
293
319
  private applyMirror;
294
320
  }
295
321
 
322
+ declare function parseLengthToMm(input: number | string, defaultUnit: Unit): number;
323
+ declare function formatMm(valueMm: number, displayUnit: Unit, fractionDigits?: number): string;
324
+
325
+ declare class ViewportSystem {
326
+ private _containerSize;
327
+ private _physicalSize;
328
+ private _padding;
329
+ private _layout;
330
+ constructor(containerSize?: Size, physicalSize?: Size, padding?: number);
331
+ get layout(): Layout;
332
+ get scale(): number;
333
+ get offset(): Point;
334
+ updateContainer(width: number, height: number): void;
335
+ updatePhysical(width: number, height: number): void;
336
+ setPadding(padding: number): void;
337
+ private updateLayout;
338
+ toPixel(value: number): number;
339
+ toPhysical(value: number): number;
340
+ toPixelPoint(point: Point): Point;
341
+ toPhysicalPoint(point: Point): Point;
342
+ }
343
+
296
344
  declare class CanvasService implements Service {
297
345
  canvas: Canvas;
346
+ viewport: ViewportSystem;
298
347
  private eventBus?;
299
348
  constructor(el: HTMLCanvasElement | string | Canvas, options?: any);
300
349
  setEventBus(eventBus: EventBus): void;
@@ -316,4 +365,4 @@ declare class CanvasService implements Service {
316
365
  requestRenderAll(): void;
317
366
  }
318
367
 
319
- export { BackgroundTool, CanvasService, type DielineGeometry, type DielineState, DielineTool, FeatureTool, FilmTool, type ImageItem, ImageTool, type LineStyle, MirrorTool, RulerTool, WhiteInkTool };
368
+ export { BackgroundTool, CanvasService, type DielineGeometry, type DielineState, DielineTool, FeatureTool, FilmTool, type ImageItem, ImageTool, type LineStyle, MirrorTool, RulerTool, WhiteInkTool, formatMm, parseLengthToMm };
package/dist/index.d.ts CHANGED
@@ -23,7 +23,22 @@ declare class BackgroundTool implements Extension {
23
23
  private updateBackground;
24
24
  }
25
25
 
26
+ interface Point {
27
+ x: number;
28
+ y: number;
29
+ }
30
+ interface Size {
31
+ width: number;
32
+ height: number;
33
+ }
26
34
  type Unit = "px" | "mm" | "cm" | "in";
35
+ interface Layout {
36
+ scale: number;
37
+ offsetX: number;
38
+ offsetY: number;
39
+ width: number;
40
+ height: number;
41
+ }
27
42
 
28
43
  type FeatureOperation = "add" | "subtract";
29
44
  type FeatureShape = "rect" | "circle";
@@ -42,11 +57,16 @@ interface DielineFeature {
42
57
  color?: string;
43
58
  strokeDash?: number[];
44
59
  skipCut?: boolean;
60
+ constraints?: {
61
+ type: string;
62
+ params?: any;
63
+ };
45
64
  }
46
65
 
47
66
  interface DielineGeometry {
48
67
  shape: "rect" | "circle" | "ellipse" | "custom";
49
- unit: Unit;
68
+ unit: "mm";
69
+ displayUnit: Unit;
50
70
  x: number;
51
71
  y: number;
52
72
  width: number;
@@ -65,7 +85,7 @@ interface LineStyle {
65
85
  style: "solid" | "dashed" | "hidden";
66
86
  }
67
87
  interface DielineState {
68
- unit: Unit;
88
+ displayUnit: Unit;
69
89
  shape: "rect" | "circle" | "ellipse" | "custom";
70
90
  width: number;
71
91
  height: number;
@@ -132,7 +152,7 @@ declare class FeatureTool implements Extension {
132
152
  metadata: {
133
153
  name: string;
134
154
  };
135
- private features;
155
+ private workingFeatures;
136
156
  private canvasService?;
137
157
  private context?;
138
158
  private isUpdatingConfig;
@@ -151,6 +171,12 @@ declare class FeatureTool implements Extension {
151
171
  contribute(): {
152
172
  [ContributionPointIds.COMMANDS]: CommandContribution[];
153
173
  };
174
+ private cloneFeatures;
175
+ private emitWorkingChange;
176
+ private refreshGeometry;
177
+ private setWorkingFeatures;
178
+ private updateWorkingGroupPosition;
179
+ private completeFeatures;
154
180
  private addFeature;
155
181
  private addDoubleLayerHole;
156
182
  private getGeometryForFeature;
@@ -245,7 +271,7 @@ declare class RulerTool implements Extension {
245
271
  private fontSize;
246
272
  private dielineWidth;
247
273
  private dielineHeight;
248
- private dielineUnit;
274
+ private dielineDisplayUnit;
249
275
  private dielinePadding;
250
276
  private dielineOffset;
251
277
  private canvasService?;
@@ -293,8 +319,31 @@ declare class MirrorTool implements Extension {
293
319
  private applyMirror;
294
320
  }
295
321
 
322
+ declare function parseLengthToMm(input: number | string, defaultUnit: Unit): number;
323
+ declare function formatMm(valueMm: number, displayUnit: Unit, fractionDigits?: number): string;
324
+
325
+ declare class ViewportSystem {
326
+ private _containerSize;
327
+ private _physicalSize;
328
+ private _padding;
329
+ private _layout;
330
+ constructor(containerSize?: Size, physicalSize?: Size, padding?: number);
331
+ get layout(): Layout;
332
+ get scale(): number;
333
+ get offset(): Point;
334
+ updateContainer(width: number, height: number): void;
335
+ updatePhysical(width: number, height: number): void;
336
+ setPadding(padding: number): void;
337
+ private updateLayout;
338
+ toPixel(value: number): number;
339
+ toPhysical(value: number): number;
340
+ toPixelPoint(point: Point): Point;
341
+ toPhysicalPoint(point: Point): Point;
342
+ }
343
+
296
344
  declare class CanvasService implements Service {
297
345
  canvas: Canvas;
346
+ viewport: ViewportSystem;
298
347
  private eventBus?;
299
348
  constructor(el: HTMLCanvasElement | string | Canvas, options?: any);
300
349
  setEventBus(eventBus: EventBus): void;
@@ -316,4 +365,4 @@ declare class CanvasService implements Service {
316
365
  requestRenderAll(): void;
317
366
  }
318
367
 
319
- export { BackgroundTool, CanvasService, type DielineGeometry, type DielineState, DielineTool, FeatureTool, FilmTool, type ImageItem, ImageTool, type LineStyle, MirrorTool, RulerTool, WhiteInkTool };
368
+ export { BackgroundTool, CanvasService, type DielineGeometry, type DielineState, DielineTool, FeatureTool, FilmTool, type ImageItem, ImageTool, type LineStyle, MirrorTool, RulerTool, WhiteInkTool, formatMm, parseLengthToMm };