Files
jsonhero-web/app/components/Resizable.tsx
T
2022-03-01 09:31:09 +00:00

109 lines
2.5 KiB
TypeScript

import React, { useState, useEffect } from "react";
type ResizableProps = {
children: React.ReactNode;
isHorizontal: boolean;
initialSize: number;
minimumSize: number;
maximumSize: number;
};
export default function Resizable({
children,
isHorizontal = true,
initialSize,
minimumSize,
maximumSize,
}: ResizableProps) {
const [dimension, setDimension] = useState(initialSize);
const [previousDragPosition, setPreviousDragPosition] = useState<{
x: number;
y: number;
} | null>(null);
const handleDragStart = (e: React.MouseEvent<HTMLDivElement>): void => {
setPreviousDragPosition({
x: e.clientX,
y: e.clientY,
});
};
const handleDrag = (e: MouseEvent) => {
if (previousDragPosition === null) {
return;
}
e.preventDefault();
let offset = 0;
if (isHorizontal) {
offset = e.clientX - previousDragPosition.x;
} else {
offset = e.clientY - previousDragPosition.y;
}
let newValue = dimension - offset;
if (minimumSize != null) {
newValue = Math.max(minimumSize, newValue);
}
if (maximumSize != null) {
newValue = Math.min(maximumSize, newValue);
}
setDimension(newValue);
setPreviousDragPosition({
x: e.clientX,
y: e.clientY,
});
};
const handleDragEnd = () => {
setPreviousDragPosition(null);
};
useEffect(() => {
window.addEventListener("mousemove", handleDrag);
window.addEventListener("mouseup", handleDragEnd);
return () => {
window.removeEventListener("mousemove", handleDrag);
window.removeEventListener("mouseup", handleDragEnd);
};
}, [handleDrag, handleDragEnd]);
const style = () => {
let formatted = dimension + "px";
if (isHorizontal) {
return {
width: formatted,
};
} else {
return {
height: formatted,
};
}
};
const classes = () => {
if (isHorizontal) {
return "flex flex-none relative";
} else {
return "flex flex-none relative";
}
};
return (
<div style={style()} className={classes()}>
<div className={"flex-grow"} style={{ width: "inherit" }}>
{children}
</div>
<div
className={
isHorizontal
? "w-1 h-full absolute my-0 -ml-[1px] transition-all cursor-col-resize hover:bg-indigo-700 hover:opacity-100"
: "h-1 w-full transition-all cursor-row-resize hover:bg-indigo-700 hover:opacity-100"
}
onMouseDown={handleDragStart}
></div>
</div>
);
}