/** * name: vue-picture-cropper * version: v1.0.0 * description: A simple and easy-to-use picture cropping component for Vue 3. * author: chengpeiquan * homepage: https://cropper.chengpeiquan.com * license: MIT */ import * as vue from "vue"; import { CSSProperties, MaybeRef, ShallowRef } from "vue"; //#region src/cropper/types/library.d.ts /** * Because cropperjs does not export instance types So copied its type * declaration to here * * @source ./node_modules/cropperjs/types/index.d.ts */ declare namespace Cropper { type Action = 'crop' | 'move' | 'zoom' | 'e' | 's' | 'w' | 'n' | 'ne' | 'nw' | 'se' | 'sw' | 'all'; type DragMode = 'crop' | 'move' | 'none'; type ImageSmoothingQuality = 'low' | 'medium' | 'high'; type ViewMode = 0 | 1 | 2 | 3; interface Data { x: number; y: number; width: number; height: number; rotate: number; scaleX: number; scaleY: number; } interface ContainerData { width: number; height: number; } interface ImageData { left: number; top: number; width: number; height: number; rotate: number; scaleX: number; scaleY: number; naturalWidth: number; naturalHeight: number; aspectRatio: number; } interface CanvasData { left: number; top: number; width: number; height: number; naturalWidth: number; naturalHeight: number; } interface CropBoxData { left: number; top: number; width: number; height: number; } interface GetCroppedCanvasOptions { width?: number; height?: number; minWidth?: number; minHeight?: number; maxWidth?: number; maxHeight?: number; rounded?: boolean; fillColor?: string; imageSmoothingEnabled?: boolean; imageSmoothingQuality?: ImageSmoothingQuality; } interface SetDataOptions { x?: number; y?: number; width?: number; height?: number; rotate?: number; scaleX?: number; scaleY?: number; } interface SetCanvasDataOptions { left?: number; top?: number; width?: number; height?: number; } interface SetCropBoxDataOptions { left?: number; top?: number; width?: number; height?: number; } interface CropperEvent extends CustomEvent { currentTarget: T & { cropper: Cropper; }; } type ReadyEvent = CropperEvent; interface CropEvent extends CropperEvent { detail: Data; } interface CropEventData { originalEvent: PointerEvent | TouchEvent | MouseEvent; action: Action; } interface CropStartEvent extends CropperEvent { detail: CropEventData; } interface CropMoveEvent extends CropperEvent { detail: CropEventData; } interface CropEndEvent extends CropperEvent { detail: CropEventData; } interface ZoomEventData { originalEvent: WheelEvent | PointerEvent | TouchEvent | MouseEvent; oldRatio: number; ratio: number; } interface ZoomEvent extends CropperEvent { detail: ZoomEventData; } interface Options { aspectRatio?: number; autoCrop?: boolean; autoCropArea?: number; background?: boolean; center?: boolean; checkCrossOrigin?: boolean; checkOrientation?: boolean; cropBoxMovable?: boolean; cropBoxResizable?: boolean; data?: SetDataOptions; dragMode?: DragMode; guides?: boolean; highlight?: boolean; initialAspectRatio?: number; minCanvasHeight?: number; minCanvasWidth?: number; minContainerHeight?: number; minContainerWidth?: number; minCropBoxHeight?: number; minCropBoxWidth?: number; modal?: boolean; movable?: boolean; preview?: HTMLElement | HTMLElement[] | NodeListOf | string; responsive?: boolean; restore?: boolean; rotatable?: boolean; scalable?: boolean; toggleDragModeOnDblclick?: boolean; viewMode?: ViewMode; wheelZoomRatio?: number; zoomOnTouch?: boolean; zoomOnWheel?: boolean; zoomable?: boolean; ready?(event: ReadyEvent): void; crop?(event: CropEvent): void; cropend?(event: CropEndEvent): void; cropmove?(event: CropMoveEvent): void; cropstart?(event: CropStartEvent): void; zoom?(event: ZoomEvent): void; } } declare class Cropper { constructor(element: HTMLImageElement, options?: Cropper.Options); constructor(element: HTMLCanvasElement, options?: Cropper.Options); clear(): Cropper; crop(): Cropper; destroy(): Cropper; disable(): Cropper; enable(): Cropper; getCanvasData(): Cropper.CanvasData; getContainerData(): Cropper.ContainerData; getCropBoxData(): Cropper.CropBoxData; getCroppedCanvas(options?: Cropper.GetCroppedCanvasOptions): HTMLCanvasElement; getData(rounded?: boolean): Cropper.Data; getImageData(): Cropper.ImageData; move(offsetX: number, offsetY?: number): Cropper; moveTo(x: number, y?: number): Cropper; replace(url: string, onlyColorChanged?: boolean): Cropper; reset(): Cropper; rotate(degree: number): Cropper; rotateTo(degree: number): Cropper; scale(scaleX: number, scaleY?: number): Cropper; scaleX(scaleX: number): Cropper; scaleY(scaleY: number): Cropper; setAspectRatio(aspectRatio: number): Cropper; setCanvasData(data: Cropper.SetCanvasDataOptions): Cropper; setCropBoxData(data: Cropper.SetCropBoxDataOptions): Cropper; setData(data: Cropper.SetDataOptions): Cropper; setDragMode(dragMode: Cropper.DragMode): Cropper; zoom(ratio: number): Cropper; zoomTo(ratio: number, pivot?: { x: number; y: number; }): Cropper; static noConflict(): Cropper; static setDefaults(options: Cropper.Options): void; } //#endregion //#region src/cropper/types/dom-events.d.ts /** * Augment HTMLElementEventMap so that addEventListener('crop', ...) etc. get * the correct event type when used on the cropper's element. * * @example * el.addEventListener('crop', (e) => { * e.detail // Cropper.Data * e.currentTarget?.cropper * }) */ declare global { interface HTMLElementEventMap { ready: Cropper.ReadyEvent; crop: Cropper.CropEvent; cropend: Cropper.CropEndEvent; cropmove: Cropper.CropMoveEvent; cropstart: Cropper.CropStartEvent; zoom: Cropper.ZoomEvent; } } //#endregion //#region src/cropper/types/instance.d.ts /** * The Cropper instance provided with the component * * Use CropperInstance as the unified entry for all cropper types: * * - CropperInstance (interface) - the instance type * - CropperInstance.Options - constructor/component options * - CropperInstance.Data - getData() return type * - CropperInstance.GetCroppedCanvasOptions - getDataURL/getBlob/getFile options */ interface CropperInstance extends Cropper { /** * The image element passed to Cropper. Events (crop, ready, zoom, etc.) are * dispatched on this element. This component only uses img, not canvas. */ readonly element: HTMLImageElement; /** * Options object for this instance (image element only). */ options: Cropper.Options; /** * Get the cropped Base64 result */ getDataURL: (options?: Cropper.GetCroppedCanvasOptions) => string; /** * Get the cropped blob result */ getBlob: (options?: Cropper.GetCroppedCanvasOptions) => Promise; /** * Get the cropped file result */ getFile: (options?: Cropper.GetCroppedCanvasOptions & { fileName?: string; }) => Promise; } /** * Re-export cropper types under CropperInstance for unified API */ declare namespace CropperInstance { type Options = Cropper.Options; type Data = Cropper.Data; type GetCroppedCanvasOptions = Cropper.GetCroppedCanvasOptions; type SetDataOptions = Cropper.SetDataOptions; type SetCropBoxDataOptions = Cropper.SetCropBoxDataOptions; } //#endregion //#region src/cropper/types/component.d.ts /** * Preset Modes Supported by Components */ type SupportedPresetMode = /** * Specifies the size of the cropped result */ 'fixedSize' /** * Generate a round cropping result */ | 'round'; /** * Preset options for component props * * @since 0.4.0 */ interface PresetModeOptions { /** * The preset mode to use */ mode?: SupportedPresetMode; /** * The width of the cropped result */ width?: number; /** * The height of the cropped result */ height?: number; } /** * Props type for VuePictureCropper / useCropper * * Single source of truth for both runtime props and TypeScript types */ interface VuePictureCropperProps { /** * The source of the image to be cropped * * The value of the `src` attribute of `` */ img: string; /** * Style Sheet for Crop Box */ boxStyle?: CSSProperties; /** * Options for cropperjs * * @see https://github.com/fengyuanchen/cropperjs/tree/v1.6.2#options */ options?: CropperInstance.Options; /** * Some preset modes provided by this plugin */ presetMode?: PresetModeOptions; } /** * Exposed APIs in the `ref` of the VuePictureCropper component. * * Note: `cropper` is implemented as a Ref, but when you read it via the * component ref (e.g. `vpcRef.value?.cropper`), Vue's reactive proxy * auto-unwraps it, so you get `CropperInstance | null` directly. Do not use * `.cropper.value` — use `.cropper` only. */ interface VuePictureCropperRefValue { cropper: ShallowRef; } //#endregion //#region src/cropper/index.vue.d.ts declare const __VLS_export: vue.DefineComponent & Readonly<{}>, { boxStyle: vue.CSSProperties; options: CropperInstance.Options; presetMode: PresetModeOptions; }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>; declare const _default: typeof __VLS_export; //#endregion //#region src/hooks/useCropper.d.ts /** * Use VuePictureCropper without template ref. * * **Important:** In Vue, `setup()` runs only once per component. If you pass a * plain object, e.g. `useCropper({ img: someRef.value })`, that value is * captured at call time and will **not** update when `someRef` changes. For * reactive props (e.g. `img` that changes when the user picks a new file), pass * a **ref or computed**: `useCropper(computed(() => ({ img: someRef.value, * options })))`, so the current value is read on each render. * * @since 1.0.0 * @example * const [Component, cropper] = useCropper({ img, options }) * // Template: * // Same as v0.x: cropper.getDataURL(), cropper.getBlob(), cropper.getFile() * // Full API: cropper.getInstance()?.getData(), cropper.getInstance()?.rotate(90) * * @param props - Same as VuePictureCropper component props (img, options, * etc.). Pass a **ref or computed** when props must stay in sync with * reactive state (e.g. dynamic `img`); a plain object is a one-time * snapshot. * @returns A tuple `[Component, cropper]`: * * - `Component`: Vue component to render in template (e.g. ``). * - `cropper`: An object that **is not** the same as the v0.x cropper instance. * It is a thin wrapper that only exposes a subset of APIs for * compatibility: `getDataURL`, `getBlob`, `getFile` (same usage as v0.x), * and `getInstance()` to access the real Cropper instance when you need * full cropperjs API (e.g. `getData()`, `rotate()`, `setData()`). */ declare const useCropper: (props: MaybeRef) => readonly [vue.DefineComponent<{}, () => vue.VNode, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>, { readonly getInstance: () => CropperInstance | null; readonly getDataURL: (options?: Cropper.GetCroppedCanvasOptions) => string; readonly getBlob: (options?: Cropper.GetCroppedCanvasOptions) => Promise; readonly getFile: (options?: (Cropper.GetCroppedCanvasOptions & { fileName?: string; }) | undefined) => Promise; readonly clear: () => Cropper; readonly reset: () => Cropper; readonly onInstanceEffect: (effect: (instance: CropperInstance) => undefined | (() => void), options?: { once?: boolean; }) => () => void; }]; //#endregion export { type Cropper, CropperInstance, PresetModeOptions, SupportedPresetMode, VuePictureCropperProps, VuePictureCropperRefValue, _default as default, useCropper };