@uppy/image-editor
Version:
Image editor and cropping UI
153 lines • 5.17 kB
TypeScript
import type { Body, DefinePluginOpts, Meta, UIPluginOptions, Uppy, UppyFile } from '@uppy/core';
import { UIPlugin } from '@uppy/core';
import type { LocaleStrings } from '@uppy/utils';
import Cropper from 'cropperjs';
import locale from './locale.js';
declare module '@uppy/core' {
interface PluginTypeRegistry<M extends Meta, B extends Body> {
ImageEditor: ImageEditor<M, B>;
}
}
declare global {
namespace preact {
interface Component {
refs: Record<string, any>;
}
}
}
type ThumbnailGeneratedCallback<M extends Meta, B extends Body> = (file: UppyFile<M, B>, preview: string) => void;
type GenericCallback<M extends Meta, B extends Body> = (file: UppyFile<M, B>) => void;
declare module '@uppy/core' {
interface UppyEventMap<M extends Meta, B extends Body> {
'thumbnail:request': GenericCallback<M, B>;
'thumbnail:generated': ThumbnailGeneratedCallback<M, B>;
'file-editor:complete': GenericCallback<M, B>;
'file-editor:start': GenericCallback<M, B>;
'file-editor:cancel': GenericCallback<M, B>;
}
}
export interface Opts extends UIPluginOptions {
quality?: number;
cropperOptions?: Cropper.Options & {
croppedCanvasOptions?: Cropper.GetCroppedCanvasOptions;
};
actions?: {
revert?: boolean;
rotate?: boolean;
granularRotate?: boolean;
flip?: boolean;
zoomIn?: boolean;
zoomOut?: boolean;
cropSquare?: boolean;
cropWidescreen?: boolean;
cropWidescreenVertical?: boolean;
};
locale?: LocaleStrings<typeof locale>;
}
export type { Opts as ImageEditorOptions };
type PluginState<M extends Meta, B extends Body> = {
currentImage: UppyFile<M, B> | null;
angle: number;
angleGranular: number;
isFlippedHorizontally: boolean;
aspectRatio: AspectRatio;
cropperReady: boolean;
};
export type AspectRatio = 'free' | '1:1' | '16:9' | '9:16';
declare const defaultCropperOptions: {
viewMode: 0;
background: false;
autoCropArea: number;
responsive: true;
minCropBoxWidth: number;
minCropBoxHeight: number;
croppedCanvasOptions: {};
initialAspectRatio: number;
};
declare const defaultActions: {
revert: true;
rotate: true;
granularRotate: true;
flip: true;
zoomIn: true;
zoomOut: true;
cropSquare: true;
cropWidescreen: true;
cropWidescreenVertical: true;
};
declare const defaultOptions: {
quality: number;
actions: {
revert: true;
rotate: true;
granularRotate: true;
flip: true;
zoomIn: true;
zoomOut: true;
cropSquare: true;
cropWidescreen: true;
cropWidescreenVertical: true;
};
cropperOptions: {
viewMode: 0;
background: false;
autoCropArea: number;
responsive: true;
minCropBoxWidth: number;
minCropBoxHeight: number;
croppedCanvasOptions: {};
initialAspectRatio: number;
};
};
type InternalImageEditorOpts = Omit<DefinePluginOpts<Opts, keyof typeof defaultOptions>, 'actions' | 'cropperOptions'> & {
actions: DefinePluginOpts<NonNullable<Opts['actions']>, keyof typeof defaultActions>;
cropperOptions: DefinePluginOpts<NonNullable<Opts['cropperOptions']>, keyof typeof defaultCropperOptions>;
};
export default class ImageEditor<M extends Meta, B extends Body> extends UIPlugin<InternalImageEditorOpts, M, B, PluginState<M, B>> {
static VERSION: string;
cropper: Cropper | null;
objectUrl: string | null;
prevCropboxData: Cropper.CropBoxData | null;
private imgElement;
private cropstartHandler;
private cropendHandler;
private cropperReadyHandler;
constructor(uppy: Uppy<M, B>, opts?: Opts);
canEditFile(file: UppyFile<M, B>): boolean;
save: () => void;
storeCropperInstance: (cropper: Cropper) => void;
selectFile: (file: UppyFile<M, B>) => void;
resetEditorState: (currentImage?: UppyFile<M, B> | null) => void;
rotateBy: (degrees: number) => void;
rotateGranular: (granularAngle: number) => void;
flipHorizontal: () => void;
zoom: (ratio: number) => void;
setAspectRatio: (newRatio: AspectRatio) => void;
reset: () => void;
/**
* Start editing a file - creates object URL and prepares state.
* Called by hook's start() or when user opens editor.
*/
start: (file: UppyFile<M, B>) => void;
/**
* Stop editing - destroys cropper, revokes object URL, cleans up listeners.
*/
stop: () => void;
/**
* Initialize cropper on the image element. Called lazily when first edit action is triggered.
* For headless use, the hook provides the image element.
*/
initCropper: (imgElement: HTMLImageElement) => void;
/**
* Destroy cropper and clean up event listeners.
*/
destroyCropper: () => void;
/**
* Get object URL for the current image (used by headless hook).
*/
getObjectUrl: () => string | null;
install(): void;
uninstall(): void;
render(): import("preact").JSX.Element | null;
}
//# sourceMappingURL=ImageEditor.d.ts.map