@bensitu/image-editor 1.5.2 → 2.1.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 +460 -509
- package/dist/cjs/index.cjs +6892 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/esm/animation/animation-queue.js +74 -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 +529 -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 +157 -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 +252 -0
- package/dist/esm/core/state-serializer.js.map +1 -0
- package/dist/esm/crop/crop-controller.js +405 -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 +607 -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 +89 -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 +238 -0
- package/dist/esm/image/image-loader.js.map +1 -0
- package/dist/esm/image/image-resampler.js +60 -0
- package/dist/esm/image/image-resampler.js.map +1 -0
- package/dist/esm/image/layout-manager.js +206 -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 +2076 -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 +356 -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 +53 -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/mosaic/mosaic-controller.js +670 -0
- package/dist/esm/mosaic/mosaic-controller.js.map +1 -0
- package/dist/esm/mosaic/mosaic-geometry.js +81 -0
- package/dist/esm/mosaic/mosaic-geometry.js.map +1 -0
- package/dist/esm/mosaic/mosaic-pixelate.js +71 -0
- package/dist/esm/mosaic/mosaic-pixelate.js.map +1 -0
- package/dist/esm/ui/dom-bindings.js +67 -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 +84 -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 +194 -0
- package/dist/types/core/operation-guard.d.ts.map +1 -0
- package/dist/types/core/public-types.d.ts +788 -0
- package/dist/types/core/public-types.d.ts.map +1 -0
- package/dist/types/core/state-serializer.d.ts +303 -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 +263 -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 +211 -0
- package/dist/types/image/layout-manager.d.ts.map +1 -0
- package/dist/types/image/transform-controller.d.ts +286 -0
- package/dist/types/image/transform-controller.d.ts.map +1 -0
- package/dist/types/image-editor.d.ts +661 -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 +212 -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/mosaic/mosaic-controller.d.ts +82 -0
- package/dist/types/mosaic/mosaic-controller.d.ts.map +1 -0
- package/dist/types/mosaic/mosaic-geometry.d.ts +29 -0
- package/dist/types/mosaic/mosaic-geometry.d.ts.map +1 -0
- package/dist/types/mosaic/mosaic-pixelate.d.ts +23 -0
- package/dist/types/mosaic/mosaic-pixelate.d.ts.map +1 -0
- package/dist/types/ui/dom-bindings.d.ts +105 -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 +131 -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,333 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base64, file, and download entry points for the current export
|
|
3
|
+
* pipeline. The orchestrator (`image-editor.ts`) delegates
|
|
4
|
+
* `exportImageBase64`, `exportImageFile`, and `downloadImage`
|
|
5
|
+
* to the helpers in this module so the export logic lives in
|
|
6
|
+
* a single owner module per the documented module-decomposition
|
|
7
|
+
* table.
|
|
8
|
+
*
|
|
9
|
+
* ## Owned contracts
|
|
10
|
+
*
|
|
11
|
+
* - Before computing the export region, every
|
|
12
|
+
* export entry point SHALL discard any active Fabric `ActiveSelection`
|
|
13
|
+
* so it is not serialized into the output. The discard is performed
|
|
14
|
+
* unconditionally; calling `canvas.discardActiveObject` with no active
|
|
15
|
+
* selection is a documented no-op.
|
|
16
|
+
* - `exportImageBase64(options?: Base64ExportOptions)`
|
|
17
|
+
* is the only canonical base64 export entry point. It accepts both
|
|
18
|
+
* `fileType` and `format` for ergonomic interop and
|
|
19
|
+
* returns a `Promise<string>` resolving to a `data:image/...;base64...`
|
|
20
|
+
* data URL.
|
|
21
|
+
* - `exportImageFile(options?: ImageFileExportOptions)`
|
|
22
|
+
* resolves to a `File` whose name comes from `options.fileName` or the
|
|
23
|
+
* editor's `defaultDownloadFileName`.
|
|
24
|
+
* - `downloadImage(fileName?: string)` triggers a
|
|
25
|
+
* browser download with the resolved filename. The bytes match the same
|
|
26
|
+
* pipeline used by `exportImageBase64`.
|
|
27
|
+
* - When `isImageLoaded` is `false`, the three
|
|
28
|
+
* entry points exhibit the documented "no image loaded" shapes:
|
|
29
|
+
*
|
|
30
|
+
* | entry point | shape on no image |
|
|
31
|
+
* | -------------------- | ----------------------------------- |
|
|
32
|
+
* | `exportImageBase64` | resolves to `''` |
|
|
33
|
+
* | `exportImageFile` | rejects with `ExportNotReadyError` |
|
|
34
|
+
* | `downloadImage` | no-op (returns synchronously) |
|
|
35
|
+
*
|
|
36
|
+
* Each path emits a single `console.warn` naming the missing image so
|
|
37
|
+
* the consumer's logs identify which export attempt was skipped.
|
|
38
|
+
* - When `exportArea` resolves
|
|
39
|
+
* to `'image'` and a valid `originalImage` exists, the export region is
|
|
40
|
+
* computed from `originalImage.getBoundingRect` and passed directly
|
|
41
|
+
* as `left`/`top`/`width`/`height` to Fabric's `toDataURL` options.
|
|
42
|
+
* No intermediate `<canvas>` element is created, and sub-pixel
|
|
43
|
+
* width/height values are floored to integer pixels through the
|
|
44
|
+
* {@link floorRegion} helper before Fabric receives the region.
|
|
45
|
+
* - When `mergeMask` is
|
|
46
|
+
* `true`, every mask's live style (`opacity`, `fill`, `stroke`,
|
|
47
|
+
* `strokeWidth`, `selectable`, `lockRotation`) is captured BEFORE the
|
|
48
|
+
* mutator forces the bake-in style (`opacity: 1, fill: '#000',
|
|
49
|
+
* strokeWidth: 0, stroke: null, selectable: false`) and restored
|
|
50
|
+
* inside a `finally` block whether the inner render resolved or
|
|
51
|
+
* rejected. The backup/restore bracket is owned by
|
|
52
|
+
* {@link withMaskStyleBackup} in `mask/mask-style.ts`; this module
|
|
53
|
+
* only contributes the bake-in mutator.
|
|
54
|
+
* - **mergeMasks pre-export** — Before computing the merged
|
|
55
|
+
* bitmap, {@link mergeMasks} discards any active Fabric
|
|
56
|
+
* `ActiveSelection`. {@link exportImageBase64} also discards on its
|
|
57
|
+
* own entry, so the discard runs at most twice (both calls are
|
|
58
|
+
* idempotent no-ops when nothing is selected).
|
|
59
|
+
* - **mergeMasks atomicity** —
|
|
60
|
+
* {@link mergeMasks} is the canonical merge entry point
|
|
61
|
+
* (`Promise<void>`). It captures a pre-merge snapshot suitable for
|
|
62
|
+
* `loadFromState`, renders the merged bitmap via
|
|
63
|
+
* {@link exportImageBase64}, removes every mask without history,
|
|
64
|
+
* reloads the merged data URL through the transactional
|
|
65
|
+
* `image/image-loader.ts`, and on success pushes exactly one
|
|
66
|
+
* {@link Command} whose `undo` restores the pre-merge snapshot and
|
|
67
|
+
* whose `execute` re-applies the merged image. On any failure
|
|
68
|
+
* between snapshot capture and history push, the pre-merge snapshot
|
|
69
|
+
* is restored and the promise rejects with
|
|
70
|
+
* {@link MergeMasksError}. Container scroll position is preserved
|
|
71
|
+
* across the success path (canonically via
|
|
72
|
+
* `loadImage(..., { preserveScroll: true})`, with a defensive
|
|
73
|
+
* restore at the tail of the merge).
|
|
74
|
+
*
|
|
75
|
+
* ## Why a service-shaped module
|
|
76
|
+
*
|
|
77
|
+
* Per the documented "Mapping Contracts to modules" table the export
|
|
78
|
+
* pipeline owns its own module so the orchestrator stays thin. The
|
|
79
|
+
* service is a stateless function-collection (matching
|
|
80
|
+
* `image/image-loader.ts` and `core/state-serializer.ts`) and reads every
|
|
81
|
+
* editor field through an explicit {@link ExportServiceContext} bundle.
|
|
82
|
+
* This keeps the orchestrator authoritative for editor state — the export
|
|
83
|
+
* helpers never store a reference to the canvas or options between
|
|
84
|
+
* invocations — and makes the module trivially mockable from unit and
|
|
85
|
+
* property tests.
|
|
86
|
+
*
|
|
87
|
+
* The module is intentionally NOT re-exported from `src/index.ts`
|
|
88
|
+
* (only `ImageEditor`, `isMaskObject`, and the
|
|
89
|
+
* documented public types are root-exported).
|
|
90
|
+
*
|
|
91
|
+
* @module
|
|
92
|
+
*/
|
|
93
|
+
import type * as FabricNS from 'fabric';
|
|
94
|
+
import type { Base64ExportOptions, FabricModule, ImageFileExportOptions, LoadImageOptions, ResolvedOptions } from '../core/public-types.js';
|
|
95
|
+
import { type HistoryManager } from '../history/history-manager.js';
|
|
96
|
+
/**
|
|
97
|
+
* Dependency bundle passed by the `ImageEditor` facade into every export
|
|
98
|
+
* entry point. The service has no class state of its own — every editor
|
|
99
|
+
* field it reads is exposed here as a value or callback so the facade
|
|
100
|
+
* keeps ownership of the canonical state.
|
|
101
|
+
*
|
|
102
|
+
* Mirrors the shape of {@link import('../image/image-loader.js').LoadImageContext}
|
|
103
|
+
* for consistency across pipeline modules.
|
|
104
|
+
*
|
|
105
|
+
* @see image/image-loader.ts (the same context-bundle pattern)
|
|
106
|
+
*/
|
|
107
|
+
export interface ExportServiceContext {
|
|
108
|
+
/** The Fabric module providing `Canvas` / `FabricImage`. */
|
|
109
|
+
readonly fabric: FabricModule;
|
|
110
|
+
/** The live Fabric canvas. Always non-null on a constructed editor. */
|
|
111
|
+
readonly canvas: FabricNS.Canvas;
|
|
112
|
+
/** Resolved editor options — supplies `defaultDownloadFileName`,
|
|
113
|
+
* `downsampleQuality`, `exportMultiplier`, and
|
|
114
|
+
* `exportAreaByDefault`. */
|
|
115
|
+
readonly options: ResolvedOptions;
|
|
116
|
+
/**
|
|
117
|
+
* Predicate matching `ImageEditor.isImageLoaded`. Returns `true`
|
|
118
|
+
* only when an `originalImage` has been committed and has positive
|
|
119
|
+
* dimensions (reads through this gate).
|
|
120
|
+
*/
|
|
121
|
+
isImageLoaded(): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* The currently committed `originalImage`, or `null` when no image is
|
|
124
|
+
* loaded. {@link computeExportRegion} reads it through this callback
|
|
125
|
+
* to derive the floored bounding box for image-area
|
|
126
|
+
* exports. When the image has been disposed or
|
|
127
|
+
* never loaded the seam falls through to a full-canvas export.
|
|
128
|
+
*/
|
|
129
|
+
getOriginalImage(): FabricNS.FabricImage | null;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Render the live canvas to a base64 data URL.
|
|
133
|
+
*
|
|
134
|
+
* Steps, in order:
|
|
135
|
+
*
|
|
136
|
+
* 1. **No-image gate** — when `context.isImageLoaded`
|
|
137
|
+
* is `false`, emit a `console.warn` and resolve to `''` without
|
|
138
|
+
* touching the canvas.
|
|
139
|
+
* 2. **Discard ActiveSelection** — call
|
|
140
|
+
* `canvas.discardActiveObject` once before computing the export
|
|
141
|
+
* region. Subsequent steps render against the post-discard canvas
|
|
142
|
+
* state, which never carries a top-level `ActiveSelection`.
|
|
143
|
+
* 3. **Resolve format/quality**
|
|
144
|
+
* via {@link resolveExportFormat}.
|
|
145
|
+
* 4. **Resolve multiplier** — `options.multiplier || exportMultiplier || 1`.
|
|
146
|
+
* 5. **Compute region** — see {@link computeExportRegion}. Returns
|
|
147
|
+
* `null` for full-canvas exports and a floored {@link IntegerRegion}
|
|
148
|
+
* when `exportArea` is `'image'` and an `originalImage` is
|
|
149
|
+
* committed.
|
|
150
|
+
* 6. **Render** through {@link withMaskExportState} so mask styles are
|
|
151
|
+
* captured, the export bake-in (`opacity: 1, fill: '#000',
|
|
152
|
+
* strokeWidth: 0, stroke: null, selectable: false`) is applied for
|
|
153
|
+
* `mergeMask === true` exports, and the live styles are
|
|
154
|
+
* restored in a `finally` block whether the render resolved or
|
|
155
|
+
* threw. The inner step is a single
|
|
156
|
+
* `canvas.toDataURL` call — no intermediate `<canvas>`.
|
|
157
|
+
*
|
|
158
|
+
* @param context - Export context bundle.
|
|
159
|
+
* @param options - Optional {@link Base64ExportOptions}. Both `fileType`
|
|
160
|
+
* and `format` are accepted; when
|
|
161
|
+
* both are supplied, `fileType` wins.
|
|
162
|
+
* @returns Resolves to a `data:image/...;base64...` URL on
|
|
163
|
+
* success, or `''` when no image is loaded.
|
|
164
|
+
*
|
|
165
|
+
*/
|
|
166
|
+
export declare function exportImageBase64(context: ExportServiceContext, options?: Base64ExportOptions): Promise<string>;
|
|
167
|
+
/**
|
|
168
|
+
* Render the live canvas to a `File`.
|
|
169
|
+
*
|
|
170
|
+
* The bytes come from {@link exportImageBase64} so format/quality/
|
|
171
|
+
* multiplier resolution stays consistent with the base64 path. The
|
|
172
|
+
* resulting data URL is repainted through an offscreen `<canvas>` only
|
|
173
|
+
* when its MIME prefix does not match the requested type — some browsers
|
|
174
|
+
* silently fall back to PNG when the requested format is unsupported,
|
|
175
|
+
* and the export contract requires the output MIME to match the resolved
|
|
176
|
+
* `fileType`.
|
|
177
|
+
*
|
|
178
|
+
* @param context - Export context bundle.
|
|
179
|
+
* @param options - Optional {@link ImageFileExportOptions}.
|
|
180
|
+
* @returns Resolves with the rendered `File`.
|
|
181
|
+
* @throws {@link ExportNotReadyError} when no image is loaded.
|
|
182
|
+
*
|
|
183
|
+
*/
|
|
184
|
+
export declare function exportImageFile(context: ExportServiceContext, options?: ImageFileExportOptions): Promise<File>;
|
|
185
|
+
/**
|
|
186
|
+
* Trigger a browser download of the live canvas.
|
|
187
|
+
*
|
|
188
|
+
* Mirrors legacy's "anchor with `download` attribute" approach: an `<a>`
|
|
189
|
+
* element is created, pointed at the data URL, appended to the document
|
|
190
|
+
* so Firefox dispatches the click, clicked, and removed. The function
|
|
191
|
+
* returns synchronously; the data URL is rendered
|
|
192
|
+
* asynchronously and the click is deferred until that promise resolves.
|
|
193
|
+
*
|
|
194
|
+
* No-image gate emits the same `console.warn` as the
|
|
195
|
+
* other entry points and returns without touching the DOM.
|
|
196
|
+
*
|
|
197
|
+
* Errors raised by the underlying `exportImageBase64` call are reported
|
|
198
|
+
* with `console.error` rather than rethrown — `downloadImage` returns
|
|
199
|
+
* `void` and there is no caller-visible promise to reject.
|
|
200
|
+
*
|
|
201
|
+
* @param context - Export context bundle.
|
|
202
|
+
* @param fileName - Optional filename override. Defaults to
|
|
203
|
+
* `options.defaultDownloadFileName`.
|
|
204
|
+
*
|
|
205
|
+
*/
|
|
206
|
+
export declare function downloadImage(context: ExportServiceContext, fileName?: string): void;
|
|
207
|
+
/**
|
|
208
|
+
* Dependency bundle passed by the `ImageEditor` facade into
|
|
209
|
+
* {@link mergeMasks}. Extends {@link ExportServiceContext} with the
|
|
210
|
+
* extra slots the merge pipeline needs:
|
|
211
|
+
*
|
|
212
|
+
* - the {@link HistoryManager} that records the merge as one undoable
|
|
213
|
+
* step;
|
|
214
|
+
* - the canonical `loadImage` entry point (transactional load with
|
|
215
|
+
* rollback) so a failed reload of the merged bitmap propagates back
|
|
216
|
+
* to the merge's own rollback path;
|
|
217
|
+
* - the `saveState` / `loadFromState` callbacks the orchestrator
|
|
218
|
+
* already wires for `undo` / `redo`, so the merge can capture and
|
|
219
|
+
* restore the pre-merge snapshot through the same
|
|
220
|
+
* `core/state-serializer.ts` helpers used by the rest of the editor;
|
|
221
|
+
* - a `removeAllMasks(saveHistory: false)` callback so the merge's
|
|
222
|
+
* single enclosing history entry is the only one pushed for the
|
|
223
|
+
* operation (exactly one history entry);
|
|
224
|
+
* - the live container element so the success path can preserve scroll
|
|
225
|
+
* even when the inner `loadImage` did not honor `preserveScroll`.
|
|
226
|
+
*
|
|
227
|
+
* Mirrors the shape of `image/image-loader.ts → LoadImageContext` for
|
|
228
|
+
* consistency across pipeline modules. The `ImageEditor` facade constructs
|
|
229
|
+
* this bundle from its own state.
|
|
230
|
+
*
|
|
231
|
+
*/
|
|
232
|
+
export interface MergeMasksContext extends ExportServiceContext {
|
|
233
|
+
/** History manager that records the single merge command. */
|
|
234
|
+
readonly historyManager: HistoryManager;
|
|
235
|
+
/**
|
|
236
|
+
* Scrollable container wrapping the canvas, or `null`. Read at the
|
|
237
|
+
* head of `mergeMasks` so the success path can restore the captured
|
|
238
|
+
* scroll position regardless of the layout
|
|
239
|
+
* strategy applied by the inner `loadImage`.
|
|
240
|
+
*/
|
|
241
|
+
readonly containerElement: HTMLElement | null;
|
|
242
|
+
/**
|
|
243
|
+
* Transactional image loader. The merge passes
|
|
244
|
+
* `{ preserveScroll: true}` so the inner load tries to keep scroll
|
|
245
|
+
* stable; the merge also restores scroll defensively at the tail of
|
|
246
|
+
* the success path.
|
|
247
|
+
*/
|
|
248
|
+
loadImage(imageBase64: string, options?: LoadImageOptions): Promise<void>;
|
|
249
|
+
/**
|
|
250
|
+
* Capture a snapshot suitable for {@link loadFromStateFn}. Reads the
|
|
251
|
+
* orchestrator's `lastSnapshot`-producing path so the merge stores
|
|
252
|
+
* exactly the same wire format used by `undo` / `redo`.
|
|
253
|
+
*/
|
|
254
|
+
saveState(): string;
|
|
255
|
+
/**
|
|
256
|
+
* Restore a snapshot produced by {@link saveStateFn}. Used both as
|
|
257
|
+
* the `undo` callback of the merge command and
|
|
258
|
+
* as the rollback step on any merge-pipeline failure.
|
|
259
|
+
*/
|
|
260
|
+
loadFromState(snapshot: string): Promise<void>;
|
|
261
|
+
/**
|
|
262
|
+
* Remove every mask from the canvas WITHOUT pushing a history
|
|
263
|
+
* entry. The merge owns the single enclosing history entry, so the
|
|
264
|
+
* inner mask-removal step must opt out
|
|
265
|
+
* of its own history push.
|
|
266
|
+
*/
|
|
267
|
+
removeAllMasksNoHistory(): void;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Flatten every mask into the base image and reload the flattened
|
|
271
|
+
* image as the new canvas state. Atomic with respect to the editor:
|
|
272
|
+
* either the merged image is committed and exactly one history entry
|
|
273
|
+
* is pushed, or the editor is rewound to its pre-merge state and the
|
|
274
|
+
* returned promise rejects with {@link MergeMasksError}.
|
|
275
|
+
*
|
|
276
|
+
* Steps, in order:
|
|
277
|
+
*
|
|
278
|
+
* 1. **No-op gates** — return without mutating anything when no image
|
|
279
|
+
* is loaded or when the canvas carries no mask objects (matches
|
|
280
|
+
* legacy's `if (!this.originalImage) return; … if (!masks.length) return;`).
|
|
281
|
+
* 2. **Capture pre-merge snapshot** — call
|
|
282
|
+
* `context.saveState` so the snapshot is suitable for
|
|
283
|
+
* `context.loadFromState(...)`. The snapshot is the one source of
|
|
284
|
+
* truth for both the merge command's `undo` and
|
|
285
|
+
* the rollback path.
|
|
286
|
+
* 3. **Discard ActiveSelection** — drop any active
|
|
287
|
+
* selection wrapper before computing the merged bitmap.
|
|
288
|
+
* 4. **Capture container scroll** — read `scrollTop` / `scrollLeft`
|
|
289
|
+
* from the editor container so the success path can restore them
|
|
290
|
+
* after the inner `loadImage` runs.
|
|
291
|
+
* 5. **Render the merged bitmap** — delegate to
|
|
292
|
+
* {@link exportImageBase64} with `exportArea: 'image'` and
|
|
293
|
+
* `multiplier: options.exportMultiplier`. The bake-in/restore
|
|
294
|
+
* bracket inside `exportImageBase64` ensures every live mask style
|
|
295
|
+
* is captured before the export-only style is applied and restored
|
|
296
|
+
* on both success and failure.
|
|
297
|
+
* 6. **Remove all masks** without pushing history — the merge owns
|
|
298
|
+
* the single enclosing history entry, so the
|
|
299
|
+
* inner removal step providedOptions out of its own history push.
|
|
300
|
+
* 7. **Reload the merged image** through the transactional
|
|
301
|
+
* `image/image-loader.ts` with `preserveScroll: true`. A failed
|
|
302
|
+
* reload propagates here so the rollback path catches it.
|
|
303
|
+
* 8. **Capture post-merge snapshot** — call `context.saveState` again so
|
|
304
|
+
* the merge command's `execute` can replay the merged state on
|
|
305
|
+
* redo.
|
|
306
|
+
* 9. **Restore scroll defensively** — write the
|
|
307
|
+
* captured `scrollTop` / `scrollLeft` back to the container even
|
|
308
|
+
* though the inner `loadImage` was asked to preserve scroll, so
|
|
309
|
+
* the user's view does not jump regardless of the layout strategy
|
|
310
|
+
* chosen by the loader.
|
|
311
|
+
* 10. **Push exactly one history command** whose
|
|
312
|
+
* `undo` restores the pre-merge snapshot via `context.loadFromState`
|
|
313
|
+
* and whose `execute` re-applies the merged snapshot via
|
|
314
|
+
* `context.loadFromState`. The command is pushed via
|
|
315
|
+
* {@link HistoryManager.push} (NOT `execute`) because the merged
|
|
316
|
+
* state is already on the canvas — the first `redo` call should
|
|
317
|
+
* re-run the merged-state restore, but the initial commit should
|
|
318
|
+
* not double-render.
|
|
319
|
+
*
|
|
320
|
+
* On any failure between step 3 and step 10, the pre-merge snapshot
|
|
321
|
+
* captured in step 3 is restored via `context.loadFromState` and the
|
|
322
|
+
* promise rejects with {@link MergeMasksError} wrapping the original
|
|
323
|
+
* cause. A failure inside the rollback itself is
|
|
324
|
+
* logged via `console.warn` but does not mask the original error.
|
|
325
|
+
*
|
|
326
|
+
* @param context - Editor dependency bundle — see {@link MergeMasksContext}.
|
|
327
|
+
* @returns Resolves on success; rejects with
|
|
328
|
+
* {@link MergeMasksError} on any pipeline failure (after
|
|
329
|
+
* the pre-merge snapshot has been restored).
|
|
330
|
+
*
|
|
331
|
+
*/
|
|
332
|
+
export declare function mergeMasks(context: MergeMasksContext): Promise<void>;
|
|
333
|
+
//# sourceMappingURL=export-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-service.d.ts","sourceRoot":"","sources":["../../../src/export/export-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2FG;AAEH,OAAO,KAAK,KAAK,QAAQ,MAAM,QAAQ,CAAC;AAIxC,OAAO,KAAK,EACR,mBAAmB,EAEnB,YAAY,EACZ,sBAAsB,EACtB,gBAAgB,EAGhB,eAAe,EAClB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAsC7E;;;;;;;;;;GAUG;AACH,MAAM,WAAW,oBAAoB;IACjC,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC;IACjC;;iCAE6B;IAC7B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAElC;;;;OAIG;IACH,aAAa,IAAI,OAAO,CAAC;IAEzB;;;;;;OAMG;IACH,gBAAgB,IAAI,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC;CACnD;AAsqBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,iBAAiB,CACnC,OAAO,EAAE,oBAAoB,EAC7B,OAAO,CAAC,EAAE,mBAAmB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAiDjB;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CACjC,OAAO,EAAE,oBAAoB,EAC7B,OAAO,CAAC,EAAE,sBAAsB,GACjC,OAAO,CAAC,IAAI,CAAC,CAsCf;AAID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAmCpF;AAID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,iBAAkB,SAAQ,oBAAoB;IAC3D,6DAA6D;IAC7D,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,EAAE,WAAW,GAAG,IAAI,CAAC;IAE9C;;;;;OAKG;IACH,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E;;;;OAIG;IACH,SAAS,IAAI,MAAM,CAAC;IAEpB;;;;OAIG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/C;;;;;OAKG;IACH,uBAAuB,IAAI,IAAI,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyH1E"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects the Fabric.js v7 module from the constructor's
|
|
3
|
+
* first argument or from `globalThis.fabric`, and reports
|
|
4
|
+
* whether a usable module was found.
|
|
5
|
+
*
|
|
6
|
+
* Two delivery channels share the same source tree:
|
|
7
|
+
*
|
|
8
|
+
* 1. **ESM consumers** pass the imported Fabric module explicitly:
|
|
9
|
+
* `new ImageEditor(fabric, options)`. Detected by `Canvas` being a
|
|
10
|
+
* function on the first argument.
|
|
11
|
+
*
|
|
12
|
+
* 2. **UMD / CDN consumers** rely on `<script>` tags exposing
|
|
13
|
+
* `window.fabric`, and call `new ImageEditor(options)` with no module
|
|
14
|
+
* argument. The adapter reads `globalScope.fabric` and treats the
|
|
15
|
+
* first argument as options.
|
|
16
|
+
*
|
|
17
|
+
* If neither channel produces a Fabric module with a `Canvas` constructor,
|
|
18
|
+
* the adapter returns `{ fabric: null, isFabricLoaded: false}`. The caller
|
|
19
|
+
* (the {@link ImageEditor} constructor) is then expected to make `init`
|
|
20
|
+
* and `loadImage` no-ops that resolve to `undefined`.
|
|
21
|
+
*
|
|
22
|
+
* Wrapping policy: this adapter does NOT proxy or normalize Fabric APIs.
|
|
23
|
+
* Callers MUST only invoke Fabric v7-compatible APIs directly:
|
|
24
|
+
* - `FabricImage.fromURL(...)` returning a Promise
|
|
25
|
+
* - `canvas.loadFromJSON(...)` returning a Promise
|
|
26
|
+
* - `canvas.setDimensions({ width, height})`
|
|
27
|
+
* - `canvas.bringObjectToFront(object)` / `canvas.sendObjectToBack(object)`
|
|
28
|
+
* - `canvas.backgroundColor` as a plain property (no setter callback)
|
|
29
|
+
* - `object.animate(...)` returning `Animation[]` (wrap with a Promise)
|
|
30
|
+
* (Fabric v7 surface only.)
|
|
31
|
+
*
|
|
32
|
+
* @module
|
|
33
|
+
*/
|
|
34
|
+
import type { FabricModule, ImageEditorOptions } from '../core/public-types.js';
|
|
35
|
+
/**
|
|
36
|
+
* Result of {@link detectFabric}. The caller should:
|
|
37
|
+
* - assign `fabric` and `isFabricLoaded` to private fields on the editor,
|
|
38
|
+
* - use `options` as the ImageEditorOptions partial to feed into
|
|
39
|
+
* `core/default-options.ts`.
|
|
40
|
+
*
|
|
41
|
+
* `isFabricLoaded === false` means no usable Fabric module was found and
|
|
42
|
+
* `fabric` is `null`. The constructor SHALL guard `init` and
|
|
43
|
+
* `loadImage` accordingly.
|
|
44
|
+
*/
|
|
45
|
+
export interface FabricDetectionResult {
|
|
46
|
+
/** The detected Fabric module, or `null` when no module is available. */
|
|
47
|
+
fabric: FabricModule | null;
|
|
48
|
+
/** `true` iff `fabric` is non-null and `fabric.Canvas` is a function. */
|
|
49
|
+
isFabricLoaded: boolean;
|
|
50
|
+
/** The options partial extracted from the constructor arguments. */
|
|
51
|
+
options: ImageEditorOptions;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Detects whether the constructor's first argument is the Fabric module or
|
|
55
|
+
* an `ImageEditorOptions` object, and finds Fabric in the appropriate place.
|
|
56
|
+
*
|
|
57
|
+
* Behavior matrix:
|
|
58
|
+
*
|
|
59
|
+
* | First arg | Result |
|
|
60
|
+
* | ------------------------------------------------- | ------------------------------------------------------------ |
|
|
61
|
+
* | Has `Canvas` function property | `{ fabric: arg, isFabricLoaded: true, options: maybeOptions}` |
|
|
62
|
+
* | Lacks `Canvas`, `globalScope.fabric.Canvas` is callback | `{ fabric: globalScope.fabric, isFabricLoaded: true, options: arg}` |
|
|
63
|
+
* | Lacks `Canvas`, no usable global | `{ fabric: null, isFabricLoaded: false, options: arg}` + single `console.error` |
|
|
64
|
+
*
|
|
65
|
+
* `null` / `undefined` first argument is normalized to an empty options
|
|
66
|
+
* object before being returned.
|
|
67
|
+
*
|
|
68
|
+
* @param fabricOrOptions - Constructor's first argument: either a Fabric module or an options partial.
|
|
69
|
+
* @param maybeOptions - Constructor's second argument, only consulted in the explicit-module form.
|
|
70
|
+
* @param globalScope - Global scope to consult for the UMD fallback. Defaults to `globalThis`; a custom scope is accepted to keep the adapter unit-testable.
|
|
71
|
+
*
|
|
72
|
+
*/
|
|
73
|
+
export declare function detectFabric(fabricOrOptions: FabricModule | ImageEditorOptions | null | undefined, maybeOptions: ImageEditorOptions | undefined, globalScope?: typeof globalThis): FabricDetectionResult;
|
|
74
|
+
//# sourceMappingURL=fabric-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fabric-adapter.d.ts","sourceRoot":"","sources":["../../../src/fabric/fabric-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAIhF;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IAClC,yEAAyE;IACzE,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,yEAAyE;IACzE,cAAc,EAAE,OAAO,CAAC;IACxB,oEAAoE;IACpE,OAAO,EAAE,kBAAkB,CAAC;CAC/B;AAkCD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CACxB,eAAe,EAAE,YAAY,GAAG,kBAAkB,GAAG,IAAI,GAAG,SAAS,EACrE,YAAY,EAAE,kBAAkB,GAAG,SAAS,EAC5C,WAAW,GAAE,OAAO,UAAuB,GAC5C,qBAAqB,CAyCvB"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Promise-shaped wrapper around Fabric.js v7's
|
|
3
|
+
* {@link FabricNS.FabricObject.animate} for the current transform
|
|
4
|
+
* pipeline. v7's `animate(props, providedOptions)` returns an
|
|
5
|
+
* `Animation[]`-like map of contexts (one per animated
|
|
6
|
+
* property) and signals completion through the `onComplete`
|
|
7
|
+
* callback rather than a Promise. To plug it into the
|
|
8
|
+
* `AnimationQueue`, we wrap
|
|
9
|
+
* the call into a single Promise that resolves only after
|
|
10
|
+
* every property animation has fired its callback.
|
|
11
|
+
*
|
|
12
|
+
* ## Owned contracts
|
|
13
|
+
*
|
|
14
|
+
* - Wrap only Fabric v7-compatible APIs. v7's
|
|
15
|
+
* `object.animate` returns `Animation[]` (a map of per-property contexts)
|
|
16
|
+
* and reports completion via `onComplete`; multi-property tweens fire
|
|
17
|
+
* the callback once per property. {@link animateProps} hides that shape
|
|
18
|
+
* behind a single Promise so callers do not encode v7-specific shapes.
|
|
19
|
+
* - `scaleImage(factor)` animates the original
|
|
20
|
+
* image over `options.animationDuration`. `scaleX` and `scaleY` are
|
|
21
|
+
* tweened together, so the resolution count is two — see
|
|
22
|
+
* {@link animateProps}.
|
|
23
|
+
* - `rotateImage(degrees)` animates `angle` over
|
|
24
|
+
* `options.animationDuration`. The single-property case still flows
|
|
25
|
+
* through the same wrapper and resolves on the first `onComplete`.
|
|
26
|
+
* - In-flight animation callbacks check
|
|
27
|
+
* `isDisposed` (via `OperationGuard.isDisposed()`)
|
|
28
|
+
* before touching the canvas. {@link animateProps} short-circuits the
|
|
29
|
+
* `onChange` invocation when the editor has been disposed and still
|
|
30
|
+
* settles its Promise so queued callers never hang
|
|
31
|
+
* (the `AnimationQueue` contract).
|
|
32
|
+
* - Rotation animations temporarily set the image
|
|
33
|
+
* origin to `'center'/'center'` so Fabric tweens around the visual
|
|
34
|
+
* centroid. If dispose interrupts the animation between begin and the
|
|
35
|
+
* post-animation origin restore in `image/transform-controller.ts`,
|
|
36
|
+
* {@link restoreOrigin} replays the origin restore on the original
|
|
37
|
+
* image so it is not left in the temporary center-origin state.
|
|
38
|
+
*
|
|
39
|
+
* The wrapper does not call `saveState`, mark the queue, or set
|
|
40
|
+
* `isAnimating` — those live in the orchestrator and {@link OperationGuard}.
|
|
41
|
+
* This file is intentionally
|
|
42
|
+
* tiny: it owns one Fabric v7 quirk (the `Animation[]` return shape) and
|
|
43
|
+
* one dispose-safety detail (origin restore on interrupt). Per the
|
|
44
|
+
* Module Responsibilities table, it is NOT re-exported from
|
|
45
|
+
* `src/index.ts`.
|
|
46
|
+
*
|
|
47
|
+
* @module
|
|
48
|
+
*/
|
|
49
|
+
import type * as FabricNS from 'fabric';
|
|
50
|
+
import type { OperationGuard } from '../core/operation-guard.js';
|
|
51
|
+
/**
|
|
52
|
+
* Options accepted by {@link animateProps}.
|
|
53
|
+
*
|
|
54
|
+
* Mirrors the subset of Fabric's `AnimationOptions` that the current transform
|
|
55
|
+
* pipeline uses. Additional fields (easing, duration jitter, etc.) are
|
|
56
|
+
* intentionally omitted so the wrapper has a single observable shape per
|
|
57
|
+
*/
|
|
58
|
+
export interface AnimateOptions {
|
|
59
|
+
/** Animation duration in milliseconds (matches `options.animationDuration`). */
|
|
60
|
+
duration: number;
|
|
61
|
+
/**
|
|
62
|
+
* Per-frame hook. Called on every Fabric animation tick while the
|
|
63
|
+
* editor is not disposed. Typically used to call
|
|
64
|
+
* `canvas.requestRenderAll`.
|
|
65
|
+
*
|
|
66
|
+
* The wrapper guards this call with {@link OperationGuard.isDisposed}
|
|
67
|
+
* so post-dispose ticks become no-ops.
|
|
68
|
+
*/
|
|
69
|
+
onChange?: () => void;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Animate one or more numeric properties on a Fabric object and resolve
|
|
73
|
+
* a single Promise once **all** property animations have completed.
|
|
74
|
+
*
|
|
75
|
+
* In Fabric v7, `object.animate(props, providedOptions)` returns a per-property
|
|
76
|
+
* `Animation[]`-like map and signals completion via the `onComplete`
|
|
77
|
+
* callback. For multi-property tweens (e.g. `scale` requires both
|
|
78
|
+
* `scaleX` and `scaleY`), `onComplete` fires once per property — so we
|
|
79
|
+
* count completions before resolving.
|
|
80
|
+
*
|
|
81
|
+
* Dispose safety:
|
|
82
|
+
*
|
|
83
|
+
* - When the editor is disposed mid-animation, {@link AnimateOptions.onChange}
|
|
84
|
+
* becomes a no-op so canvas references that may already be torn down
|
|
85
|
+
* are not touched.
|
|
86
|
+
* - The Promise still settles (resolves) so the
|
|
87
|
+
* `AnimationQueue` can drain queued
|
|
88
|
+
* callers without hanging.
|
|
89
|
+
*
|
|
90
|
+
* Caller responsibilities:
|
|
91
|
+
*
|
|
92
|
+
* - The caller (transform controller) is responsible for the post-animation
|
|
93
|
+
* `object.set({...}); object.setCoords;` snap so the final value is exact even
|
|
94
|
+
* if Fabric rounds the last tick. The wrapper does not commit values.
|
|
95
|
+
* - The caller is responsible for `OperationGuard.runAnimation` bracketing
|
|
96
|
+
* so `isAnimating` is `false` before the returned Promise resolves.
|
|
97
|
+
*
|
|
98
|
+
* @typeParam T - Concrete Fabric object subtype (FabricImage, Rect, etc.).
|
|
99
|
+
* @param object - Fabric object to animate.
|
|
100
|
+
* @param props - Map of property names to target numeric values (e.g.
|
|
101
|
+
* `{ scaleX: 1.5, scaleY: 1.5}` or `{ angle: 90}`).
|
|
102
|
+
* @param options - Duration and per-tick hook.
|
|
103
|
+
* @param guard - Operation guard providing the `isDisposed` flag that
|
|
104
|
+
* inner callbacks consult before touching the canvas.
|
|
105
|
+
* @returns Resolves once every animated property has signalled
|
|
106
|
+
* completion. Rejects only if `object.animate` itself throws
|
|
107
|
+
* synchronously (an empty `props` map resolves immediately).
|
|
108
|
+
*
|
|
109
|
+
*/
|
|
110
|
+
export declare function animateProps<T extends FabricNS.FabricObject>(object: T, props: Record<string, number>, options: AnimateOptions, guard: OperationGuard): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Restore the `originX` / `originY` pair on a Fabric object after a
|
|
113
|
+
* rotation animation has been interrupted by dispose.
|
|
114
|
+
*
|
|
115
|
+
* `image/transform-controller.ts.rotateImage` temporarily sets the image
|
|
116
|
+
* origin to `'center'/'center'` so Fabric tweens the angle around the
|
|
117
|
+
* visual centroid (Fabric v7 defaults `originX`/`originY` to `'center'`,
|
|
118
|
+
* but the compatibility path uses `'left'/'top'` for placement math). The
|
|
119
|
+
* controller restores the original origin after the animation resolves.
|
|
120
|
+
* If dispose runs between begin and the post-animation restore, the
|
|
121
|
+
* controller's restore branch is skipped — leaving the image in the
|
|
122
|
+
* temporary center-origin state. This helper replays the restore so a
|
|
123
|
+
* post-dispose inspector (or a re-init that reuses the image reference)
|
|
124
|
+
* sees the documented top-left origin.
|
|
125
|
+
*
|
|
126
|
+
* The helper is intentionally side-effect-tolerant:
|
|
127
|
+
*
|
|
128
|
+
* - Errors are swallowed because the canvas may already have been
|
|
129
|
+
* disposed and `setCoords` could throw on a torn-down object. The
|
|
130
|
+
* point of the helper is best-effort cleanup, not a hard guarantee.
|
|
131
|
+
* - It does NOT request a render. The canvas is, by contract, on its way
|
|
132
|
+
* out (this is only called from the dispose path).
|
|
133
|
+
*
|
|
134
|
+
* @param object - Fabric object whose origin pair needs restoring.
|
|
135
|
+
* In practice this is the editor's `originalImage`.
|
|
136
|
+
* @param originX - Origin to restore on the X axis (typically `'left'`).
|
|
137
|
+
* @param originY - Origin to restore on the Y axis (typically `'top'`).
|
|
138
|
+
*
|
|
139
|
+
*/
|
|
140
|
+
export declare function restoreOrigin(object: FabricNS.FabricObject, originX: FabricNS.TOriginX, originY: FabricNS.TOriginY): void;
|
|
141
|
+
//# sourceMappingURL=fabric-animation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fabric-animation.d.ts","sourceRoot":"","sources":["../../../src/fabric/fabric-animation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAEH,OAAO,KAAK,KAAK,QAAQ,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAQjE;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC3B,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,QAAQ,CAAC,YAAY,EACxD,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAiFf;AAeD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,aAAa,CACzB,MAAM,EAAE,QAAQ,CAAC,YAAY,EAC7B,OAAO,EAAE,QAAQ,CAAC,QAAQ,EAC1B,OAAO,EAAE,QAAQ,CAAC,QAAQ,GAC3B,IAAI,CASN"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export shim for the {@link Command} class.
|
|
3
|
+
*
|
|
4
|
+
* The class itself is defined alongside {@link HistoryManager} in
|
|
5
|
+
* `./history-manager.ts` so the history module can be loaded directly
|
|
6
|
+
* from source by property tests running under Node's type-stripping
|
|
7
|
+
* mode without needing to resolve a sibling `.js` specifier at runtime.
|
|
8
|
+
*
|
|
9
|
+
* Module-layout consumers — and the canonical Module Responsibilities
|
|
10
|
+
* table — continue to see `command.ts` as the named home of the
|
|
11
|
+
* `Command` primitive.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
export { Command } from './history-manager.js';
|
|
16
|
+
//# sourceMappingURL=command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/history/command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC"}
|