UNPKG

react-moveable

Version:

A React Component that create Moveable, Draggable, Resizable, Scalable, Rotatable, Warpable, Pinchable, Groupable.

442 lines (441 loc) 15.1 kB
import * as React from "react"; import Gesto from "gesto"; import { MoveableManagerProps, MoveableManagerState, Able, RectInfo, Requester, HitRect, MoveableManagerInterface, MoveableDefaultOptions, MoveableRefType } from "./types"; import { IObject } from "@daybrush/utils"; import EventManager from "./EventManager"; import EventEmitter from "@scena/event-emitter"; export default class MoveableManager<T = {}> extends React.PureComponent<MoveableManagerProps<T>, MoveableManagerState> { static defaultProps: Required<MoveableManagerProps>; state: MoveableManagerState; renderState: Record<string, any>; enabledAbles: Able[]; targetAbles: Able[]; controlAbles: Able[]; controlBox: HTMLElement; areaElement: HTMLElement; targetGesto: Gesto; controlGesto: Gesto; rotation: number; scale: number[]; isMoveableMounted: boolean; isUnmounted: boolean; events: Record<string, EventManager | null>; protected _emitter: EventEmitter; protected _prevOriginalDragTarget: MoveableRefType | null; protected _originalDragTarget: MoveableRefType | null; protected _prevDragTarget: HTMLElement | SVGElement | null | undefined; protected _dragTarget: HTMLElement | SVGElement | null | undefined; protected _prevPropTarget: HTMLElement | SVGElement | null | undefined; protected _propTarget: HTMLElement | SVGElement | null | undefined; protected _prevDragArea: boolean; protected _isPropTargetChanged: boolean; protected _hasFirstTarget: boolean; private _reiszeObserver; private _observerId; private _mutationObserver; _rootContainer: HTMLElement | null | undefined; private _viewContainer; private _viewClassNames; private _store; render(): JSX.Element; componentDidMount(): void; componentDidUpdate(prevProps: any): void; componentWillUnmount(): void; getTargets(): Array<HTMLElement | SVGElement>; /** * Get the able used in MoveableManager. * @method Moveable#getAble * @param - able name */ getAble<T extends Able>(ableName: string): T | undefined; getContainer(): HTMLElement | SVGElement; /** * Returns the element of the control box. * @method Moveable#getControlBoxElement */ getControlBoxElement(): HTMLElement; /** * Target element to be dragged in moveable * @method Moveable#getDragElement */ getDragElement(): HTMLElement | SVGElement | null | undefined; /** * Check if the target is an element included in the moveable. * @method Moveable#isMoveableElement * @param - the target * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * window.addEventListener("click", e => { * if (!moveable.isMoveableElement(e.target)) { * moveable.target = e.target; * } * }); */ isMoveableElement(target: Element): boolean; /** * You can drag start the Moveable through the external `MouseEvent`or `TouchEvent`. (Angular: ngDragStart) * @method Moveable#dragStart * @param - external `MouseEvent`or `TouchEvent` * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * document.body.addEventListener("mousedown", e => { * if (!moveable.isMoveableElement(e.target)) { * moveable.dragStart(e); * } * }); */ dragStart(e: MouseEvent | TouchEvent, target?: EventTarget | null): this; /** * Hit test an element or rect on a moveable target. * (100% = 100) * @method Moveable#hitTest * @param - element or rect to test * @return - Get hit test rate (rate > 0 is hitted) * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * document.body.addEventListener("mousedown", e => { * if (moveable.hitTest(e.target) > 0) { * console.log("hiited"); * } * }); */ hitTest(el: Element | HitRect): number; /** * Whether the coordinates are inside Moveable * @method Moveable#isInside * @param - x coordinate * @param - y coordinate * @return - True if the coordinate is in moveable or false * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * document.body.addEventListener("mousedown", e => { * if (moveable.isInside(e.clientX, e.clientY)) { * console.log("inside"); * } * }); */ isInside(clientX: number, clientY: number): boolean; /** * If the width, height, left, and top of all elements change, update the shape of the moveable. * @method Moveable#updateRect * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * window.addEventListener("resize", e => { * moveable.updateRect(); * }); */ updateRect(type?: "Start" | "" | "End", isTarget?: boolean, isSetState?: boolean): void; /** * Check if the moveable state is being dragged. * @method Moveable#isDragging * @param - If you want to check if able is dragging, specify ableName. * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * // false * console.log(moveable.isDragging()); * * moveable.on("drag", () => { * // true * console.log(moveable.isDragging()); * }); */ isDragging(ableName?: string): boolean; /** * If the width, height, left, and top of the only target change, update the shape of the moveable. * Use `.updateRect()` method * @method Moveable#updateTarget * @deprecated * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * moveable.updateTarget(); */ updateTarget(type?: "Start" | "" | "End"): void; /** * You can get the vertex information, position and offset size information of the target based on the container. * @method Moveable#getRect * @return - The Rect Info * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * const rectInfo = moveable.getRect(); */ getRect(): RectInfo; /** * Get a manager that manages the moveable's state and props. * @method Moveable#getManager * @return - The Rect Info * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * const manager = moveable.getManager(); // real moveable class instance */ getManager(): MoveableManagerInterface<any, any>; /** * You can stop the dragging currently in progress through a method from outside. * @method Moveable#stopDrag * @return - The Rect Info * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * moveable.stopDrag(); */ stopDrag(type?: "target" | "control"): void; getRotation(): number; /** * Request able through a method rather than an event. * At the moment of execution, requestStart is executed, * and then request and requestEnd can be executed through Requester. * @method Moveable#request * @see {@link https://daybrush.com/moveable/release/latest/doc/Moveable.Draggable.html#request|Draggable Requester} * @see {@link https://daybrush.com/moveable/release/latest/doc/Moveable.Resizable.html#request|Resizable Requester} * @see {@link https://daybrush.com/moveable/release/latest/doc/Moveable.Scalable.html#request|Scalable Requester} * @see {@link https://daybrush.com/moveable/release/latest/doc/Moveable.Rotatable.html#request|Rotatable Requester} * @see {@link https://daybrush.com/moveable/release/latest/doc/Moveable.OriginDraggable.html#request|OriginDraggable Requester} * @param - ableName * @param - request to be able params. * @param - If isInstant is true, request and requestEnd are executed immediately. * @return - Able Requester. If there is no request in able, nothing will work. * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * // Instantly Request (requestStart - request - requestEnd) * moveable.request("draggable", { deltaX: 10, deltaY: 10 }, true); * * // Start move * const requester = moveable.request("draggable"); * requester.request({ deltaX: 10, deltaY: 10 }); * requester.request({ deltaX: 10, deltaY: 10 }); * requester.request({ deltaX: 10, deltaY: 10 }); * requester.requestEnd(); */ request(ableName: string, param?: IObject<any>, isInstant?: boolean): Requester; /** * moveable is the top level that manages targets * `Single`: MoveableManager instance * `Group`: MoveableGroup instance * `IndividualGroup`: MoveableIndividaulGroup instance * Returns leaf target MoveableManagers. */ getMoveables(): MoveableManagerInterface[]; /** * Remove the Moveable object and the events. * @method Moveable#destroy * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * * moveable.destroy(); */ destroy(): void; updateRenderPoses(): void; checkUpdate(): void; waitToChangeTarget(): Promise<void>; triggerEvent(name: string, e: any): any; useCSS(tag: string, css: string): any; checkUpdateRect: () => void; getState(): MoveableManagerState; updateSelectors(): void; protected unsetAbles(): void; protected updateAbles(ables?: Able[], eventAffix?: string): void; protected updateState(nextState: any, isSetState?: boolean): void; protected getEnabledAbles(ables?: Able[]): Able<IObject<any>, IObject<any>>[]; protected renderAbles(): any[]; protected updateCheckInput(): void; protected _getRequestStyles(): (keyof CSSStyleDeclaration)[]; protected _updateObserver(prevProps: MoveableDefaultOptions): void; protected _updateEvents(): void; protected _updateTargets(): void; private _renderLines; private _onPreventClick; private _isTargetChanged; private _updateNativeEvents; private _checkUpdateRootContainer; private _checkUpdateViewContainer; private _changeAbleViewClassNames; private _getAbleViewClassNames; private _getAbleClassName; private _updateResizeObserver; private _updateMutationObserver; } /** * The target to indicate Moveable Control Box. * @name Moveable#target * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * moveable.target = document.querySelector(".target"); */ /** * Zooms in the elements of a moveable. * @name Moveable#zoom * @default 1 * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * moveable.zoom = 2; */ /** * Whether the target size is detected and updated whenever it changes. * @name Moveable#useResizeObserver * @default false * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * moveable.useResizeObserver = true; */ /** * Resize, Scale Events at edges * @name Moveable#edge * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * moveable.edge = true; */ /** * You can specify the className of the moveable controlbox. * @name Moveable#className * @default "" * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body, { * className: "", * }); * * moveable.className = "moveable1"; */ /** * The target(s) to drag Moveable target(s) * @name Moveable#dragTarget * @default target * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body); * moveable.target = document.querySelector(".target"); * moveable.dragTarget = document.querySelector(".dragTarget"); */ /** * `renderStart` event occurs at the first start of all events. * @memberof Moveable * @event renderStart * @param {Moveable.OnRenderStart} - Parameters for the `renderStart` event * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body, { * target: document.querySelector(".target"), * }); * moveable.on("renderStart", ({ target }) => { * console.log("onRenderStart", target); * }); */ /** * `render` event occurs before the target is drawn on the screen. * @memberof Moveable * @event render * @param {Moveable.OnRender} - Parameters for the `render` event * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body, { * target: document.querySelector(".target"), * }); * moveable.on("render", ({ target }) => { * console.log("onRender", target); * }); */ /** * `renderEnd` event occurs at the end of all events. * @memberof Moveable * @event renderEnd * @param {Moveable.OnRenderEnd} - Parameters for the `renderEnd` event * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body, { * target: document.querySelector(".target"), * }); * moveable.on("renderEnd", ({ target }) => { * console.log("onRenderEnd", target); * }); */ /** * `renderGroupStart` event occurs at the first start of all events in group. * @memberof Moveable * @event renderGroupStart * @param {Moveable.OnRenderGroupStart} - Parameters for the `renderGroupStart` event * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body, { * target: [].slice.call(document.querySelectorAll(".target")), * }); * moveable.on("renderGroupStart", ({ targets }) => { * console.log("onRenderGroupStart", targets); * }); */ /** * `renderGroup` event occurs before the target is drawn on the screen in group. * @memberof Moveable * @event renderGroup * @param {Moveable.OnRenderGroup} - Parameters for the `renderGroup` event * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body, { * target: [].slice.call(document.querySelectorAll(".target")), * }); * moveable.on("renderGroup", ({ targets }) => { * console.log("onRenderGroup", targets); * }); */ /** * `renderGroupEnd` event occurs at the end of all events in group. * @memberof Moveable * @event renderGroupEnd * @param {Moveable.OnRenderGroupEnd} - Parameters for the `renderGroupEnd` event * @example * import Moveable from "moveable"; * * const moveable = new Moveable(document.body, { * target: [].slice.call(document.querySelectorAll(".target")), * }); * moveable.on("renderGroupEnd", ({ targets }) => { * console.log("onRenderGroupEnd", targets); * }); */