@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,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hover, selection, and "original style restore" helpers for
|
|
3
|
+
* mask visual state. Owns the legacy `_getMaskNormalStyle`,
|
|
4
|
+
* `_withNormalizedMaskStyles`, `_rebindMaskEvents`, and the
|
|
5
|
+
* selected/unselected stroke logic from `_handleSelectionChanged`
|
|
6
|
+
* that were inlined on the editor in legacy and are now extracted
|
|
7
|
+
* into pure(ish) helpers that take a {@link MaskStyleContext}.
|
|
8
|
+
*
|
|
9
|
+
* Two callers consume the same backup shape:
|
|
10
|
+
*
|
|
11
|
+
* - Export bake-in (`export/export-service.ts`) — temporarily forces every
|
|
12
|
+
* mask to `opacity: 1, fill: '#000', strokeWidth: 0, stroke: null,
|
|
13
|
+
* selectable: false` so the rendered raster has solid black masks, and
|
|
14
|
+
* restores the live values inside a `finally` block whether the export
|
|
15
|
+
* succeeded or threw.
|
|
16
|
+
*
|
|
17
|
+
* - Crop session (`crop/crop-controller.ts`) — backs up the same fields plus
|
|
18
|
+
* `lockRotation` when entering crop mode and restores them on
|
|
19
|
+
* `cancelCrop`.
|
|
20
|
+
*
|
|
21
|
+
* Centralizing the backup shape, the hover style literals (`#ff5500`,
|
|
22
|
+
* `strokeWidth: 2`, `opacity = originalAlpha + 0.2`), and the
|
|
23
|
+
* selected/unselected stroke literals (`#ff0000`, `mask.originalStroke ||
|
|
24
|
+
* '#ccc'`) here means the legacy visuals stay pixel-identical and any future
|
|
25
|
+
* tweak happens in one place.
|
|
26
|
+
*
|
|
27
|
+
* ## Owned contracts
|
|
28
|
+
*
|
|
29
|
+
* - {@link captureMaskStyleBackup} captures the prior
|
|
30
|
+
* live values for `opacity`, `fill`, `stroke`, `strokeWidth`, `selectable`,
|
|
31
|
+
* `evented`, and `lockRotation` BEFORE any export-only mutation runs. The backup
|
|
32
|
+
* shape matches {@link MaskBackup} in `core/public-types.ts`.
|
|
33
|
+
*
|
|
34
|
+
* - {@link withMaskStyleBackup} runs the supplied
|
|
35
|
+
* mutator → callback inside a `try/finally` so {@link restoreMaskStyleBackup}
|
|
36
|
+
* is called regardless of whether the callback resolved or threw.
|
|
37
|
+
*
|
|
38
|
+
* - Each restored field is the exact value captured
|
|
39
|
+
* at the start of the operation; the restore performs no defaulting and
|
|
40
|
+
* no clamping, so an export-only style is never observable on any mask
|
|
41
|
+
* after the operation returns.
|
|
42
|
+
*
|
|
43
|
+
* - {@link applyCropHideMaskStyle} sets `opacity: 0`
|
|
44
|
+
* and `evented: false` on a mask so the user cannot interact with it
|
|
45
|
+
* while the crop rectangle is the only interactive object. The caller is
|
|
46
|
+
* expected to have captured a backup via {@link captureMaskStyleBackup}
|
|
47
|
+
* first.
|
|
48
|
+
*
|
|
49
|
+
* - {@link restoreMaskStyleBackup} restores
|
|
50
|
+
* `opacity`, `fill`, `strokeWidth`, `stroke`, `selectable`, `evented`,
|
|
51
|
+
* and `lockRotation` from the captured {@link MaskBackup}, matching the current
|
|
52
|
+
* documented `MaskBackup` interface.
|
|
53
|
+
*
|
|
54
|
+
* - **Mirrors legacy hover behavior** — {@link attachMaskHoverHandlers} and
|
|
55
|
+
* {@link reattachMaskHoverHandlers} bind the same `mouseover`/`mouseout`
|
|
56
|
+
* handlers legacy's `_rebindMaskEvents` used. The handlers read
|
|
57
|
+
* `mask.originalAlpha` / `mask.originalStroke` / `mask.originalStrokeWidth`
|
|
58
|
+
* on each invocation so they always reflect the current "live" state
|
|
59
|
+
* (e.g. after a stroke change from a selection event).
|
|
60
|
+
*
|
|
61
|
+
* - **Mirrors legacy selection styling** — {@link applyMaskSelectedStyle} sets
|
|
62
|
+
* the selection-highlight stroke (`#ff0000`, `strokeWidth: 1`) and
|
|
63
|
+
* {@link applyMaskUnselectedStyle} restores the normal stroke from the
|
|
64
|
+
* per-mask `originalStroke` / `originalStrokeWidth`. Both literals match
|
|
65
|
+
* legacy's `_handleSelectionChanged`.
|
|
66
|
+
*
|
|
67
|
+
* ## Out of scope (handled by sibling modules)
|
|
68
|
+
*
|
|
69
|
+
* - Mask creation, falsy-style preservation, polygon placement — see
|
|
70
|
+
* `mask/mask-factory.ts`.
|
|
71
|
+
* - Mask label overlay — see `mask/mask-label-manager.ts`.
|
|
72
|
+
* - Mask list DOM — see `mask/mask-list.ts`.
|
|
73
|
+
*
|
|
74
|
+
* ## Implementation notes
|
|
75
|
+
*
|
|
76
|
+
* - The orchestrator (`src/image-editor.ts`) owns the canvas reference and
|
|
77
|
+
* the resolved options. The helpers in this module receive those slots
|
|
78
|
+
* through a {@link MaskStyleContext} so the module is independent of the
|
|
79
|
+
* `ImageEditor` class shape and can be unit tested in isolation against
|
|
80
|
+
* a stub Fabric environment.
|
|
81
|
+
* - Hover handlers do NOT cache the normal/hover style at attach time. They
|
|
82
|
+
* read `mask.originalAlpha` / `mask.originalStroke` / `mask.originalStrokeWidth`
|
|
83
|
+
* on every event so the visual matches the live "original" values even
|
|
84
|
+
* after a stroke or opacity change (matching legacy).
|
|
85
|
+
* - The handlers are tagged on `mask.imageEditorMaskHandlers` exactly as
|
|
86
|
+
* legacy did so {@link reattachMaskHoverHandlers} can drop the old pair before
|
|
87
|
+
* binding fresh ones, avoiding duplicate listeners after `loadFromJSON`.
|
|
88
|
+
*
|
|
89
|
+
* @module
|
|
90
|
+
*/
|
|
91
|
+
import type * as FabricNS from 'fabric';
|
|
92
|
+
import type { MaskBackup, MaskObject, ResolvedOptions } from '../core/public-types.js';
|
|
93
|
+
/**
|
|
94
|
+
* State the mask-style helpers read from the `ImageEditor` orchestrator.
|
|
95
|
+
*
|
|
96
|
+
* The module does NOT own any of these slots — it only reads them so
|
|
97
|
+
* ownership of the canvas and resolved options stays on the orchestrator
|
|
98
|
+
* (where legacy left them).
|
|
99
|
+
*/
|
|
100
|
+
export interface MaskStyleContext {
|
|
101
|
+
/**
|
|
102
|
+
* The live Fabric canvas. May be `null` after `dispose` or before
|
|
103
|
+
* `init` has run; the helpers no-op in that case.
|
|
104
|
+
*/
|
|
105
|
+
canvas: FabricNS.Canvas | null;
|
|
106
|
+
/**
|
|
107
|
+
* Fully resolved editor options. Only consulted by helpers that need
|
|
108
|
+
* the export-bake-in fill (`#000` matches legacy) or the crop visibility
|
|
109
|
+
* defaults; most helpers operate on the per-mask `original*` fields
|
|
110
|
+
* and do not need this slot.
|
|
111
|
+
*/
|
|
112
|
+
options?: ResolvedOptions;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* The "normal" (non-hover, non-selected) style of a mask, computed from
|
|
116
|
+
* its persisted `original*` fields. Matches the shape returned by legacy's
|
|
117
|
+
* `_getMaskNormalStyle`.
|
|
118
|
+
*/
|
|
119
|
+
export interface MaskNormalStyle {
|
|
120
|
+
stroke: FabricNS.TFiller | string | null;
|
|
121
|
+
strokeWidth: number;
|
|
122
|
+
opacity: number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Compute the "normal" (non-hover, non-selected) style of `mask` from its
|
|
126
|
+
* persisted `original*` fields, with legacy-identical fallbacks.
|
|
127
|
+
*
|
|
128
|
+
* - `stroke` → `mask.originalStroke`, falling back to `'#ccc'` (legacy).
|
|
129
|
+
* - `strokeWidth` → `Number(mask.originalStrokeWidth)` if finite, else `1`.
|
|
130
|
+
* - `opacity` → `Number(mask.originalAlpha)` if finite, else `0.5`.
|
|
131
|
+
*
|
|
132
|
+
* The result is used by:
|
|
133
|
+
* - {@link applyMaskNormalStyle} to restore on `mouseout`,
|
|
134
|
+
* - {@link applyMaskUnselectedStyle} to restore the un-highlighted stroke,
|
|
135
|
+
* - export bake-in callers that want a pre-mutation snapshot of the live
|
|
136
|
+
* visual when no `MaskBackup` is being captured.
|
|
137
|
+
*
|
|
138
|
+
* @param mask - The mask to inspect.
|
|
139
|
+
* @returns A {@link MaskNormalStyle} ready to pass to `mask.set(...)`.
|
|
140
|
+
*/
|
|
141
|
+
export declare function getMaskNormalStyle(mask: MaskObject): MaskNormalStyle;
|
|
142
|
+
/**
|
|
143
|
+
* Compute the "hover" style for `mask`, derived from its normal style.
|
|
144
|
+
*
|
|
145
|
+
* - `stroke` → `'#ff5500'` (legacy).
|
|
146
|
+
* - `strokeWidth` → `2` (legacy).
|
|
147
|
+
* - `opacity` → `min(originalAlpha + 0.2, 1)` (legacy).
|
|
148
|
+
*
|
|
149
|
+
* @param mask - The mask to inspect.
|
|
150
|
+
* @returns A style patch ready to pass to `mask.set(...)`.
|
|
151
|
+
*/
|
|
152
|
+
export declare function getMaskHoverStyle(mask: MaskObject): MaskNormalStyle;
|
|
153
|
+
/**
|
|
154
|
+
* Apply the selected-mask highlight stroke. Matches legacy's literal
|
|
155
|
+
* (`stroke: '#ff0000'`, `strokeWidth: 1`).
|
|
156
|
+
*
|
|
157
|
+
* Does NOT change opacity — the selection highlight only modifies the
|
|
158
|
+
* outline so the user can still see the mask's tinted fill.
|
|
159
|
+
*
|
|
160
|
+
* @param mask - The mask becoming selected.
|
|
161
|
+
*/
|
|
162
|
+
export declare function applyMaskSelectedStyle(mask: MaskObject): void;
|
|
163
|
+
/**
|
|
164
|
+
* Restore the un-highlighted stroke on `mask` after selection moves to a
|
|
165
|
+
* different object. Reads the per-mask `originalStroke`/`originalStrokeWidth`
|
|
166
|
+
* (matching legacy's `_handleSelectionChanged`) so the value is the one the
|
|
167
|
+
* mask carried before any selection-time mutation.
|
|
168
|
+
*
|
|
169
|
+
* Does NOT touch `opacity` — the un-highlighted state retains the live
|
|
170
|
+
* opacity (which may differ from `originalAlpha` while a hover is in
|
|
171
|
+
* progress, etc.).
|
|
172
|
+
*
|
|
173
|
+
* @param mask - The mask becoming un-selected.
|
|
174
|
+
*/
|
|
175
|
+
export declare function applyMaskUnselectedStyle(mask: MaskObject): void;
|
|
176
|
+
/**
|
|
177
|
+
* Bind `mouseover`/`mouseout` handlers on `mask` that toggle the legacy hover
|
|
178
|
+
* highlight. The handlers re-read `mask.originalAlpha` /
|
|
179
|
+
* `mask.originalStroke` / `mask.originalStrokeWidth` on each event so they
|
|
180
|
+
* track any post-attach mutation (matching legacy's `_rebindMaskEvents`).
|
|
181
|
+
*
|
|
182
|
+
* Handlers are tagged on `mask.imageEditorMaskHandlers` so
|
|
183
|
+
* {@link reattachMaskHoverHandlers} can drop them before binding a new
|
|
184
|
+
* pair, avoiding duplicates after a `loadFromJSON` restore.
|
|
185
|
+
*
|
|
186
|
+
* Idempotent — calling twice on the same mask without an intervening
|
|
187
|
+
* detach simply produces two pairs of listeners. Use
|
|
188
|
+
* {@link reattachMaskHoverHandlers} to refresh listeners safely.
|
|
189
|
+
*
|
|
190
|
+
* @param mask - The mask to bind handlers on.
|
|
191
|
+
*/
|
|
192
|
+
export declare function attachMaskHoverHandlers(mask: MaskObject): void;
|
|
193
|
+
/**
|
|
194
|
+
* Drop any previously-attached hover handler pair (best-effort) and bind a
|
|
195
|
+
* fresh pair via {@link attachMaskHoverHandlers}.
|
|
196
|
+
*
|
|
197
|
+
* Used after `canvas.loadFromJSON` in `core/state-serializer.ts`'s
|
|
198
|
+
* `loadFromState` flow, because Fabric never serializes event listeners,
|
|
199
|
+
* so masks restored from history have lost their hover styling. The
|
|
200
|
+
* orchestrator re-runs this helper for every restored mask.
|
|
201
|
+
*
|
|
202
|
+
* Also re-asserts the persisted `original*` metadata when missing — legacy's
|
|
203
|
+
* `_rebindMaskEvents` did the same so a snapshot from an older format that
|
|
204
|
+
* happens to lack `originalStroke`/`originalStrokeWidth` still hovers
|
|
205
|
+
* correctly. The current Pretty_Printer always serializes
|
|
206
|
+
* `originalAlpha`, but we defend against partial payloads here too.
|
|
207
|
+
*
|
|
208
|
+
* @param mask - The mask to refresh handlers on.
|
|
209
|
+
*/
|
|
210
|
+
export declare function reattachMaskHoverHandlers(mask: MaskObject): void;
|
|
211
|
+
/**
|
|
212
|
+
* Detach the hover handler pair previously bound by
|
|
213
|
+
* {@link attachMaskHoverHandlers} (or {@link reattachMaskHoverHandlers}).
|
|
214
|
+
*
|
|
215
|
+
* Best-effort — wraps each `off(...)` in `try/catch` so a stale Fabric
|
|
216
|
+
* reference does not break callers that iterate every mask (e.g. the
|
|
217
|
+
* `dispose` path or `removeAllMasks`).
|
|
218
|
+
*
|
|
219
|
+
* @param mask - The mask to detach handlers from.
|
|
220
|
+
*/
|
|
221
|
+
export declare function detachMaskHoverHandlers(mask: MaskObject): void;
|
|
222
|
+
/**
|
|
223
|
+
* Snapshot the current live values of the fields that both the export
|
|
224
|
+
* bake-in path and the crop session need to restore later.
|
|
225
|
+
*
|
|
226
|
+
* Captured fields:
|
|
227
|
+
*
|
|
228
|
+
* - `opacity` — restored when the export ends or the crop is canceled.
|
|
229
|
+
* - `fill` — export bake-in temporarily forces `'#000'`; crop never
|
|
230
|
+
* changes fill but captures it so a single restore call works for both.
|
|
231
|
+
* - `strokeWidth` — export bake-in forces `0`.
|
|
232
|
+
* - `stroke` — export bake-in forces `null`.
|
|
233
|
+
* - `selectable` — both paths force `false` so the mask is not draggable
|
|
234
|
+
* while the operation is in progress.
|
|
235
|
+
* - `evented` — the crop session forces `false` while the crop rectangle is
|
|
236
|
+
* the only interactive object.
|
|
237
|
+
* - `lockRotation` — the crop session captures this because some integrators
|
|
238
|
+
* set `maskRotatable: true` and the rotation lock is part of the
|
|
239
|
+
* per-mask state.
|
|
240
|
+
*
|
|
241
|
+
* Defaults match legacy: missing `opacity` → `1`, missing `selectable` →
|
|
242
|
+
* `true`, missing `lockRotation` → `false`. They never override a
|
|
243
|
+
* caller-supplied value because the snapshot reads from the live mask.
|
|
244
|
+
*
|
|
245
|
+
* @param mask - The mask whose live style should be captured.
|
|
246
|
+
* @returns A {@link MaskBackup} suitable for passing to
|
|
247
|
+
* {@link restoreMaskStyleBackup}.
|
|
248
|
+
*/
|
|
249
|
+
export declare function captureMaskStyleBackup(mask: MaskObject): MaskBackup;
|
|
250
|
+
/**
|
|
251
|
+
* Restore every backed-up field from a {@link MaskBackup} onto the mask
|
|
252
|
+
* referenced by `backup.object`.
|
|
253
|
+
*
|
|
254
|
+
* Wraps the `set(...)` call in `try/catch` so a stale Fabric reference (a
|
|
255
|
+
* mask removed after the backup was captured but before the restore
|
|
256
|
+
* finally block ran) does not break callers iterating multiple backups.
|
|
257
|
+
* After a successful restore, `setCoords` is called to keep Fabric's
|
|
258
|
+
* cached bounding rect in sync (matching legacy's mergeMasks restore).
|
|
259
|
+
*
|
|
260
|
+
* @param backup - The backup produced by {@link captureMaskStyleBackup}.
|
|
261
|
+
*
|
|
262
|
+
*/
|
|
263
|
+
export declare function restoreMaskStyleBackup(backup: MaskBackup): void;
|
|
264
|
+
/**
|
|
265
|
+
* Run `callback` with every mask's stroke/strokeWidth/opacity reset to the
|
|
266
|
+
* persisted "normal" style ({@link getMaskNormalStyle}), then restore each
|
|
267
|
+
* mutated field inside a `finally` block.
|
|
268
|
+
*
|
|
269
|
+
* Mirrors legacy's `_withNormalizedMaskStyles`. The two callers are:
|
|
270
|
+
*
|
|
271
|
+
* - The pre-snapshot pass in some history paths that wants the snapshot
|
|
272
|
+
* to capture a "clean" un-hovered, un-selected canvas regardless of the
|
|
273
|
+
* live UI state.
|
|
274
|
+
* - The crop-cancel restore path that wants to clear any selection
|
|
275
|
+
* highlight before re-rendering.
|
|
276
|
+
*
|
|
277
|
+
* Only fields that ACTUALLY changed are captured and restored — if a mask
|
|
278
|
+
* is already at its normal style, no patch is recorded for it.
|
|
279
|
+
*
|
|
280
|
+
* The `finally` block runs whether `callback` returned, threw, or
|
|
281
|
+
* rejected. The function returns whatever `callback` returns (sync or
|
|
282
|
+
* Promise), preserving the caller's control flow.
|
|
283
|
+
*
|
|
284
|
+
* @param context - Orchestration context — see {@link MaskStyleContext}.
|
|
285
|
+
* @param callback - Body to execute with normalized mask styles.
|
|
286
|
+
* @returns The value returned by `callback` (or the promise it returned).
|
|
287
|
+
*/
|
|
288
|
+
export declare function withNormalizedMaskStyles<T>(context: MaskStyleContext, callback: () => T): T;
|
|
289
|
+
/**
|
|
290
|
+
* Captures every mask's live style via {@link captureMaskStyleBackup},
|
|
291
|
+
* runs the supplied async `callback` (which is allowed to mutate masks
|
|
292
|
+
* freely — typically by forcing the export bake-in style of
|
|
293
|
+
* `opacity: 1, fill: '#000', strokeWidth: 0, stroke: null,
|
|
294
|
+
* selectable: false`), then restores every mask's pre-callback state in a
|
|
295
|
+
* `finally` block — even if `callback` rejected.
|
|
296
|
+
*
|
|
297
|
+
* This is the canonical owner of the "export-only style restoration"
|
|
298
|
+
* contract. Callers in
|
|
299
|
+
* `export/export-service.ts` use this so they never need to write their
|
|
300
|
+
* own `try/finally` block — and so a future refactor cannot accidentally
|
|
301
|
+
* forget the restore step on an early return path.
|
|
302
|
+
*
|
|
303
|
+
* The function returns whatever `callback` resolves to.
|
|
304
|
+
*
|
|
305
|
+
* @typeParam T - The return type of `callback`.
|
|
306
|
+
* @param context - Orchestration context — see {@link MaskStyleContext}.
|
|
307
|
+
* @param mutator - Synchronous function applied to each captured mask
|
|
308
|
+
* BEFORE `callback` runs. Typically applies the export
|
|
309
|
+
* bake-in style. Called once per mask in canvas object
|
|
310
|
+
* order with `(mask, index)`. Backups are captured BEFORE
|
|
311
|
+
* the mutator runs so an exception in the mutator still
|
|
312
|
+
* triggers the `finally` restore for already-mutated
|
|
313
|
+
* masks.
|
|
314
|
+
* @param callback - The export body to run after every mutator pass
|
|
315
|
+
* completed. Typically `canvas.toDataURL` plus any
|
|
316
|
+
* post-processing.
|
|
317
|
+
* @returns The value `callback` resolved to.
|
|
318
|
+
*
|
|
319
|
+
*/
|
|
320
|
+
export declare function withMaskStyleBackup<T>(context: MaskStyleContext, mutator: (mask: MaskObject, index: number) => void, callback: () => Promise<T> | T): Promise<T>;
|
|
321
|
+
/**
|
|
322
|
+
* Apply the crop-mode hide style on `mask`: opacity 0 + non-interactive.
|
|
323
|
+
*
|
|
324
|
+
* Used by `crop/crop-controller.ts` when entering crop mode with
|
|
325
|
+
* `options.crop.hideMasksDuringCrop === true`. Callers MUST capture a
|
|
326
|
+
* {@link MaskBackup} via {@link captureMaskStyleBackup} BEFORE calling
|
|
327
|
+
* this helper so {@link restoreMaskStyleBackup} can revert the change on
|
|
328
|
+
* `cancelCrop`.
|
|
329
|
+
*
|
|
330
|
+
* Sets `evented: false` and `selectable: false` so the user cannot
|
|
331
|
+
* interact with the mask while only the crop rectangle should respond to
|
|
332
|
+
* pointer events. Wraps the `set(...)` in `try/catch` so a removed mask
|
|
333
|
+
* does not break the loop in the controller.
|
|
334
|
+
*
|
|
335
|
+
* @param mask - The mask to hide.
|
|
336
|
+
*/
|
|
337
|
+
export declare function applyCropHideMaskStyle(mask: MaskObject): void;
|
|
338
|
+
//# sourceMappingURL=mask-style.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask-style.d.ts","sourceRoot":"","sources":["../../../src/mask/mask-style.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyFG;AAEH,OAAO,KAAK,KAAK,QAAQ,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAwBvF;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;;OAGG;IACH,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,QAAQ,CAAC,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACnB;AAoBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,eAAe,CAQpE;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,eAAe,CAQnE;AAID;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAE7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAM/D;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAe9D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAwChE;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAU9D;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAWnE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAiB/D;AAeD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAiC3F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACvC,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,EAClD,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAM7D"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mosaic mode controller.
|
|
3
|
+
*
|
|
4
|
+
* Owns the Mosaic session lifecycle, preview objects, Fabric pointer handlers,
|
|
5
|
+
* and the base-image pixel replacement pipeline. The ImageEditor facade owns
|
|
6
|
+
* canonical editor state and passes it in through the context callbacks.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import type * as FabricNS from 'fabric';
|
|
11
|
+
import type { FabricModule, ImageEditorCallbackContext, ImageEditorOperation, ImageMimeType, ResolvedMosaicConfig, ResolvedOptions } from '../core/public-types.js';
|
|
12
|
+
import { type HistoryManager } from '../history/history-manager.js';
|
|
13
|
+
import { type MosaicImagePoint } from './mosaic-geometry.js';
|
|
14
|
+
interface MosaicPreviewCircle extends FabricNS.Circle {
|
|
15
|
+
isMosaicPreview?: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface MosaicPreviewImage extends FabricNS.FabricImage {
|
|
18
|
+
isMosaicPreview?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface MosaicSession {
|
|
21
|
+
previewCircle: MosaicPreviewCircle | null;
|
|
22
|
+
previewImage: MosaicPreviewImage | null;
|
|
23
|
+
prevSelection: boolean;
|
|
24
|
+
prevDefaultCursor: string | undefined;
|
|
25
|
+
prevObjectStates: Array<{
|
|
26
|
+
object: FabricNS.FabricObject;
|
|
27
|
+
evented: boolean;
|
|
28
|
+
selectable: boolean;
|
|
29
|
+
}>;
|
|
30
|
+
handlers: Array<{
|
|
31
|
+
eventName: string;
|
|
32
|
+
callback: (event: unknown) => void;
|
|
33
|
+
}>;
|
|
34
|
+
rasterCache: MosaicRasterCache | null;
|
|
35
|
+
pendingCanvasPoints: Array<{
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
}>;
|
|
39
|
+
isPointerDown: boolean;
|
|
40
|
+
isApplying: boolean;
|
|
41
|
+
commitRequested: boolean;
|
|
42
|
+
hasUncommittedChanges: boolean;
|
|
43
|
+
lastImagePoint: MosaicImagePoint | null;
|
|
44
|
+
}
|
|
45
|
+
export interface MosaicControllerContext {
|
|
46
|
+
readonly fabric: FabricModule;
|
|
47
|
+
readonly canvas: FabricNS.Canvas;
|
|
48
|
+
readonly options: ResolvedOptions;
|
|
49
|
+
readonly historyManager: HistoryManager;
|
|
50
|
+
getMosaicConfig(): ResolvedMosaicConfig;
|
|
51
|
+
isImageLoaded(): boolean;
|
|
52
|
+
getOriginalImage(): FabricNS.FabricImage | null;
|
|
53
|
+
setOriginalImage(image: FabricNS.FabricImage | null): void;
|
|
54
|
+
getCurrentImageMimeType(): ImageMimeType | null;
|
|
55
|
+
setCurrentImageMimeType(mimeType: ImageMimeType | null): void;
|
|
56
|
+
getLastSnapshot(): string | null;
|
|
57
|
+
setLastSnapshot(snapshot: string | null): void;
|
|
58
|
+
captureSnapshot(): string;
|
|
59
|
+
loadFromState(snapshot: string): Promise<void>;
|
|
60
|
+
updateUi(): void;
|
|
61
|
+
updateInputs(): void;
|
|
62
|
+
hideAllMaskLabels(): void;
|
|
63
|
+
emitImageChanged(context: ImageEditorCallbackContext): void;
|
|
64
|
+
emitBusyChangeIfChanged(context: ImageEditorCallbackContext): void;
|
|
65
|
+
buildCallbackContext(operation: ImageEditorOperation, isInternal?: boolean): ImageEditorCallbackContext;
|
|
66
|
+
getMosaicSession(): MosaicSession | null;
|
|
67
|
+
setMosaicSession(session: MosaicSession | null): void;
|
|
68
|
+
}
|
|
69
|
+
interface MosaicRasterCache {
|
|
70
|
+
offscreenCanvas: HTMLCanvasElement;
|
|
71
|
+
renderingContext: CanvasRenderingContext2D;
|
|
72
|
+
imageData: ImageData;
|
|
73
|
+
source: string;
|
|
74
|
+
width: number;
|
|
75
|
+
height: number;
|
|
76
|
+
}
|
|
77
|
+
export declare function enterMosaicMode(context: MosaicControllerContext): void;
|
|
78
|
+
export declare function exitMosaicMode(context: MosaicControllerContext): void;
|
|
79
|
+
export declare function updateMosaicPreview(context: MosaicControllerContext): void;
|
|
80
|
+
export declare function isMosaicPreviewObject(object: FabricNS.FabricObject): boolean;
|
|
81
|
+
export {};
|
|
82
|
+
//# sourceMappingURL=mosaic-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mosaic-controller.d.ts","sourceRoot":"","sources":["../../../src/mosaic/mosaic-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canvas-to-source-image coordinate conversion for Mosaic mode.
|
|
3
|
+
*
|
|
4
|
+
* Fabric object bounding boxes are not sufficient for rotated images. These
|
|
5
|
+
* helpers invert the image transform matrix and convert the pointer into the
|
|
6
|
+
* image's natural pixel coordinate space.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import type * as FabricNS from 'fabric';
|
|
11
|
+
import type { FabricModule } from '../core/public-types.js';
|
|
12
|
+
export interface MosaicImagePoint {
|
|
13
|
+
sourceX: number;
|
|
14
|
+
sourceY: number;
|
|
15
|
+
sourceRadius: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Convert a Fabric canvas pointer into source-image pixels.
|
|
19
|
+
*
|
|
20
|
+
* For non-uniform image scale, `sourceRadius` uses the smaller canvas scale
|
|
21
|
+
* axis, which yields the larger source-space radius. This conservative
|
|
22
|
+
* deterministic strategy ensures the circular canvas brush covers the clicked
|
|
23
|
+
* image area after inverse transformation.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getMosaicImagePoint(fabric: FabricModule, image: FabricNS.FabricImage, canvasPoint: {
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
}, brushDiameterCanvasPx: number): MosaicImagePoint | null;
|
|
29
|
+
//# sourceMappingURL=mosaic-geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mosaic-geometry.d.ts","sourceRoot":"","sources":["../../../src/mosaic/mosaic-geometry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,KAAK,QAAQ,MAAM,QAAQ,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACxB;AAwED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,QAAQ,CAAC,WAAW,EAC3B,WAAW,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EACrC,qBAAqB,EAAE,MAAM,GAC9B,gBAAgB,GAAG,IAAI,CAmCzB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure pixelation helpers for Mosaic mode.
|
|
3
|
+
*
|
|
4
|
+
* The helpers mutate caller-supplied ImageData in place and do not touch DOM
|
|
5
|
+
* or Fabric state, which keeps the algorithm deterministic and directly
|
|
6
|
+
* testable.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
export interface MosaicPixelateOptions {
|
|
11
|
+
imageData: ImageData;
|
|
12
|
+
centerX: number;
|
|
13
|
+
centerY: number;
|
|
14
|
+
radius: number;
|
|
15
|
+
blockSize: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Applies blocky pixelation inside a circular brush region.
|
|
19
|
+
*
|
|
20
|
+
* @returns `true` when at least one pixel was processed, otherwise `false`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function applyCircularMosaicToImageData(options: MosaicPixelateOptions): boolean;
|
|
23
|
+
//# sourceMappingURL=mosaic-pixelate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mosaic-pixelate.d.ts","sourceRoot":"","sources":["../../../src/mosaic/mosaic-pixelate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,qBAAqB;IAClC,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACrB;AAsBD;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAiEtF"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Managed registry of DOM event listeners owned by the
|
|
3
|
+
* {@link ImageEditor} facade. Records every listener it adds so
|
|
4
|
+
* `dispose` can detach them all idempotently.
|
|
5
|
+
*
|
|
6
|
+
* ## Owned contracts
|
|
7
|
+
*
|
|
8
|
+
* - `bindIfExists(key, event, handler)` records the
|
|
9
|
+
* `{ elementKey, eventType, handler}` triple in an internal registry as
|
|
10
|
+
* the listener is attached.
|
|
11
|
+
* - `removeAll` iterates the registry, calls
|
|
12
|
+
* `removeEventListener` for every recorded entry, and clears the registry
|
|
13
|
+
* afterwards.
|
|
14
|
+
* - Every `removeEventListener` call is wrapped in
|
|
15
|
+
* `try/catch` so a second `dispose` (or a listener that has already been
|
|
16
|
+
* detached by other means) never throws. `removeAll` is idempotent.
|
|
17
|
+
* - Every bound handler is wrapped so it consults the
|
|
18
|
+
* editor's `isDisposed` flag (via the `isDisposed` callback supplied to the
|
|
19
|
+
* constructor) and exits early without touching the canvas while disposed.
|
|
20
|
+
*
|
|
21
|
+
* ## Why this lives in its own module
|
|
22
|
+
*
|
|
23
|
+
* The orchestrator's `dispose` path needs to detach DOM listeners without
|
|
24
|
+
* caring about which logical key originally owned each one. Co-locating the
|
|
25
|
+
* registry here keeps the orchestrator free of bookkeeping and lets unit
|
|
26
|
+
* tests exercise the bindings registry without instantiating a full editor.
|
|
27
|
+
* This module is imported by `image-editor.ts` only and is intentionally not
|
|
28
|
+
* re-exported from `src/index.ts`.
|
|
29
|
+
*
|
|
30
|
+
* @module
|
|
31
|
+
*/
|
|
32
|
+
import type { ElementIdMap } from '../core/public-types.js';
|
|
33
|
+
/**
|
|
34
|
+
* Logical element-name keys understood by the editor's `idMap`. Mirrors the
|
|
35
|
+
* `ElementKey` alias used internally by `image-editor.ts` so callers can
|
|
36
|
+
* speak the same vocabulary without crossing the public-types boundary.
|
|
37
|
+
*/
|
|
38
|
+
export type ElementKey = keyof Required<ElementIdMap>;
|
|
39
|
+
/**
|
|
40
|
+
* Lightweight registry of DOM event listeners owned by an editor instance.
|
|
41
|
+
*
|
|
42
|
+
* The class is intentionally small: it does not know about Fabric, the
|
|
43
|
+
* animation queue, or the operation guard — it only knows how to look up an
|
|
44
|
+
* element ID for a key and how to add/remove a listener. Disposed-state
|
|
45
|
+
* awareness comes in via the `isDisposed` callback so the guard can stay the
|
|
46
|
+
* single source of truth for the `isDisposed` flag (see
|
|
47
|
+
* `core/operation-guard.ts`).
|
|
48
|
+
*
|
|
49
|
+
* Usage:
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* const bindings = new DomBindings(
|
|
53
|
+
* (key) => this.elements[key],
|
|
54
|
+
* () => this.guard.isDisposed(),
|
|
55
|
+
* );
|
|
56
|
+
* bindings.bindIfExists('zoomInButton', 'click', () =>
|
|
57
|
+
* this.scaleImage(s + step),
|
|
58
|
+
* );
|
|
59
|
+
* // ...
|
|
60
|
+
* bindings.removeAll(); // called from dispose
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare class DomBindings {
|
|
64
|
+
private registry;
|
|
65
|
+
private readonly resolveElementId;
|
|
66
|
+
private readonly isDisposed;
|
|
67
|
+
private readonly resolveDocument;
|
|
68
|
+
/**
|
|
69
|
+
* @param resolveElementId - Returns the resolved DOM element ID for a given logical key, or a
|
|
70
|
+
* falsy value when the integrator omitted that key from the `idMap`.
|
|
71
|
+
* The orchestrator's `elements` table fills this role.
|
|
72
|
+
* @param isDisposed - Returns the editor's current `isDisposed` flag. Bound handlers
|
|
73
|
+
* consult this on every dispatch and exit early when it returns
|
|
74
|
+
* `true`.
|
|
75
|
+
* @param resolveDocument - Returns the document that owns the bound controls.
|
|
76
|
+
*/
|
|
77
|
+
constructor(resolveElementId: (key: ElementKey) => string | null | undefined, isDisposed: () => boolean, resolveDocument?: () => Document);
|
|
78
|
+
/**
|
|
79
|
+
* Look up the element registered under `key`. If it exists, attach
|
|
80
|
+
* `handler` for `eventType` and record the binding so `removeAll` can
|
|
81
|
+
* detach it later. The handler is wrapped to short-circuit when the
|
|
82
|
+
* editor has been disposed.
|
|
83
|
+
*
|
|
84
|
+
* Missing keys and missing elements are silently ignored — the editor
|
|
85
|
+
* tolerates partial DOM as documented under {@link ElementIdMap}.
|
|
86
|
+
*
|
|
87
|
+
* @returns `true` if the listener was attached, `false` if the element
|
|
88
|
+
* could not be resolved.
|
|
89
|
+
*/
|
|
90
|
+
bindIfExists(key: ElementKey, eventType: string, handler: EventListener): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Detach every recorded listener and clear the registry. Each
|
|
93
|
+
* `removeEventListener` call is wrapped in `try/catch` so an
|
|
94
|
+
* already-detached listener (for example because the host page swapped
|
|
95
|
+
* out the DOM node) does not abort the cleanup loop. Calling `removeAll`
|
|
96
|
+
* a second time is a no-op.
|
|
97
|
+
*/
|
|
98
|
+
removeAll(): void;
|
|
99
|
+
/**
|
|
100
|
+
* Number of currently-registered listeners. Exposed for diagnostics and
|
|
101
|
+
* for the unit tests under `tests/units/dom-bindings.test.mjs`.
|
|
102
|
+
*/
|
|
103
|
+
size(): number;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=dom-bindings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-bindings.d.ts","sourceRoot":"","sources":["../../../src/ui/dom-bindings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,CAAC;AActD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAiD;IAClF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IAEjD;;;;;;;;OAQG;gBAEC,gBAAgB,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,EAChE,UAAU,EAAE,MAAM,OAAO,EACzB,eAAe,GAAE,MAAM,QAAyB;IAOpD;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO;IAmBjF;;;;;;OAMG;IACH,SAAS,IAAI,IAAI;IAgBjB;;;OAGG;IACH,IAAI,IAAI,MAAM;CAGjB"}
|