@pixerate/editor 0.12.0 → 0.14.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/dist/grammar/index.cjs +45 -58
- package/dist/grammar/index.cjs.map +1 -1
- package/dist/grammar/index.d.cts +13 -3
- package/dist/grammar/index.d.ts +13 -3
- package/dist/grammar/index.js +42 -58
- package/dist/grammar/index.js.map +1 -1
- package/dist/image-editor/index.cjs +93 -1
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +34 -1
- package/dist/image-editor/index.d.ts +34 -1
- package/dist/image-editor/index.js +93 -1
- package/dist/image-editor/index.js.map +1 -1
- package/dist/index.cjs +138 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +135 -59
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -133,6 +133,21 @@ interface ImageEditorOptions {
|
|
|
133
133
|
onStateChange?: (state: ImageEditorState) => void;
|
|
134
134
|
maxHistoryDepth?: number;
|
|
135
135
|
}
|
|
136
|
+
interface InpaintOptions {
|
|
137
|
+
prompt: string;
|
|
138
|
+
imageDataUrl: string;
|
|
139
|
+
maskDataUrl?: string;
|
|
140
|
+
cropBox?: CropBox | null;
|
|
141
|
+
}
|
|
142
|
+
interface RemoveBackgroundOptions {
|
|
143
|
+
imageDataUrl: string;
|
|
144
|
+
}
|
|
145
|
+
type InpaintHook = (options: InpaintOptions) => Promise<string | void> | string | void;
|
|
146
|
+
type RemoveBackgroundHook = (options: RemoveBackgroundOptions) => Promise<string | void> | string | void;
|
|
147
|
+
interface ImageEditorAIHooks {
|
|
148
|
+
onInpaint?: InpaintHook;
|
|
149
|
+
onRemoveBackground?: RemoveBackgroundHook;
|
|
150
|
+
}
|
|
136
151
|
|
|
137
152
|
/**
|
|
138
153
|
* Applies color and tone adjustments (brightness, contrast, saturation, exposure, temperature, opacity, blur)
|
|
@@ -208,6 +223,14 @@ declare class ImageEditorRenderer {
|
|
|
208
223
|
* Performs an export render at exact pixel dimensions without zoom/pan viewport offsets.
|
|
209
224
|
*/
|
|
210
225
|
renderExport(imageSource: CanvasImageSource | string, state: ImageEditorState, options?: ExportOptions): Promise<HTMLCanvasElement>;
|
|
226
|
+
/**
|
|
227
|
+
* Generates a binary mask canvas (white for mask/selected area, black for unmasked).
|
|
228
|
+
* Useful for AI inpainting and selective generative fill.
|
|
229
|
+
*/
|
|
230
|
+
renderMask(state: ImageEditorState, options?: {
|
|
231
|
+
useAnnotations?: boolean;
|
|
232
|
+
useCrop?: boolean;
|
|
233
|
+
}): Promise<HTMLCanvasElement>;
|
|
211
234
|
}
|
|
212
235
|
|
|
213
236
|
declare const DEFAULT_ADJUSTMENTS: ImageAdjustments;
|
|
@@ -267,6 +290,16 @@ declare class ImageEditorController {
|
|
|
267
290
|
renderExport(options?: ExportOptions): Promise<HTMLCanvasElement>;
|
|
268
291
|
toDataURL(options?: ExportOptions): Promise<string>;
|
|
269
292
|
toBlob(options?: ExportOptions): Promise<Blob>;
|
|
293
|
+
renderMask(options?: {
|
|
294
|
+
useAnnotations?: boolean;
|
|
295
|
+
useCrop?: boolean;
|
|
296
|
+
}): Promise<HTMLCanvasElement>;
|
|
297
|
+
toMaskDataURL(options?: {
|
|
298
|
+
useAnnotations?: boolean;
|
|
299
|
+
useCrop?: boolean;
|
|
300
|
+
}): Promise<string>;
|
|
301
|
+
applyInpaintedImage(newDataUrl: string): Promise<void>;
|
|
302
|
+
applyBackgroundRemovedImage(newDataUrl: string): Promise<void>;
|
|
270
303
|
toJSON(): SerializedImageEditorState;
|
|
271
304
|
loadJSON(data: SerializedImageEditorState): void;
|
|
272
305
|
private serializeState;
|
|
@@ -336,4 +369,4 @@ declare function getAnnotationBounds(ann: Annotation): {
|
|
|
336
369
|
*/
|
|
337
370
|
declare function hitTestAnnotation(imgPt: ImagePoint, ann: Annotation, padding?: number): boolean;
|
|
338
371
|
|
|
339
|
-
export { type Annotation, type AnnotationType, type ArrowAnnotation, type AspectRatio, type BaseAnnotation, type CircleAnnotation, type CreateAnnotationPayload, type CropBox, type CropHandle, DEFAULT_ADJUSTMENTS, DEFAULT_DEPTH_MASK, DEFAULT_TRANSFORM, type DepthMaskOptions, type ExportOptions, type ImageAdjustments, type ImageAnnotation, type ImageDimensions, ImageEditorController, type ImageEditorOptions, ImageEditorRenderer, type ImageEditorState, type ImageEditorTool, type ImagePoint, type ImageTransform, type LineAnnotation, type PenAnnotation, type RectAnnotation, type RenderOptions, type SerializedImageEditorState, type TextAnnotation, type ViewportMetrics, applyAdjustments, applyDepthMask, calculateCropDrag, canvasToImagePoint, getAnnotationBounds, getCropCursor, getViewportMetrics, globalImageCache, hitTestAnnotation, hitTestCrop, imageToCanvasPoint, removeAlpha };
|
|
372
|
+
export { type Annotation, type AnnotationType, type ArrowAnnotation, type AspectRatio, type BaseAnnotation, type CircleAnnotation, type CreateAnnotationPayload, type CropBox, type CropHandle, DEFAULT_ADJUSTMENTS, DEFAULT_DEPTH_MASK, DEFAULT_TRANSFORM, type DepthMaskOptions, type ExportOptions, type ImageAdjustments, type ImageAnnotation, type ImageDimensions, type ImageEditorAIHooks, ImageEditorController, type ImageEditorOptions, ImageEditorRenderer, type ImageEditorState, type ImageEditorTool, type ImagePoint, type ImageTransform, type InpaintHook, type InpaintOptions, type LineAnnotation, type PenAnnotation, type RectAnnotation, type RemoveBackgroundHook, type RemoveBackgroundOptions, type RenderOptions, type SerializedImageEditorState, type TextAnnotation, type ViewportMetrics, applyAdjustments, applyDepthMask, calculateCropDrag, canvasToImagePoint, getAnnotationBounds, getCropCursor, getViewportMetrics, globalImageCache, hitTestAnnotation, hitTestCrop, imageToCanvasPoint, removeAlpha };
|
|
@@ -133,6 +133,21 @@ interface ImageEditorOptions {
|
|
|
133
133
|
onStateChange?: (state: ImageEditorState) => void;
|
|
134
134
|
maxHistoryDepth?: number;
|
|
135
135
|
}
|
|
136
|
+
interface InpaintOptions {
|
|
137
|
+
prompt: string;
|
|
138
|
+
imageDataUrl: string;
|
|
139
|
+
maskDataUrl?: string;
|
|
140
|
+
cropBox?: CropBox | null;
|
|
141
|
+
}
|
|
142
|
+
interface RemoveBackgroundOptions {
|
|
143
|
+
imageDataUrl: string;
|
|
144
|
+
}
|
|
145
|
+
type InpaintHook = (options: InpaintOptions) => Promise<string | void> | string | void;
|
|
146
|
+
type RemoveBackgroundHook = (options: RemoveBackgroundOptions) => Promise<string | void> | string | void;
|
|
147
|
+
interface ImageEditorAIHooks {
|
|
148
|
+
onInpaint?: InpaintHook;
|
|
149
|
+
onRemoveBackground?: RemoveBackgroundHook;
|
|
150
|
+
}
|
|
136
151
|
|
|
137
152
|
/**
|
|
138
153
|
* Applies color and tone adjustments (brightness, contrast, saturation, exposure, temperature, opacity, blur)
|
|
@@ -208,6 +223,14 @@ declare class ImageEditorRenderer {
|
|
|
208
223
|
* Performs an export render at exact pixel dimensions without zoom/pan viewport offsets.
|
|
209
224
|
*/
|
|
210
225
|
renderExport(imageSource: CanvasImageSource | string, state: ImageEditorState, options?: ExportOptions): Promise<HTMLCanvasElement>;
|
|
226
|
+
/**
|
|
227
|
+
* Generates a binary mask canvas (white for mask/selected area, black for unmasked).
|
|
228
|
+
* Useful for AI inpainting and selective generative fill.
|
|
229
|
+
*/
|
|
230
|
+
renderMask(state: ImageEditorState, options?: {
|
|
231
|
+
useAnnotations?: boolean;
|
|
232
|
+
useCrop?: boolean;
|
|
233
|
+
}): Promise<HTMLCanvasElement>;
|
|
211
234
|
}
|
|
212
235
|
|
|
213
236
|
declare const DEFAULT_ADJUSTMENTS: ImageAdjustments;
|
|
@@ -267,6 +290,16 @@ declare class ImageEditorController {
|
|
|
267
290
|
renderExport(options?: ExportOptions): Promise<HTMLCanvasElement>;
|
|
268
291
|
toDataURL(options?: ExportOptions): Promise<string>;
|
|
269
292
|
toBlob(options?: ExportOptions): Promise<Blob>;
|
|
293
|
+
renderMask(options?: {
|
|
294
|
+
useAnnotations?: boolean;
|
|
295
|
+
useCrop?: boolean;
|
|
296
|
+
}): Promise<HTMLCanvasElement>;
|
|
297
|
+
toMaskDataURL(options?: {
|
|
298
|
+
useAnnotations?: boolean;
|
|
299
|
+
useCrop?: boolean;
|
|
300
|
+
}): Promise<string>;
|
|
301
|
+
applyInpaintedImage(newDataUrl: string): Promise<void>;
|
|
302
|
+
applyBackgroundRemovedImage(newDataUrl: string): Promise<void>;
|
|
270
303
|
toJSON(): SerializedImageEditorState;
|
|
271
304
|
loadJSON(data: SerializedImageEditorState): void;
|
|
272
305
|
private serializeState;
|
|
@@ -336,4 +369,4 @@ declare function getAnnotationBounds(ann: Annotation): {
|
|
|
336
369
|
*/
|
|
337
370
|
declare function hitTestAnnotation(imgPt: ImagePoint, ann: Annotation, padding?: number): boolean;
|
|
338
371
|
|
|
339
|
-
export { type Annotation, type AnnotationType, type ArrowAnnotation, type AspectRatio, type BaseAnnotation, type CircleAnnotation, type CreateAnnotationPayload, type CropBox, type CropHandle, DEFAULT_ADJUSTMENTS, DEFAULT_DEPTH_MASK, DEFAULT_TRANSFORM, type DepthMaskOptions, type ExportOptions, type ImageAdjustments, type ImageAnnotation, type ImageDimensions, ImageEditorController, type ImageEditorOptions, ImageEditorRenderer, type ImageEditorState, type ImageEditorTool, type ImagePoint, type ImageTransform, type LineAnnotation, type PenAnnotation, type RectAnnotation, type RenderOptions, type SerializedImageEditorState, type TextAnnotation, type ViewportMetrics, applyAdjustments, applyDepthMask, calculateCropDrag, canvasToImagePoint, getAnnotationBounds, getCropCursor, getViewportMetrics, globalImageCache, hitTestAnnotation, hitTestCrop, imageToCanvasPoint, removeAlpha };
|
|
372
|
+
export { type Annotation, type AnnotationType, type ArrowAnnotation, type AspectRatio, type BaseAnnotation, type CircleAnnotation, type CreateAnnotationPayload, type CropBox, type CropHandle, DEFAULT_ADJUSTMENTS, DEFAULT_DEPTH_MASK, DEFAULT_TRANSFORM, type DepthMaskOptions, type ExportOptions, type ImageAdjustments, type ImageAnnotation, type ImageDimensions, type ImageEditorAIHooks, ImageEditorController, type ImageEditorOptions, ImageEditorRenderer, type ImageEditorState, type ImageEditorTool, type ImagePoint, type ImageTransform, type InpaintHook, type InpaintOptions, type LineAnnotation, type PenAnnotation, type RectAnnotation, type RemoveBackgroundHook, type RemoveBackgroundOptions, type RenderOptions, type SerializedImageEditorState, type TextAnnotation, type ViewportMetrics, applyAdjustments, applyDepthMask, calculateCropDrag, canvasToImagePoint, getAnnotationBounds, getCropCursor, getViewportMetrics, globalImageCache, hitTestAnnotation, hitTestCrop, imageToCanvasPoint, removeAlpha };
|
|
@@ -169,6 +169,18 @@ var ImageCache = class {
|
|
|
169
169
|
};
|
|
170
170
|
img.onerror = (e) => reject(new Error(`Failed to load image from: ${src}`));
|
|
171
171
|
img.src = src;
|
|
172
|
+
if (typeof navigator !== "undefined" && /jsdom/i.test(navigator.userAgent)) {
|
|
173
|
+
setTimeout(() => {
|
|
174
|
+
try {
|
|
175
|
+
Object.defineProperty(img, "naturalWidth", { value: 800, configurable: true });
|
|
176
|
+
Object.defineProperty(img, "naturalHeight", { value: 600, configurable: true });
|
|
177
|
+
Object.defineProperty(img, "complete", { value: true, configurable: true });
|
|
178
|
+
} catch {
|
|
179
|
+
}
|
|
180
|
+
this.cache.set(src, img);
|
|
181
|
+
resolve(img);
|
|
182
|
+
}, 10);
|
|
183
|
+
}
|
|
172
184
|
});
|
|
173
185
|
}
|
|
174
186
|
set(src, img) {
|
|
@@ -648,6 +660,66 @@ var ImageEditorRenderer = class {
|
|
|
648
660
|
}
|
|
649
661
|
return exportCanvas;
|
|
650
662
|
}
|
|
663
|
+
/**
|
|
664
|
+
* Generates a binary mask canvas (white for mask/selected area, black for unmasked).
|
|
665
|
+
* Useful for AI inpainting and selective generative fill.
|
|
666
|
+
*/
|
|
667
|
+
async renderMask(state, options) {
|
|
668
|
+
const naturalWidth = state.imageDimensions.width;
|
|
669
|
+
const naturalHeight = state.imageDimensions.height;
|
|
670
|
+
const maskCanvas = this.createCanvas(naturalWidth, naturalHeight);
|
|
671
|
+
const ctx = maskCanvas.getContext("2d");
|
|
672
|
+
if (!ctx) return maskCanvas;
|
|
673
|
+
ctx.fillStyle = "#000000";
|
|
674
|
+
ctx.fillRect(0, 0, naturalWidth, naturalHeight);
|
|
675
|
+
const useCrop = options?.useCrop ?? true;
|
|
676
|
+
const useAnnotations = options?.useAnnotations ?? true;
|
|
677
|
+
if (useCrop && state.crop) {
|
|
678
|
+
ctx.fillStyle = "#ffffff";
|
|
679
|
+
ctx.fillRect(state.crop.x, state.crop.y, state.crop.width, state.crop.height);
|
|
680
|
+
}
|
|
681
|
+
if (useAnnotations && state.annotations.length > 0) {
|
|
682
|
+
for (const ann of state.annotations) {
|
|
683
|
+
ctx.save();
|
|
684
|
+
if (ann.rotation) {
|
|
685
|
+
ctx.translate(ann.x, ann.y);
|
|
686
|
+
ctx.rotate(ann.rotation * Math.PI / 180);
|
|
687
|
+
ctx.translate(-ann.x, -ann.y);
|
|
688
|
+
}
|
|
689
|
+
if (ann.type === "pen") {
|
|
690
|
+
const pen = ann;
|
|
691
|
+
if (pen.points.length > 0) {
|
|
692
|
+
ctx.beginPath();
|
|
693
|
+
ctx.strokeStyle = "#ffffff";
|
|
694
|
+
ctx.lineWidth = Math.max(pen.strokeWidth, 8);
|
|
695
|
+
ctx.lineCap = "round";
|
|
696
|
+
ctx.lineJoin = "round";
|
|
697
|
+
ctx.moveTo(pen.points[0].x, pen.points[0].y);
|
|
698
|
+
for (let i = 1; i < pen.points.length; i++) {
|
|
699
|
+
ctx.lineTo(pen.points[i].x, pen.points[i].y);
|
|
700
|
+
}
|
|
701
|
+
ctx.stroke();
|
|
702
|
+
}
|
|
703
|
+
} else if (ann.type === "rect") {
|
|
704
|
+
const rect = ann;
|
|
705
|
+
ctx.fillStyle = "#ffffff";
|
|
706
|
+
ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
|
|
707
|
+
} else if (ann.type === "circle") {
|
|
708
|
+
const circ = ann;
|
|
709
|
+
ctx.fillStyle = "#ffffff";
|
|
710
|
+
ctx.beginPath();
|
|
711
|
+
ctx.ellipse(circ.x, circ.y, circ.radiusX, circ.radiusY, 0, 0, Math.PI * 2);
|
|
712
|
+
ctx.fill();
|
|
713
|
+
} else {
|
|
714
|
+
ctx.strokeStyle = "#ffffff";
|
|
715
|
+
ctx.fillStyle = "#ffffff";
|
|
716
|
+
await this.drawAnnotation(ctx, ann);
|
|
717
|
+
}
|
|
718
|
+
ctx.restore();
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return maskCanvas;
|
|
722
|
+
}
|
|
651
723
|
};
|
|
652
724
|
|
|
653
725
|
// src/image-editor/controller.ts
|
|
@@ -990,7 +1062,10 @@ var ImageEditorController = class {
|
|
|
990
1062
|
async render(targetCanvas, options) {
|
|
991
1063
|
const source = this.imageElement || this.state.sourceUrl;
|
|
992
1064
|
if (!source) return;
|
|
993
|
-
|
|
1065
|
+
try {
|
|
1066
|
+
await this.renderer.renderToCanvas(targetCanvas, source, this.state, options);
|
|
1067
|
+
} catch {
|
|
1068
|
+
}
|
|
994
1069
|
}
|
|
995
1070
|
async renderExport(options) {
|
|
996
1071
|
const source = this.imageElement || this.state.sourceUrl;
|
|
@@ -1032,6 +1107,23 @@ var ImageEditorController = class {
|
|
|
1032
1107
|
}
|
|
1033
1108
|
});
|
|
1034
1109
|
}
|
|
1110
|
+
// --- AI Masking & Transformation Helpers ---
|
|
1111
|
+
async renderMask(options) {
|
|
1112
|
+
return this.renderer.renderMask(this.state, options);
|
|
1113
|
+
}
|
|
1114
|
+
async toMaskDataURL(options) {
|
|
1115
|
+
const canvas = await this.renderMask(options);
|
|
1116
|
+
return canvas.toDataURL("image/png");
|
|
1117
|
+
}
|
|
1118
|
+
async applyInpaintedImage(newDataUrl) {
|
|
1119
|
+
this.recordHistory();
|
|
1120
|
+
await this.loadImage(newDataUrl);
|
|
1121
|
+
this.clearAnnotations();
|
|
1122
|
+
}
|
|
1123
|
+
async applyBackgroundRemovedImage(newDataUrl) {
|
|
1124
|
+
this.recordHistory();
|
|
1125
|
+
await this.loadImage(newDataUrl);
|
|
1126
|
+
}
|
|
1035
1127
|
// --- Serialization ---
|
|
1036
1128
|
toJSON() {
|
|
1037
1129
|
return this.serializeState();
|