@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,111 @@
1
+ /**
2
+ * FIFO sequential animation queue that prevents overlapping
3
+ * animations and provides dispose-safe settlement so callers do not
4
+ * hang during `dispose` or hard-reset paths.
5
+ *
6
+ * Implements:
7
+ * - at most one entry runs at a time, in enqueue order.
8
+ * - animation-producing operations (`scaleImage`,
9
+ * `rotateImage`, `resetImageTransform`, `undo`, `redo`) are routed
10
+ * through this queue by the orchestrator.
11
+ * - every promise returned by {@link AnimationQueue.add}
12
+ * eventually settles, even when the queue is drained by
13
+ * {@link AnimationQueue.clear}.
14
+ * - the active entry's promise settles only after
15
+ * its function settles, so the orchestrator can flip its
16
+ * `isAnimating` flag inside the wrapped function before this queue
17
+ * resolves the caller.
18
+ * - dispose paths can drain pending
19
+ * entries via {@link AnimationQueue.clear} so queued callers do not
20
+ * hang. In-flight animation wrappers (see `fabric/fabric-animation.ts`)
21
+ * check `isDisposed` independently and exit without touching the
22
+ * canvas; the queue itself never inspects editor state.
23
+ *
24
+ * @module
25
+ */
26
+ /**
27
+ * Guarantees that animation-producing operations are executed strictly
28
+ * one after another, in the order they were enqueued.
29
+ *
30
+ * The queue is dispose-aware in the sense that {@link AnimationQueue.clear}
31
+ * settles every pending entry, so callers awaiting an enqueued slot
32
+ * (for example, `await editor.scaleImage(2)`) never hang once the
33
+ * orchestrator tears down. The queue itself does not call into Fabric
34
+ * and does not know whether the editor is disposed; it is the caller's
35
+ * responsibility to invoke `clear` when the underlying work can no
36
+ * longer be performed.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * const queue = new AnimationQueue();
41
+ * queue.add(() => object.scale(2, { duration: 300 }));
42
+ * queue.add(() => object.rotate(90, { duration: 300 }));
43
+ * // The rotate starts only after the scale completes.
44
+ * ```
45
+ */
46
+ export declare class AnimationQueue {
47
+ /** Pending entries waiting to start, in FIFO order. */
48
+ private queue;
49
+ /** True while an entry is being awaited inside {@link drainQueue}. */
50
+ private running;
51
+ /**
52
+ * Enqueues an animation function and returns a Promise that settles
53
+ * when that specific entry completes.
54
+ *
55
+ * The promise resolves when `animationFn`'s returned promise resolves
56
+ * and rejects when it rejects, after the queue has popped the entry
57
+ * and before the next entry begins. This preserves FIFO ordering and
58
+ * lets the orchestrator flip its `isAnimating` flag inside
59
+ * `animationFn` before the public promise settles.
60
+ *
61
+ * @param animationFn - Function that performs async work and resolves
62
+ * when the animation has finished or rejects with the original error.
63
+ * @returns A promise that settles once this specific entry has
64
+ * completed, been rejected, or been drained by {@link clear}.
65
+ */
66
+ add(animationFn: () => Promise<void>): Promise<void>;
67
+ /**
68
+ * Cancels every pending entry so callers awaiting a queued slot do
69
+ * not hang. Used by `dispose` and hard-reset paths in the editor
70
+ * orchestrator.
71
+ *
72
+ * The currently active entry (if any) is not interrupted by this
73
+ * method; its promise settles when its function settles. Animation
74
+ * wrappers in `fabric/fabric-animation.ts` observe `isDisposed`
75
+ * independently and exit without touching the canvas, so the active
76
+ * entry typically settles promptly after dispose calls `clear`.
77
+ *
78
+ * @param reason - When provided, pending entries reject with this
79
+ * value (typed errors from `core/errors.ts` are recommended for
80
+ * diagnostics). When omitted, pending entries resolve normally,
81
+ * which is the documented dispose default — the orchestrator's
82
+ * own dispose guards prevent further canvas access.
83
+ */
84
+ clear(reason?: unknown): void;
85
+ /**
86
+ * Reports whether an entry is currently active. Returns `true` only
87
+ * while {@link drainQueue} is awaiting an entry's function; pending
88
+ * entries that have not yet started do not count as running.
89
+ */
90
+ isRunning(): boolean;
91
+ /**
92
+ * Reports whether an entry is active or waiting to run.
93
+ */
94
+ isBusy(): boolean;
95
+ /**
96
+ * Resolves after the active entry and every currently pending entry
97
+ * has settled (resolved or rejected). This is the public hook the
98
+ * orchestrator uses to await a quiescent queue, for example before
99
+ * tearing down the canvas in a hard-reset path.
100
+ *
101
+ * The implementation appends a no-op sentinel so the returned
102
+ * promise inherits the FIFO settlement order. If the queue is
103
+ * already idle, the returned promise resolves on the microtask
104
+ * tick. Sentinel rejections (from {@link clear} with a reason) are
105
+ * swallowed; "settled" includes "rejected" for the purposes of this
106
+ * method.
107
+ */
108
+ waitForIdle(): Promise<void>;
109
+ private drainQueue;
110
+ }
111
+ //# sourceMappingURL=animation-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animation-queue.d.ts","sourceRoot":"","sources":["../../../src/animation/animation-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAWH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,cAAc;IACvB,uDAAuD;IACvD,OAAO,CAAC,KAAK,CAAoB;IACjC,sEAAsE;IACtE,OAAO,CAAC,OAAO,CAAS;IAExB;;;;;;;;;;;;;;OAcG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IASpD;;;;;;;;;;;;;;;;OAgBG;IACH,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAiB7B;;;;OAIG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;;;;;;;;;;;OAYG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;YAUd,UAAU;CAkB3B"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Helpers that route editor warnings and errors through the
3
+ * public `onWarning` and `onError` callbacks declared on
4
+ * {@link ImageEditorOptions}.
5
+ *
6
+ * ## Owned contracts
7
+ *
8
+ * - When the editor reports a recoverable warning
9
+ * through `onWarning`, the editor SHALL call the callback with
10
+ * `(error, message)` and SHALL catch and log any callback exception
11
+ * without changing editor state.
12
+ * - When the editor reports an error through
13
+ * `onError`, the editor SHALL call the callback with `(error, message)`
14
+ * and SHALL catch and log any callback exception without masking the
15
+ * original editor error.
16
+ *
17
+ * The argument order `(error, message)` is part of the public surface and
18
+ * is also enforced by the `ImageEditorOptions` type.
19
+ *
20
+ * ## Why a dedicated module
21
+ *
22
+ * Callback isolation is owned here rather than by the operation guard or
23
+ * the orchestrator. Co-locating warning/error reporting gives every
24
+ * pipeline a single, side-effect-light helper to call when something goes
25
+ * wrong.
26
+ *
27
+ * ## Non-goals
28
+ *
29
+ * - The helpers do NOT throw or rethrow. Callers that need to reject a
30
+ * promise with the original error should do so explicitly *after*
31
+ * `reportError(...)` returns. This keeps the "callback failure must not
32
+ * mask the original editor error" invariant
33
+ * trivially satisfied.
34
+ * - The helpers do NOT mutate editor state. They only invoke the
35
+ * user-supplied callback and, on callback exception, write a single
36
+ * diagnostic line to `console.warn` / `console.error`.
37
+ *
38
+ * The module is intentionally NOT re-exported from `src/index.ts`
39
+ * (only `ImageEditor`, `isMaskObject`, and the
40
+ * documented public types are root-exported).
41
+ *
42
+ * @module
43
+ */
44
+ import type { ResolvedOptions } from './public-types.js';
45
+ /**
46
+ * Minimum slice of {@link ResolvedOptions} required to dispatch a warning.
47
+ * Accepting a structural sub-type lets pipeline modules pass either the
48
+ * full `ResolvedOptions` reference or a focused stub (used in unit tests).
49
+ */
50
+ export type WarningCallbackHost = Pick<ResolvedOptions, 'onWarning'>;
51
+ /**
52
+ * Minimum slice of {@link ResolvedOptions} required to dispatch an error.
53
+ *
54
+ * @see WarningCallbackHost
55
+ */
56
+ export type ErrorCallbackHost = Pick<ResolvedOptions, 'onError'>;
57
+ /**
58
+ * Report a recoverable warning to the consumer's `onWarning` callback, if
59
+ * one was supplied.
60
+ *
61
+ * The callback is invoked with the public `(error, message)` argument
62
+ * order. The original `error` value is forwarded
63
+ * unchanged — primitives, plain objects, and `Error` instances all flow
64
+ * through verbatim so consumers can introspect them with `instanceof`.
65
+ *
66
+ * If the callback itself throws, the exception is caught and logged with
67
+ * `console.warn`. The helper never throws and never returns a value, so
68
+ * callers can chain it before continuing recovery without a `try`/`catch`
69
+ * of their own.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * try {
74
+ * await tryDownsample(...);
75
+ * } catch (error) {
76
+ * reportWarning(this.options, error, 'Downsample fell back to source format.');
77
+ * // continue with the un-downsampled image — no rethrow
78
+ * }
79
+ * ```
80
+ *
81
+ * @param options - Object exposing the resolved `onWarning` callback. May be
82
+ * {@link ResolvedOptions} directly or any structural sub-type
83
+ * ({@link WarningCallbackHost}).
84
+ * @param error - The original error value. Forwarded as the first callback argument.
85
+ * Accepts `unknown` because rejected promises and thrown values are not
86
+ * guaranteed to be `Error` instances.
87
+ * @param message - Human-readable description of what happened. Forwarded as the second
88
+ * callback argument.
89
+ */
90
+ export declare function reportWarning(options: WarningCallbackHost, error: unknown, message: string): void;
91
+ /**
92
+ * Report an error to the consumer's `onError` callback, if one was
93
+ * supplied.
94
+ *
95
+ * The callback is invoked with the public `(error, message)` argument
96
+ * order. Like {@link reportWarning}, this helper never
97
+ * throws — callbacks that throw are caught and logged with
98
+ * `console.error`.
99
+ *
100
+ * The "do not mask the original editor error" half is
101
+ * a contract on the *caller*: pipelines that intend to reject a promise
102
+ * (or rethrow) with the original `error` MUST do so themselves *after*
103
+ * this helper returns. By keeping reporting and rethrow separate, a
104
+ * faulty `onError` callback cannot replace the original error with the
105
+ * callback's own exception in the consumer's promise chain.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * try {
110
+ * await loadFabricImage(dataUrl);
111
+ * } catch (error) {
112
+ * reportError(this.options, error, `Image load failed: ${describe(error)}`);
113
+ * throw error; // original error is preserved on the consumer's promise
114
+ * }
115
+ * ```
116
+ *
117
+ * @param options - Object exposing the resolved `onError` callback. May be
118
+ * {@link ResolvedOptions} directly or any structural sub-type
119
+ * ({@link ErrorCallbackHost}).
120
+ * @param error - The original error value. Forwarded as the first callback argument.
121
+ * @param message - Human-readable description of what happened. Forwarded as the second
122
+ * callback argument.
123
+ */
124
+ export declare function reportError(options: ErrorCallbackHost, error: unknown, message: string): void;
125
+ //# sourceMappingURL=callback-reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callback-reporter.d.ts","sourceRoot":"","sources":["../../../src/core/callback-reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;AAErE;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAgBjG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAc7F"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Resolves user-supplied {@link ImageEditorOptions} into the
3
+ * runtime {@link ResolvedOptions} object used by the editor.
4
+ *
5
+ * Behavior is defined by the documented option-resolution rules: every
6
+ * required option falls back to a default, nested `label.textOptions` and
7
+ * `crop` values merge with their defaults, callback values normalize to a
8
+ * function or `null`, unknown top-level keys are ignored, top-level scalar
9
+ * values remain internally mutable for controlled updates such as
10
+ * `setLayoutMode()`, and returned nested config objects are frozen.
11
+ *
12
+ * @module
13
+ */
14
+ import type { ImageEditorOptions, LabelConfig, ResolvedCropConfig, ResolvedOptions } from './public-types.js';
15
+ /**
16
+ * Documented defaults for every top-level option except the nested
17
+ * {@link LabelConfig} and {@link CropConfig} configs, which are owned by
18
+ * {@link DEFAULT_LABEL} and {@link DEFAULT_CROP} respectively.
19
+ *
20
+ * Values are the runtime defaults used when callers omit an option.
21
+ * Nested label and crop defaults are carried by {@link DEFAULT_LABEL} and
22
+ * {@link DEFAULT_CROP}.
23
+ */
24
+ export declare const DEFAULT_OPTIONS: Omit<ResolvedOptions, 'label' | 'crop'>;
25
+ /**
26
+ * Default {@link LabelConfig}. Consumers can override `getText`, supply a
27
+ * `create` factory, or provide partial `textOptions` — unspecified keys fall
28
+ * back to {@link DEFAULT_LABEL_TEXT_OPTIONS}.
29
+ */
30
+ export declare const DEFAULT_LABEL: LabelConfig;
31
+ /**
32
+ * Default {@link CropConfig}.
33
+ */
34
+ export declare const DEFAULT_CROP: ResolvedCropConfig;
35
+ /**
36
+ * Resolves a partial {@link ImageEditorOptions} into a fully populated
37
+ * {@link ResolvedOptions} object.
38
+ *
39
+ * Behavior matrix:
40
+ * - Every top-level key is taken from `input` when supplied, else from
41
+ * {@link DEFAULT_OPTIONS}.
42
+ * - `label.textOptions` is deep-merged with {@link DEFAULT_LABEL_TEXT_OPTIONS}
43
+ * so user keys override defaults and unspecified keys remain.
44
+ * - `crop.*` is shallow-merged with {@link DEFAULT_CROP} so each field falls
45
+ * back to its documented default when unspecified.
46
+ * - Callback values are normalized: function values are kept, anything
47
+ * else becomes `null`.
48
+ * - Unknown top-level keys are silently dropped.
49
+ * - The returned `label` and `crop` references are frozen so that mutating
50
+ * `input.label`, `input.label.textOptions`, or `input.crop` after the call
51
+ * cannot affect the live editor.
52
+ *
53
+ * @param input - Optional partial options object. Defaults to `{}`.
54
+ */
55
+ export declare function resolveOptions(input?: ImageEditorOptions | null): ResolvedOptions;
56
+ //# sourceMappingURL=default-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-options.d.ts","sourceRoot":"","sources":["../../../src/core/default-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAGR,kBAAkB,EAClB,WAAW,EACX,kBAAkB,EAClB,eAAe,EAClB,MAAM,mBAAmB,CAAC;AAI3B;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,MAAM,CAgEnE,CAAC;AAmBF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,WAG3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,kBAS1B,CAAC;AAwHF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,eAAe,CAqNjF"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Typed error classes raised by the editor pipelines (load,
3
+ * downsample, merge, crop, export).
4
+ *
5
+ * All errors that may surface to consumers extend {@link Error} directly so
6
+ * callers can discriminate via `instanceof` or `error.name` checks. The
7
+ * hierarchy is intentionally flat — there is no shared `ImageEditorError`
8
+ * base class — to keep `name`/message contracts independent per pipeline
9
+ * and to keep name/message contracts independent per pipeline.
10
+ *
11
+ * These classes are internal to the package and are NOT re-exported from
12
+ * `src/index.ts`. Consumers see them via promise rejections from public
13
+ * methods (e.g. `loadImage.catch(error =>...)`) and should branch on
14
+ * `error.name` or `instanceof` for fine-grained handling.
15
+ *
16
+ * @module
17
+ */
18
+ /**
19
+ * Raised by `fabric/fabric-adapter.ts` when neither constructor argument
20
+ * provides a Fabric module and `globalThis.fabric` is also absent. The
21
+ * editor logs a single descriptive `console.error` and makes `init` and
22
+ * `loadImage` no-ops that resolve to `undefined`.
23
+ *
24
+ * Surfaces to consumer as: a single `console.error`; subsequent public
25
+ * methods are guarded by the adapter's `isFabricLoaded === false` flag.
26
+ *
27
+ */
28
+ export declare class FabricUnavailableError extends Error {
29
+ readonly name = "FabricUnavailableError";
30
+ constructor(message?: string);
31
+ }
32
+ /**
33
+ * Raised by `image/image-loader.ts` when the internal `decodeImageElement`
34
+ * helper rejects (the `<img>` `onerror` fires while decoding the data URL).
35
+ *
36
+ * Surfaces to consumer as: rejection of the `loadImage` promise. The
37
+ * editor restores every field captured in the rollback bundle before
38
+ * rejecting, so `loadImage` is observably atomic.
39
+ *
40
+ */
41
+ export declare class ImageDecodeError extends Error {
42
+ readonly name = "ImageDecodeError";
43
+ /** Original error or `ErrorEvent` from the `<img>` element, if any. */
44
+ readonly originalError: unknown;
45
+ constructor(message?: string, originalError?: unknown);
46
+ }
47
+ /**
48
+ * Raised by `utils/timeout.ts` after `imageLoadTimeoutMs` (default 30000)
49
+ * elapses on either the decode step or the `FabricImage.fromURL` step of
50
+ * `loadImage`. The error message includes both the elapsed milliseconds
51
+ * and the label of the step that timed out, so consumers and logs can
52
+ * tell which phase stalled.
53
+ *
54
+ * Surfaces to consumer as: rejection of the `loadImage` promise after
55
+ * the rollback bundle has been replayed.
56
+ *
57
+ */
58
+ export declare class ImageLoadTimeoutError extends Error {
59
+ readonly name = "ImageLoadTimeoutError";
60
+ /** Step label, e.g. `'image decode'` or `'FabricImage.fromURL'`. */
61
+ readonly label: string;
62
+ /** Elapsed milliseconds at the time the timer fired. */
63
+ readonly elapsedMs: number;
64
+ constructor(label: string, elapsedMs: number);
65
+ }
66
+ /**
67
+ * Raised by `image/image-resampler.ts` when the offscreen canvas required
68
+ * for downsampling cannot obtain a 2D rendering context (i.e.
69
+ * `OffscreenCanvas.getContext('2d')` or the fallback `<canvas>.getContext`
70
+ * returns `null`).
71
+ *
72
+ * Surfaces to consumer as: rejection of the `loadImage` promise. The
73
+ * Transactional_Load rollback runs before the rejection.
74
+ *
75
+ */
76
+ export declare class DownsampleError extends Error {
77
+ readonly name = "DownsampleError";
78
+ /** Original error, if any. Usually `null`. */
79
+ readonly originalError: unknown;
80
+ constructor(message?: string, originalError?: unknown);
81
+ }
82
+ /**
83
+ * Raised by `export/export-service.ts.mergeMasks` when the in-memory render
84
+ * or any post-merge step fails. The pre-merge snapshot is restored before
85
+ * the rejection.
86
+ *
87
+ * Surfaces to consumer as: rejection of the `mergeMasks` promise.
88
+ *
89
+ */
90
+ export declare class MergeMasksError extends Error {
91
+ readonly name = "MergeMasksError";
92
+ /** Original error thrown during the merge pipeline. */
93
+ readonly originalError: unknown;
94
+ constructor(message?: string, originalError?: unknown);
95
+ }
96
+ /**
97
+ * Raised by `crop/crop-controller.ts.applyCrop` on any failure during the
98
+ * crop pipeline (crop computation, cropped-image load via the loader, or
99
+ * any post-merge step). The pre-crop snapshot is restored, the
100
+ * `CropSession` is dropped, and crop-specific Fabric handlers are detached
101
+ * before the rejection.
102
+ *
103
+ * Surfaces to consumer as: rejection of the `applyCrop` promise.
104
+ *
105
+ */
106
+ export declare class CropApplyError extends Error {
107
+ readonly name = "CropApplyError";
108
+ /** Original error thrown during the crop pipeline. */
109
+ readonly originalError: unknown;
110
+ constructor(message?: string, originalError?: unknown);
111
+ }
112
+ /**
113
+ * Raised by `export/export-service.ts.exportImageFile` when
114
+ * `isImageLoaded` is `false`. A console warning naming the missing image
115
+ * is emitted alongside the rejection.
116
+ *
117
+ * Note: `exportImageBase64` and `downloadImage` do NOT raise this error —
118
+ * they resolve to `''` or no-op respectively, and emit the same warning.
119
+ *
120
+ * Surfaces to consumer as: rejection of the `exportImageFile` promise.
121
+ *
122
+ */
123
+ export declare class ExportNotReadyError extends Error {
124
+ readonly name = "ExportNotReadyError";
125
+ /** Name of the export operation that was attempted. */
126
+ readonly operation: string;
127
+ constructor(operation?: string);
128
+ }
129
+ /**
130
+ * Raised by export helpers when an image is loaded but the export pipeline
131
+ * cannot produce a valid output, for example because the computed image
132
+ * region is empty or the rendered data URL cannot be decoded into bytes.
133
+ *
134
+ * Surfaces to consumer as: rejection of the relevant export promise.
135
+ */
136
+ export declare class ExportError extends Error {
137
+ readonly name = "ExportError";
138
+ /** Original error thrown during the export pipeline. */
139
+ readonly originalError: unknown;
140
+ constructor(message?: string, originalError?: unknown);
141
+ }
142
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAkBH;;;;;;;;;GASG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC7C,SAAyB,IAAI,4BAA4B;gBAGrD,OAAO,SAA6H;CAK3I;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACvC,SAAyB,IAAI,sBAAsB;IAEnD,uEAAuE;IACvE,SAAgB,aAAa,EAAE,OAAO,CAAC;gBAE3B,OAAO,SAAqC,EAAE,aAAa,GAAE,OAAc;CAK1F;AAED;;;;;;;;;;GAUG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC5C,SAAyB,IAAI,2BAA2B;IAExD,oEAAoE;IACpE,SAAgB,KAAK,EAAE,MAAM,CAAC;IAC9B,wDAAwD;IACxD,SAAgB,SAAS,EAAE,MAAM,CAAC;gBAEtB,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAM/C;AAED;;;;;;;;;GASG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACtC,SAAyB,IAAI,qBAAqB;IAElD,8CAA8C;IAC9C,SAAgB,aAAa,EAAE,OAAO,CAAC;gBAGnC,OAAO,SAAoD,EAC3D,aAAa,GAAE,OAAc;CAMpC;AAED;;;;;;;GAOG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACtC,SAAyB,IAAI,qBAAqB;IAElD,uDAAuD;IACvD,SAAgB,aAAa,EAAE,OAAO,CAAC;gBAE3B,OAAO,SAA0C,EAAE,aAAa,GAAE,OAAc;CAK/F;AAED;;;;;;;;;GASG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACrC,SAAyB,IAAI,oBAAoB;IAEjD,sDAAsD;IACtD,SAAgB,aAAa,EAAE,OAAO,CAAC;gBAE3B,OAAO,SAAuC,EAAE,aAAa,GAAE,OAAc;CAK5F;AAED;;;;;;;;;;GAUG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC1C,SAAyB,IAAI,yBAAyB;IAEtD,uDAAuD;IACvD,SAAgB,SAAS,EAAE,MAAM,CAAC;gBAEtB,SAAS,SAAoB;CAK5C;AAED;;;;;;GAMG;AACH,qBAAa,WAAY,SAAQ,KAAK;IAClC,SAAyB,IAAI,iBAAiB;IAE9C,wDAAwD;IACxD,SAAgB,aAAa,EAAE,OAAO,CAAC;gBAE3B,OAAO,SAA4B,EAAE,aAAa,GAAE,OAAc;CAKjF"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Animation-state guard used by the {@link ImageEditor} facade
3
+ * to block stateful public operations while an animation is in
4
+ * progress, and to centralize the dispose flag that in-flight
5
+ * animation callbacks check before touching the canvas.
6
+ *
7
+ * ## Owned contracts
8
+ *
9
+ * - While `isAnimating` is `true`, the editor SHALL
10
+ * reject calls to `mergeMasks`, `exportImageBase64`, `exportImageFile`,
11
+ * `downloadImage`, `enterCropMode`, `applyCrop`, `removeAllMasks`, and
12
+ * `loadImage` with a clear error or no-op (documented per method).
13
+ * - `undo` and `redo` are NOT routed through this
14
+ * guard; they are serialized by the `AnimationQueue` instead. Callers that
15
+ * would otherwise be blocked by the `isAnimating` flag still flow
16
+ * through `assertNotAnimating`; `undo` / `redo` skip the guard
17
+ * entirely (see `image-editor.ts`).
18
+ * - When an animation completes or fails, the
19
+ * editor SHALL set `isAnimating` to `false` *before* resolving or
20
+ * rejecting the returned promise. The {@link OperationGuard.runAnimation}
21
+ * helper enforces this by clearing the flag inside a `finally` block.
22
+ *
23
+ * ## Why the guard owns the dispose flag too
24
+ *
25
+ * In-flight animation callbacks check `isDisposed` before touching the
26
+ * canvas. Co-locating the disposed flag here keeps both checks behind a
27
+ * single small object so the Fabric animation wrapper
28
+ * (`fabric/fabric-animation.ts`) and the dispose path (`image-editor.ts`)
29
+ * can share state without a circular dependency on the orchestrator.
30
+ *
31
+ * The guard does NOT log on rejection — the contract is "no state mutation
32
+ * and a documented no-op shape per method"; logging is left to the caller
33
+ * so each public method can choose between resolved-promise, empty-string,
34
+ * or rejection-with-typed-error per the documented per-method documentation.
35
+ *
36
+ * The guard is imported by `image-editor.ts` and
37
+ * `fabric/fabric-animation.ts`. It is intentionally NOT re-exported from
38
+ * `src/index.ts`.
39
+ *
40
+ * @module
41
+ */
42
+ /**
43
+ * Read-only view of the guard state. Useful for diagnostics, property
44
+ * tests, and `fabric/fabric-animation.ts` callbacks that only need to
45
+ * observe (never mutate) the flags.
46
+ */
47
+ export interface AnimationState {
48
+ /** `true` while a queued animation is bracketed by begin/endAnimation. */
49
+ readonly isAnimating: boolean;
50
+ /** `true` after {@link OperationGuard.markDisposed} has been called. */
51
+ readonly isDisposed: boolean;
52
+ }
53
+ export type OperationToken = symbol;
54
+ /**
55
+ * Tracks the editor's `isAnimating` and `isDisposed` flags and exposes the
56
+ * single-line `assertNotAnimating` gate used by every guarded public
57
+ * method.
58
+ *
59
+ * Lifetime is one-per-editor — a fresh `OperationGuard` is created in the
60
+ * `ImageEditor` constructor and disposed alongside the canvas.
61
+ *
62
+ */
63
+ export declare class OperationGuard {
64
+ private isAnimationActive;
65
+ private isDisposedFlag;
66
+ private isLoadingActive;
67
+ private currentOperationName;
68
+ private currentOperationToken;
69
+ /**
70
+ * Returns `true` while an animation block is open (between
71
+ * {@link beginAnimation} and {@link endAnimation}).
72
+ *
73
+ * Public surface for the orchestrator's `isAnimating` check used by
74
+ * the per-method guards.
75
+ */
76
+ isAnimating(): boolean;
77
+ /**
78
+ * Returns `true` once {@link markDisposed} has been called. Animation
79
+ * callbacks consult this before touching the canvas.
80
+ */
81
+ isDisposed(): boolean;
82
+ /**
83
+ * Returns `true` while a transactional image load is in progress.
84
+ */
85
+ isLoading(): boolean;
86
+ /**
87
+ * Returns the currently active non-load operation name, if any.
88
+ */
89
+ activeOperationName(): string | null;
90
+ /**
91
+ * Returns `true` while any guard-owned busy state is active.
92
+ */
93
+ isBusy(): boolean;
94
+ /**
95
+ * Begin an animation block. Subsequent calls to {@link assertNotAnimating}
96
+ * will throw until {@link endAnimation} runs.
97
+ *
98
+ * Prefer {@link runAnimation} over manually calling begin/end so the
99
+ * "isAnimating false before resolve/reject" invariant is enforced by
100
+ * `try/finally` rather than caller discipline.
101
+ */
102
+ beginAnimation(): void;
103
+ /**
104
+ * End an animation block and clear the `isAnimating` flag. Always called
105
+ * from a `finally` so the flag is `false` before the surrounding promise
106
+ * resolves or rejects.
107
+ */
108
+ endAnimation(): void;
109
+ /**
110
+ * Mark the editor disposed. After this call:
111
+ *
112
+ * - `isDisposed` returns `true`.
113
+ * - `isAnimating` is forced to `false` so any post-dispose `finally`
114
+ * that runs after the animation queue is cleared still leaves the
115
+ * guard in a quiescent state.
116
+ *
117
+ * Idempotent: calling twice is a no-op.
118
+ */
119
+ markDisposed(): void;
120
+ /**
121
+ * Mark a transactional image load as active.
122
+ */
123
+ beginLoading(): void;
124
+ /**
125
+ * Clear the transactional image load flag.
126
+ */
127
+ endLoading(): void;
128
+ /**
129
+ * Mark a longer-running public operation active and return the token
130
+ * that authorizes its internal calls.
131
+ */
132
+ beginBusyOperation(operationName: string): OperationToken;
133
+ /**
134
+ * Clear the active operation only when the matching token finishes.
135
+ */
136
+ endBusyOperation(token: OperationToken | null | undefined): void;
137
+ /**
138
+ * Returns `true` when `token` belongs to the currently active operation.
139
+ */
140
+ isOwnOperation(token: OperationToken | null | undefined): boolean;
141
+ /**
142
+ * Run an async function inside a `beginAnimation` / `endAnimation`
143
+ * bracket. The bracket is released in a `finally` so the
144
+ * `isAnimating === false` invariant holds even
145
+ * when `animationTask` rejects.
146
+ *
147
+ * Used by the orchestrator's transform pipeline (`scaleImage`,
148
+ * `rotateImage`, `resetImageTransform`) when wrapping a single Fabric
149
+ * animation. The animation queue (`animation/animation-queue.ts`)
150
+ * enforces FIFO ordering across multiple wrappers, so callers do not
151
+ * need to coordinate begin/end across queue entries.
152
+ *
153
+ * @typeParam T - Resolved value of the wrapped animation.
154
+ * @param animationTask - Animation function returning a promise.
155
+ * @returns The promise returned by `animationTask`, with begin/end bracketing
156
+ * applied around its lifetime.
157
+ */
158
+ runAnimation<T>(animationTask: () => Promise<T>): Promise<T>;
159
+ /**
160
+ * Throw if an animation is currently in progress. Used as the gate for
161
+ * the operations enumerated: `mergeMasks`,
162
+ * `exportImageBase64`, `exportImageFile`, `downloadImage`,
163
+ * `enterCropMode`, `applyCrop`, `removeAllMasks`, and `loadImage`.
164
+ *
165
+ * `undo` and `redo` are NOT routed through this gate;
166
+ * they go through the animation queue, which serializes them after any
167
+ * in-flight animation entry.
168
+ *
169
+ * The thrown error is intentionally a plain `Error` rather than one of
170
+ * the typed classes from `core/errors.ts`; some public methods translate
171
+ * the failure into a documented no-op shape before it reaches the
172
+ * consumer.
173
+ *
174
+ * @param operationLabel - Short, user-facing operation name (e.g. `'mergeMasks'`).
175
+ * Embedded in the error message verbatim.
176
+ * @throws Error when {@link isAnimating} returns `true`.
177
+ */
178
+ assertNotAnimating(operationLabel: string): void;
179
+ /**
180
+ * Throw when a public operation would overlap loading, animation, or
181
+ * another active transaction. Internal calls may pass their active
182
+ * operation token to proceed.
183
+ */
184
+ assertIdleForOperation(operationLabel: string, token?: OperationToken | null): void;
185
+ /**
186
+ * Throw when an animation cannot even be queued because a load or
187
+ * transaction is currently active. Existing animations are intentionally
188
+ * left to the animation queue.
189
+ */
190
+ assertCanQueueAnimation(operationLabel: string, token?: OperationToken | null): void;
191
+ }
192
+ //# sourceMappingURL=operation-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-guard.d.ts","sourceRoot":"","sources":["../../../src/core/operation-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,qBAAqB,CAA+B;IAE5D;;;;;;OAMG;IACH,WAAW,IAAI,OAAO;IAItB;;;OAGG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAIpC;;OAEG;IACH,MAAM,IAAI,OAAO;IAMjB;;;;;;;OAOG;IACH,cAAc,IAAI,IAAI;IAItB;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAIpB;;;;;;;;;OASG;IACH,YAAY,IAAI,IAAI;IAQpB;;OAEG;IACH,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;;OAGG;IACH,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc;IAOzD;;OAEG;IACH,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI;IAOhE;;OAEG;IACH,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO;IAIjE;;;;;;;;;;;;;;;;OAgBG;IACG,YAAY,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IASlE;;;;;;;;;;;;;;;;;;OAkBG;IACH,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAQhD;;;;OAIG;IACH,sBAAsB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI;IAuBnF;;;;OAIG;IACH,uBAAuB,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI;CAiBvF"}