@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.
Files changed (154) hide show
  1. package/README.md +367 -518
  2. package/dist/cjs/index.cjs +5422 -0
  3. package/dist/cjs/index.cjs.map +1 -0
  4. package/dist/esm/animation/animation-queue.js +67 -0
  5. package/dist/esm/animation/animation-queue.js.map +1 -0
  6. package/dist/esm/core/callback-reporter.js +23 -0
  7. package/dist/esm/core/callback-reporter.js.map +1 -0
  8. package/dist/esm/core/default-options.js +322 -0
  9. package/dist/esm/core/default-options.js.map +1 -0
  10. package/dist/esm/core/errors.js +156 -0
  11. package/dist/esm/core/errors.js.map +1 -0
  12. package/dist/esm/core/operation-guard.js +129 -0
  13. package/dist/esm/core/operation-guard.js.map +1 -0
  14. package/dist/esm/core/public-types.js +4 -0
  15. package/dist/esm/core/public-types.js.map +1 -0
  16. package/dist/esm/core/state-serializer.js +251 -0
  17. package/dist/esm/core/state-serializer.js.map +1 -0
  18. package/dist/esm/crop/crop-controller.js +403 -0
  19. package/dist/esm/crop/crop-controller.js.map +1 -0
  20. package/dist/esm/export/export-format.js +53 -0
  21. package/dist/esm/export/export-format.js.map +1 -0
  22. package/dist/esm/export/export-service.js +596 -0
  23. package/dist/esm/export/export-service.js.map +1 -0
  24. package/dist/esm/fabric/fabric-adapter.js +37 -0
  25. package/dist/esm/fabric/fabric-adapter.js.map +1 -0
  26. package/dist/esm/fabric/fabric-animation.js +37 -0
  27. package/dist/esm/fabric/fabric-animation.js.map +1 -0
  28. package/dist/esm/history/command.js +2 -0
  29. package/dist/esm/history/command.js.map +1 -0
  30. package/dist/esm/history/history-manager.js +103 -0
  31. package/dist/esm/history/history-manager.js.map +1 -0
  32. package/dist/esm/image/image-loader.js +245 -0
  33. package/dist/esm/image/image-loader.js.map +1 -0
  34. package/dist/esm/image/image-resampler.js +55 -0
  35. package/dist/esm/image/image-resampler.js.map +1 -0
  36. package/dist/esm/image/layout-manager.js +224 -0
  37. package/dist/esm/image/layout-manager.js.map +1 -0
  38. package/dist/esm/image/transform-controller.js +132 -0
  39. package/dist/esm/image/transform-controller.js.map +1 -0
  40. package/dist/esm/image-editor.js +1740 -0
  41. package/dist/esm/image-editor.js.map +1 -0
  42. package/dist/esm/index.js +5 -0
  43. package/dist/esm/index.js.map +1 -0
  44. package/dist/esm/mask/mask-factory.js +332 -0
  45. package/dist/esm/mask/mask-factory.js.map +1 -0
  46. package/dist/esm/mask/mask-label-manager.js +120 -0
  47. package/dist/esm/mask/mask-label-manager.js.map +1 -0
  48. package/dist/esm/mask/mask-list.js +47 -0
  49. package/dist/esm/mask/mask-list.js.map +1 -0
  50. package/dist/esm/mask/mask-style.js +182 -0
  51. package/dist/esm/mask/mask-style.js.map +1 -0
  52. package/dist/esm/ui/dom-bindings.js +60 -0
  53. package/dist/esm/ui/dom-bindings.js.map +1 -0
  54. package/dist/esm/ui/ui-state.js +25 -0
  55. package/dist/esm/ui/ui-state.js.map +1 -0
  56. package/dist/esm/ui/visibility-state.js +11 -0
  57. package/dist/esm/ui/visibility-state.js.map +1 -0
  58. package/dist/esm/utils/canvas-region.js +100 -0
  59. package/dist/esm/utils/canvas-region.js.map +1 -0
  60. package/dist/esm/utils/dom.js +6 -0
  61. package/dist/esm/utils/dom.js.map +1 -0
  62. package/dist/esm/utils/file.js +53 -0
  63. package/dist/esm/utils/file.js.map +1 -0
  64. package/dist/esm/utils/number.js +24 -0
  65. package/dist/esm/utils/number.js.map +1 -0
  66. package/dist/esm/utils/timeout.js +17 -0
  67. package/dist/esm/utils/timeout.js.map +1 -0
  68. package/dist/types/animation/animation-queue.d.ts +111 -0
  69. package/dist/types/animation/animation-queue.d.ts.map +1 -0
  70. package/dist/types/core/callback-reporter.d.ts +125 -0
  71. package/dist/types/core/callback-reporter.d.ts.map +1 -0
  72. package/dist/types/core/default-options.d.ts +56 -0
  73. package/dist/types/core/default-options.d.ts.map +1 -0
  74. package/dist/types/core/errors.d.ts +142 -0
  75. package/dist/types/core/errors.d.ts.map +1 -0
  76. package/dist/types/core/operation-guard.d.ts +192 -0
  77. package/dist/types/core/operation-guard.d.ts.map +1 -0
  78. package/dist/types/core/public-types.d.ts +678 -0
  79. package/dist/types/core/public-types.d.ts.map +1 -0
  80. package/dist/types/core/state-serializer.d.ts +301 -0
  81. package/dist/types/core/state-serializer.d.ts.map +1 -0
  82. package/dist/types/crop/crop-controller.d.ts +407 -0
  83. package/dist/types/crop/crop-controller.d.ts.map +1 -0
  84. package/dist/types/export/export-format.d.ts +136 -0
  85. package/dist/types/export/export-format.d.ts.map +1 -0
  86. package/dist/types/export/export-service.d.ts +333 -0
  87. package/dist/types/export/export-service.d.ts.map +1 -0
  88. package/dist/types/fabric/fabric-adapter.d.ts +74 -0
  89. package/dist/types/fabric/fabric-adapter.d.ts.map +1 -0
  90. package/dist/types/fabric/fabric-animation.d.ts +141 -0
  91. package/dist/types/fabric/fabric-animation.d.ts.map +1 -0
  92. package/dist/types/history/command.d.ts +16 -0
  93. package/dist/types/history/command.d.ts.map +1 -0
  94. package/dist/types/history/history-manager.d.ts +129 -0
  95. package/dist/types/history/history-manager.d.ts.map +1 -0
  96. package/dist/types/image/image-loader.d.ts +265 -0
  97. package/dist/types/image/image-loader.d.ts.map +1 -0
  98. package/dist/types/image/image-resampler.d.ts +139 -0
  99. package/dist/types/image/image-resampler.d.ts.map +1 -0
  100. package/dist/types/image/layout-manager.d.ts +255 -0
  101. package/dist/types/image/layout-manager.d.ts.map +1 -0
  102. package/dist/types/image/transform-controller.d.ts +287 -0
  103. package/dist/types/image/transform-controller.d.ts.map +1 -0
  104. package/dist/types/image-editor.d.ts +650 -0
  105. package/dist/types/image-editor.d.ts.map +1 -0
  106. package/dist/types/index.d.cts +31 -0
  107. package/dist/types/index.d.cts.map +1 -0
  108. package/dist/types/index.d.ts +31 -0
  109. package/dist/types/index.d.ts.map +1 -0
  110. package/dist/types/mask/mask-factory.d.ts +209 -0
  111. package/dist/types/mask/mask-factory.d.ts.map +1 -0
  112. package/dist/types/mask/mask-label-manager.d.ts +171 -0
  113. package/dist/types/mask/mask-label-manager.d.ts.map +1 -0
  114. package/dist/types/mask/mask-list.d.ts +144 -0
  115. package/dist/types/mask/mask-list.d.ts.map +1 -0
  116. package/dist/types/mask/mask-style.d.ts +338 -0
  117. package/dist/types/mask/mask-style.d.ts.map +1 -0
  118. package/dist/types/ui/dom-bindings.d.ts +103 -0
  119. package/dist/types/ui/dom-bindings.d.ts.map +1 -0
  120. package/dist/types/ui/ui-state.d.ts +112 -0
  121. package/dist/types/ui/ui-state.d.ts.map +1 -0
  122. package/dist/types/ui/visibility-state.d.ts +77 -0
  123. package/dist/types/ui/visibility-state.d.ts.map +1 -0
  124. package/dist/types/utils/canvas-region.d.ts +177 -0
  125. package/dist/types/utils/canvas-region.d.ts.map +1 -0
  126. package/dist/types/utils/dom.d.ts +26 -0
  127. package/dist/types/utils/dom.d.ts.map +1 -0
  128. package/dist/types/utils/file.d.ts +80 -0
  129. package/dist/types/utils/file.d.ts.map +1 -0
  130. package/dist/types/utils/number.d.ts +132 -0
  131. package/dist/types/utils/number.d.ts.map +1 -0
  132. package/dist/types/utils/timeout.d.ts +84 -0
  133. package/dist/types/utils/timeout.d.ts.map +1 -0
  134. package/dist/umd/image-editor.umd.js +2 -0
  135. package/dist/umd/image-editor.umd.js.map +1 -0
  136. package/package.json +72 -66
  137. package/dist/image-editor.cjs +0 -4407
  138. package/dist/image-editor.cjs.map +0 -7
  139. package/dist/image-editor.esm.js +0 -4376
  140. package/dist/image-editor.esm.js.map +0 -7
  141. package/dist/image-editor.esm.min.js +0 -9
  142. package/dist/image-editor.esm.min.js.map +0 -7
  143. package/dist/image-editor.esm.min.mjs +0 -9
  144. package/dist/image-editor.esm.min.mjs.map +0 -7
  145. package/dist/image-editor.esm.mjs +0 -4376
  146. package/dist/image-editor.esm.mjs.map +0 -7
  147. package/dist/image-editor.js +0 -4373
  148. package/dist/image-editor.js.map +0 -7
  149. package/dist/image-editor.min.js +0 -9
  150. package/dist/image-editor.min.js.map +0 -7
  151. package/image-editor.d.ts +0 -271
  152. package/src/browser.js +0 -11
  153. package/src/esm.js +0 -9
  154. 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,103 @@
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
+ /**
68
+ * @param resolveElementId - Returns the resolved DOM element ID for a given logical key, or a
69
+ * falsy value when the integrator omitted that key from the `idMap`.
70
+ * The orchestrator's `elements` table fills this role.
71
+ * @param isDisposed - Returns the editor's current `isDisposed` flag. Bound handlers
72
+ * consult this on every dispatch and exit early when it returns
73
+ * `true`.
74
+ */
75
+ constructor(resolveElementId: (key: ElementKey) => string | null | undefined, isDisposed: () => boolean);
76
+ /**
77
+ * Look up the element registered under `key`. If it exists, attach
78
+ * `handler` for `eventType` and record the binding so `removeAll` can
79
+ * detach it later. The handler is wrapped to short-circuit when the
80
+ * editor has been disposed.
81
+ *
82
+ * Missing keys and missing elements are silently ignored — the editor
83
+ * tolerates partial DOM as documented under {@link ElementIdMap}.
84
+ *
85
+ * @returns `true` if the listener was attached, `false` if the element
86
+ * could not be resolved.
87
+ */
88
+ bindIfExists(key: ElementKey, eventType: string, handler: EventListener): boolean;
89
+ /**
90
+ * Detach every recorded listener and clear the registry. Each
91
+ * `removeEventListener` call is wrapped in `try/catch` so an
92
+ * already-detached listener (for example because the host page swapped
93
+ * out the DOM node) does not abort the cleanup loop. Calling `removeAll`
94
+ * a second time is a no-op.
95
+ */
96
+ removeAll(): void;
97
+ /**
98
+ * Number of currently-registered listeners. Exposed for diagnostics and
99
+ * for the unit tests under `tests/units/dom-bindings.test.mjs`.
100
+ */
101
+ size(): number;
102
+ }
103
+ //# 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;IAE3C;;;;;;;OAOG;gBAEC,gBAAgB,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,EAChE,UAAU,EAAE,MAAM,OAAO;IAM7B;;;;;;;;;;;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"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Disabled-state, aria-state, and toolbar-state helpers used by
3
+ * {@link ImageEditor}'s `init` and operation handlers. These
4
+ * helpers share the same `idMap`-driven element-resolution
5
+ * vocabulary as `dom-bindings.ts` so the orchestrator can speak
6
+ * one language when wiring or refreshing UI state.
7
+ *
8
+ * ## Owned contracts
9
+ *
10
+ * - Bound DOM controls live in the orchestrator's
11
+ * bindings registry and are addressed by logical {@link ElementKey}.
12
+ * These helpers consume the same key vocabulary so toolbar-state updates
13
+ * stay aligned with what `dom-bindings.ts` originally bound.
14
+ * - Toolbar-state mutation must remain a no-op when
15
+ * the editor is disposed or when a logical key is unmapped. Each helper
16
+ * short-circuits on a missing element ID or missing DOM node so
17
+ * post-`dispose` `updateUi`-style calls cannot throw or surprise the
18
+ * host page.
19
+ *
20
+ * ## Why this lives in its own module
21
+ *
22
+ * Splitting low-level DOM state out keeps `image-editor.ts` focused on
23
+ * toolbar policy while helpers here own native DOM writes such as setting
24
+ * `disabled` by logical key.
25
+ *
26
+ * Like `dom-bindings.ts` and `visibility-state.ts`, this module is imported
27
+ * by `image-editor.ts` only and is intentionally NOT re-exported from
28
+ * `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`. Matches the
35
+ * `ElementKey` alias exported from `dom-bindings.ts` so the orchestrator's
36
+ * registry and the toolbar-state helpers can be driven from the same
37
+ * lookup function without crossing the public-types boundary.
38
+ */
39
+ export type ElementKey = keyof Required<ElementIdMap>;
40
+ /**
41
+ * Callback used by every helper in this module to translate a logical
42
+ * {@link ElementKey} to the resolved DOM element ID supplied by the host
43
+ * page through `idMap`. Returning a falsy value (`null`, `undefined`, or
44
+ * empty string) means the host omitted that key — helpers MUST treat that
45
+ * as a no-op rather than a bug.
46
+ */
47
+ export type ElementIdResolver = (key: ElementKey) => string | null | undefined;
48
+ /**
49
+ * Set the native `disabled` IDL property on a button-like control resolved
50
+ * from `key`. Used by the orchestrator's `updateUi` policy: each toolbar
51
+ * button maps to one logical key, and the policy decides whether the
52
+ * button is currently usable.
53
+ *
54
+ * Behaviour:
55
+ *
56
+ * - If `resolveElementId(key)` returns a falsy value, the helper returns
57
+ * without touching the DOM (the integrator chose not to wire that
58
+ * control).
59
+ * - If `document.getElementById(id)` returns `null`, the helper returns
60
+ * without throwing. A missing node is a partial-DOM scenario, not a
61
+ * fatal error.
62
+ * - Otherwise the resolved element's `disabled` property is set to the
63
+ * requested boolean. Using the IDL property (not `setAttribute`)
64
+ * keeps the keyboard/click behaviour the
65
+ * browser provides "for free" on real `<button>` elements.
66
+ *
67
+ * The element is typed as `HTMLButtonElement` because every key in the
68
+ * documented toolbar set (`zoomInButton`, `applyCropButton`, …) resolves to a
69
+ * `<button>`. A non-button host element will still receive the `disabled`
70
+ * assignment via the IDL slot but will not visually reflect it; that is
71
+ * the integrator's responsibility per the public `idMap` contract.
72
+ *
73
+ * @param resolveElementId - Resolver from logical key to DOM element ID.
74
+ * @param key - Logical toolbar element key.
75
+ * @param disabled - Target `disabled` value.
76
+ */
77
+ export declare function setDisabled(resolveElementId: ElementIdResolver, key: ElementKey, disabled: boolean): void;
78
+ /**
79
+ * Set the `aria-disabled` attribute on the element resolved from `key`.
80
+ * Useful for non-button toolbar controls (links, custom widgets) that do
81
+ * not honour the native `disabled` IDL property but still need to expose
82
+ * disabled state to assistive technology.
83
+ *
84
+ * Behaviour mirrors {@link setDisabled}: missing key or missing element
85
+ * results in a silent no-op. The attribute value is
86
+ * always the canonical string `'true'` or `'false'` as required by the
87
+ * ARIA spec — never the empty string and never removed entirely, so a
88
+ * subsequent toggle is a single `setAttribute` away.
89
+ *
90
+ * @param resolveElementId - Resolver from logical key to DOM element ID.
91
+ * @param key - Logical toolbar element key.
92
+ * @param disabled - Target `aria-disabled` value.
93
+ */
94
+ export declare function setAriaDisabled(resolveElementId: ElementIdResolver, key: ElementKey, disabled: boolean): void;
95
+ /**
96
+ * Toggle a CSS class on the element resolved from `key`. Used for toolbar
97
+ * state that does not correspond to `disabled` / `aria-disabled` — for
98
+ * example, marking the active mask in the mask list or flipping a button
99
+ * into a "pressed" visual style during crop mode.
100
+ *
101
+ * The helper delegates to `Element.classList.toggle(className, force)`, so
102
+ * the caller's `enabled` flag deterministically adds or removes the class
103
+ * regardless of its current presence. Missing key or missing element is a
104
+ * silent no-op.
105
+ *
106
+ * @param resolveElementId - Resolver from logical key to DOM element ID.
107
+ * @param key - Logical toolbar element key.
108
+ * @param className - CSS class name to toggle.
109
+ * @param enabled - `true` to add the class, `false` to remove it.
110
+ */
111
+ export declare function setClass(resolveElementId: ElementIdResolver, key: ElementKey, className: string, enabled: boolean): void;
112
+ //# sourceMappingURL=ui-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-state.d.ts","sourceRoot":"","sources":["../../../src/ui/ui-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,WAAW,CACvB,gBAAgB,EAAE,iBAAiB,EACnC,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,OAAO,GAClB,IAAI,CAKN;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC3B,gBAAgB,EAAE,iBAAiB,EACnC,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,OAAO,GAClB,IAAI,CAKN;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CACpB,gBAAgB,EAAE,iBAAiB,EACnC,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,GACjB,IAAI,CAKN"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Placeholder/canvas-container visibility helper. Owns the
3
+ * standard-DOM-state transition that the orchestrator's
4
+ * private `_setPlaceholderVisible` method delegates to.
5
+ *
6
+ * ## Owned contracts
7
+ *
8
+ * - `setPlaceholderVisible(..., true)` SHALL set the
9
+ * placeholder's `hidden` to `false` and `aria-hidden` to `'false'`, and
10
+ * SHALL set the canvas container's `hidden` to `true` and `aria-hidden`
11
+ * to `'true'`.
12
+ * - `setPlaceholderVisible(..., false)` SHALL set the
13
+ * placeholder's `hidden` to `true` and `aria-hidden` to `'true'`, and
14
+ * SHALL set the canvas container's `hidden` to `false` and `aria-hidden`
15
+ * to `'false'`.
16
+ * - This module SHALL NOT add or remove the
17
+ * Bootstrap `d-none` class on either element. The host page is free to
18
+ * style `[hidden]` however it likes; the editor stays out of utility-class
19
+ * territory so it works with or without Bootstrap.
20
+ * - When `containerElement` is `null`, the
21
+ * placeholder's `hidden` and `aria-hidden` SHALL still be updated
22
+ * correctly. A missing container is a partial-DOM scenario, not a fatal
23
+ * error.
24
+ *
25
+ * ## Why this lives in its own module
26
+ *
27
+ * The helper uses standard DOM state instead of Bootstrap utility classes so
28
+ * the editor works with or without a host stylesheet. Keeping the transition
29
+ * here makes the orchestrator's private method a one-line delegate and keeps
30
+ * the behavior unit-testable in isolation. This module is imported by
31
+ * `image-editor.ts` only and is intentionally not re-exported from
32
+ * `src/index.ts`.
33
+ *
34
+ * @module
35
+ */
36
+ /**
37
+ * Toggle placeholder/canvas-container visibility using only standard DOM
38
+ * state. The function is total: it never throws on null inputs and never
39
+ * touches utility classes.
40
+ *
41
+ * Visibility semantics:
42
+ *
43
+ * - `show === true` means **show the placeholder** (and therefore hide the
44
+ * canvas container). The placeholder is the "no image yet" affordance, so
45
+ * showing it implies the live canvas is not the right thing to render.
46
+ * - `show === false` means **hide the placeholder** (and therefore show the
47
+ * canvas container). This is the post-`loadImage` steady state.
48
+ *
49
+ * In both branches the function:
50
+ *
51
+ * 1. Sets the DOM `hidden` property. Using the
52
+ * property — not the attribute — keeps the IDL flag and the reflected
53
+ * attribute in sync without an extra `setAttribute` call.
54
+ * 2. Sets `aria-hidden` to the matching string so assistive technology
55
+ * tracks the visual state.
56
+ * 3. Leaves every other class and inline style untouched. In particular,
57
+ * Bootstrap's `d-none` is never added or removed,
58
+ * which lets the editor coexist with host pages that use `d-none` for
59
+ * their own purposes.
60
+ *
61
+ * When `containerElement` is `null` (partial DOM, or a host page that does
62
+ * not wrap the canvas in a dedicated container), the placeholder side of
63
+ * the transition still runs to completion. When
64
+ * `placeholderElement` is `null` the function is a no-op for that side; the
65
+ * orchestrator's `updatePlaceholderStatus` already early-returns in that
66
+ * case, but defending here keeps the helper safe to call from any future
67
+ * code path.
68
+ *
69
+ * @param placeholderElement - The placeholder DOM element shown when no image is loaded, or `null`
70
+ * when the host page omitted the placeholder slot from the `idMap`.
71
+ * @param containerElement - The canvas container DOM element wrapping the live `<canvas>`, or
72
+ * `null` when no container is available.
73
+ * @param show - `true` to make the placeholder visible (and hide the canvas container);
74
+ * `false` to hide the placeholder (and show the canvas container).
75
+ */
76
+ export declare function setPlaceholderVisible(placeholderElement: HTMLElement | null, containerElement: HTMLElement | null, show: boolean): void;
77
+ //# sourceMappingURL=visibility-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visibility-state.d.ts","sourceRoot":"","sources":["../../../src/ui/visibility-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,qBAAqB,CACjC,kBAAkB,EAAE,WAAW,GAAG,IAAI,EACtC,gBAAgB,EAAE,WAAW,GAAG,IAAI,EACpC,IAAI,EAAE,OAAO,GACd,IAAI,CAgBN"}