249 lines
5.1 KiB
JavaScript
249 lines
5.1 KiB
JavaScript
|
|
import { useState } from "react";
|
||
|
|
import Paper from "@mui/material/Paper";
|
||
|
|
import Box from "@mui/material/Box";
|
||
|
|
|
||
|
|
function Pointer({
|
||
|
|
direction,
|
||
|
|
size,
|
||
|
|
setSize,
|
||
|
|
position,
|
||
|
|
setPosition,
|
||
|
|
children,
|
||
|
|
minSize,
|
||
|
|
maxSize,
|
||
|
|
...props
|
||
|
|
}) {
|
||
|
|
const [origin, setOrigin] = useState(null);
|
||
|
|
|
||
|
|
function handlePointerDown(e) {
|
||
|
|
e.target.setPointerCapture(e.pointerId);
|
||
|
|
setOrigin({
|
||
|
|
x: position.x,
|
||
|
|
y: position.y,
|
||
|
|
w: size.w,
|
||
|
|
h: size.h,
|
||
|
|
clientX: e.clientX,
|
||
|
|
clientY: e.clientY,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function handlePointerMove(e) {
|
||
|
|
if (origin) {
|
||
|
|
const dx = e.clientX - origin.clientX;
|
||
|
|
const dy = e.clientY - origin.clientY;
|
||
|
|
let x = position.x;
|
||
|
|
let y = position.y;
|
||
|
|
let w = size.w;
|
||
|
|
let h = size.h;
|
||
|
|
|
||
|
|
switch (direction) {
|
||
|
|
case "Header":
|
||
|
|
x = origin.x + dx;
|
||
|
|
y = origin.y + dy;
|
||
|
|
break;
|
||
|
|
case "TopLeft":
|
||
|
|
x = origin.x + dx;
|
||
|
|
y = origin.y + dy;
|
||
|
|
w = origin.w - dx;
|
||
|
|
h = origin.h - dy;
|
||
|
|
break;
|
||
|
|
case "Top":
|
||
|
|
y = origin.y + dy;
|
||
|
|
h = origin.h - dy;
|
||
|
|
break;
|
||
|
|
case "TopRight":
|
||
|
|
y = origin.y + dy;
|
||
|
|
w = origin.w + dx;
|
||
|
|
h = origin.h - dy;
|
||
|
|
break;
|
||
|
|
case "Left":
|
||
|
|
x = origin.x + dx;
|
||
|
|
w = origin.w - dx;
|
||
|
|
break;
|
||
|
|
case "Right":
|
||
|
|
w = origin.w + dx;
|
||
|
|
break;
|
||
|
|
case "BottomLeft":
|
||
|
|
x = origin.x + dx;
|
||
|
|
w = origin.w - dx;
|
||
|
|
h = origin.h + dy;
|
||
|
|
break;
|
||
|
|
case "Bottom":
|
||
|
|
h = origin.h + dy;
|
||
|
|
break;
|
||
|
|
case "BottomRight":
|
||
|
|
w = origin.w + dx;
|
||
|
|
h = origin.h + dy;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (w < minSize.w) {
|
||
|
|
w = minSize.w;
|
||
|
|
x = position.x;
|
||
|
|
}
|
||
|
|
if (w > maxSize.w) {
|
||
|
|
w = maxSize.w;
|
||
|
|
x = position.x;
|
||
|
|
}
|
||
|
|
if (h < minSize.h) {
|
||
|
|
h = minSize.h;
|
||
|
|
y = position.y;
|
||
|
|
}
|
||
|
|
if (h > maxSize.h) {
|
||
|
|
h = maxSize.h;
|
||
|
|
y = position.y;
|
||
|
|
}
|
||
|
|
|
||
|
|
setPosition({ x, y });
|
||
|
|
setSize({ w, h });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function handlePointerUp(e) {
|
||
|
|
setOrigin(null);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div
|
||
|
|
{...props}
|
||
|
|
onPointerDown={handlePointerDown}
|
||
|
|
onPointerMove={handlePointerMove}
|
||
|
|
onPointerUp={handlePointerUp}
|
||
|
|
>
|
||
|
|
{children}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
export default function DraggableResizable({
|
||
|
|
header,
|
||
|
|
children,
|
||
|
|
defaultPosition = {
|
||
|
|
x: 0,
|
||
|
|
y: 0,
|
||
|
|
},
|
||
|
|
defaultSize = {
|
||
|
|
w: 600,
|
||
|
|
h: 400,
|
||
|
|
},
|
||
|
|
minSize = {
|
||
|
|
w: 300,
|
||
|
|
h: 200,
|
||
|
|
},
|
||
|
|
maxSize = {
|
||
|
|
w: 1200,
|
||
|
|
h: 1200,
|
||
|
|
},
|
||
|
|
sx,
|
||
|
|
}) {
|
||
|
|
const lineWidth = 4;
|
||
|
|
const [position, setPosition] = useState(defaultPosition);
|
||
|
|
const [size, setSize] = useState(defaultSize);
|
||
|
|
|
||
|
|
const opts = {
|
||
|
|
size,
|
||
|
|
setSize,
|
||
|
|
position,
|
||
|
|
setPosition,
|
||
|
|
minSize,
|
||
|
|
maxSize,
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Box
|
||
|
|
style={{
|
||
|
|
position: "fixed",
|
||
|
|
left: position.x,
|
||
|
|
top: position.y,
|
||
|
|
display: "grid",
|
||
|
|
gridTemplateColumns: `${lineWidth * 2}px auto ${lineWidth * 2}px`,
|
||
|
|
gridTemplateRows: `${lineWidth * 2}px auto ${lineWidth * 2}px`,
|
||
|
|
zIndex: 10000,
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<Pointer
|
||
|
|
direction="TopLeft"
|
||
|
|
style={{
|
||
|
|
transform: `translate(${lineWidth}px, ${lineWidth}px)`,
|
||
|
|
cursor: "nw-resize",
|
||
|
|
}}
|
||
|
|
{...opts}
|
||
|
|
/>
|
||
|
|
<Pointer
|
||
|
|
direction="Top"
|
||
|
|
style={{
|
||
|
|
margin: `0 ${lineWidth}px`,
|
||
|
|
transform: `translate(0px, ${lineWidth}px)`,
|
||
|
|
cursor: "row-resize",
|
||
|
|
}}
|
||
|
|
{...opts}
|
||
|
|
/>
|
||
|
|
<Pointer
|
||
|
|
direction="TopRight"
|
||
|
|
style={{
|
||
|
|
transform: `translate(-${lineWidth}px, ${lineWidth}px)`,
|
||
|
|
cursor: "ne-resize",
|
||
|
|
}}
|
||
|
|
{...opts}
|
||
|
|
/>
|
||
|
|
<Pointer
|
||
|
|
direction="Left"
|
||
|
|
style={{
|
||
|
|
margin: `${lineWidth}px 0`,
|
||
|
|
transform: `translate(${lineWidth}px, 0px)`,
|
||
|
|
cursor: "col-resize",
|
||
|
|
}}
|
||
|
|
{...opts}
|
||
|
|
/>
|
||
|
|
<Paper elevation={4}>
|
||
|
|
<Pointer direction="Header" style={{ cursor: "move" }} {...opts}>
|
||
|
|
{header}
|
||
|
|
</Pointer>
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
width: size.w,
|
||
|
|
height: size.h,
|
||
|
|
overflow: "hidden auto",
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{children}
|
||
|
|
</div>
|
||
|
|
</Paper>
|
||
|
|
<Pointer
|
||
|
|
direction="Right"
|
||
|
|
style={{
|
||
|
|
margin: `${lineWidth}px 0`,
|
||
|
|
transform: `translate(-${lineWidth}px, 0px)`,
|
||
|
|
cursor: "col-resize",
|
||
|
|
}}
|
||
|
|
{...opts}
|
||
|
|
/>
|
||
|
|
<Pointer
|
||
|
|
direction="BottomLeft"
|
||
|
|
style={{
|
||
|
|
transform: `translate(${lineWidth}px, -${lineWidth}px)`,
|
||
|
|
cursor: "ne-resize",
|
||
|
|
}}
|
||
|
|
{...opts}
|
||
|
|
/>
|
||
|
|
<Pointer
|
||
|
|
direction="Bottom"
|
||
|
|
style={{
|
||
|
|
margin: `0 ${lineWidth}px`,
|
||
|
|
transform: `translate(0px, -${lineWidth}px)`,
|
||
|
|
cursor: "row-resize",
|
||
|
|
}}
|
||
|
|
{...opts}
|
||
|
|
/>
|
||
|
|
<Pointer
|
||
|
|
direction="BottomRight"
|
||
|
|
style={{
|
||
|
|
transform: `translate(-${lineWidth}px, -${lineWidth}px)`,
|
||
|
|
cursor: "nw-resize",
|
||
|
|
}}
|
||
|
|
{...opts}
|
||
|
|
/>
|
||
|
|
</Box>
|
||
|
|
);
|
||
|
|
}
|