@bensitu/image-editor 1.5.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +367 -518
- package/dist/cjs/index.cjs +5422 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/esm/animation/animation-queue.js +67 -0
- package/dist/esm/animation/animation-queue.js.map +1 -0
- package/dist/esm/core/callback-reporter.js +23 -0
- package/dist/esm/core/callback-reporter.js.map +1 -0
- package/dist/esm/core/default-options.js +322 -0
- package/dist/esm/core/default-options.js.map +1 -0
- package/dist/esm/core/errors.js +156 -0
- package/dist/esm/core/errors.js.map +1 -0
- package/dist/esm/core/operation-guard.js +129 -0
- package/dist/esm/core/operation-guard.js.map +1 -0
- package/dist/esm/core/public-types.js +4 -0
- package/dist/esm/core/public-types.js.map +1 -0
- package/dist/esm/core/state-serializer.js +251 -0
- package/dist/esm/core/state-serializer.js.map +1 -0
- package/dist/esm/crop/crop-controller.js +403 -0
- package/dist/esm/crop/crop-controller.js.map +1 -0
- package/dist/esm/export/export-format.js +53 -0
- package/dist/esm/export/export-format.js.map +1 -0
- package/dist/esm/export/export-service.js +596 -0
- package/dist/esm/export/export-service.js.map +1 -0
- package/dist/esm/fabric/fabric-adapter.js +37 -0
- package/dist/esm/fabric/fabric-adapter.js.map +1 -0
- package/dist/esm/fabric/fabric-animation.js +37 -0
- package/dist/esm/fabric/fabric-animation.js.map +1 -0
- package/dist/esm/history/command.js +2 -0
- package/dist/esm/history/command.js.map +1 -0
- package/dist/esm/history/history-manager.js +103 -0
- package/dist/esm/history/history-manager.js.map +1 -0
- package/dist/esm/image/image-loader.js +245 -0
- package/dist/esm/image/image-loader.js.map +1 -0
- package/dist/esm/image/image-resampler.js +55 -0
- package/dist/esm/image/image-resampler.js.map +1 -0
- package/dist/esm/image/layout-manager.js +224 -0
- package/dist/esm/image/layout-manager.js.map +1 -0
- package/dist/esm/image/transform-controller.js +132 -0
- package/dist/esm/image/transform-controller.js.map +1 -0
- package/dist/esm/image-editor.js +1740 -0
- package/dist/esm/image-editor.js.map +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/mask/mask-factory.js +332 -0
- package/dist/esm/mask/mask-factory.js.map +1 -0
- package/dist/esm/mask/mask-label-manager.js +120 -0
- package/dist/esm/mask/mask-label-manager.js.map +1 -0
- package/dist/esm/mask/mask-list.js +47 -0
- package/dist/esm/mask/mask-list.js.map +1 -0
- package/dist/esm/mask/mask-style.js +182 -0
- package/dist/esm/mask/mask-style.js.map +1 -0
- package/dist/esm/ui/dom-bindings.js +60 -0
- package/dist/esm/ui/dom-bindings.js.map +1 -0
- package/dist/esm/ui/ui-state.js +25 -0
- package/dist/esm/ui/ui-state.js.map +1 -0
- package/dist/esm/ui/visibility-state.js +11 -0
- package/dist/esm/ui/visibility-state.js.map +1 -0
- package/dist/esm/utils/canvas-region.js +100 -0
- package/dist/esm/utils/canvas-region.js.map +1 -0
- package/dist/esm/utils/dom.js +6 -0
- package/dist/esm/utils/dom.js.map +1 -0
- package/dist/esm/utils/file.js +53 -0
- package/dist/esm/utils/file.js.map +1 -0
- package/dist/esm/utils/number.js +24 -0
- package/dist/esm/utils/number.js.map +1 -0
- package/dist/esm/utils/timeout.js +17 -0
- package/dist/esm/utils/timeout.js.map +1 -0
- package/dist/types/animation/animation-queue.d.ts +111 -0
- package/dist/types/animation/animation-queue.d.ts.map +1 -0
- package/dist/types/core/callback-reporter.d.ts +125 -0
- package/dist/types/core/callback-reporter.d.ts.map +1 -0
- package/dist/types/core/default-options.d.ts +56 -0
- package/dist/types/core/default-options.d.ts.map +1 -0
- package/dist/types/core/errors.d.ts +142 -0
- package/dist/types/core/errors.d.ts.map +1 -0
- package/dist/types/core/operation-guard.d.ts +192 -0
- package/dist/types/core/operation-guard.d.ts.map +1 -0
- package/dist/types/core/public-types.d.ts +678 -0
- package/dist/types/core/public-types.d.ts.map +1 -0
- package/dist/types/core/state-serializer.d.ts +301 -0
- package/dist/types/core/state-serializer.d.ts.map +1 -0
- package/dist/types/crop/crop-controller.d.ts +407 -0
- package/dist/types/crop/crop-controller.d.ts.map +1 -0
- package/dist/types/export/export-format.d.ts +136 -0
- package/dist/types/export/export-format.d.ts.map +1 -0
- package/dist/types/export/export-service.d.ts +333 -0
- package/dist/types/export/export-service.d.ts.map +1 -0
- package/dist/types/fabric/fabric-adapter.d.ts +74 -0
- package/dist/types/fabric/fabric-adapter.d.ts.map +1 -0
- package/dist/types/fabric/fabric-animation.d.ts +141 -0
- package/dist/types/fabric/fabric-animation.d.ts.map +1 -0
- package/dist/types/history/command.d.ts +16 -0
- package/dist/types/history/command.d.ts.map +1 -0
- package/dist/types/history/history-manager.d.ts +129 -0
- package/dist/types/history/history-manager.d.ts.map +1 -0
- package/dist/types/image/image-loader.d.ts +265 -0
- package/dist/types/image/image-loader.d.ts.map +1 -0
- package/dist/types/image/image-resampler.d.ts +139 -0
- package/dist/types/image/image-resampler.d.ts.map +1 -0
- package/dist/types/image/layout-manager.d.ts +255 -0
- package/dist/types/image/layout-manager.d.ts.map +1 -0
- package/dist/types/image/transform-controller.d.ts +287 -0
- package/dist/types/image/transform-controller.d.ts.map +1 -0
- package/dist/types/image-editor.d.ts +650 -0
- package/dist/types/image-editor.d.ts.map +1 -0
- package/dist/types/index.d.cts +31 -0
- package/dist/types/index.d.cts.map +1 -0
- package/dist/types/index.d.ts +31 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/mask/mask-factory.d.ts +209 -0
- package/dist/types/mask/mask-factory.d.ts.map +1 -0
- package/dist/types/mask/mask-label-manager.d.ts +171 -0
- package/dist/types/mask/mask-label-manager.d.ts.map +1 -0
- package/dist/types/mask/mask-list.d.ts +144 -0
- package/dist/types/mask/mask-list.d.ts.map +1 -0
- package/dist/types/mask/mask-style.d.ts +338 -0
- package/dist/types/mask/mask-style.d.ts.map +1 -0
- package/dist/types/ui/dom-bindings.d.ts +103 -0
- package/dist/types/ui/dom-bindings.d.ts.map +1 -0
- package/dist/types/ui/ui-state.d.ts +112 -0
- package/dist/types/ui/ui-state.d.ts.map +1 -0
- package/dist/types/ui/visibility-state.d.ts +77 -0
- package/dist/types/ui/visibility-state.d.ts.map +1 -0
- package/dist/types/utils/canvas-region.d.ts +177 -0
- package/dist/types/utils/canvas-region.d.ts.map +1 -0
- package/dist/types/utils/dom.d.ts +26 -0
- package/dist/types/utils/dom.d.ts.map +1 -0
- package/dist/types/utils/file.d.ts +80 -0
- package/dist/types/utils/file.d.ts.map +1 -0
- package/dist/types/utils/number.d.ts +132 -0
- package/dist/types/utils/number.d.ts.map +1 -0
- package/dist/types/utils/timeout.d.ts +84 -0
- package/dist/types/utils/timeout.d.ts.map +1 -0
- package/dist/umd/image-editor.umd.js +2 -0
- package/dist/umd/image-editor.umd.js.map +1 -0
- package/package.json +72 -66
- package/dist/image-editor.cjs +0 -4407
- package/dist/image-editor.cjs.map +0 -7
- package/dist/image-editor.esm.js +0 -4376
- package/dist/image-editor.esm.js.map +0 -7
- package/dist/image-editor.esm.min.js +0 -9
- package/dist/image-editor.esm.min.js.map +0 -7
- package/dist/image-editor.esm.min.mjs +0 -9
- package/dist/image-editor.esm.min.mjs.map +0 -7
- package/dist/image-editor.esm.mjs +0 -4376
- package/dist/image-editor.esm.mjs.map +0 -7
- package/dist/image-editor.js +0 -4373
- package/dist/image-editor.js.map +0 -7
- package/dist/image-editor.min.js +0 -9
- package/dist/image-editor.min.js.map +0 -7
- package/image-editor.d.ts +0 -271
- package/src/browser.js +0 -11
- package/src/esm.js +0 -9
- package/src/image-editor.js +0 -5013
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers that turn floating-point Fabric.js bounding
|
|
3
|
+
* rectangles into integer pixel regions and provide the
|
|
4
|
+
* bounding-box math that mask preservation across crop and
|
|
5
|
+
* export paths share.
|
|
6
|
+
*
|
|
7
|
+
* ## Owned contracts
|
|
8
|
+
*
|
|
9
|
+
* - Export regions SHALL include partially covered trailing pixels so
|
|
10
|
+
* sub-pixel image bounds do not lose the right or bottom edge.
|
|
11
|
+
* - Crop regions SHALL exclude trailing partial pixels so crop does not
|
|
12
|
+
* grow by a transparent row or column.
|
|
13
|
+
* - When `applyCrop` runs with
|
|
14
|
+
* `preserveMasksAfterCrop === true` and the image has been rotated,
|
|
15
|
+
* each mask's new `left` and `top` SHALL be expressed in the cropped
|
|
16
|
+
* image's coordinate frame using the rotation angle.
|
|
17
|
+
* - Across a crop apply, each mask's `angle`,
|
|
18
|
+
* `scaleX`, and `scaleY` SHALL be preserved so the visible shape does
|
|
19
|
+
* not change size or orientation.
|
|
20
|
+
*
|
|
21
|
+
* ## Why a dedicated module
|
|
22
|
+
*
|
|
23
|
+
* Region math is shared by export, crop, expand-to-image sizing, and crop
|
|
24
|
+
* rectangle initialization. Centralizing it prevents one call site from
|
|
25
|
+
* drifting from the others (for example, applying `Math.floor` instead of
|
|
26
|
+
* `Math.round`, or forgetting the `width >= 1` floor).
|
|
27
|
+
*
|
|
28
|
+
* ## Design notes
|
|
29
|
+
*
|
|
30
|
+
* - Region floors are total: any non-finite input collapses to a
|
|
31
|
+
* `1×1` region anchored at `(0, 0)` rather than throwing. The export
|
|
32
|
+
* and crop pipelines already validate the presence of an
|
|
33
|
+
* `originalImage` upstream, so a defensive fallback here keeps the
|
|
34
|
+
* `<canvas>.drawImage` call from being passed `NaN` if Fabric ever
|
|
35
|
+
* reports a degenerate bounding rect.
|
|
36
|
+
* - `getObjectBBox` calls `setCoords` before reading the bounding
|
|
37
|
+
* rect because Fabric.js v7's `getBoundingRect` returns the cached
|
|
38
|
+
* absolute rect; without the refresh a freshly-mutated mask returns
|
|
39
|
+
* stale coordinates. Callers that have already refreshed coords pay
|
|
40
|
+
* only a single redundant call, which is cheaper than double-tracking
|
|
41
|
+
* "is this object's cache fresh?" at every site.
|
|
42
|
+
* - `clampRegionToCanvas` exists for the crop pipeline, where the crop
|
|
43
|
+
* rectangle's bounding rect can briefly exceed the canvas after a
|
|
44
|
+
* user drag near the edge; clamping before the `drawImage` keeps the
|
|
45
|
+
* blit inside the source canvas.
|
|
46
|
+
*
|
|
47
|
+
* ## Non-goals
|
|
48
|
+
*
|
|
49
|
+
* - This module does not perform any coordinate transformation between
|
|
50
|
+
* pre-crop and post-crop frames; the rotation math for the
|
|
51
|
+
* rotated-mask coordinate frame lives in `crop/crop-controller.ts`,
|
|
52
|
+
* which uses
|
|
53
|
+
* `getObjectBBox` here only as one input to that calculation.
|
|
54
|
+
* - This module does not mutate the Fabric object passed to
|
|
55
|
+
* `getObjectBBox` beyond the `setCoords` refresh required by
|
|
56
|
+
* Fabric.js v7's API.
|
|
57
|
+
*
|
|
58
|
+
* @module
|
|
59
|
+
*/
|
|
60
|
+
import type * as FabricNS from 'fabric';
|
|
61
|
+
/**
|
|
62
|
+
* A canvas region whose `left` / `top` / `width` / `height` are all
|
|
63
|
+
* integer pixels suitable for `CanvasRenderingContext2D.drawImage` and
|
|
64
|
+
* Fabric.js `toDataURL({ left, top, width, height})`.
|
|
65
|
+
*
|
|
66
|
+
* Produced by {@link floorRegion} and {@link clampRegionToCanvas}; the
|
|
67
|
+
* `width` and `height` fields are guaranteed to be at least `1` so
|
|
68
|
+
* region exports never collapse to a zero-pixel image.
|
|
69
|
+
*/
|
|
70
|
+
export interface IntegerRegion {
|
|
71
|
+
left: number;
|
|
72
|
+
top: number;
|
|
73
|
+
width: number;
|
|
74
|
+
height: number;
|
|
75
|
+
}
|
|
76
|
+
export interface RegionRoundingOptions {
|
|
77
|
+
/**
|
|
78
|
+
* When true, `right` / `bottom` are ceiled to include partially covered
|
|
79
|
+
* trailing pixels. When false, they are floored to exclude them.
|
|
80
|
+
* @default true
|
|
81
|
+
*/
|
|
82
|
+
includePartialPixels?: boolean;
|
|
83
|
+
}
|
|
84
|
+
export interface PartialExportEdges {
|
|
85
|
+
left: boolean;
|
|
86
|
+
top: boolean;
|
|
87
|
+
right: boolean;
|
|
88
|
+
bottom: boolean;
|
|
89
|
+
}
|
|
90
|
+
export declare function hasMeaningfulCanvasRegion(rect: {
|
|
91
|
+
left: number;
|
|
92
|
+
top: number;
|
|
93
|
+
width: number;
|
|
94
|
+
height: number;
|
|
95
|
+
}, canvasWidth?: number, canvasHeight?: number): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Convert a floating-point rectangle into an {@link IntegerRegion}.
|
|
98
|
+
*
|
|
99
|
+
* - `left` / `top` are floored and clamped to `>= 0` so the region
|
|
100
|
+
* never starts before the source canvas's top-left corner.
|
|
101
|
+
* - `right` / `bottom` are ceiled by default to include partially covered
|
|
102
|
+
* trailing pixels, or floored when `includePartialPixels` is false.
|
|
103
|
+
* - `width` / `height` are derived from those integer edges and clamped
|
|
104
|
+
* to `>= 1` so no sub-pixel dimensions reach Fabric's region export.
|
|
105
|
+
* - Non-finite inputs collapse to a `1×1` region at `(0, 0)` rather than
|
|
106
|
+
* propagating `NaN` into the canvas pipeline.
|
|
107
|
+
*
|
|
108
|
+
* region floor before mask remapping).
|
|
109
|
+
*
|
|
110
|
+
* @param rect - The floating-point bounding rect to discretize.
|
|
111
|
+
* @returns An {@link IntegerRegion} safe to pass to `drawImage`.
|
|
112
|
+
*/
|
|
113
|
+
export declare function getClampedCanvasRegion(rect: {
|
|
114
|
+
left: number;
|
|
115
|
+
top: number;
|
|
116
|
+
width: number;
|
|
117
|
+
height: number;
|
|
118
|
+
}, canvasWidth?: number, canvasHeight?: number, options?: RegionRoundingOptions): IntegerRegion;
|
|
119
|
+
export declare function floorRegion(rect: {
|
|
120
|
+
left: number;
|
|
121
|
+
top: number;
|
|
122
|
+
width: number;
|
|
123
|
+
height: number;
|
|
124
|
+
}): IntegerRegion;
|
|
125
|
+
export declare function hasFractionalCanvasEdge(value: number): boolean;
|
|
126
|
+
export declare function getPartialExportEdges(bounds: {
|
|
127
|
+
left: number;
|
|
128
|
+
top: number;
|
|
129
|
+
width: number;
|
|
130
|
+
height: number;
|
|
131
|
+
} | null, angle?: number): PartialExportEdges | null;
|
|
132
|
+
/**
|
|
133
|
+
* Read a Fabric.js object's absolute bounding rectangle in canvas-pixel
|
|
134
|
+
* coordinates.
|
|
135
|
+
*
|
|
136
|
+
* `setCoords` is called first because Fabric.js v7's
|
|
137
|
+
* `getBoundingRect` returns the cached absolute rect — the per-frame
|
|
138
|
+
* cache the canvas already maintains. Without the refresh a freshly
|
|
139
|
+
* mutated mask returns stale coordinates, which can make rotated masks
|
|
140
|
+
* drift after crop.
|
|
141
|
+
*
|
|
142
|
+
* The returned rect uses floating-point coordinates; callers that need
|
|
143
|
+
* integer pixel regions should pipe the result through
|
|
144
|
+
* {@link floorRegion}.
|
|
145
|
+
*
|
|
146
|
+
* @param object - The Fabric.js object to measure.
|
|
147
|
+
* @returns The absolute bounding rect in canvas pixels.
|
|
148
|
+
*/
|
|
149
|
+
export declare function getObjectBBox(object: FabricNS.FabricObject): {
|
|
150
|
+
left: number;
|
|
151
|
+
top: number;
|
|
152
|
+
width: number;
|
|
153
|
+
height: number;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Clamp an {@link IntegerRegion} so it fits entirely inside a canvas of
|
|
157
|
+
* `canvasWidth × canvasHeight` pixels.
|
|
158
|
+
*
|
|
159
|
+
* - `left` is clamped to `[0, canvasWidth - 1]`.
|
|
160
|
+
* - `top` is clamped to `[0, canvasHeight - 1]`.
|
|
161
|
+
* - `width` is clamped so `left + width <= canvasWidth`.
|
|
162
|
+
* - `height` is clamped so `top + height <= canvasHeight`.
|
|
163
|
+
*
|
|
164
|
+
* The function preserves the `width >= 1` / `height >= 1` invariant
|
|
165
|
+
* established by {@link floorRegion}, which keeps callers from having
|
|
166
|
+
* to special-case zero-sized regions when the supplied rect lands
|
|
167
|
+
* entirely outside the canvas.
|
|
168
|
+
*
|
|
169
|
+
* canvas before the mask coordinate remap).
|
|
170
|
+
*
|
|
171
|
+
* @param region - The integer region to clamp.
|
|
172
|
+
* @param canvasWidth - The source canvas's pixel width.
|
|
173
|
+
* @param canvasHeight - The source canvas's pixel height.
|
|
174
|
+
* @returns A clamped {@link IntegerRegion}.
|
|
175
|
+
*/
|
|
176
|
+
export declare function clampRegionToCanvas(region: IntegerRegion, canvasWidth: number, canvasHeight: number): IntegerRegion;
|
|
177
|
+
//# sourceMappingURL=canvas-region.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-region.d.ts","sourceRoot":"","sources":["../../../src/utils/canvas-region.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAEH,OAAO,KAAK,KAAK,QAAQ,MAAM,QAAQ,CAAC;AAExC;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,yBAAyB,CACrC,IAAI,EAAE;IACF,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB,EACD,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE,MAAM,GACtB,OAAO,CAkCT;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAClC,IAAI,EAAE;IACF,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB,EACD,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,GAAE,qBAA0B,GACpC,aAAa,CA4Bf;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB,GAAG,aAAa,CAEhB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAI9D;AAED,wBAAgB,qBAAqB,CACjC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EAC3E,KAAK,SAAI,GACV,kBAAkB,GAAG,IAAI,CAc3B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,YAAY,GAAG;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAClB,CASA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACrB,aAAa,CASf"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM micro-helpers used by sizing and visibility flows.
|
|
3
|
+
*
|
|
4
|
+
* Kept intentionally small: the editor depends on a single synchronous
|
|
5
|
+
* reflow primitive after canvas dimension changes, and exposing it as a
|
|
6
|
+
* named utility lets layout, visibility, and crop flows share the same
|
|
7
|
+
* documented contract.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Force a synchronous layout reflow on `element`.
|
|
11
|
+
*
|
|
12
|
+
* Reading an offset/scroll/clientWidth-like property forces the browser
|
|
13
|
+
* to flush queued style and layout work on the spot, before any further
|
|
14
|
+
* script runs. The editor relies on this after `Canvas.setDimensions`
|
|
15
|
+
* so a container with `overflow: auto` shows or hides scrollbars before
|
|
16
|
+
* the next paint, instead of waiting for the next frame.
|
|
17
|
+
*
|
|
18
|
+
* The read is cast to `void` and isolated in this helper so optimizers
|
|
19
|
+
* cannot eliminate it as a dead access. The function is a no-op when
|
|
20
|
+
* `element` is `null` or `undefined`, which keeps callers free of guards in
|
|
21
|
+
* environments where the container element may not yet be attached.
|
|
22
|
+
*
|
|
23
|
+
* @param element - The element whose layout should be flushed. `null` is ignored.
|
|
24
|
+
*/
|
|
25
|
+
export declare function forceReflow(element: HTMLElement | null | undefined): void;
|
|
26
|
+
//# sourceMappingURL=dom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../../src/utils/dom.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAMzE"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-input helpers used by the editor's file-input flow.
|
|
3
|
+
*
|
|
4
|
+
* These helpers cover three concerns:
|
|
5
|
+
*
|
|
6
|
+
* - Determining whether a `File` selected through the upload control is a
|
|
7
|
+
* supported image, including the extension fallback when `file.type` is
|
|
8
|
+
* empty (some operating systems and browsers report an empty MIME type
|
|
9
|
+
* for known extensions).
|
|
10
|
+
* - Reading the file as a base64 data URL so the result can be routed
|
|
11
|
+
* through the existing transactional `loadImage` pipeline (and therefore
|
|
12
|
+
* inherit its rollback behavior on decode/Fabric/timeout failure).
|
|
13
|
+
* - Resetting the file input value after every attempt so selecting the
|
|
14
|
+
* same file again triggers a fresh `change` event.
|
|
15
|
+
*
|
|
16
|
+
* The helpers do not call `loadImage` themselves; the orchestrator wires
|
|
17
|
+
* them into the file-input change handler. That keeps the public
|
|
18
|
+
* `loadImage` API unchanged beyond `LoadImageOptions`.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Supported image extensions and the MIME type each one resolves to.
|
|
22
|
+
*
|
|
23
|
+
* Supported file extensions: `png`, `jpg`/`jpeg`, `webp`, `gif`, `bmp`.
|
|
24
|
+
* GIF and BMP are accepted as static raster input for canvas editing. GIF
|
|
25
|
+
* animation and GIF/BMP source-format preservation are not retained; exports
|
|
26
|
+
* are emitted through the editor's JPEG, PNG, or WebP export options.
|
|
27
|
+
*
|
|
28
|
+
* Keys are lowercase extensions without the leading `.`.
|
|
29
|
+
*/
|
|
30
|
+
export declare const SUPPORTED_IMAGE_EXTENSIONS: Record<string, string>;
|
|
31
|
+
export declare const SUPPORTED_IMAGE_MIME_TYPES: Set<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Determine whether a `File` is a supported image and return its resolved
|
|
34
|
+
* MIME type, or `null` when it should be rejected.
|
|
35
|
+
*
|
|
36
|
+
* Resolution order:
|
|
37
|
+
*
|
|
38
|
+
* 1. If `file.type` is one of the supported image MIME types, return it
|
|
39
|
+
* verbatim.
|
|
40
|
+
* 2. If `file.type` is empty, infer the MIME type from the file
|
|
41
|
+
* extension via {@link SUPPORTED_IMAGE_EXTENSIONS}. This covers the
|
|
42
|
+
* case where a browser or OS reports `''` for files with a known
|
|
43
|
+
* extension.
|
|
44
|
+
* 3. Otherwise, return `null` so the caller can skip the load without
|
|
45
|
+
* mutating editor state.
|
|
46
|
+
*
|
|
47
|
+
* @param file - File selected via the upload control.
|
|
48
|
+
* @returns The resolved MIME type, or `null` when the file is not a
|
|
49
|
+
* supported image.
|
|
50
|
+
*/
|
|
51
|
+
export declare function inferImageMimeType(file: File): string | null;
|
|
52
|
+
/**
|
|
53
|
+
* Read a `File` as a base64 data URL using `FileReader`.
|
|
54
|
+
*
|
|
55
|
+
* The returned data URL is suitable for the transactional `loadImage`
|
|
56
|
+
* pipeline: on failure the editor's existing
|
|
57
|
+
* rollback bundle restores placeholder visibility, scroll, overflow,
|
|
58
|
+
* `originalImage`, `lastSnapshot`, and the canvas JSON snapshot.
|
|
59
|
+
*
|
|
60
|
+
* @param file - File to read.
|
|
61
|
+
* @returns A promise that resolves to the data URL string, or rejects when
|
|
62
|
+
* the underlying `FileReader` errors out or returns a non-string
|
|
63
|
+
* result.
|
|
64
|
+
*/
|
|
65
|
+
export declare function readFileAsDataUrl(file: File): Promise<string>;
|
|
66
|
+
/**
|
|
67
|
+
* Reset a file input element's value so selecting the same file again
|
|
68
|
+
* triggers a fresh `change` event.
|
|
69
|
+
*
|
|
70
|
+
* Some browsers reject programmatic assignment to `input.value` on
|
|
71
|
+
* security grounds; the assignment is wrapped in a `try`/`catch` so the
|
|
72
|
+
* caller never has to special-case those environments. A `null` input is
|
|
73
|
+
* a no-op so callers can pass the result of `document.getElementById`
|
|
74
|
+
* without an extra null check.
|
|
75
|
+
*
|
|
76
|
+
* @param input - File input element, or `null` when the element is not
|
|
77
|
+
* present in the DOM.
|
|
78
|
+
*/
|
|
79
|
+
export declare function resetFileInput(input: HTMLInputElement | null): void;
|
|
80
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../src/utils/file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAO7D,CAAC;AAEF,eAAO,MAAM,0BAA0B,aAAqD,CAAC;AAE7F;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAO5D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAmB7D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAOnE"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers used by `mask/mask-factory.ts` to turn the
|
|
3
|
+
* flexible `MaskNumericProp` and `PolygonPoint` inputs of
|
|
4
|
+
* {@link MaskConfig} into concrete numbers and `{ x, y }`
|
|
5
|
+
* points before a Fabric.js shape is constructed.
|
|
6
|
+
*
|
|
7
|
+
* ## Owned contracts
|
|
8
|
+
*
|
|
9
|
+
* - `MaskConfig` percentage values supplied for
|
|
10
|
+
* `left`, `width`, `rx`, or `radius` SHALL resolve against the canvas
|
|
11
|
+
* pixel **width** (axis `'x'`).
|
|
12
|
+
* - `MaskConfig` percentage values supplied for
|
|
13
|
+
* `top`, `height`, or `ry` SHALL resolve against the canvas pixel
|
|
14
|
+
* **height** (axis `'y'`).
|
|
15
|
+
* - A `MaskNumericProp` provided as a function
|
|
16
|
+
* SHALL be invoked with `(canvas, ResolvedOptions)` and the returned
|
|
17
|
+
* number used directly.
|
|
18
|
+
* - Polygon point items SHALL be accepted in
|
|
19
|
+
* either `{ x, y }` object form or `[x, y]` tuple form and coerced to
|
|
20
|
+
* numeric `{ x, y }` internally.
|
|
21
|
+
*
|
|
22
|
+
* ## Why a dedicated module
|
|
23
|
+
*
|
|
24
|
+
* `resolveNumeric` is axis-aware so horizontal values resolve against
|
|
25
|
+
* canvas width and vertical values resolve against canvas height.
|
|
26
|
+
* `coercePoint` lives next to it because both helpers are pure functions
|
|
27
|
+
* consumed by the same mask-factory pipeline.
|
|
28
|
+
*
|
|
29
|
+
* ## Design notes
|
|
30
|
+
*
|
|
31
|
+
* - `resolveNumeric` is total: any input that is not a number, a finite
|
|
32
|
+
* percentage string, or a function falls through to `fallback` rather
|
|
33
|
+
* than throwing.
|
|
34
|
+
* - Percentages are floored (`Math.floor`) to keep rendered placement
|
|
35
|
+
* deterministic across canvas resizes.
|
|
36
|
+
* - The helper does NOT clamp the result against canvas bounds; callers
|
|
37
|
+
* are responsible for any subsequent clamping (the mask factory may
|
|
38
|
+
* expand the canvas to accommodate larger placements when
|
|
39
|
+
* `expandCanvasToImage` is enabled).
|
|
40
|
+
*
|
|
41
|
+
* ## Non-goals
|
|
42
|
+
*
|
|
43
|
+
* - This module does not validate that the supplied `axis` matches the
|
|
44
|
+
* field being resolved. Routing each `MaskConfig` field to the correct
|
|
45
|
+
* axis is the mask factory's responsibility.
|
|
46
|
+
* - This module does not coerce or round the output of factory functions
|
|
47
|
+
* (`(canvas, options) => number`); their return value is used verbatim
|
|
48
|
+
* so consumers retain full control over sub-pixel placement.
|
|
49
|
+
*
|
|
50
|
+
* @module
|
|
51
|
+
*/
|
|
52
|
+
import type * as FabricNS from 'fabric';
|
|
53
|
+
import type { MaskNumericProp, PolygonPoint, ResolvedOptions } from '../core/public-types.js';
|
|
54
|
+
/**
|
|
55
|
+
* Axis selector used by {@link resolveNumeric} to decide which canvas
|
|
56
|
+
* dimension a percentage value resolves against.
|
|
57
|
+
*
|
|
58
|
+
* - `'x'` → `canvas.getWidth`
|
|
59
|
+
* - `'y'` → `canvas.getHeight`
|
|
60
|
+
*/
|
|
61
|
+
export type Axis = 'x' | 'y';
|
|
62
|
+
/**
|
|
63
|
+
* Resolve a {@link MaskNumericProp} into a concrete pixel number.
|
|
64
|
+
*
|
|
65
|
+
* Resolution rules (in order):
|
|
66
|
+
* 1. If `val` is a `number`, return it unchanged.
|
|
67
|
+
* 2. If `val` is a function, invoke it as `val(canvas, options)` and
|
|
68
|
+
* return the result.
|
|
69
|
+
* 3. If `val` is a string ending in `'%'`, parse the leading number,
|
|
70
|
+
* multiply by `canvas.getWidth` (axis `'x'`) or
|
|
71
|
+
* `canvas.getHeight` (axis `'y'`), floor the product, and return
|
|
72
|
+
* it. Strings that do not parse to a
|
|
73
|
+
* finite number fall through to `fallback`.
|
|
74
|
+
* 4. Anything else (including `undefined`, `null`, non-percent strings,
|
|
75
|
+
* booleans, etc.) returns `fallback`.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* // 50% of an 800px-wide canvas:
|
|
80
|
+
* resolveNumeric('50%', 'x', 0, canvas, options); // → 400
|
|
81
|
+
*
|
|
82
|
+
* // Function form receives the live canvas and ResolvedOptions:
|
|
83
|
+
* resolveNumeric(
|
|
84
|
+
* (canvas) => canvas.getWidth() - 20,
|
|
85
|
+
* 'x',
|
|
86
|
+
* 0,
|
|
87
|
+
* canvas,
|
|
88
|
+
* options,
|
|
89
|
+
* ); // → canvas.getWidth() - 20
|
|
90
|
+
*
|
|
91
|
+
* // Unrecognized input falls back:
|
|
92
|
+
* resolveNumeric(undefined, 'x', 10, canvas, options); // → 10
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* @param val - The flexible mask numeric property to resolve.
|
|
96
|
+
* @param axis - Which canvas dimension a percentage resolves against.
|
|
97
|
+
* @param fallback - Value returned when `val` cannot be resolved.
|
|
98
|
+
* @param canvas - Live Fabric.js canvas; only `getWidth`/`getHeight`
|
|
99
|
+
* are read here, but the entire canvas is forwarded to
|
|
100
|
+
* factory functions.
|
|
101
|
+
* @param options - Fully-resolved editor options forwarded to factory
|
|
102
|
+
* functions.
|
|
103
|
+
*
|
|
104
|
+
* @returns The resolved pixel number, or `fallback` when no rule applies.
|
|
105
|
+
*/
|
|
106
|
+
export declare function resolveNumeric(val: MaskNumericProp | undefined, axis: Axis, fallback: number, canvas: FabricNS.Canvas, options: ResolvedOptions): number;
|
|
107
|
+
/**
|
|
108
|
+
* Coerce a {@link PolygonPoint} into the canonical `{ x, y }` numeric
|
|
109
|
+
* shape used by Fabric.js polygon construction.
|
|
110
|
+
*
|
|
111
|
+
* Both input forms are accepted so callers may write polygon points in
|
|
112
|
+
* whichever style is most ergonomic at the call site:
|
|
113
|
+
*
|
|
114
|
+
* ```ts
|
|
115
|
+
* coercePoint({ x: 10, y: 20 }); // → { x: 10, y: 20 }
|
|
116
|
+
* coercePoint([10, 20]); // → { x: 10, y: 20 }
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* Values are coerced via `Number(...)` so string-encoded coordinates
|
|
120
|
+
* (e.g. coming straight from a JSON payload) round-trip correctly. Any
|
|
121
|
+
* value that fails to coerce becomes `NaN`, matching the rest of the
|
|
122
|
+
* mask pipeline's tolerant input handling — callers that need stricter
|
|
123
|
+
* validation should perform it before constructing the polygon.
|
|
124
|
+
*
|
|
125
|
+
* @param pt - A polygon vertex in object or tuple form.
|
|
126
|
+
* @returns An `{ x, y }` numeric point.
|
|
127
|
+
*/
|
|
128
|
+
export declare function coercePoint(pt: PolygonPoint): {
|
|
129
|
+
x: number;
|
|
130
|
+
y: number;
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=number.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number.d.ts","sourceRoot":"","sources":["../../../src/utils/number.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,OAAO,KAAK,KAAK,QAAQ,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE9F;;;;;;GAMG;AACH,MAAM,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,cAAc,CAC1B,GAAG,EAAE,eAAe,GAAG,SAAS,EAChC,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,QAAQ,CAAC,MAAM,EACvB,OAAO,EAAE,eAAe,GACzB,MAAM,CAgBR;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,YAAY,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAKtE"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Promise/timer race helper used by the image-loader pipeline
|
|
3
|
+
* to bound the decode and `FabricImage.fromURL` steps.
|
|
4
|
+
*
|
|
5
|
+
* ## Owned contracts
|
|
6
|
+
*
|
|
7
|
+
* - `loadImage(base64)` decode of the data URL into
|
|
8
|
+
* an `HTMLImageElement` SHALL be bounded by `options.imageLoadTimeoutMs`.
|
|
9
|
+
* - `loadImage(base64)` `FabricImage.fromURL` step
|
|
10
|
+
* SHALL be bounded by the same `options.imageLoadTimeoutMs`.
|
|
11
|
+
* - If either timeout elapses, the returned promise
|
|
12
|
+
* SHALL reject with a timeout error whose message includes the elapsed
|
|
13
|
+
* milliseconds. The {@link ImageLoadTimeoutError} class owns the message
|
|
14
|
+
* format; this module simply produces the error with the correct
|
|
15
|
+
* `(label, elapsedMs)` pair.
|
|
16
|
+
*
|
|
17
|
+
* ## Why a dedicated module
|
|
18
|
+
*
|
|
19
|
+
* The image-loader needs to apply the *same* timeout policy to two
|
|
20
|
+
* independent async steps (decode and Fabric image creation). Centralizing
|
|
21
|
+
* the race in one helper keeps the loader straight-line, ensures both
|
|
22
|
+
* steps reject with the same error type, and gives the timeout logic a
|
|
23
|
+
* single place to evolve (for example, future cancellation hooks).
|
|
24
|
+
*
|
|
25
|
+
* ## Design notes
|
|
26
|
+
*
|
|
27
|
+
* - The race is implemented with a `setTimeout`-based timer that is
|
|
28
|
+
* cleared as soon as the wrapped promise settles, so a slow-but-eventual
|
|
29
|
+
* resolution does not leave a dangling timer (and the elapsed-time
|
|
30
|
+
* measurement remains tight).
|
|
31
|
+
* - On timeout, the helper computes elapsed ms from a `Date.now` taken
|
|
32
|
+
* at the start of the race. This avoids drift versus the `ms` argument
|
|
33
|
+
* for callers that want to log the actual wall-clock duration.
|
|
34
|
+
* - On rejection of the wrapped promise, the original error is forwarded
|
|
35
|
+
* verbatim so the loader can branch on its specific type
|
|
36
|
+
* (`ImageDecodeError`, `DownsampleError`, etc.) rather than always
|
|
37
|
+
* seeing a `ImageLoadTimeoutError`.
|
|
38
|
+
*
|
|
39
|
+
* ## Non-goals
|
|
40
|
+
*
|
|
41
|
+
* - The helper does NOT cancel the wrapped promise. JavaScript promises
|
|
42
|
+
* have no built-in cancellation; the caller is responsible for any
|
|
43
|
+
* cleanup of the underlying work (e.g. clearing an `<img>.src`).
|
|
44
|
+
* - The helper does NOT validate `ms`. Callers pass the resolved
|
|
45
|
+
* `imageLoadTimeoutMs` from `default-options.ts`, which is already
|
|
46
|
+
* coerced to a finite non-negative number.
|
|
47
|
+
*
|
|
48
|
+
* @module
|
|
49
|
+
*/
|
|
50
|
+
/**
|
|
51
|
+
* Race a promise against a timer. If the timer fires first, reject with
|
|
52
|
+
* an {@link ImageLoadTimeoutError} whose message includes `label` and the
|
|
53
|
+
* elapsed milliseconds. If the wrapped promise settles
|
|
54
|
+
* first, the timer is cleared and the original outcome is forwarded.
|
|
55
|
+
*
|
|
56
|
+
* Used by `image/image-loader.ts` to bound both the decode step and the
|
|
57
|
+
* `FabricImage.fromURL` step of `loadImage`.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* await withTimeout(
|
|
62
|
+
* decodeImageElement(base64),
|
|
63
|
+
* options.imageLoadTimeoutMs,
|
|
64
|
+
* 'image decode',
|
|
65
|
+
* );
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @typeParam T - Resolved value type of the wrapped promise.
|
|
69
|
+
*
|
|
70
|
+
* @param promise - The async work to race. Forwarded verbatim on resolution; rejection
|
|
71
|
+
* reasons are forwarded unchanged so callers can branch on the original
|
|
72
|
+
* error type.
|
|
73
|
+
* @param ms - Timeout duration in milliseconds. Expected to be a finite,
|
|
74
|
+
* non-negative number; the caller (typically `default-options.ts`) is
|
|
75
|
+
* responsible for coercion.
|
|
76
|
+
* @param label - Human-readable step label embedded in the timeout error message
|
|
77
|
+
* (e.g. `'image decode'`, `'FabricImage.fromURL'`).
|
|
78
|
+
*
|
|
79
|
+
* @returns A promise that resolves to the wrapped promise's value, or
|
|
80
|
+
* rejects with the wrapped promise's reason, or rejects with
|
|
81
|
+
* {@link ImageLoadTimeoutError} if the timer fires first.
|
|
82
|
+
*/
|
|
83
|
+
export declare function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T>;
|
|
84
|
+
//# sourceMappingURL=timeout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../../../src/utils/timeout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAIH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAkBzF"}
|