import {
triggerEvent,
fillParams,
fillEndParams,
getAbsolutePosesByState,
catchEvent,
getOffsetSizeDist,
getProps,
getDirectionCondition,
calculatePoses,
fillAfterTransform,
getDirectionViewClassName,
getTotalDirection,
abs,
} from "../utils";
import {
setDragStart,
getResizeDist,
getAbsolutePosition,
getNextMatrix,
getNextTransforms,
} from "../gesto/GestoUtils";
import {
ResizableProps, OnResizeGroup, OnResizeGroupEnd,
OnResizeGroupStart, DraggableProps, OnDrag, OnResizeStart, SnappableState,
OnResize, OnResizeEnd, MoveableManagerInterface, MoveableGroupInterface, SnappableProps,
OnBeforeResize, OnBeforeResizeGroup, ResizableRequestParam,
} from "../types";
import { getRenderDirections } from "../renderDirections";
import {
fillChildEvents,
startChildDist,
triggerChildAbles,
} from "../groupUtils";
import Draggable from "./Draggable";
import { calculate, convertDimension, createRotateMatrix, plus } from "@scena/matrix";
import CustomGesto, { setCustomDrag } from "../gesto/CustomGesto";
import { checkSnapResize } from "./Snappable";
import {
calculateBoundSize,
isString, convertUnitSize,
throttle,
isNumber,
} from "@daybrush/utils";
import { TINY_NUM } from "../consts";
import { parseMat } from "css-to-mat";
import { getFixedDirectionInfo, getOffsetFixedPositionInfo } from "../utils/getFixedDirection";
/**
* @namespace Resizable
* @memberof Moveable
* @description Resizable indicates whether the target's width and height can be increased or decreased.
*/
const directionCondition = getDirectionCondition("resizable");
export default {
name: "resizable",
ableGroup: "size",
canPinch: true,
props: [
"resizable",
"throttleResize",
"renderDirections",
"displayAroundControls",
"keepRatio",
"resizeFormat",
"keepRatioFinally",
"edge",
"checkResizableError",
] as const,
events: [
"resizeStart",
"beforeResize",
"resize",
"resizeEnd",
"resizeGroupStart",
"beforeResizeGroup",
"resizeGroup",
"resizeGroupEnd",
] as const,
render: getRenderDirections("resizable"),
dragControlCondition: directionCondition,
viewClassName: getDirectionViewClassName("resizable"),
dragControlStart(
moveable: MoveableManagerInterface<ResizableProps & DraggableProps, SnappableState>,
e: any,
) {
const {
inputEvent,
isPinch,
isGroup,
parentDirection,
parentGesto,
datas,
parentFixedDirection,
parentEvent,
} = e;
const direction = getTotalDirection(
parentDirection,
isPinch,
inputEvent,
datas,
);
const state = moveable.state;
const { target, width, height, gestos } = state;
if (!direction || !target) {
return false;
}
if (gestos.resizable) {
return false;
}
gestos.resizable = parentGesto || moveable.controlGesto;
!isPinch && setDragStart(moveable, e);
datas.datas = {};
datas.direction = direction;
datas.startOffsetWidth = width;
datas.startOffsetHeight = height;
datas.prevWidth = 0;
datas.prevHeight = 0;
datas.minSize = [0, 0];
datas.startWidth = state.inlineCSSWidth || state.cssWidth;
datas.startHeight = state.inlineCSSHeight || state.cssHeight;
datas.maxSize = [Infinity, Infinity];
if (!isGroup) {
datas.minSize = [
state.minOffsetWidth,
state.minOffsetHeight,
];
datas.maxSize = [
state.maxOffsetWidth,
state.maxOffsetHeight,
];
}
const transformOrigin = moveable.props.transformOrigin || "% %";
datas.transformOrigin = transformOrigin && isString(transformOrigin)
? transformOrigin.split(" ")
: transformOrigin;
datas.startOffsetMatrix = state.offsetMatrix;
datas.startTransformOrigin = state.transformOrigin;
datas.isWidth = e?.parentIsWidth ?? ((!direction[0] && !direction[1]) || direction[0] || !direction[1]);
function setRatio(ratio: number) {
datas.ratio = ratio && isFinite(ratio) ? ratio : 0;
}
datas.startPositions = getAbsolutePosesByState(moveable.state);
function setFixedDirection(fixedDirection: number[]) {
const result = getFixedDirectionInfo(datas.startPositions, fixedDirection);
datas.fixedDirection = result.fixedDirection;
datas.fixedPosition = result.fixedPosition;
datas.fixedOffset = result.fixedOffset;
}
function setFixedPosition(fixedPosition: number[]) {
const result = getOffsetFixedPositionInfo(moveable.state, fixedPosition);
datas.fixedDirection = result.fixedDirection;
datas.fixedPosition = result.fixedPosition;
datas.fixedOffset = result.fixedOffset;
}
function setMin(minSize: Array<string | number>) {
datas.minSize = [
convertUnitSize(`${minSize[0]}`, 0) || 0,
convertUnitSize(`${minSize[1]}`, 0) || 0,
];
}
function setMax(maxSize: Array<string | number>) {
const nextMaxSize = [
maxSize[0] || Infinity,
maxSize[1] || Infinity,
];
if (!isNumber(nextMaxSize[0]) || isFinite(nextMaxSize[0])) {
nextMaxSize[0] = convertUnitSize(`${nextMaxSize[0]}`, 0) || Infinity;
}
if (!isNumber(nextMaxSize[1]) || isFinite(nextMaxSize[1])) {
nextMaxSize[1] = convertUnitSize(`${nextMaxSize[1]}`, 0) || Infinity;
}
datas.maxSize = nextMaxSize;
}
setRatio(width / height);
setFixedDirection(parentFixedDirection || [-direction[0], -direction[1]]);
datas.setFixedDirection = setFixedDirection;
datas.setFixedPosition = setFixedPosition;
datas.setMin = setMin;
datas.setMax = setMax;
const params = fillParams<OnResizeStart>(moveable, e, {
direction,
startRatio: datas.ratio,
set: ([startWidth, startHeight]: number[]) => {
datas.startWidth = startWidth;
datas.startHeight = startHeight;
},
setMin,
setMax,
setRatio,
setFixedDirection,
setFixedPosition,
setOrigin: (origin: Array<string | number>) => {
datas.transformOrigin = origin;
},
dragStart: Draggable.dragStart(
moveable,
new CustomGesto().dragStart([0, 0], e),
),
});
const result = parentEvent || triggerEvent(moveable, "onResizeStart", params);
datas.startFixedDirection = datas.fixedDirection;
datas.startFixedPosition = datas.fixedPosition;
if (result !== false) {
datas.isResize = true;
moveable.state.snapRenderInfo = {
request: e.isRequest,
direction,
};
}
return datas.isResize ? params : false;
},
dragControl(
moveable: MoveableManagerInterface<ResizableProps & DraggableProps & SnappableProps>,
e: any,
) {
const {
datas,
parentFlag,
isPinch,
parentKeepRatio,
dragClient,
parentDist,
useSnap,
isRequest,
isGroup,
parentEvent,
resolveMatrix,
} = e;
const {
isResize,
transformOrigin,
startWidth,
startHeight,
prevWidth,
prevHeight,
minSize,
maxSize,
ratio,
startOffsetWidth,
startOffsetHeight,
isWidth,
} = datas;
if (!isResize) {
return;
}
if (resolveMatrix) {
const {
is3d,
} = moveable.state;
const {
startOffsetMatrix,
startTransformOrigin,
} = datas;
const n = is3d ? 4 : 3;
let targetMatrix = parseMat(getNextTransforms(e));
const targetN = Math.sqrt(targetMatrix.length);
if (n !== targetN) {
targetMatrix = convertDimension(targetMatrix, targetN, n);
}
const nextAllMatrix = getNextMatrix(
startOffsetMatrix,
targetMatrix,
startTransformOrigin,
n,
);
const poses = calculatePoses(nextAllMatrix, startOffsetWidth, startOffsetHeight, n);
datas.startPositions = poses;
datas.nextTargetMatrix = targetMatrix;
datas.nextAllMatrix = nextAllMatrix;
}
const props = getProps(moveable.props, "resizable");
const {
resizeFormat,
throttleResize = parentFlag ? 0 : 1,
parentMoveable,
keepRatioFinally,
} = props;
const direction = datas.direction;
let sizeDirection = direction;
let distWidth = 0;
let distHeight = 0;
if (!direction[0] && !direction[1]) {
sizeDirection = [1, 1];
}
const keepRatio = (ratio && (parentKeepRatio != null ? parentKeepRatio : props.keepRatio)) || false;
function getNextBoundingSize() {
const fixedDirection = datas.fixedDirection;
const nextSize = getOffsetSizeDist(sizeDirection, keepRatio, datas, e);
distWidth = nextSize.distWidth;
distHeight = nextSize.distHeight;
let nextWidth = (sizeDirection[0] - fixedDirection[0]) || keepRatio
? Math.max(startOffsetWidth + distWidth, TINY_NUM) : startOffsetWidth;
let nextHeight = (sizeDirection[1] - fixedDirection[1]) || keepRatio
? Math.max(startOffsetHeight + distHeight, TINY_NUM) : startOffsetHeight;
if (keepRatio && startOffsetWidth && startOffsetHeight) {
// startOffsetWidth : startOffsetHeight = nextWidth : nextHeight
if (isWidth) {
nextHeight = nextWidth / ratio;
} else {
nextWidth = nextHeight * ratio;
}
}
return [nextWidth, nextHeight];
}
let [boundingWidth, boundingHeight] = getNextBoundingSize();
if (!parentEvent) {
datas.setFixedDirection(datas.fixedDirection);
triggerEvent(moveable, "onBeforeResize", fillParams<OnBeforeResize>(moveable, e, {
startFixedDirection: datas.startFixedDirection,
startFixedPosition: datas.startFixedPosition,
setFixedDirection(nextFixedDirection: number[]) {
datas.setFixedDirection(nextFixedDirection);
[boundingWidth, boundingHeight] = getNextBoundingSize();
return [boundingWidth, boundingHeight];
},
setFixedPosition(nextFixedPosition: number[]) {
datas.setFixedPosition(nextFixedPosition);
[boundingWidth, boundingHeight] = getNextBoundingSize();
return [boundingWidth, boundingHeight];
},
boundingWidth,
boundingHeight,
setSize(size: number[]) {
[boundingWidth, boundingHeight] = size;
},
}, true));
}
let fixedPosition = dragClient;
if (!dragClient) {
if (!parentFlag && isPinch) {
fixedPosition = getAbsolutePosition(moveable, [0, 0]);
} else {
fixedPosition = datas.fixedPosition;
}
}
let snapDist = [0, 0];
if (!isPinch) {
snapDist = checkSnapResize(
moveable,
boundingWidth,
boundingHeight,
direction,
fixedPosition,
!useSnap && isRequest,
datas,
);
}
if (parentDist) {
!parentDist[0] && (snapDist[0] = 0);
!parentDist[1] && (snapDist[1] = 0);
}
function computeSize() {
if (resizeFormat) {
[boundingWidth, boundingHeight] = resizeFormat([boundingWidth, boundingHeight]);
}
boundingWidth = throttle(boundingWidth, throttleResize!);
boundingHeight = throttle(boundingHeight, throttleResize!);
}
if (keepRatio) {
if (sizeDirection[0] && sizeDirection[1] && snapDist[0] && snapDist[1]) {
if (abs(snapDist[0]) > abs(snapDist[1])) {
snapDist[1] = 0;
} else {
snapDist[0] = 0;
}
}
const isNoSnap = !snapDist[0] && !snapDist[1];
if (isNoSnap) {
// pre-compute before maintaining the ratio
computeSize();
}
if (
(sizeDirection[0] && !sizeDirection[1])
|| (snapDist[0] && !snapDist[1])
|| (isNoSnap && isWidth)
) {
boundingWidth += snapDist[0];
boundingHeight = boundingWidth / ratio;
} else if (
(!sizeDirection[0] && sizeDirection[1])
|| (!snapDist[0] && snapDist[1])
|| (isNoSnap && !isWidth)
) {
boundingHeight += snapDist[1];
boundingWidth = boundingHeight * ratio;
}
} else {
boundingWidth += snapDist[0];
boundingHeight += snapDist[1];
boundingWidth = Math.max(0, boundingWidth);
boundingHeight = Math.max(0, boundingHeight);
}
[boundingWidth, boundingHeight] = calculateBoundSize(
[boundingWidth, boundingHeight],
minSize,
maxSize,
keepRatio ? ratio : false,
);
computeSize();
if (keepRatio && (isGroup || keepRatioFinally)) {
if (isWidth) {
boundingHeight = boundingWidth / ratio;
} else {
boundingWidth = boundingHeight * ratio;
}
}
distWidth = boundingWidth - startOffsetWidth;
distHeight = boundingHeight - startOffsetHeight;
const delta = [distWidth - prevWidth, distHeight - prevHeight];
datas.prevWidth = distWidth;
datas.prevHeight = distHeight;
const inverseDelta = getResizeDist(
moveable,
boundingWidth,
boundingHeight,
fixedPosition,
transformOrigin,
datas,
);
if (!parentMoveable && delta.every(num => !num) && inverseDelta.every(num => !num)) {
return;
}
const drag = Draggable.drag(
moveable,
setCustomDrag(e, moveable.state, inverseDelta, !!isPinch, false, "draggable"),
) as OnDrag;
const transform = drag.transform;
const nextWidth = startWidth + distWidth;
const nextHeight = startHeight + distHeight;
const params = fillParams<OnResize>(moveable, e, {
width: nextWidth,
height: nextHeight,
offsetWidth: Math.round(boundingWidth),
offsetHeight: Math.round(boundingHeight),
startRatio: ratio,
boundingWidth,
boundingHeight,
direction,
dist: [distWidth, distHeight],
delta,
isPinch: !!isPinch,
drag,
...fillAfterTransform({
style: {
width: `${nextWidth}px`,
height: `${nextHeight}px`,
},
transform,
}, drag, e),
});
!parentEvent && triggerEvent(moveable, "onResize", params);
return params;
},
dragControlAfter(
moveable: MoveableManagerInterface<ResizableProps & DraggableProps>,
e: any,
) {
const datas = e.datas;
const {
isResize,
startOffsetWidth,
startOffsetHeight,
prevWidth,
prevHeight,
} = datas;
if (!isResize || moveable.props.checkResizableError === false) {
return;
}
const {
width,
height,
} = moveable.state;
const errorWidth = width - (startOffsetWidth + prevWidth);
const errorHeight = height - (startOffsetHeight + prevHeight);
const isErrorWidth = abs(errorWidth) > 3;
const isErrorHeight = abs(errorHeight) > 3;
if (isErrorWidth) {
datas.startWidth += errorWidth;
datas.startOffsetWidth += errorWidth;
datas.prevWidth += errorWidth;
}
if (isErrorHeight) {
datas.startHeight += errorHeight;
datas.startOffsetHeight += errorHeight;
datas.prevHeight += errorHeight;
}
if (isErrorWidth || isErrorHeight) {
return this.dragControl(moveable, e);
}
},
dragControlEnd(
moveable: MoveableManagerInterface<ResizableProps & DraggableProps>,
e: any,
) {
const { datas, parentEvent } = e;
if (!datas.isResize) {
return;
}
datas.isResize = false;
const params = fillEndParams<OnResizeEnd>(moveable, e, {});
!parentEvent && triggerEvent(moveable, "onResizeEnd", params);
return params;
},
dragGroupControlCondition: directionCondition,
dragGroupControlStart(moveable: MoveableGroupInterface<any, any>, e: any) {
const { datas } = e;
const params = this.dragControlStart(moveable, {...e, isGroup: true });
if (!params) {
return false;
}
const originalEvents = fillChildEvents(moveable, "resizable", e);
const {
startOffsetWidth: parentStartOffsetWidth,
startOffsetHeight: parentStartOffsetHeight,
} = datas;
function updateGroupMin() {
const originalMinSize = datas.minSize;
originalEvents.forEach(ev => {
const {
minSize: childMinSize,
startOffsetWidth: childStartOffsetWidth,
startOffsetHeight: childStartOffsetHeight,
} = ev.datas;
const parentMinWidth = parentStartOffsetWidth
* (childStartOffsetWidth ? childMinSize[0] / childStartOffsetWidth : 0);
const parentMinHeight = parentStartOffsetHeight
* (childStartOffsetHeight ? childMinSize[1] / childStartOffsetHeight : 0);
originalMinSize[0] = Math.max(originalMinSize[0], parentMinWidth);
originalMinSize[1] = Math.max(originalMinSize[1], parentMinHeight);
});
}
function updateGroupMax() {
const originalMaxSize = datas.maxSize;
originalEvents.forEach(ev => {
const {
maxSize: childMaxSize,
startOffsetWidth: childStartOffsetWidth,
startOffsetHeight: childStartOffsetHeight,
} = ev.datas;
const parentMaxWidth = parentStartOffsetWidth
* (childStartOffsetWidth ? childMaxSize[0] / childStartOffsetWidth : 0);
const parentMaxHeight = parentStartOffsetHeight
* (childStartOffsetHeight ? childMaxSize[1] / childStartOffsetHeight : 0);
originalMaxSize[0] = Math.min(originalMaxSize[0], parentMaxWidth);
originalMaxSize[1] = Math.min(originalMaxSize[1], parentMaxHeight);
});
}
const events = triggerChildAbles(
moveable,
this,
"dragControlStart",
e,
(child, ev) => {
return startChildDist(moveable, child, datas, ev);
},
);
updateGroupMin();
updateGroupMax();
const setFixedDirection = (fixedDirection: number[]) => {
params.setFixedDirection(fixedDirection);
events.forEach((ev, i) => {
ev.setFixedDirection(fixedDirection);
startChildDist(moveable, ev.moveable, datas, originalEvents[i]);
});
};
datas.setFixedDirection = setFixedDirection;
const nextParams: OnResizeGroupStart = {
...params,
targets: moveable.props.targets!,
events: events.map(ev => {
return {
...ev,
setMin: (minSize: Array<number | string>) => {
ev.setMin(minSize);
updateGroupMin();
},
setMax: (maxSize: Array<number | string>) => {
ev.setMax(maxSize);
updateGroupMax();
},
};
}),
setFixedDirection,
setMin: (minSize: Array<number | string>) => {
params.setMin(minSize);
updateGroupMin();
},
setMax: (maxSize: Array<number | string>) => {
params.setMax(maxSize);
updateGroupMax();
},
};
const result = triggerEvent(moveable, "onResizeGroupStart", nextParams);
datas.isResize = result !== false;
return datas.isResize ? params : false;
},
dragGroupControl(moveable: MoveableGroupInterface<any, any>, e: any) {
const { datas } = e;
if (!datas.isResize) {
return;
}
const props = getProps(moveable.props, "resizable");
catchEvent(moveable, "onBeforeResize", parentEvent => {
triggerEvent(moveable, "onBeforeResizeGroup", fillParams<OnBeforeResizeGroup>(moveable, e, {
...parentEvent,
targets: props.targets!,
}, true));
});
const params = this.dragControl(moveable, {...e, isGroup: true });
if (!params) {
return;
}
const {
boundingWidth,
boundingHeight,
dist,
} = params;
const keepRatio = props.keepRatio;
const parentScale = [
boundingWidth / (boundingWidth - dist[0]),
boundingHeight / (boundingHeight - dist[1]),
];
const fixedPosition = datas.fixedPosition;
const events = triggerChildAbles(
moveable,
this,
"dragControl",
e,
(_, ev) => {
const [clientX, clientY] = calculate(
createRotateMatrix(moveable.rotation / 180 * Math.PI, 3),
[
ev.datas.originalX * parentScale[0],
ev.datas.originalY * parentScale[1],
1,
],
3,
);
return {
...ev,
parentDist: null,
parentScale,
dragClient: plus(fixedPosition, [clientX, clientY]),
parentKeepRatio: keepRatio,
};
},
);
const nextParams: OnResizeGroup = {
targets: props.targets!,
events,
...params,
};
triggerEvent(moveable, "onResizeGroup", nextParams);
return nextParams;
},
dragGroupControlEnd(moveable: MoveableGroupInterface<any, any>, e: any) {
const { isDrag, datas } = e;
if (!datas.isResize) {
return;
}
this.dragControlEnd(moveable, e);
const events = triggerChildAbles(moveable, this, "dragControlEnd", e);
const nextParams: OnResizeGroupEnd = fillEndParams<OnResizeGroupEnd>(moveable, e, {
targets: moveable.props.targets!,
events,
});
triggerEvent(moveable, "onResizeGroupEnd", nextParams);
return isDrag;
},
/**
* @method Moveable.Resizable#request
* @param {Moveable.Resizable.ResizableRequestParam} e - the Resizable's request parameter
* @return {Moveable.Requester} Moveable Requester
* @example
* // Instantly Request (requestStart - request - requestEnd)
* // Use Relative Value
* moveable.request("resizable", { deltaWidth: 10, deltaHeight: 10 }, true);
*
* // Use Absolute Value
* moveable.request("resizable", { offsetWidth: 100, offsetHeight: 100 }, true);
*
* // requestStart
* const requester = moveable.request("resizable");
*
* // request
* // Use Relative Value
* requester.request({ deltaWidth: 10, deltaHeight: 10 });
* requester.request({ deltaWidth: 10, deltaHeight: 10 });
* requester.request({ deltaWidth: 10, deltaHeight: 10 });
*
* // Use Absolute Value
* moveable.request("resizable", { offsetWidth: 100, offsetHeight: 100 });
* moveable.request("resizable", { offsetWidth: 110, offsetHeight: 100 });
* moveable.request("resizable", { offsetWidth: 120, offsetHeight: 100 });
*
* // requestEnd
* requester.requestEnd();
*/
request(moveable: MoveableManagerInterface<any>) {
const datas: Record<string, any> = {};
let distWidth = 0;
let distHeight = 0;
let useSnap = false;
const rect = moveable.getRect();
return {
isControl: true,
requestStart(e: ResizableRequestParam) {
useSnap = e.useSnap!;
return {
datas, parentDirection: e.direction || [1, 1],
parentIsWidth: e?.horizontal ?? true,
useSnap,
};
},
request(e: ResizableRequestParam) {
if ("offsetWidth" in e) {
distWidth = e.offsetWidth! - rect.offsetWidth;
} else if ("deltaWidth" in e) {
distWidth += e.deltaWidth!;
}
if ("offsetHeight" in e) {
distHeight = e.offsetHeight! - rect.offsetHeight;
} else if ("deltaHeight" in e) {
distHeight += e.deltaHeight!;
}
return {
datas,
parentDist: [distWidth, distHeight],
parentKeepRatio: e.keepRatio,
useSnap,
};
},
requestEnd() {
return { datas, isDrag: true, useSnap };
},
};
},
unset(moveable: MoveableManagerInterface<any, {}>) {
moveable.state.gestos.resizable = null;
},
};
/**
* Whether or not target can be resized.
* @name Moveable.Resizable#resizable
* @default false
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, {
* resizable: false,
* });
*
* moveable.resizable = true;
*/
/**
* throttle of width, height when resize. If throttleResize is set to less than 1, the target may shake.
* @name Moveable.Resizable#throttleResize
* @default 1
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, {
* resizable: true,
* throttleResize: 1,
* });
*
* moveable.throttleResize = 0;
*/
/**
* When resize or scale, keeps a ratio of the width, height.
* @name Moveable.Resizable#keepRatio
* @default false
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, {
* resizable: true,
* });
*
* moveable.keepRatio = true;
*/
/**
* Set directions to show the control box.
* @name Moveable.Resizable#renderDirections
* @default ["n", "nw", "ne", "s", "se", "sw", "e", "w"]
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, {
* resizable: true,
* renderDirections: ["n", "nw", "ne", "s", "se", "sw", "e", "w"],
* });
*
* moveable.renderDirections = ["nw", "ne", "sw", "se"];
*/
/**
* Function to convert size for resize
* @name Moveable.Resizable#resizeFormat
* @default oneself
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, {
* resizable: true,
* resizeFormat: v => v,
* });
*
* moveable.resizeFormat = (size: number[]) => ([Math.trunc(size[0]), Math.trunc(size[1])];
*/
/**
* When the resize starts, the resizeStart event is called.
* @memberof Moveable.Resizable
* @event resizeStart
* @param {Moveable.Resizable.OnResizeStart} - Parameters for the resizeStart event
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, { resizable: true });
* moveable.on("resizeStart", ({ target }) => {
* console.log(target);
* });
*/
/**
* When resizing, `beforeResize` is called before `resize` occurs. In `beforeResize`, you can get and set the pre-value before resizing.
* @memberof Moveable.Resizable
* @event beforeResize
* @param {Moveable.Resizable.OnBeforeResize} - Parameters for the `beforeResize` event
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, { resizable: true });
* moveable.on("beforeResize", ({ setFixedDirection }) => {
* if (shiftKey) {
* setFixedDirection([0, 0]);
* }
* });
* moveable.on("resize", ({ target, width, height, drag }) => {
* target.style.width = `${width}px`;
* target.style.height = `${height}px`;
* target.style.transform = drag.transform;
* });
*/
/**
* When resizing, the resize event is called.
* @memberof Moveable.Resizable
* @event resize
* @param {Moveable.Resizable.OnResize} - Parameters for the resize event
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, { resizable: true });
* moveable.on("resize", ({ target, width, height }) => {
* target.style.width = `${e.width}px`;
* target.style.height = `${e.height}px`;
* });
*/
/**
* When the resize finishes, the resizeEnd event is called.
* @memberof Moveable.Resizable
* @event resizeEnd
* @param {Moveable.Resizable.OnResizeEnd} - Parameters for the resizeEnd event
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, { resizable: true });
* moveable.on("resizeEnd", ({ target, isDrag }) => {
* console.log(target, isDrag);
* });
*/
/**
* When the group resize starts, the `resizeGroupStart` event is called.
* @memberof Moveable.Resizable
* @event resizeGroupStart
* @param {Moveable.Resizable.OnResizeGroupStart} - Parameters for the `resizeGroupStart` event
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, {
* target: [].slice.call(document.querySelectorAll(".target")),
* resizable: true
* });
* moveable.on("resizeGroupStart", ({ targets }) => {
* console.log("onResizeGroupStart", targets);
* });
*/
/**
* When the group resize, the `resizeGroup` event is called.
* @memberof Moveable.Resizable
* @event resizeGroup
* @param {Moveable.Resizable.onResizeGroup} - Parameters for the `resizeGroup` event
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, {
* target: [].slice.call(document.querySelectorAll(".target")),
* resizable: true
* });
* moveable.on("resizeGroup", ({ targets, events }) => {
* console.log("onResizeGroup", targets);
* events.forEach(ev => {
* const offset = [
* direction[0] < 0 ? -ev.delta[0] : 0,
* direction[1] < 0 ? -ev.delta[1] : 0,
* ];
* // ev.drag is a drag event that occurs when the group resize.
* const left = offset[0] + ev.drag.beforeDist[0];
* const top = offset[1] + ev.drag.beforeDist[1];
* const width = ev.width;
* const top = ev.top;
* });
* });
*/
/**
* When the group resize finishes, the `resizeGroupEnd` event is called.
* @memberof Moveable.Resizable
* @event resizeGroupEnd
* @param {Moveable.Resizable.OnResizeGroupEnd} - Parameters for the `resizeGroupEnd` event
* @example
* import Moveable from "moveable";
*
* const moveable = new Moveable(document.body, {
* target: [].slice.call(document.querySelectorAll(".target")),
* resizable: true
* });
* moveable.on("resizeGroupEnd", ({ targets, isDrag }) => {
* console.log("onResizeGroupEnd", targets, isDrag);
* });
*/