react-moveable
Version:
A React Component that create Moveable, Draggable, Resizable, Scalable, Rotatable, Warpable, Pinchable, Groupable.
811 lines (765 loc) • 26.8 kB
text/typescript
import { IObject } from "@daybrush/utils";
import Dragger, * as DraggerTypes from "@daybrush/drag";
import CustomDragger from "./CustomDragger";
import { Position } from "@daybrush/drag";
export type MoveableManagerProps<T = {}> = {
target?: SVGElement | HTMLElement | null;
container?: SVGElement | HTMLElement | null;
dragArea?: boolean;
parentMoveable?: any;
parentPosition?: { left: number, top: number } | null;
origin?: boolean;
transformOrigin?: Array<string | number> | "";
edge?: boolean;
keepRatio?: boolean;
pinchThreshold?: number;
ables?: Array<Able<T>>;
} & T;
export type MoveableManagerState<T = {}> = {
target: SVGElement | HTMLElement | null | undefined;
left: number;
top: number;
right: number;
bottom: number;
width: number;
height: number;
beforeMatrix: number[];
matrix: number[];
targetTransform: string;
targetMatrix: number[];
offsetMatrix: number[];
is3d: boolean;
transformOrigin: number[];
beforeOrigin: number[];
origin: number[];
beforeDirection: 1 | -1;
direction: 1 | -1;
pos1: number[];
pos2: number[];
pos3: number[];
pos4: number[];
dragger: Dragger | CustomDragger | null;
} & T;
export interface Renderer {
createElement(type: any, props?: any, ...children: any[]): any;
}
export interface Guideline {
type: "horizontal" | "vertical";
element?: Element | null;
center?: boolean;
pos: number[];
size: number;
}
export interface BoundInfo {
isBound: boolean;
offset: number;
pos: number;
}
export interface SnapInfo {
isSnap: boolean;
dist: number;
offset: number;
guidelines: Guideline[];
snapPoses: number[];
}
export interface MoveableProps
extends DraggableProps,
RotatableProps,
ResizableProps,
ScalableProps,
WarpableProps,
PinchableProps,
GroupableProps,
SnappableProps {
target?: SVGElement | HTMLElement | Array<SVGElement | HTMLElement> | null;
container?: SVGElement | HTMLElement | null;
origin?: boolean;
keepRatio?: boolean;
edge?: boolean;
pinchThreshold?: number;
ables?: Able[];
}
export type MoveableState = MoveableManagerState;
/**
* @typedef
* @memberof Moveable
* @property - a target to pinch
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
*/
export interface OnPinchStart {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @property - a pinching target
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
*/
export interface OnPinch {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @property - a pinch finished target
* @property - Whether pinch called
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
*/
export interface OnPinchEnd {
target: HTMLElement | SVGElement;
isDrag: boolean;
clientX: number;
clientY: number;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @property - a target to drag
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - You can set the start translate value.
*/
export interface OnDragStart {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
set: (translate: number[]) => void;
}
/**
* @typedef
* @memberof Moveable
* @property - a dragging target
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - The delta of [left, top]
* @property - The distance of [left, top]
* @property - The position of [left, top]
* @property - The delta of [translateX, translateY]
* @property - The distance of [translateX, translateY]
* @property - The position of [translateX, translateY]
* @property - a target's transform
* @property - a target's left
* @property - a target's top
* @property - a target's bottom
* @property - a target's right
* @property - Whether or not it is being pinched.
*/
export interface OnDrag {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
beforeDelta: number[];
beforeDist: number[];
beforeTranslate: number[];
delta: number[];
dist: number[];
translate: number[];
transform: string;
left: number;
top: number;
bottom: number;
right: number;
isPinch: boolean;
}
/**
* @typedef
* @memberof Moveable
* @property - a drag finished target
* @property - Whether drag called
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
*/
export interface OnDragEnd {
target: HTMLElement | SVGElement;
isDrag: boolean;
clientX: number;
clientY: number;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @property - a target to scale
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - The direction of scale.
* @property - Objects that can send information to the following events.
* @property - scale causes a `dragStart` event.
* @property - You can set the start scale value.
*/
export interface OnScaleStart {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
direction: number[];
datas: IObject<any>;
dragStart: OnDragStart | false;
set: (scale: number[]) => void;
}
/**
* @typedef
* @memberof Moveable
* @property - a scaling target
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - The direction of scale.
* @property - a target's scale
* @property - The distance of scale
* @property - The delta of scale
* @property - a target's transform
* @property - scale causes a `drag` event.
*/
export interface OnScale {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
direction: number[];
scale: number[];
dist: number[];
delta: number[];
transform: string;
isPinch: boolean;
drag: OnDrag;
}
/**
* @typedef
* @memberof Moveable
* @property - a scale finished target
* @property - Whether scale called
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
*/
export interface OnScaleEnd {
target: HTMLElement | SVGElement;
isDrag: boolean;
clientX: number;
clientY: number;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @property - a target to resize
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - The direction of resize.
* @property - resize causes a `dragStart` event.
* @property - You can set the css width, height value.
*/
export interface OnResizeStart {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
direction: number[];
dragStart: OnDragStart | false;
set: (sizes: number[]) => any;
setOrigin: (origin: Array<string | number>) => any;
}
/**
* @typedef
* @memberof Moveable
* @property - a resizng target
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - The direction of resize.
* @property - a target's width
* @property - a target's height
* @property - The distance of [width, height]
* @property - The delta of [width, height]
* @property - resize causes a `drag` event.
*/
export interface OnResize {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
direction: number[];
width: number;
height: number;
dist: number[];
delta: number[];
isPinch: boolean;
drag: OnDrag;
}
/**
* @typedef
* @memberof Moveable
* @property - a resize finished target
* @property - Whether resize called
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
*/
export interface OnResizeEnd {
target: HTMLElement | SVGElement;
isDrag: boolean;
clientX: number;
clientY: number;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @property - a target to rotate
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - You can set the start rotate value.
*/
export interface OnRotateStart {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
set: (rotate: number) => void;
}
/**
* @typedef
* @memberof Moveable
* @property - a rotating target
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - The distance of rotation rad before transform is applied
* @property - The delta of rotation rad before transform is applied
* @property - The now rotation rad before transform is applied
* @property - The distance of rotation rad
* @property - The delta of rotation rad
* @property - The now rotation rad
* @property - a target's transform
*/
export interface OnRotate {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
beforeDist: number;
beforeDelta: number;
beforeRotate: number;
dist: number;
delta: number;
rotate: number;
transform: string;
isPinch: boolean;
}
/**
* @typedef
* @memberof Moveable
* @property - a rotate finished target
* @property - Whether rotate called
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
*/
export interface OnRotateEnd {
target: HTMLElement | SVGElement;
isDrag: boolean;
clientX: number;
clientY: number;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @property - a target to warp
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - You can set the start matrix value.
*/
export interface OnWarpStart {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
set: (matrix: number[]) => any;
}
/**
* @typedef
* @memberof Moveable
* @property - a warping target
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - a target's transform
* @property - The delta of warp matrix
* @property - The dist of warp matrix
* @property - The caculated warp matrix
* @property - Multiply function that can multiply previous matrix by warp matrix
*/
export interface OnWarp {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
datas: IObject<any>;
transform: string;
delta: number[];
dist: number[];
matrix: number[];
multiply: (matrix1: number[], matrix2: number[], n?: number) => number[];
}
/**
* @typedef
* @memberof Moveable
* @property - a warp finished target
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Whether rotate called
* @property - Objects that can send information to the following events.
*/
export interface OnWarpEnd {
target: HTMLElement | SVGElement;
clientX: number;
clientY: number;
isDrag: boolean;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @extends Moveable.OnDragStart
* @property - targets to drag
* @property - Each `dragStart` event on the targets
*/
export interface OnDragGroupStart extends OnDragStart {
targets: Array<HTMLElement | SVGElement>;
events: OnDragStart[];
}
/**
* @typedef
* @memberof Moveable
* @extends Moveable.OnDrag
* @property - The dragging targets
* @property - Each `drag` event on the targets
*/
export interface OnDragGroup extends OnDrag {
targets: Array<HTMLElement | SVGElement>;
events: OnDrag[];
}
/**
* @typedef
* @memberof Moveable
* @property - The drag finished targets
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - Whether `dragGroup` called
*/
export interface OnDragGroupEnd {
targets: Array<HTMLElement | SVGElement>;
clientX: number;
clientY: number;
datas: IObject<any>;
isDrag: boolean;
}
/**
* @typedef
* @memberof Moveable
* @extends Moveable.OnRotateStart
* @property - targets to rotate
* @property - Each `rotateStart` & `dragStart` event on the targets
*/
export interface OnRotateGroupStart extends OnRotateStart {
targets: Array<HTMLElement | SVGElement>;
events: Array<OnRotateStart & { dragStart: OnDragStart | false }>;
}
/**
* @typedef
* @memberof Moveable
* @extends Moveable.OnRotate
* @property - The rotating targets
* @property - Each `rotate` & `drag` event on the targets
*/
export interface OnRotateGroup extends OnRotate {
targets: Array<HTMLElement | SVGElement>;
events: Array<OnRotate & { drag: OnDrag }>;
}
/**
* @typedef
* @memberof Moveable
* @property - The rotate finished targets
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - Whether `rotateGroup` called
*/
export interface OnRotateGroupEnd {
targets: Array<HTMLElement | SVGElement>;
clientX: number;
clientY: number;
datas: IObject<any>;
isDrag: boolean;
}
/**
* @typedef
* @memberof Moveable
* @extends Moveable.OnResizeStart
* @property - targets to resize
* @property - Each `resizeStart` event on the targets
*/
export interface OnResizeGroupStart extends OnResizeStart {
targets: Array<HTMLElement | SVGElement>;
events: OnResizeStart[];
}
/**
* @typedef
* @memberof Moveable
* @extends Moveable.OnResize
* @property - The resizing targets
* @property - Each `resize` & `drag `event on the targets
*/
export interface OnResizeGroup extends OnResize {
targets: Array<HTMLElement | SVGElement>;
events: Array<OnResize & { drag: OnDrag }>;
}
/**
* @typedef
* @memberof Moveable
* @property - The resize finished targets
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - Whether `resizeGroup` called
*/
export interface OnResizeGroupEnd {
targets: Array<HTMLElement | SVGElement>;
clientX: number;
clientY: number;
isDrag: boolean;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @extends Moveable.OnScaleStart
* @property - targets to scale
* @property - Each `scaleStart` & `dragStart` event on the targets
*/
export interface OnScaleGroupStart extends OnScaleStart {
targets: Array<HTMLElement | SVGElement>;
events: OnScaleStart[];
}
/**
* @typedef
* @memberof Moveable
* @extends Moveable.OnScale
* @property - The scaling targets
* @property - Each `scale` & `drag` event on the targets
*/
export interface OnScaleGroup extends OnScale {
targets: Array<HTMLElement | SVGElement>;
events: Array<OnScale & { drag: OnDrag }>;
}
/**
* @typedef
* @memberof Moveable
* @property - The scale finished targets
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - Whether `scaleGroup` called
*/
export interface OnScaleGroupEnd {
targets: Array<HTMLElement | SVGElement>;
clientX: number;
clientY: number;
isDrag: boolean;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @property - targets to pinch
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
*/
export interface OnPinchGroupStart {
targets: Array<HTMLElement | SVGElement>;
clientX: number;
clientY: number;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @extends Moveable.OnPinch
* @property - targets to pinch
*/
export interface OnPinchGroup extends OnPinch {
targets: Array<HTMLElement | SVGElement>;
}
/**
* @typedef
* @memberof Moveable
* @property - The pinch finished targets
* @property - The horizontal coordinate within the application's client area at which the event occurred.
* @property - The vertical coordinate within the application's client area at which the event occurred.
* @property - Objects that can send information to the following events.
* @property - Whether `pinchGroup` called
*/
export interface OnPinchGroupEnd {
targets: Array<HTMLElement | SVGElement>;
clientX: number;
clientY: number;
isDrag: boolean;
datas: IObject<any>;
}
/**
* @typedef
* @memberof Moveable
* @property - targets set to group.
* @property - Clicked target.
* @property - Whether the clicked target is on the targets set in the group.
* @property - Whether the clicked target is a child of the targets set in the group.
* @property - The corresponding index among the targets set as a group.
*/
export interface OnClickGroup {
targets: Array<HTMLElement | SVGElement>;
target: HTMLElement | SVGElement;
hasTarget: boolean;
containsTarget: boolean;
targetIndex: number;
}
export interface Able<T = any> {
name: string & keyof MoveableManagerProps<T>;
dragControlOnly?: boolean;
updateRect?: boolean;
canPinch?: boolean;
unset?: (moveable: MoveableManagerProps<any>) => any;
render?: (moveable: MoveableManagerProps<any>, renderer: Renderer) => any;
dragStart?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDragStart) => any;
drag?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDrag) => any;
dragEnd?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDragEnd) => any;
pinchStart?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnPinchStart) => any;
pinch?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnPinch) => any;
pinchEnd?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnPinchEnd) => any;
dragControlCondition?: (target: SVGElement | HTMLElement) => boolean;
dragControlStart?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDragStart) => any;
dragControl?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDrag) => any;
dragControlEnd?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDragEnd) => any;
dragGroupCondition?: (target: SVGElement | HTMLElement) => boolean;
dragGroupStart?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDragStart) => any;
dragGroup?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDrag) => any;
dragGroupEnd?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDragEnd) => any;
pinchGroupStart?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnPinchStart) => any;
pinchGroup?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnPinch) => any;
pinchGroupEnd?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnPinchEnd) => any;
dragGroupControlCondition?: (target: SVGElement | HTMLElement) => boolean;
dragGroupControlStart?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDragStart) => any;
dragGroupControl?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDragStart) => any;
dragGroupControlEnd?: (moveable: MoveableManagerProps<any>, e: DraggerTypes.OnDragEnd) => any;
}
export interface OriginProps {
origin: boolean;
}
export interface DraggableProps {
draggable?: boolean;
throttleDrag?: number;
onDragStart?: (e: OnDragStart) => any;
onDrag?: (e: OnDrag) => any;
onDragEnd?: (e: OnDragEnd) => any;
onDragGroupStart?: (e: OnDragGroupStart) => any;
onDragGroup?: (e: OnDragGroup) => any;
onDragGroupEnd?: (e: OnDragGroupEnd) => any;
}
export interface ResizableProps {
resizable?: boolean;
throttleResize?: number;
onResizeStart?: (e: OnResizeStart) => any;
onResize?: (e: OnResize) => any;
onResizeEnd?: (e: OnResizeEnd) => any;
onResizeGroupStart?: (e: OnResizeGroupStart) => any;
onResizeGroup?: (e: OnResizeGroup) => any;
onResizeGroupEnd?: (e: OnResizeGroupEnd) => any;
}
export interface ScalableProps {
scalable?: boolean;
throttleScale?: number;
onScaleStart?: (e: OnScaleStart) => any;
onScale?: (e: OnScale) => any;
onScaleEnd?: (e: OnScaleEnd) => any;
onScaleGroupStart?: (e: OnScaleGroupStart) => any;
onScaleGroup?: (e: OnScaleGroup) => any;
onScaleGroupEnd?: (e: OnScaleGroupEnd) => any;
}
export interface RotatableProps {
rotatable?: boolean;
rotationPosition?: "top" | "bottom" | "left" | "right";
throttleRotate?: number;
onRotateStart?: (e: OnRotateStart) => any;
onRotate?: (e: OnRotate) => any;
onRotateEnd?: (e: OnRotateEnd) => any;
onRotateGroupStart?: (e: OnRotateGroupStart) => any;
onRotateGroup?: (e: OnRotateGroup) => any;
onRotateGroupEnd?: (e: OnRotateGroupEnd) => any;
}
export interface WarpableProps {
warpable?: boolean;
onWarpStart?: (e: OnWarpStart) => any;
onWarp?: (e: OnWarp) => any;
onWarpEnd?: (e: OnWarpEnd) => any;
}
export interface PinchableProps extends ResizableProps, ScalableProps, RotatableProps {
pinchable?: boolean | Array<"rotatable" | "resizable" | "scalable">;
onPinchStart?: (e: OnPinchStart) => any;
onPinch?: (e: OnPinch) => any;
onPinchEnd?: (e: OnPinchEnd) => any;
onPinchGroupStart?: (e: OnPinchGroupStart) => any;
onPinchGroup?: (e: OnPinchGroup) => any;
onPinchGroupEnd?: (e: OnPinchGroupEnd) => any;
}
export interface GroupableProps extends PinchableProps, DraggableProps, RotatableProps, ResizableProps, ScalableProps {
groupable?: boolean;
targets?: Array<HTMLElement | SVGElement>;
updateGroup?: boolean;
onClickGroup?: (e: OnClickGroup) => any;
}
export interface SnappableProps {
snappable?: boolean | string[];
snapCenter?: boolean;
snapThreshold?: number;
horizontalGuidelines?: number[];
verticalGuidelines?: number[];
elementGuildelines?: Element[];
bounds?: { left?: number, top?: number, right?: number, bottom?: number };
}
export interface SnappableState {
guidelines: any[];
snapDirection: number[] | true | null;
startLeft: number;
startTop: number;
startRight: number;
startBottom: number;
}
export interface OnCustomDrag extends Position {
inputEvent: any;
isDrag: boolean;
datas: IObject<any>;
parentEvent: boolean;
parentDragger: CustomDragger;
}