@bensitu/image-editor 1.5.2 → 2.0.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/README.md +367 -518
- package/dist/cjs/index.cjs +5422 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/esm/animation/animation-queue.js +67 -0
- package/dist/esm/animation/animation-queue.js.map +1 -0
- package/dist/esm/core/callback-reporter.js +23 -0
- package/dist/esm/core/callback-reporter.js.map +1 -0
- package/dist/esm/core/default-options.js +322 -0
- package/dist/esm/core/default-options.js.map +1 -0
- package/dist/esm/core/errors.js +156 -0
- package/dist/esm/core/errors.js.map +1 -0
- package/dist/esm/core/operation-guard.js +129 -0
- package/dist/esm/core/operation-guard.js.map +1 -0
- package/dist/esm/core/public-types.js +4 -0
- package/dist/esm/core/public-types.js.map +1 -0
- package/dist/esm/core/state-serializer.js +251 -0
- package/dist/esm/core/state-serializer.js.map +1 -0
- package/dist/esm/crop/crop-controller.js +403 -0
- package/dist/esm/crop/crop-controller.js.map +1 -0
- package/dist/esm/export/export-format.js +53 -0
- package/dist/esm/export/export-format.js.map +1 -0
- package/dist/esm/export/export-service.js +596 -0
- package/dist/esm/export/export-service.js.map +1 -0
- package/dist/esm/fabric/fabric-adapter.js +37 -0
- package/dist/esm/fabric/fabric-adapter.js.map +1 -0
- package/dist/esm/fabric/fabric-animation.js +37 -0
- package/dist/esm/fabric/fabric-animation.js.map +1 -0
- package/dist/esm/history/command.js +2 -0
- package/dist/esm/history/command.js.map +1 -0
- package/dist/esm/history/history-manager.js +103 -0
- package/dist/esm/history/history-manager.js.map +1 -0
- package/dist/esm/image/image-loader.js +245 -0
- package/dist/esm/image/image-loader.js.map +1 -0
- package/dist/esm/image/image-resampler.js +55 -0
- package/dist/esm/image/image-resampler.js.map +1 -0
- package/dist/esm/image/layout-manager.js +224 -0
- package/dist/esm/image/layout-manager.js.map +1 -0
- package/dist/esm/image/transform-controller.js +132 -0
- package/dist/esm/image/transform-controller.js.map +1 -0
- package/dist/esm/image-editor.js +1740 -0
- package/dist/esm/image-editor.js.map +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/mask/mask-factory.js +332 -0
- package/dist/esm/mask/mask-factory.js.map +1 -0
- package/dist/esm/mask/mask-label-manager.js +120 -0
- package/dist/esm/mask/mask-label-manager.js.map +1 -0
- package/dist/esm/mask/mask-list.js +47 -0
- package/dist/esm/mask/mask-list.js.map +1 -0
- package/dist/esm/mask/mask-style.js +182 -0
- package/dist/esm/mask/mask-style.js.map +1 -0
- package/dist/esm/ui/dom-bindings.js +60 -0
- package/dist/esm/ui/dom-bindings.js.map +1 -0
- package/dist/esm/ui/ui-state.js +25 -0
- package/dist/esm/ui/ui-state.js.map +1 -0
- package/dist/esm/ui/visibility-state.js +11 -0
- package/dist/esm/ui/visibility-state.js.map +1 -0
- package/dist/esm/utils/canvas-region.js +100 -0
- package/dist/esm/utils/canvas-region.js.map +1 -0
- package/dist/esm/utils/dom.js +6 -0
- package/dist/esm/utils/dom.js.map +1 -0
- package/dist/esm/utils/file.js +53 -0
- package/dist/esm/utils/file.js.map +1 -0
- package/dist/esm/utils/number.js +24 -0
- package/dist/esm/utils/number.js.map +1 -0
- package/dist/esm/utils/timeout.js +17 -0
- package/dist/esm/utils/timeout.js.map +1 -0
- package/dist/types/animation/animation-queue.d.ts +111 -0
- package/dist/types/animation/animation-queue.d.ts.map +1 -0
- package/dist/types/core/callback-reporter.d.ts +125 -0
- package/dist/types/core/callback-reporter.d.ts.map +1 -0
- package/dist/types/core/default-options.d.ts +56 -0
- package/dist/types/core/default-options.d.ts.map +1 -0
- package/dist/types/core/errors.d.ts +142 -0
- package/dist/types/core/errors.d.ts.map +1 -0
- package/dist/types/core/operation-guard.d.ts +192 -0
- package/dist/types/core/operation-guard.d.ts.map +1 -0
- package/dist/types/core/public-types.d.ts +678 -0
- package/dist/types/core/public-types.d.ts.map +1 -0
- package/dist/types/core/state-serializer.d.ts +301 -0
- package/dist/types/core/state-serializer.d.ts.map +1 -0
- package/dist/types/crop/crop-controller.d.ts +407 -0
- package/dist/types/crop/crop-controller.d.ts.map +1 -0
- package/dist/types/export/export-format.d.ts +136 -0
- package/dist/types/export/export-format.d.ts.map +1 -0
- package/dist/types/export/export-service.d.ts +333 -0
- package/dist/types/export/export-service.d.ts.map +1 -0
- package/dist/types/fabric/fabric-adapter.d.ts +74 -0
- package/dist/types/fabric/fabric-adapter.d.ts.map +1 -0
- package/dist/types/fabric/fabric-animation.d.ts +141 -0
- package/dist/types/fabric/fabric-animation.d.ts.map +1 -0
- package/dist/types/history/command.d.ts +16 -0
- package/dist/types/history/command.d.ts.map +1 -0
- package/dist/types/history/history-manager.d.ts +129 -0
- package/dist/types/history/history-manager.d.ts.map +1 -0
- package/dist/types/image/image-loader.d.ts +265 -0
- package/dist/types/image/image-loader.d.ts.map +1 -0
- package/dist/types/image/image-resampler.d.ts +139 -0
- package/dist/types/image/image-resampler.d.ts.map +1 -0
- package/dist/types/image/layout-manager.d.ts +255 -0
- package/dist/types/image/layout-manager.d.ts.map +1 -0
- package/dist/types/image/transform-controller.d.ts +287 -0
- package/dist/types/image/transform-controller.d.ts.map +1 -0
- package/dist/types/image-editor.d.ts +650 -0
- package/dist/types/image-editor.d.ts.map +1 -0
- package/dist/types/index.d.cts +31 -0
- package/dist/types/index.d.cts.map +1 -0
- package/dist/types/index.d.ts +31 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/mask/mask-factory.d.ts +209 -0
- package/dist/types/mask/mask-factory.d.ts.map +1 -0
- package/dist/types/mask/mask-label-manager.d.ts +171 -0
- package/dist/types/mask/mask-label-manager.d.ts.map +1 -0
- package/dist/types/mask/mask-list.d.ts +144 -0
- package/dist/types/mask/mask-list.d.ts.map +1 -0
- package/dist/types/mask/mask-style.d.ts +338 -0
- package/dist/types/mask/mask-style.d.ts.map +1 -0
- package/dist/types/ui/dom-bindings.d.ts +103 -0
- package/dist/types/ui/dom-bindings.d.ts.map +1 -0
- package/dist/types/ui/ui-state.d.ts +112 -0
- package/dist/types/ui/ui-state.d.ts.map +1 -0
- package/dist/types/ui/visibility-state.d.ts +77 -0
- package/dist/types/ui/visibility-state.d.ts.map +1 -0
- package/dist/types/utils/canvas-region.d.ts +177 -0
- package/dist/types/utils/canvas-region.d.ts.map +1 -0
- package/dist/types/utils/dom.d.ts +26 -0
- package/dist/types/utils/dom.d.ts.map +1 -0
- package/dist/types/utils/file.d.ts +80 -0
- package/dist/types/utils/file.d.ts.map +1 -0
- package/dist/types/utils/number.d.ts +132 -0
- package/dist/types/utils/number.d.ts.map +1 -0
- package/dist/types/utils/timeout.d.ts +84 -0
- package/dist/types/utils/timeout.d.ts.map +1 -0
- package/dist/umd/image-editor.umd.js +2 -0
- package/dist/umd/image-editor.umd.js.map +1 -0
- package/package.json +72 -66
- package/dist/image-editor.cjs +0 -4407
- package/dist/image-editor.cjs.map +0 -7
- package/dist/image-editor.esm.js +0 -4376
- package/dist/image-editor.esm.js.map +0 -7
- package/dist/image-editor.esm.min.js +0 -9
- package/dist/image-editor.esm.min.js.map +0 -7
- package/dist/image-editor.esm.min.mjs +0 -9
- package/dist/image-editor.esm.min.mjs.map +0 -7
- package/dist/image-editor.esm.mjs +0 -4376
- package/dist/image-editor.esm.mjs.map +0 -7
- package/dist/image-editor.js +0 -4373
- package/dist/image-editor.js.map +0 -7
- package/dist/image-editor.min.js +0 -9
- package/dist/image-editor.min.js.map +0 -7
- package/image-editor.d.ts +0 -271
- package/src/browser.js +0 -11
- package/src/esm.js +0 -9
- package/src/image-editor.js +0 -5013
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crop session lifecycle owner. Implements the
|
|
3
|
+
* `enterCropMode → applyCrop` and
|
|
4
|
+
* `enterCropMode → cancelCrop` transitions atop the
|
|
5
|
+
* legacy crop pipeline, plus the dedicated crop rectangle
|
|
6
|
+
* shape, its drag/scale clamps, and the per-object
|
|
7
|
+
* `evented`/`selectable` freeze that keeps only the crop
|
|
8
|
+
* rectangle interactive while a session is open.
|
|
9
|
+
*
|
|
10
|
+
* ## Owned contracts
|
|
11
|
+
*
|
|
12
|
+
* - `enterCropMode`, `applyCrop`, and `cancelCrop`
|
|
13
|
+
* each discard any active Fabric `ActiveSelection` BEFORE mutating crop
|
|
14
|
+
* state. The state serializer's `saveState` also discards on its own
|
|
15
|
+
* path, so the explicit call here is a defense-in-depth that keeps the
|
|
16
|
+
* contract independent of the serializer's internal behaviour.
|
|
17
|
+
* - `enterCropMode` creates a {@link CropSession}
|
|
18
|
+
* that captures the pre-crop canvas snapshot (without the crop rectangle),
|
|
19
|
+
* the prior `canvas.selection` setting, and per-object `evented` /
|
|
20
|
+
* `selectable` values. The pre-crop snapshot is taken *before* the crop
|
|
21
|
+
* rectangle is added so the JSON is guaranteed crop-rect-free without
|
|
22
|
+
* relying on Fabric's serialization of the `isCropRect` custom key.
|
|
23
|
+
* - `applyCrop` pushes exactly one
|
|
24
|
+
* {@link Command} whose `undo` restores the pre-crop snapshot and whose
|
|
25
|
+
* `execute` re-applies the post-crop snapshot. The command is pushed via
|
|
26
|
+
* {@link HistoryManager.push} (NOT `execute`) because the cropped state
|
|
27
|
+
* is already on the canvas — the first `redo` after an `undo` should
|
|
28
|
+
* re-run the post-crop restore, but the initial commit must not
|
|
29
|
+
* double-render.
|
|
30
|
+
* - On any failure between the crop region read
|
|
31
|
+
* and the history push, the pre-crop snapshot is restored via
|
|
32
|
+
* `context.loadFromState`, the {@link CropSession} is dropped, all
|
|
33
|
+
* crop-specific Fabric event handlers are detached, and the returned
|
|
34
|
+
* promise rejects with {@link CropApplyError} wrapping the original
|
|
35
|
+
* cause. A failure inside the rollback itself is logged but does not
|
|
36
|
+
* mask the original error.
|
|
37
|
+
* - `cancelCrop` restores the pre-crop snapshot
|
|
38
|
+
* (via the captured `prevEvented` / `prevSelection` values, plus the
|
|
39
|
+
* per-mask style backups captured on entry), removes the crop
|
|
40
|
+
* rectangle, and drops the session WITHOUT producing a history entry.
|
|
41
|
+
* - All three transitions detach every Fabric
|
|
42
|
+
* event handler bound on the crop rectangle when the session ends, so
|
|
43
|
+
* no stale handlers remain attached to the disposed shape.
|
|
44
|
+
* - `enterCropMode` honours
|
|
45
|
+
* `options.crop.hideMasksDuringCrop`: when `true`, every mask's prior
|
|
46
|
+
* live style is captured into `session.maskBackups` via
|
|
47
|
+
* {@link captureMaskStyleBackup} and the mask is then forced to
|
|
48
|
+
* `opacity: 0`, `evented: false`, `selectable: false` via
|
|
49
|
+
* {@link applyCropHideMaskStyle}. Backups are captured BEFORE the
|
|
50
|
+
* freeze loop so the recorded `selectable` value is the true pre-crop
|
|
51
|
+
* value and not the freeze-loop's enforced `false`.
|
|
52
|
+
* - `cancelCrop` restores every entry in
|
|
53
|
+
* `session.maskBackups` via {@link restoreMaskStyleBackup} after the
|
|
54
|
+
* per-object `evented` / `selectable` restore so the mask backup's
|
|
55
|
+
* fields (`opacity`, `fill`, `strokeWidth`, `stroke`, `selectable`,
|
|
56
|
+
* `lockRotation`) are the final word.
|
|
57
|
+
* - `applyCrop` honours
|
|
58
|
+
* `options.crop.preserveMasksAfterCrop` defaulting to `false` in current:
|
|
59
|
+
* the inner `context.loadImage(croppedBase64)` replaces every canvas
|
|
60
|
+
* object with the cropped base image, so masks disappear naturally
|
|
61
|
+
* when the option is `false`.
|
|
62
|
+
* - When `options.crop.preserveMasksAfterCrop`
|
|
63
|
+
* is `true`, `applyCrop` captures each mask's `left`, `top`,
|
|
64
|
+
* `angle`, `scaleX`, and `scaleY` BEFORE the canvas is exported, and
|
|
65
|
+
* re-adds the masks AFTER the loader commits the cropped image with
|
|
66
|
+
* `left` and `top` shifted by `-cropRegion.left, -cropRegion.top`.
|
|
67
|
+
* Per-mask `angle`, `scaleX`, and `scaleY` are restored verbatim so
|
|
68
|
+
* the visible mask shape does not change size or orientation. The
|
|
69
|
+
* cropRegion-relative shift matches legacy's
|
|
70
|
+
* `_translateObjectByCanvasOffset(mask, -cropRegion.sourceX,
|
|
71
|
+
* -cropRegion.sourceY)` and is the documented legacy behavior to
|
|
72
|
+
* preserve. Because shifting `left` / `top` by a constant translates
|
|
73
|
+
* the entire object (including its rotated visual) by the same
|
|
74
|
+
* constant in canvas pixels, the post-crop position relative to the
|
|
75
|
+
* new image bounding box matches the pre-crop position relative to
|
|
76
|
+
* the old image bounding box without any explicit trig in this
|
|
77
|
+
* module — the rotation angle is encoded in the rotated image's
|
|
78
|
+
* bounding rect, which moves with the same translation as the masks.
|
|
79
|
+
*
|
|
80
|
+
* ## Post-crop mask preservation
|
|
81
|
+
*
|
|
82
|
+
* Mask visibility during crop mode is owned by the
|
|
83
|
+
* `hideMasksDuringCrop` path above: masks can be hidden on entry and
|
|
84
|
+
* restored on cancel. The apply path separately owns
|
|
85
|
+
* `preserveMasksAfterCrop`: when the option is `true`, the controller
|
|
86
|
+
* captures each mask's `left`, `top`, `angle`, `scaleX`, and `scaleY`
|
|
87
|
+
* before export and re-adds the masks shifted by
|
|
88
|
+
* `-cropRegion.left, -cropRegion.top` after
|
|
89
|
+
* `context.loadImage(croppedBase64)` commits. The intersection filter
|
|
90
|
+
* drops masks that do not overlap the crop region, matching legacy
|
|
91
|
+
* observable behavior: masks fully outside the cropped region are
|
|
92
|
+
* removed, while intersecting masks are preserved.
|
|
93
|
+
*
|
|
94
|
+
* ## Implementation notes
|
|
95
|
+
*
|
|
96
|
+
* - The controller is a set of stateless functions taking a
|
|
97
|
+
* {@link CropControllerContext}. The `ImageEditor` facade keeps
|
|
98
|
+
* ownership of the canonical session pointer (`getCropSession` /
|
|
99
|
+
* `setCropSession`) so multiple editors on the same page do not share
|
|
100
|
+
* crop state and a sub-agent unit test can exercise the controller
|
|
101
|
+
* without instantiating the full facade.
|
|
102
|
+
* - The crop rectangle's drag/scale handlers clamp `scaleX` / `scaleY`
|
|
103
|
+
* so the rect cannot grow past the available image bounding box and
|
|
104
|
+
* cannot shrink below the configured `crop.minWidth` / `crop.minHeight`.
|
|
105
|
+
* This matches legacy's `handleCropRectModified`.
|
|
106
|
+
* - In Fabric v7 the rotation handle (`mtr`) is hidden via
|
|
107
|
+
* `setControlVisible('mtr', false)` because `hasRotatingPoint` is
|
|
108
|
+
* silently ignored. `lockRotation: true` is also set as runtime
|
|
109
|
+
* defence so the rotation transform itself cannot fire even if the
|
|
110
|
+
* handle were somehow shown.
|
|
111
|
+
* - The pre-crop snapshot is captured once, in `enterCropMode`, and
|
|
112
|
+
* reused by `applyCrop`'s history command and rollback path. This
|
|
113
|
+
* avoids a re-serialization right before the crop, and — more
|
|
114
|
+
* importantly — avoids the legacy fragility of filtering `isCropRect`
|
|
115
|
+
* objects out of a post-rect snapshot when Fabric's custom-key
|
|
116
|
+
* serializer occasionally drops the marker.
|
|
117
|
+
*
|
|
118
|
+
* Owner module references (per the documented "Mapping Contracts to
|
|
119
|
+
* modules" table): this module is imported only by `image-editor.ts` and
|
|
120
|
+
* is intentionally NOT re-exported from `src/index.ts`.
|
|
121
|
+
*
|
|
122
|
+
* @module
|
|
123
|
+
*/
|
|
124
|
+
import type * as FabricNS from 'fabric';
|
|
125
|
+
import type { CropHandler, CropPrevEvented, FabricModule, ImageMimeType, LoadImageOptions, MaskBackup, ResolvedOptions } from '../core/public-types.js';
|
|
126
|
+
import { type HistoryManager } from '../history/history-manager.js';
|
|
127
|
+
/**
|
|
128
|
+
* Internal state of an open crop session. Built by {@link enterCropMode},
|
|
129
|
+
* consumed and discarded by {@link applyCrop} / {@link cancelCrop}.
|
|
130
|
+
*
|
|
131
|
+
* The `ImageEditor` facade owns the live pointer to this object; the
|
|
132
|
+
* controller reads and writes it through the
|
|
133
|
+
* {@link CropControllerContext.getCropSession} /
|
|
134
|
+
* {@link CropControllerContext.setCropSession} callbacks so multiple
|
|
135
|
+
* editor instances do not share crop state.
|
|
136
|
+
*
|
|
137
|
+
* Fields:
|
|
138
|
+
*
|
|
139
|
+
* - `beforeJson` — JSON snapshot of the canvas captured BEFORE the crop
|
|
140
|
+
* rectangle was added. Used as both the rollback target on
|
|
141
|
+
* `applyCrop` failure and the `undo` payload of
|
|
142
|
+
* the history entry pushed on success.
|
|
143
|
+
* - `prevSelection` — value of `canvas.selection` immediately before the
|
|
144
|
+
* controller forced it to `false` to keep only the crop rectangle
|
|
145
|
+
* interactive. Restored on apply or cancel.
|
|
146
|
+
* - `prevEvented` — list of `{ object, evented, selectable}` records for
|
|
147
|
+
* every canvas object that was frozen on entry. Restored on apply or
|
|
148
|
+
* cancel.
|
|
149
|
+
* - `maskBackups` — per-mask style backup list. Populated by
|
|
150
|
+
* `enterCropMode` when `options.crop.hideMasksDuringCrop` is `true`,
|
|
151
|
+
* consumed by `cancelCrop` to restore each mask's pre-crop visual
|
|
152
|
+
* state. Empty when the option is `false`.
|
|
153
|
+
* - `cropRect` — the active crop rectangle, or `null` after the rect has
|
|
154
|
+
* been removed (so subsequent calls to {@link removeCropRect} are
|
|
155
|
+
* idempotent on the success and rollback paths).
|
|
156
|
+
* - `handlers` — bound `modified` / `moving` / `scaling` handler records
|
|
157
|
+
* on the crop rectangle. Detached when the session ends.
|
|
158
|
+
*
|
|
159
|
+
*/
|
|
160
|
+
export interface CropSession {
|
|
161
|
+
beforeJson: string;
|
|
162
|
+
prevSelection: boolean;
|
|
163
|
+
prevEvented: CropPrevEvented[];
|
|
164
|
+
/** Per-mask style backups captured when masks are hidden during crop mode. */
|
|
165
|
+
maskBackups: MaskBackup[];
|
|
166
|
+
cropRect: FabricNS.Rect | null;
|
|
167
|
+
handlers: CropHandler[];
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Dependency bundle passed by the `ImageEditor` facade into every crop
|
|
171
|
+
* entry point. The controller has no class state of its own — every
|
|
172
|
+
* editor field it reads is exposed here as a value or callback so the
|
|
173
|
+
* facade keeps ownership of the canonical state.
|
|
174
|
+
*
|
|
175
|
+
* Mirrors the shape of
|
|
176
|
+
* {@link import('../export/export-service.js').MergeMasksContext} for
|
|
177
|
+
* consistency across pipeline modules.
|
|
178
|
+
*
|
|
179
|
+
* The `ImageEditor` facade constructs this bundle from its own state.
|
|
180
|
+
*/
|
|
181
|
+
export interface CropControllerContext {
|
|
182
|
+
/** Fabric module providing `Rect` for the crop rectangle. */
|
|
183
|
+
readonly fabric: FabricModule;
|
|
184
|
+
/** Live Fabric canvas. */
|
|
185
|
+
readonly canvas: FabricNS.Canvas;
|
|
186
|
+
/** Resolved editor options — supplies `crop.padding`, `crop.minWidth`,
|
|
187
|
+
* `crop.minHeight`, `crop.allowRotationOfCropRect`, and
|
|
188
|
+
* `downsampleQuality` (used as the cropped JPEG export quality). */
|
|
189
|
+
readonly options: ResolvedOptions;
|
|
190
|
+
/** History manager that records the single crop command on success. */
|
|
191
|
+
readonly historyManager: HistoryManager;
|
|
192
|
+
/**
|
|
193
|
+
* Predicate matching `ImageEditor.isImageLoaded`. Returns `true`
|
|
194
|
+
* only when an `originalImage` has been committed and has positive
|
|
195
|
+
* dimensions. `enterCropMode` and `applyCrop` no-op when this is
|
|
196
|
+
* `false` so a caller cannot open a crop session against an empty
|
|
197
|
+
* canvas (matches legacy's `isImageLoaded` gate).
|
|
198
|
+
*/
|
|
199
|
+
isImageLoaded(): boolean;
|
|
200
|
+
/**
|
|
201
|
+
* The currently committed `originalImage`, or `null`. Read by
|
|
202
|
+
* {@link enterCropMode} to derive the initial crop rectangle bounds
|
|
203
|
+
* from the image bounding box.
|
|
204
|
+
*/
|
|
205
|
+
getOriginalImage(): FabricNS.FabricImage | null;
|
|
206
|
+
/**
|
|
207
|
+
* MIME type of the currently committed image, used by source-preserving
|
|
208
|
+
* crop export.
|
|
209
|
+
*/
|
|
210
|
+
getCurrentImageMimeType?(): ImageMimeType | null;
|
|
211
|
+
/** Reads the live crop session, or `null`. */
|
|
212
|
+
getCropSession(): CropSession | null;
|
|
213
|
+
/** Writes the live crop session pointer (or clears it with `null`). */
|
|
214
|
+
setCropSession(session: CropSession | null): void;
|
|
215
|
+
/**
|
|
216
|
+
* Capture a snapshot suitable for {@link loadFromState}. Used in
|
|
217
|
+
* `enterCropMode` to record the pre-crop state and again in
|
|
218
|
+
* `applyCrop` after the cropped image is on the canvas to record
|
|
219
|
+
* the post-crop state for the redo command.
|
|
220
|
+
*/
|
|
221
|
+
saveState(): string;
|
|
222
|
+
/**
|
|
223
|
+
* Restore a snapshot produced by {@link saveState}. Used as the
|
|
224
|
+
* `undo` callback of the crop command and as the rollback step on
|
|
225
|
+
* any `applyCrop` failure.
|
|
226
|
+
*/
|
|
227
|
+
loadFromState(snapshot: string): Promise<void>;
|
|
228
|
+
/**
|
|
229
|
+
* Transactional image loader (`image/image-loader.ts`). `applyCrop`
|
|
230
|
+
* routes the cropped data URL through this so a failed reload
|
|
231
|
+
* propagates back here and the rollback path catches it.
|
|
232
|
+
*/
|
|
233
|
+
loadImage(imageBase64: string, options?: LoadImageOptions): Promise<void>;
|
|
234
|
+
/**
|
|
235
|
+
* Reads the orchestrator's mask counter. Used by the
|
|
236
|
+
* `preserveMasksAfterCrop` path so re-added masks restore the
|
|
237
|
+
* counter to `max(maskId)` after `context.loadImage` reset it to `0`
|
|
238
|
+
* on commit (invariant: subsequent `createMask`
|
|
239
|
+
* calls must not collide with a preserved mask's `maskId`).
|
|
240
|
+
*
|
|
241
|
+
* Optional — only consulted by the preserve path. The orchestrator
|
|
242
|
+
* may omit this in unit-test contexts that never enable
|
|
243
|
+
* `preserveMasksAfterCrop`.
|
|
244
|
+
*/
|
|
245
|
+
getMaskCounter?(): number;
|
|
246
|
+
/**
|
|
247
|
+
* Writes the orchestrator's mask counter. See {@link getMaskCounter}
|
|
248
|
+
* for the contract.
|
|
249
|
+
*/
|
|
250
|
+
setMaskCounter?(n: number): void;
|
|
251
|
+
/**
|
|
252
|
+
* Re-render the mask list DOM after preserved masks are re-added to
|
|
253
|
+
* the post-crop canvas. Optional — the orchestrator may omit this
|
|
254
|
+
* when no DOM list is wired (e.g., headless unit tests). Mirrors
|
|
255
|
+
* legacy's `updateMaskList` call after preserved masks land.
|
|
256
|
+
*/
|
|
257
|
+
updateMaskList?(): void;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Open a crop session. Builds a {@link CropSession} that captures:
|
|
261
|
+
*
|
|
262
|
+
* - the pre-crop canvas JSON snapshot (without the crop rectangle),
|
|
263
|
+
* - the prior `canvas.selection` setting,
|
|
264
|
+
* - per-object `evented` / `selectable` values for every existing canvas
|
|
265
|
+
* object,
|
|
266
|
+
* - per-mask style backups when `options.crop.hideMasksDuringCrop` is
|
|
267
|
+
* `true` so {@link cancelCrop} can revert the hide.
|
|
268
|
+
*
|
|
269
|
+
* After capturing the session, the function:
|
|
270
|
+
*
|
|
271
|
+
* 1. Adds an interactive crop rectangle inside the image bounding box
|
|
272
|
+
* (with the configured padding inset) and binds drag/scale clamp
|
|
273
|
+
* handlers so it cannot grow past the image bounds nor shrink below
|
|
274
|
+
* `crop.minWidth` / `crop.minHeight`.
|
|
275
|
+
* 2. Forces `canvas.selection = false` and freezes every other canvas
|
|
276
|
+
* object (`evented = false`, `selectable = false`) so only the crop
|
|
277
|
+
* rectangle responds to pointer events.
|
|
278
|
+
* 3. Marks the rectangle with the `isCropRect` custom property so the
|
|
279
|
+
* state serializer's session-only filter excludes it from any future
|
|
280
|
+
* snapshot taken while the session is open.
|
|
281
|
+
* 4. When `options.crop.hideMasksDuringCrop` is `true`, captures a
|
|
282
|
+
* {@link MaskBackup} for every mask BEFORE the freeze loop runs and
|
|
283
|
+
* then applies the crop-mode hide style (`opacity: 0`,
|
|
284
|
+
* `evented: false`, `selectable: false`) via
|
|
285
|
+
* {@link applyCropHideMaskStyle}. Capturing first ensures the
|
|
286
|
+
* backup's `selectable` field reflects the true pre-crop value
|
|
287
|
+
* rather than the freeze-loop's enforced `false`.
|
|
288
|
+
*
|
|
289
|
+
* No-ops when:
|
|
290
|
+
*
|
|
291
|
+
* - a session is already open (idempotent re-entry),
|
|
292
|
+
* - no `originalImage` is committed,
|
|
293
|
+
* - `isImageLoaded` returns `false`.
|
|
294
|
+
*
|
|
295
|
+
* `discardActiveObject` runs at the very top so the
|
|
296
|
+
* pre-crop snapshot does not capture an `ActiveSelection` wrapper. The
|
|
297
|
+
* state serializer's own discard provides a second line of defence.
|
|
298
|
+
*
|
|
299
|
+
* @param context - Editor dependency bundle — see {@link CropControllerContext}.
|
|
300
|
+
*
|
|
301
|
+
*/
|
|
302
|
+
export declare function enterCropMode(context: CropControllerContext): void;
|
|
303
|
+
/**
|
|
304
|
+
* Close an open crop session WITHOUT applying the crop. Restores the
|
|
305
|
+
* pre-crop `canvas.selection`, the per-object `evented` / `selectable`
|
|
306
|
+
* values, removes the crop rectangle, detaches every crop-bound Fabric
|
|
307
|
+
* handler, and drops the session.
|
|
308
|
+
*
|
|
309
|
+
* Produces NO history entry — the user explicitly chose to abandon the
|
|
310
|
+
* crop, and the canvas state at the end of `cancelCrop` is the same one
|
|
311
|
+
* the previous history entry already covers.
|
|
312
|
+
*
|
|
313
|
+
* No-op when no session is open.
|
|
314
|
+
*
|
|
315
|
+
* `discardActiveObject` runs at the very top so any
|
|
316
|
+
* currently-active selection (typically the crop rectangle itself) is
|
|
317
|
+
* cleared before the rect is removed.
|
|
318
|
+
*
|
|
319
|
+
* @param context - Editor dependency bundle — see {@link CropControllerContext}.
|
|
320
|
+
*
|
|
321
|
+
*/
|
|
322
|
+
export declare function cancelCrop(context: CropControllerContext): void;
|
|
323
|
+
/**
|
|
324
|
+
* Apply the active crop session: export the crop region as a JPEG data
|
|
325
|
+
* URL, reload it as the new base image through the transactional
|
|
326
|
+
* loader, and push exactly one history entry whose `undo` restores the
|
|
327
|
+
* pre-crop snapshot and whose `execute` re-applies the post-crop
|
|
328
|
+
* snapshot.
|
|
329
|
+
*
|
|
330
|
+
* Atomic: either the cropped image is committed and one history entry
|
|
331
|
+
* is pushed, or the editor is rewound to its pre-crop state and the
|
|
332
|
+
* returned promise rejects with {@link CropApplyError}.
|
|
333
|
+
*
|
|
334
|
+
* Steps, in order:
|
|
335
|
+
*
|
|
336
|
+
* 1. **No-op gates** — return without mutating anything when no session
|
|
337
|
+
* is open or the session has no crop rectangle.
|
|
338
|
+
* 2. **Discard ActiveSelection** — drop any active
|
|
339
|
+
* selection wrapper before reading the crop rect's bounding box so
|
|
340
|
+
* the export region is computed against the rect itself.
|
|
341
|
+
* 3. **Read crop region** — refresh the rect's coordinate cache, read
|
|
342
|
+
* its bounding rect, convert it to an integer region with trailing
|
|
343
|
+
* partial pixels excluded, and clamp it to the source canvas.
|
|
344
|
+
* 3a. **Capture preserved masks** — when
|
|
345
|
+
* `options.crop.preserveMasksAfterCrop === true`, capture each mask's
|
|
346
|
+
* pre-crop `left`, `top`, `angle`, `scaleX`, and `scaleY`, then
|
|
347
|
+
* remove the masks from the canvas so the cropped JPEG export does
|
|
348
|
+
* not bake them in (and so the inner `context.loadImage`'s
|
|
349
|
+
* `canvas.clear` does not dispose the captured reference). Masks
|
|
350
|
+
* fully outside the crop region are removed without a record so
|
|
351
|
+
* they do not reappear after the load (matches legacy's `intersectsCrop`
|
|
352
|
+
* filter).
|
|
353
|
+
* 4. **Tear down session in place** — restore per-object evented /
|
|
354
|
+
* selectable values (so the export sees masks in their pre-crop
|
|
355
|
+
* state) and remove the crop rectangle along with its handlers. The
|
|
356
|
+
* session pointer is NOT cleared yet
|
|
357
|
+
* because the catch path may still need `session.beforeJson`.
|
|
358
|
+
* 5. **Restore `canvas.selection`** — back to the pre-crop value before
|
|
359
|
+
* the cropped image is exported.
|
|
360
|
+
* 6. **Export the crop region** via `canvas.toDataURL` with the
|
|
361
|
+
* integer region as `left` / `top` / `width` / `height` (matches
|
|
362
|
+
* legacy's `_exportCanvasRegionToDataURL`). The cropped image is JPEG
|
|
363
|
+
* at the configured downsample quality.
|
|
364
|
+
* 7. **Reload the cropped image** through `context.loadImage`. The
|
|
365
|
+
* transactional loader either commits the new image or rolls back —
|
|
366
|
+
* a failure propagates here so the rollback path below catches it.
|
|
367
|
+
* 7a. **Reapply preserved masks** — when
|
|
368
|
+
* records were captured in step 3a, re-add each mask to the
|
|
369
|
+
* post-crop canvas with `left` and `top` shifted by
|
|
370
|
+
* `-cropRegion.left, -cropRegion.top` and `angle`, `scaleX`,
|
|
371
|
+
* `scaleY` restored verbatim. Restores the orchestrator's mask
|
|
372
|
+
* counter to `max(maskId)` so subsequent `createMask` calls do not
|
|
373
|
+
* collide with preserved IDs.
|
|
374
|
+
* 8. **Capture post-crop snapshot** for the redo command.
|
|
375
|
+
* 9. **Drop the session pointer** before pushing history.
|
|
376
|
+
* 10. **Push exactly one history command** whose
|
|
377
|
+
* `undo` restores the pre-crop snapshot and whose `execute`
|
|
378
|
+
* re-applies the post-crop snapshot.
|
|
379
|
+
*
|
|
380
|
+
* On any failure between step 3 and step 10, the helper:
|
|
381
|
+
*
|
|
382
|
+
* - tears down the session (handlers detached, rect removed,
|
|
383
|
+
* per-object state restored, `canvas.selection` reverted) so no
|
|
384
|
+
* stale crop state remains,
|
|
385
|
+
* - clears the session pointer,
|
|
386
|
+
* - restores the pre-crop snapshot via `context.loadFromState`,
|
|
387
|
+
* - rejects with {@link CropApplyError} wrapping the original cause.
|
|
388
|
+
*
|
|
389
|
+
* Mask handling note: when `options.crop.preserveMasksAfterCrop` is
|
|
390
|
+
* `false` (the current default), the inner
|
|
391
|
+
* `context.loadImage(croppedBase64)` call replaces every canvas object
|
|
392
|
+
* with the cropped base image, so any masks are removed naturally
|
|
393
|
+
* with no extra work in this function. When `preserveMasksAfterCrop`
|
|
394
|
+
* is `true`, masks intersecting the crop region are captured before
|
|
395
|
+
* the export and re-added after the load via
|
|
396
|
+
* {@link capturePreservedMasks} / {@link reapplyPreservedMasks}.
|
|
397
|
+
* Crop-mode mask hiding on entry / restoration on cancel is handled
|
|
398
|
+
* in {@link enterCropMode} and the {@link teardownSession} chain.
|
|
399
|
+
*
|
|
400
|
+
* @param context - Editor dependency bundle — see {@link CropControllerContext}.
|
|
401
|
+
* @returns Resolves on success; rejects with {@link CropApplyError}
|
|
402
|
+
* on any pipeline failure (after the pre-crop snapshot has
|
|
403
|
+
* been restored).
|
|
404
|
+
*
|
|
405
|
+
*/
|
|
406
|
+
export declare function applyCrop(context: CropControllerContext): Promise<void>;
|
|
407
|
+
//# sourceMappingURL=crop-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crop-controller.d.ts","sourceRoot":"","sources":["../../../src/crop/crop-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0HG;AAEH,OAAO,KAAK,KAAK,QAAQ,MAAM,QAAQ,CAAC;AAGxC,OAAO,KAAK,EACR,WAAW,EACX,eAAe,EACf,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,UAAU,EAGV,eAAe,EAClB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAoB7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,WAAW,WAAW;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,8EAA8E;IAC9E,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,QAAQ,EAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;IAC/B,QAAQ,EAAE,WAAW,EAAE,CAAC;CAC3B;AAID;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,qBAAqB;IAClC,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;IACjC;;yEAEqE;IACrE,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,uEAAuE;IACvE,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAExC;;;;;;OAMG;IACH,aAAa,IAAI,OAAO,CAAC;IAEzB;;;;OAIG;IACH,gBAAgB,IAAI,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC;IAEhD;;;OAGG;IACH,uBAAuB,CAAC,IAAI,aAAa,GAAG,IAAI,CAAC;IAEjD,8CAA8C;IAC9C,cAAc,IAAI,WAAW,GAAG,IAAI,CAAC;IACrC,uEAAuE;IACvE,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;IAElD;;;;;OAKG;IACH,SAAS,IAAI,MAAM,CAAC;IAEpB;;;;OAIG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C;;;;OAIG;IACH,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E;;;;;;;;;;OAUG;IACH,cAAc,CAAC,IAAI,MAAM,CAAC;IAE1B;;;OAGG;IACH,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjC;;;;;OAKG;IACH,cAAc,CAAC,IAAI,IAAI,CAAC;CAC3B;AAybD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAyLlE;AAID;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAiB/D;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkFG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoJ7E"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers that normalize the user-facing
|
|
3
|
+
* `Base64ExportOptions` / `ImageFileExportOptions` surface into the
|
|
4
|
+
* canvas-/Fabric-shaped values consumed by `export/export-service.ts`.
|
|
5
|
+
*
|
|
6
|
+
* The module owns three small, individually testable building blocks plus
|
|
7
|
+
* one orchestrating function, mirroring the shape of
|
|
8
|
+
* `image/image-resampler.ts`:
|
|
9
|
+
*
|
|
10
|
+
* - {@link normalizeImageFormat} — collapses `'jpg'` to `'jpeg'`, strips
|
|
11
|
+
* the `image/` MIME prefix, and falls back to `'jpeg'` for unknown or
|
|
12
|
+
* omitted input.
|
|
13
|
+
* - {@link mimeTypeFor} — derives the matching `image/...` MIME
|
|
14
|
+
* for a normalized format token.
|
|
15
|
+
* - {@link clampQuality} — coerces input to a finite number and
|
|
16
|
+
* clamps it into `[0, 1]`, falling back to a caller-supplied default
|
|
17
|
+
* when the input is not finite.
|
|
18
|
+
* - {@link resolveExportFormat} — composes the above with the documented
|
|
19
|
+
* `fileType`-wins-over-`format` precedence and drops `quality` for PNG
|
|
20
|
+
* output.
|
|
21
|
+
*
|
|
22
|
+
* legacy parity:
|
|
23
|
+
* - The format mapping table mirrors `_normalizeImageFormat` from
|
|
24
|
+
* `src/image-editor.js@legacy.4.0`, including the lowercase lookup and the
|
|
25
|
+
* `'jpeg'` default for unknown input.
|
|
26
|
+
* - The quality clamp mirrors `_normalizeQuality` from the same legacy file:
|
|
27
|
+
* non-finite input falls back to `options.downsampleQuality`, finite
|
|
28
|
+
* input is clamped to `[0, 1]`.
|
|
29
|
+
*
|
|
30
|
+
* This module is internal — it is NOT re-exported from `src/index.ts`.
|
|
31
|
+
*
|
|
32
|
+
* Fabric.
|
|
33
|
+
* lossless.
|
|
34
|
+
* `quality` defaulting to `options.downsampleQuality`.
|
|
35
|
+
*
|
|
36
|
+
* @module
|
|
37
|
+
*/
|
|
38
|
+
import type { Base64ExportOptions, ImageFileExportOptions, ImageMimeType, NormalizedImageFormat } from '../core/public-types.js';
|
|
39
|
+
/**
|
|
40
|
+
* Result of {@link resolveExportFormat}.
|
|
41
|
+
*
|
|
42
|
+
* `quality` is `undefined` when the resolved format is `'png'` so callers can
|
|
43
|
+
* omit it from `toDataURL` / Fabric's region-export options without an extra
|
|
44
|
+
* branch.
|
|
45
|
+
*/
|
|
46
|
+
export interface ResolvedExportFormat {
|
|
47
|
+
/** Canvas-/Fabric-compatible format token. */
|
|
48
|
+
format: NormalizedImageFormat;
|
|
49
|
+
/** Matching MIME type for `toDataURL` / `Blob` construction. */
|
|
50
|
+
mimeType: ImageMimeType;
|
|
51
|
+
/** Lossy quality in `[0, 1]`, or `undefined` for PNG. */
|
|
52
|
+
quality: number | undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Collapse a public `ImageFileType` (or any string-ish input) to the
|
|
56
|
+
* canonical `NormalizedImageFormat` token consumed by Fabric.
|
|
57
|
+
*
|
|
58
|
+
* Behavior:
|
|
59
|
+
* - `'jpg'` (and `'JPG'`, `'image/jpeg'`, `'IMAGE/JPEG'`, …) → `'jpeg'`.
|
|
60
|
+
* - `'png'` / `'image/png'` → `'png'` (case-insensitive).
|
|
61
|
+
* - `'webp'` / `'image/webp'` → `'webp'` (case-insensitive).
|
|
62
|
+
* - `null` / `undefined` / empty / unknown → `'jpeg'`.
|
|
63
|
+
*
|
|
64
|
+
* Pure function — no DOM access, safe to call from property tests.
|
|
65
|
+
*
|
|
66
|
+
* @param input - Requested file type or MIME alias (case-insensitive).
|
|
67
|
+
* @returns The normalized format token to pass to Fabric's `format` arg.
|
|
68
|
+
*
|
|
69
|
+
*/
|
|
70
|
+
export declare function normalizeImageFormat(input?: string | null): NormalizedImageFormat;
|
|
71
|
+
/**
|
|
72
|
+
* Collapse a public file type or MIME alias to a normalized format token.
|
|
73
|
+
* Returns `null` for omitted or unknown input so call sites with a different
|
|
74
|
+
* fallback policy can decide explicitly.
|
|
75
|
+
*
|
|
76
|
+
* Pure function — no DOM access, safe to call from property tests.
|
|
77
|
+
*/
|
|
78
|
+
export declare function tryNormalizeImageFormat(input?: string | null): NormalizedImageFormat | null;
|
|
79
|
+
/**
|
|
80
|
+
* Derive the `image/...` MIME type for a normalized format token.
|
|
81
|
+
*
|
|
82
|
+
* Pure function — no DOM access, safe to call from property tests.
|
|
83
|
+
*
|
|
84
|
+
* @param format - Normalized format token.
|
|
85
|
+
* @returns The matching `ImageMimeType`.
|
|
86
|
+
*
|
|
87
|
+
*/
|
|
88
|
+
export declare function mimeTypeFor(format: NormalizedImageFormat): ImageMimeType;
|
|
89
|
+
/**
|
|
90
|
+
* Coerce `quality` to a finite number and clamp it into `[0, 1]`.
|
|
91
|
+
*
|
|
92
|
+
* Behavior:
|
|
93
|
+
* - `Number(quality)` is finite → `Math.max(0, Math.min(1, n))`.
|
|
94
|
+
* - Otherwise (`NaN`, `Infinity`, non-numeric strings, `null`, `undefined`,
|
|
95
|
+
* objects, …) → `fallback` (NOT re-clamped; the editor pre-validates
|
|
96
|
+
* `downsampleQuality` at construction time).
|
|
97
|
+
*
|
|
98
|
+
* Pure function — no DOM access, safe to call from property tests.
|
|
99
|
+
*
|
|
100
|
+
* @param quality - Caller-supplied quality (may be any type).
|
|
101
|
+
* @param fallback - Quality to use when `quality` is not a finite number.
|
|
102
|
+
* Typically `options.downsampleQuality`.
|
|
103
|
+
* @returns A finite quality value in `[0, 1]`, or the `fallback` when input
|
|
104
|
+
* was not finite.
|
|
105
|
+
*
|
|
106
|
+
*/
|
|
107
|
+
export declare function clampQuality(quality: unknown, fallback: number): number;
|
|
108
|
+
/**
|
|
109
|
+
* Resolve the user-facing export options into the canvas-/Fabric-shaped
|
|
110
|
+
* values consumed by `export/export-service.ts`.
|
|
111
|
+
*
|
|
112
|
+
* Precedence (matches legacy `exportImageBase64` / `exportImageFile`):
|
|
113
|
+
* 1. `options.fileType` wins over `options.format` when both are supplied
|
|
114
|
+
* and `options.fileType` is truthy. Falsy `fileType` falls through to
|
|
115
|
+
* `options.format`. Both omitted → `'jpeg'`.
|
|
116
|
+
* 2. `options.quality` is normalized through {@link clampQuality} with
|
|
117
|
+
* `downsampleQuality` as the fallback. When `options.quality` is
|
|
118
|
+
* `undefined` or `null`, the fallback is used directly.
|
|
119
|
+
* 3. When the resolved format is `'png'`, `quality` is dropped from the
|
|
120
|
+
* result so call sites pass `undefined` to `toDataURL`.
|
|
121
|
+
*
|
|
122
|
+
* Pure function — no DOM access, safe to call from property tests.
|
|
123
|
+
*
|
|
124
|
+
* @param options - Subset of `Base64ExportOptions` /
|
|
125
|
+
* `ImageFileExportOptions` carrying `fileType`,
|
|
126
|
+
* `format`, and `quality`. Other fields are
|
|
127
|
+
* ignored. `format` is only read from options
|
|
128
|
+
* that declare it (i.e. `Base64ExportOptions`).
|
|
129
|
+
* @param downsampleQuality - Default quality used when `options.quality` is
|
|
130
|
+
* omitted or non-finite. Sourced from
|
|
131
|
+
* `ResolvedOptions.downsampleQuality`.
|
|
132
|
+
* @returns The resolved `{ format, mimeType, quality}` triple.
|
|
133
|
+
*
|
|
134
|
+
*/
|
|
135
|
+
export declare function resolveExportFormat(options: Pick<Base64ExportOptions, 'fileType' | 'format' | 'quality'> | Pick<ImageFileExportOptions, 'fileType' | 'quality'> | undefined | null, downsampleQuality: number): ResolvedExportFormat;
|
|
136
|
+
//# sourceMappingURL=export-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-format.d.ts","sourceRoot":"","sources":["../../../src/export/export-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EACR,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,qBAAqB,EACxB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACjC,8CAA8C;IAC9C,MAAM,EAAE,qBAAqB,CAAC;IAC9B,gEAAgE;IAChE,QAAQ,EAAE,aAAa,CAAC;IACxB,yDAAyD;IACzD,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AA+BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,qBAAqB,CAEjF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,qBAAqB,GAAG,IAAI,CAS3F;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,qBAAqB,GAAG,aAAa,CAExE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIvE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CAC/B,OAAO,EACD,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC,GAC5D,IAAI,CAAC,sBAAsB,EAAE,UAAU,GAAG,SAAS,CAAC,GACpD,SAAS,GACT,IAAI,EACV,iBAAiB,EAAE,MAAM,GAC1B,oBAAoB,CA8BtB"}
|