@pooder/kit 6.1.2 → 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.
@@ -17,6 +17,7 @@ const IMAGE_DEFAULT_CONTROL_CAPABILITIES = [
17
17
  "rotate",
18
18
  "scale",
19
19
  ];
20
+ const IMAGE_MOVE_SNAP_THRESHOLD_PX = 6;
20
21
  const IMAGE_CONTROL_DESCRIPTORS = [
21
22
  {
22
23
  key: "tl",
@@ -59,12 +60,17 @@ class ImageTool {
59
60
  this.renderSeq = 0;
60
61
  this.imageSpecs = [];
61
62
  this.overlaySpecs = [];
63
+ this.activeSnapX = null;
64
+ this.activeSnapY = null;
65
+ this.movingImageId = null;
66
+ this.hasRenderedSnapGuides = false;
62
67
  this.subscriptions = new subscriptions_1.SubscriptionBag();
63
68
  this.imageControlsByCapabilityKey = new Map();
64
69
  this.onToolActivated = (event) => {
65
70
  const before = this.isToolActive;
66
71
  this.syncToolActiveFromWorkbench(event.id);
67
72
  if (!this.isToolActive) {
73
+ this.endMoveSnapInteraction();
68
74
  this.setImageFocus(null, {
69
75
  syncCanvasSelection: true,
70
76
  skipRender: true,
@@ -110,6 +116,7 @@ class ImageTool {
110
116
  this.updateImages();
111
117
  };
112
118
  this.onSelectionCleared = () => {
119
+ this.endMoveSnapInteraction();
113
120
  this.setImageFocus(null, {
114
121
  syncCanvasSelection: false,
115
122
  skipRender: true,
@@ -118,6 +125,7 @@ class ImageTool {
118
125
  this.updateImages();
119
126
  };
120
127
  this.onSceneLayoutChanged = () => {
128
+ this.canvasService?.requestRenderAll();
121
129
  this.updateImages();
122
130
  };
123
131
  this.onSceneGeometryChanged = () => {
@@ -131,7 +139,11 @@ class ImageTool {
131
139
  const layerId = target?.data?.layerId;
132
140
  if (typeof id !== "string" || layerId !== layers_1.IMAGE_OBJECT_LAYER_ID)
133
141
  return;
142
+ if (this.movingImageId === id) {
143
+ this.applyMoveSnapToTarget(target);
144
+ }
134
145
  const frame = this.getFrameRect();
146
+ this.endMoveSnapInteraction();
135
147
  if (!frame.width || !frame.height)
136
148
  return;
137
149
  const center = target.getCenterPoint
@@ -195,6 +207,7 @@ class ImageTool {
195
207
  },
196
208
  ],
197
209
  }), { priority: 300 });
210
+ this.bindCanvasInteractionHandlers();
198
211
  this.subscriptions.on(context.eventBus, "tool:activated", this.onToolActivated);
199
212
  this.subscriptions.on(context.eventBus, "object:modified", this.onObjectModified);
200
213
  this.subscriptions.on(context.eventBus, "selection:created", this.onSelectionChanged);
@@ -238,6 +251,8 @@ class ImageTool {
238
251
  this.imageSpecs = [];
239
252
  this.overlaySpecs = [];
240
253
  this.imageControlsByCapabilityKey.clear();
254
+ this.endMoveSnapInteraction();
255
+ this.unbindCanvasInteractionHandlers();
241
256
  this.clearRenderedImages();
242
257
  this.renderProducerDisposable?.dispose();
243
258
  this.renderProducerDisposable = undefined;
@@ -247,6 +262,271 @@ class ImageTool {
247
262
  }
248
263
  this.context = undefined;
249
264
  }
265
+ bindCanvasInteractionHandlers() {
266
+ if (!this.canvasService || this.canvasObjectMovingHandler)
267
+ return;
268
+ this.canvasMouseUpHandler = (e) => {
269
+ const target = this.getActiveImageTarget(e?.target);
270
+ if (target &&
271
+ typeof target?.data?.id === "string" &&
272
+ target.data.id === this.movingImageId) {
273
+ this.applyMoveSnapToTarget(target);
274
+ }
275
+ this.endMoveSnapInteraction();
276
+ };
277
+ this.canvasObjectMovingHandler = (e) => {
278
+ this.handleCanvasObjectMoving(e);
279
+ };
280
+ this.canvasBeforeRenderHandler = () => {
281
+ this.handleCanvasBeforeRender();
282
+ };
283
+ this.canvasAfterRenderHandler = () => {
284
+ this.handleCanvasAfterRender();
285
+ };
286
+ this.canvasService.canvas.on("mouse:up", this.canvasMouseUpHandler);
287
+ this.canvasService.canvas.on("object:moving", this.canvasObjectMovingHandler);
288
+ this.canvasService.canvas.on("before:render", this.canvasBeforeRenderHandler);
289
+ this.canvasService.canvas.on("after:render", this.canvasAfterRenderHandler);
290
+ }
291
+ unbindCanvasInteractionHandlers() {
292
+ if (!this.canvasService)
293
+ return;
294
+ if (this.canvasMouseUpHandler) {
295
+ this.canvasService.canvas.off("mouse:up", this.canvasMouseUpHandler);
296
+ }
297
+ if (this.canvasObjectMovingHandler) {
298
+ this.canvasService.canvas.off("object:moving", this.canvasObjectMovingHandler);
299
+ }
300
+ if (this.canvasBeforeRenderHandler) {
301
+ this.canvasService.canvas.off("before:render", this.canvasBeforeRenderHandler);
302
+ }
303
+ if (this.canvasAfterRenderHandler) {
304
+ this.canvasService.canvas.off("after:render", this.canvasAfterRenderHandler);
305
+ }
306
+ this.canvasMouseUpHandler = undefined;
307
+ this.canvasObjectMovingHandler = undefined;
308
+ this.canvasBeforeRenderHandler = undefined;
309
+ this.canvasAfterRenderHandler = undefined;
310
+ }
311
+ getActiveImageTarget(target) {
312
+ if (!this.isToolActive)
313
+ return null;
314
+ if (!target)
315
+ return null;
316
+ if (target?.data?.layerId !== layers_1.IMAGE_OBJECT_LAYER_ID)
317
+ return null;
318
+ if (typeof target?.data?.id !== "string")
319
+ return null;
320
+ return target;
321
+ }
322
+ getTargetBoundsScene(target) {
323
+ if (!this.canvasService || !target)
324
+ return null;
325
+ const rawBounds = typeof target.getBoundingRect === "function"
326
+ ? target.getBoundingRect()
327
+ : {
328
+ left: Number(target.left || 0),
329
+ top: Number(target.top || 0),
330
+ width: Number(target.width || 0),
331
+ height: Number(target.height || 0),
332
+ };
333
+ return this.canvasService.toSceneRect({
334
+ left: Number(rawBounds.left || 0),
335
+ top: Number(rawBounds.top || 0),
336
+ width: Number(rawBounds.width || 0),
337
+ height: Number(rawBounds.height || 0),
338
+ });
339
+ }
340
+ getSnapThresholdScene(px) {
341
+ if (!this.canvasService)
342
+ return px;
343
+ return this.canvasService.toSceneLength(px);
344
+ }
345
+ pickSnapMatch(candidates) {
346
+ if (!candidates.length)
347
+ return null;
348
+ const snapThreshold = this.getSnapThresholdScene(IMAGE_MOVE_SNAP_THRESHOLD_PX);
349
+ let best = null;
350
+ candidates.forEach((candidate) => {
351
+ if (Math.abs(candidate.deltaScene) > snapThreshold)
352
+ return;
353
+ if (!best || Math.abs(candidate.deltaScene) < Math.abs(best.deltaScene)) {
354
+ best = candidate;
355
+ }
356
+ });
357
+ return best;
358
+ }
359
+ computeMoveSnapMatches(bounds, frame) {
360
+ if (!bounds || frame.width <= 0 || frame.height <= 0) {
361
+ return { x: null, y: null };
362
+ }
363
+ const xCandidates = [
364
+ {
365
+ axis: "x",
366
+ lineId: "frame-left",
367
+ kind: "edge",
368
+ lineScene: frame.left,
369
+ deltaScene: frame.left - bounds.left,
370
+ },
371
+ {
372
+ axis: "x",
373
+ lineId: "frame-center-x",
374
+ kind: "center",
375
+ lineScene: frame.left + frame.width / 2,
376
+ deltaScene: frame.left + frame.width / 2 - (bounds.left + bounds.width / 2),
377
+ },
378
+ {
379
+ axis: "x",
380
+ lineId: "frame-right",
381
+ kind: "edge",
382
+ lineScene: frame.left + frame.width,
383
+ deltaScene: frame.left + frame.width - (bounds.left + bounds.width),
384
+ },
385
+ ];
386
+ const yCandidates = [
387
+ {
388
+ axis: "y",
389
+ lineId: "frame-top",
390
+ kind: "edge",
391
+ lineScene: frame.top,
392
+ deltaScene: frame.top - bounds.top,
393
+ },
394
+ {
395
+ axis: "y",
396
+ lineId: "frame-center-y",
397
+ kind: "center",
398
+ lineScene: frame.top + frame.height / 2,
399
+ deltaScene: frame.top + frame.height / 2 - (bounds.top + bounds.height / 2),
400
+ },
401
+ {
402
+ axis: "y",
403
+ lineId: "frame-bottom",
404
+ kind: "edge",
405
+ lineScene: frame.top + frame.height,
406
+ deltaScene: frame.top + frame.height - (bounds.top + bounds.height),
407
+ },
408
+ ];
409
+ return {
410
+ x: this.pickSnapMatch(xCandidates),
411
+ y: this.pickSnapMatch(yCandidates),
412
+ };
413
+ }
414
+ areSnapMatchesEqual(a, b) {
415
+ if (!a && !b)
416
+ return true;
417
+ if (!a || !b)
418
+ return false;
419
+ return a.lineId === b.lineId && a.axis === b.axis && a.kind === b.kind;
420
+ }
421
+ updateSnapMatchState(nextX, nextY) {
422
+ const changed = !this.areSnapMatchesEqual(this.activeSnapX, nextX) ||
423
+ !this.areSnapMatchesEqual(this.activeSnapY, nextY);
424
+ this.activeSnapX = nextX;
425
+ this.activeSnapY = nextY;
426
+ if (changed) {
427
+ this.canvasService?.requestRenderAll();
428
+ }
429
+ }
430
+ clearSnapPreview() {
431
+ this.activeSnapX = null;
432
+ this.activeSnapY = null;
433
+ this.hasRenderedSnapGuides = false;
434
+ this.canvasService?.requestRenderAll();
435
+ }
436
+ endMoveSnapInteraction() {
437
+ this.movingImageId = null;
438
+ this.clearSnapPreview();
439
+ }
440
+ applyMoveSnapToTarget(target) {
441
+ if (!this.canvasService) {
442
+ return { x: null, y: null };
443
+ }
444
+ const frame = this.getFrameRect();
445
+ if (frame.width <= 0 || frame.height <= 0) {
446
+ return { x: null, y: null };
447
+ }
448
+ const bounds = this.getTargetBoundsScene(target);
449
+ const matches = this.computeMoveSnapMatches(bounds, frame);
450
+ const deltaScreenX = this.canvasService.toScreenLength(matches.x?.deltaScene ?? 0);
451
+ const deltaScreenY = this.canvasService.toScreenLength(matches.y?.deltaScene ?? 0);
452
+ if (deltaScreenX || deltaScreenY) {
453
+ target.set({
454
+ left: Number(target.left || 0) + deltaScreenX,
455
+ top: Number(target.top || 0) + deltaScreenY,
456
+ });
457
+ target.setCoords();
458
+ }
459
+ return matches;
460
+ }
461
+ handleCanvasBeforeRender() {
462
+ if (!this.canvasService)
463
+ return;
464
+ if (!this.hasRenderedSnapGuides && !this.activeSnapX && !this.activeSnapY) {
465
+ return;
466
+ }
467
+ this.canvasService.canvas.clearContext(this.canvasService.canvas.contextTop);
468
+ this.hasRenderedSnapGuides = false;
469
+ }
470
+ drawSnapGuideLine(from, to) {
471
+ if (!this.canvasService)
472
+ return;
473
+ const ctx = this.canvasService.canvas.contextTop;
474
+ if (!ctx)
475
+ return;
476
+ const color = this.getConfig("image.control.borderColor", "#1677ff") ||
477
+ "#1677ff";
478
+ ctx.save();
479
+ ctx.strokeStyle = color;
480
+ ctx.lineWidth = 1;
481
+ ctx.beginPath();
482
+ ctx.moveTo(from.x, from.y);
483
+ ctx.lineTo(to.x, to.y);
484
+ ctx.stroke();
485
+ ctx.restore();
486
+ }
487
+ handleCanvasAfterRender() {
488
+ if (!this.canvasService || !this.isImageEditingVisible()) {
489
+ return;
490
+ }
491
+ const frame = this.getFrameRect();
492
+ if (frame.width <= 0 || frame.height <= 0) {
493
+ return;
494
+ }
495
+ const frameScreen = this.getFrameRectScreen(frame);
496
+ let drew = false;
497
+ if (this.activeSnapX) {
498
+ const x = this.canvasService.toScreenPoint({
499
+ x: this.activeSnapX.lineScene,
500
+ y: frame.top,
501
+ }).x;
502
+ this.drawSnapGuideLine({ x, y: frameScreen.top }, { x, y: frameScreen.top + frameScreen.height });
503
+ drew = true;
504
+ }
505
+ if (this.activeSnapY) {
506
+ const y = this.canvasService.toScreenPoint({
507
+ x: frame.left,
508
+ y: this.activeSnapY.lineScene,
509
+ }).y;
510
+ this.drawSnapGuideLine({ x: frameScreen.left, y }, { x: frameScreen.left + frameScreen.width, y });
511
+ drew = true;
512
+ }
513
+ this.hasRenderedSnapGuides = drew;
514
+ }
515
+ handleCanvasObjectMoving(e) {
516
+ const target = this.getActiveImageTarget(e?.target);
517
+ if (!target || !this.canvasService)
518
+ return;
519
+ this.movingImageId =
520
+ typeof target?.data?.id === "string" ? target.data.id : null;
521
+ const frame = this.getFrameRect();
522
+ if (frame.width <= 0 || frame.height <= 0) {
523
+ this.endMoveSnapInteraction();
524
+ return;
525
+ }
526
+ const rawBounds = this.getTargetBoundsScene(target);
527
+ const matches = this.computeMoveSnapMatches(rawBounds, frame);
528
+ this.updateSnapMatchState(matches.x, matches.y);
529
+ }
250
530
  syncToolActiveFromWorkbench(fallbackId) {
251
531
  const wb = this.context?.services.get("WorkbenchService");
252
532
  const activeId = wb?.activeToolId;
@@ -864,33 +1144,9 @@ class ImageTool {
864
1144
  originY: "top",
865
1145
  fill: hatchFill,
866
1146
  opacity: patternFill ? 1 : 0.8,
867
- stroke: null,
868
- fillRule: "evenodd",
869
- selectable: false,
870
- evented: false,
871
- excludeFromExport: true,
872
- objectCaching: false,
873
- },
874
- },
875
- {
876
- id: "image.cropShapePath",
877
- type: "path",
878
- data: { id: "image.cropShapePath", zIndex: 6 },
879
- layout: {
880
- reference: "custom",
881
- referenceRect: frameRect,
882
- alignX: "start",
883
- alignY: "start",
884
- offsetX: shapeBounds.x,
885
- offsetY: shapeBounds.y,
886
- },
887
- props: {
888
- pathData: shapePathData,
889
- originX: "left",
890
- originY: "top",
891
- fill: "rgba(0,0,0,0)",
892
1147
  stroke: "rgba(255, 0, 0, 0.9)",
893
1148
  strokeWidth: this.canvasService?.toSceneLength(1) ?? 1,
1149
+ fillRule: "evenodd",
894
1150
  selectable: false,
895
1151
  evented: false,
896
1152
  excludeFromExport: true,
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LAYER_IDS = exports.FILM_LAYER_ID = exports.RULER_LAYER_ID = exports.FEATURE_OVERLAY_LAYER_ID = exports.DIELINE_LAYER_ID = exports.WHITE_INK_OVERLAY_LAYER_ID = exports.WHITE_INK_COVER_LAYER_ID = exports.WHITE_INK_OBJECT_LAYER_ID = exports.IMAGE_OVERLAY_LAYER_ID = exports.IMAGE_OBJECT_LAYER_ID = exports.BACKGROUND_LAYER_ID = void 0;
3
+ exports.LAYER_IDS = exports.FILM_LAYER_ID = exports.RULER_LAYER_ID = exports.FEATURE_OVERLAY_LAYER_ID = exports.FEATURE_DIELINE_LAYER_ID = exports.DIELINE_LAYER_ID = exports.WHITE_INK_OVERLAY_LAYER_ID = exports.WHITE_INK_COVER_LAYER_ID = exports.WHITE_INK_OBJECT_LAYER_ID = exports.IMAGE_OVERLAY_LAYER_ID = exports.IMAGE_OBJECT_LAYER_ID = exports.BACKGROUND_LAYER_ID = void 0;
4
4
  exports.BACKGROUND_LAYER_ID = "background";
5
5
  exports.IMAGE_OBJECT_LAYER_ID = "image.user";
6
6
  exports.IMAGE_OVERLAY_LAYER_ID = "image-overlay";
@@ -8,6 +8,7 @@ exports.WHITE_INK_OBJECT_LAYER_ID = "white-ink.user";
8
8
  exports.WHITE_INK_COVER_LAYER_ID = "white-ink.cover";
9
9
  exports.WHITE_INK_OVERLAY_LAYER_ID = "white-ink.overlay";
10
10
  exports.DIELINE_LAYER_ID = "dieline-overlay";
11
+ exports.FEATURE_DIELINE_LAYER_ID = "feature-dieline-overlay";
11
12
  exports.FEATURE_OVERLAY_LAYER_ID = "feature-overlay";
12
13
  exports.RULER_LAYER_ID = "ruler-overlay";
13
14
  exports.FILM_LAYER_ID = "overlay";
@@ -19,6 +20,7 @@ exports.LAYER_IDS = {
19
20
  whiteInkCover: exports.WHITE_INK_COVER_LAYER_ID,
20
21
  whiteInkOverlay: exports.WHITE_INK_OVERLAY_LAYER_ID,
21
22
  dieline: exports.DIELINE_LAYER_ID,
23
+ featureDieline: exports.FEATURE_DIELINE_LAYER_ID,
22
24
  featureOverlay: exports.FEATURE_OVERLAY_LAYER_ID,
23
25
  rulerOverlay: exports.RULER_LAYER_ID,
24
26
  filmOverlay: exports.FILM_LAYER_ID,
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @pooder/kit
2
2
 
3
+ ## 6.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - refactor the dieline feature and modify the image snap
8
+
3
9
  ## 6.1.2
4
10
 
5
11
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,9 +1,23 @@
1
1
  import * as _pooder_core from '@pooder/core';
2
- import { Extension, ExtensionContext, ContributionPointIds, ConfigurationContribution, CommandContribution, Service, ServiceContext, EventBus } from '@pooder/core';
2
+ import { Extension, ExtensionContext, ContributionPointIds, ConfigurationContribution, CommandContribution, ConfigurationService, Service, ServiceContext, EventBus } from '@pooder/core';
3
3
  import { Canvas, FabricObject } from 'fabric';
4
4
 
5
5
  type BackgroundLayerKind = "color" | "image";
6
6
  type BackgroundFitMode = "cover" | "contain" | "stretch";
7
+ type BackgroundRegionUnit = "normalized" | "px";
8
+ type BackgroundRegistrationFrame = "trim" | "cut" | "bleed" | "focus" | "viewport";
9
+ interface BackgroundRegistrationRegion {
10
+ left: number;
11
+ top: number;
12
+ width: number;
13
+ height: number;
14
+ unit: BackgroundRegionUnit;
15
+ }
16
+ interface BackgroundRegistration {
17
+ sourceRegion?: BackgroundRegistrationRegion;
18
+ targetFrame?: BackgroundRegistrationFrame;
19
+ fit?: BackgroundFitMode;
20
+ }
7
21
  interface BackgroundLayer {
8
22
  id: string;
9
23
  kind: BackgroundLayerKind;
@@ -15,6 +29,7 @@ interface BackgroundLayer {
15
29
  exportable: boolean;
16
30
  color?: string;
17
31
  src?: string;
32
+ registration?: BackgroundRegistration;
18
33
  }
19
34
  interface BackgroundConfig {
20
35
  version: number;
@@ -47,8 +62,11 @@ declare class BackgroundTool implements Extension {
47
62
  private getViewportRect;
48
63
  private resolveSceneLayout;
49
64
  private resolveFocusRect;
65
+ private resolveTargetFrameRect;
50
66
  private resolveAnchorRect;
51
67
  private resolveImagePlacement;
68
+ private resolveRegistrationRegion;
69
+ private resolveRegistrationPlacement;
52
70
  private buildColorLayerSpec;
53
71
  private buildImageLayerSpec;
54
72
  private buildBackgroundSpecs;
@@ -94,9 +112,12 @@ declare class ImageTool implements Extension {
94
112
  private overlaySpecs;
95
113
  private activeSnapX;
96
114
  private activeSnapY;
97
- private snapGuideXObject?;
98
- private snapGuideYObject?;
115
+ private movingImageId;
116
+ private hasRenderedSnapGuides;
99
117
  private canvasObjectMovingHandler?;
118
+ private canvasMouseUpHandler?;
119
+ private canvasBeforeRenderHandler?;
120
+ private canvasAfterRenderHandler?;
100
121
  private renderProducerDisposable?;
101
122
  private readonly subscriptions;
102
123
  private imageControlsByCapabilityKey;
@@ -116,12 +137,13 @@ declare class ImageTool implements Extension {
116
137
  private computeMoveSnapMatches;
117
138
  private areSnapMatchesEqual;
118
139
  private updateSnapMatchState;
119
- private clearSnapGuides;
120
- private removeSnapGuideObject;
121
- private createOrUpdateSnapGuideObject;
122
- private updateSnapGuideVisuals;
140
+ private clearSnapPreview;
141
+ private endMoveSnapInteraction;
142
+ private applyMoveSnapToTarget;
143
+ private handleCanvasBeforeRender;
144
+ private drawSnapGuideLine;
145
+ private handleCanvasAfterRender;
123
146
  private handleCanvasObjectMoving;
124
- private applySnapMatchesToTarget;
125
147
  private syncToolActiveFromWorkbench;
126
148
  private isImageEditingVisible;
127
149
  private getEnabledImageControlCapabilities;
@@ -313,6 +335,9 @@ interface DielineState {
313
335
  customSourceWidthPx?: number;
314
336
  customSourceHeightPx?: number;
315
337
  }
338
+ declare function createDefaultDielineState(): DielineState;
339
+ declare function readDielineState(configService: ConfigurationService, fallback?: Partial<DielineState>): DielineState;
340
+
316
341
  declare class DielineTool implements Extension {
317
342
  id: string;
318
343
  metadata: {
@@ -345,7 +370,6 @@ declare class DielineTool implements Extension {
345
370
  private createHatchPattern;
346
371
  private getConfigService;
347
372
  private hasImageItems;
348
- private syncSizeState;
349
373
  private buildDielineSpecs;
350
374
  private buildImageClipEffects;
351
375
  updateDieline(_emitEvent?: boolean): void;
@@ -739,7 +763,9 @@ declare class FeatureTool implements Extension {
739
763
  private hasWorkingChanges;
740
764
  private dirtyTrackerDisposable?;
741
765
  private renderProducerDisposable?;
742
- private specs;
766
+ private markerSpecs;
767
+ private sessionDielineSpecs;
768
+ private sessionDielineEffects;
743
769
  private renderSeq;
744
770
  private readonly subscriptions;
745
771
  private handleMoving;
@@ -753,6 +779,7 @@ declare class FeatureTool implements Extension {
753
779
  deactivate(context: ExtensionContext): void;
754
780
  private onToolActivated;
755
781
  private updateVisibility;
782
+ private isSessionVisible;
756
783
  contribute(): {
757
784
  [ContributionPointIds.TOOLS]: {
758
785
  id: string;
@@ -774,8 +801,10 @@ declare class FeatureTool implements Extension {
774
801
  private getConfigService;
775
802
  private getCommittedFeatures;
776
803
  private updateCommittedFeatures;
804
+ private hasFeatureSessionDraft;
777
805
  private clearFeatureSessionState;
778
- private restoreSessionFeaturesToConfig;
806
+ private restoreCommittedFeaturesToConfig;
807
+ private suspendFeatureSession;
779
808
  private emitWorkingChange;
780
809
  private refreshGeometry;
781
810
  private resetWorkingFeaturesFromSource;
@@ -787,6 +816,7 @@ declare class FeatureTool implements Extension {
787
816
  private getGeometryForFeature;
788
817
  private setup;
789
818
  private teardown;
819
+ private createHatchPattern;
790
820
  private getDraggableMarkerTarget;
791
821
  private getFeatureForMarker;
792
822
  private constrainPosition;
@@ -795,7 +825,9 @@ declare class FeatureTool implements Extension {
795
825
  private syncGroupFromCanvas;
796
826
  private redraw;
797
827
  private redrawAsync;
798
- private buildFeatureSpecs;
828
+ private buildSessionDielineRender;
829
+ private hasImageItems;
830
+ private buildMarkerSpecs;
799
831
  private appendMarkerSpecs;
800
832
  private buildMarkerData;
801
833
  private markerId;
@@ -1028,4 +1060,4 @@ declare function createWhiteInkCommands(tool: any): CommandContribution[];
1028
1060
 
1029
1061
  declare function createWhiteInkConfigurations(): ConfigurationContribution[];
1030
1062
 
1031
- export { type BackgroundConfig, type BackgroundFitMode, type BackgroundLayer, type BackgroundLayerKind, BackgroundTool, CanvasService, type DielineGeometry, type DielineState, DielineTool, FeatureTool, FilmTool, type ImageItem, ImageTool, type LayerObjectCountComparator, type LineStyle, MirrorTool, type RenderClipPathEffectSpec, type RenderCoordinateSpace, type RenderEffectSpec, type RenderLayoutAlign, type RenderLayoutInsets, type RenderLayoutLength, type RenderLayoutRect, type RenderLayoutReference, type RenderObjectLayoutSpec, type RenderObjectSpec, type RenderObjectType, type RenderPassSpec, type RenderProps, RulerTool, SceneLayoutService, SizeTool, ViewportSystem, type VisibilityEvalContext, type VisibilityExpr, type VisibilityLayerState, type WhiteInkItem, WhiteInkTool, getCoverScale as computeImageCoverScale, getCoverScale as computeWhiteInkCoverScale, createDielineCommands, createDielineConfigurations, createImageCommands, createImageConfigurations, createWhiteInkCommands, createWhiteInkConfigurations, evaluateVisibilityExpr };
1063
+ export { type BackgroundConfig, type BackgroundFitMode, type BackgroundLayer, type BackgroundLayerKind, type BackgroundRegionUnit, type BackgroundRegistration, type BackgroundRegistrationFrame, type BackgroundRegistrationRegion, BackgroundTool, CanvasService, type DielineGeometry, type DielineState, DielineTool, FeatureTool, FilmTool, type ImageItem, ImageTool, type LayerObjectCountComparator, type LineStyle, MirrorTool, type RenderClipPathEffectSpec, type RenderCoordinateSpace, type RenderEffectSpec, type RenderLayoutAlign, type RenderLayoutInsets, type RenderLayoutLength, type RenderLayoutRect, type RenderLayoutReference, type RenderObjectLayoutSpec, type RenderObjectSpec, type RenderObjectType, type RenderPassSpec, type RenderProps, RulerTool, SceneLayoutService, SizeTool, ViewportSystem, type VisibilityEvalContext, type VisibilityExpr, type VisibilityLayerState, type WhiteInkItem, WhiteInkTool, getCoverScale as computeImageCoverScale, getCoverScale as computeWhiteInkCoverScale, createDefaultDielineState, createDielineCommands, createDielineConfigurations, createImageCommands, createImageConfigurations, createWhiteInkCommands, createWhiteInkConfigurations, evaluateVisibilityExpr, readDielineState };