Files
kiss-translator/src/views/Selection/DraggableResizable.js

280 lines
5.9 KiB
JavaScript
Raw Normal View History

2024-04-20 18:07:16 +08:00
import { useState } from "react";
2023-10-23 18:02:42 +08:00
import Paper from "@mui/material/Paper";
import Box from "@mui/material/Box";
import { isMobile } from "../../libs/mobile";
2023-10-23 18:02:42 +08:00
function Pointer({
direction,
size,
setSize,
position,
setPosition,
children,
minSize,
maxSize,
...props
}) {
const [origin, setOrigin] = useState(null);
function handlePointerDown(e) {
!isMobile && e.target.setPointerCapture(e.pointerId);
const { clientX, clientY } = isMobile ? e.targetTouches[0] : e;
2023-10-23 18:02:42 +08:00
setOrigin({
x: position.x,
y: position.y,
w: size.w,
h: size.h,
clientX,
clientY,
2023-10-23 18:02:42 +08:00
});
}
function handlePointerMove(e) {
const { clientX, clientY } = isMobile ? e.targetTouches[0] : e;
2023-10-23 18:02:42 +08:00
if (origin) {
const dx = clientX - origin.clientX;
const dy = clientY - origin.clientY;
2023-10-23 18:02:42 +08:00
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;
2023-10-24 17:58:37 +08:00
default:
2023-10-23 18:02:42 +08:00
}
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) {
e.stopPropagation();
2023-10-23 18:02:42 +08:00
setOrigin(null);
}
const touchProps = isMobile
? {
onTouchStart: handlePointerDown,
onTouchMove: handlePointerMove,
onTouchEnd: handlePointerUp,
}
: {
onPointerDown: handlePointerDown,
onPointerMove: handlePointerMove,
onPointerUp: handlePointerUp,
};
2023-10-23 18:02:42 +08:00
return (
<div {...props} {...touchProps}>
2023-10-23 18:02:42 +08:00
{children}
</div>
);
}
export default function DraggableResizable({
header,
children,
2024-04-20 18:07:16 +08:00
position = {
2023-10-23 18:02:42 +08:00
x: 0,
y: 0,
},
2024-04-20 18:07:16 +08:00
size = {
2023-10-23 18:02:42 +08:00
w: 600,
h: 400,
},
minSize = {
w: 300,
h: 200,
},
maxSize = {
w: 1200,
h: 1200,
},
2024-04-20 18:07:16 +08:00
setSize,
setPosition,
2023-10-24 17:58:37 +08:00
onChangeSize,
onChangePosition,
autoHeight,
2024-04-01 12:25:59 +08:00
...props
2023-10-23 18:02:42 +08:00
}) {
const lineWidth = 4;
const opts = {
size,
setSize,
position,
setPosition,
minSize,
maxSize,
};
return (
<Box
2024-04-17 15:35:44 +08:00
className="KT-draggable"
2023-10-23 18:02:42 +08:00
style={{
touchAction: "none",
2023-10-23 18:02:42 +08:00
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`,
2023-10-24 17:58:37 +08:00
zIndex: 2147483647,
2023-10-23 18:02:42 +08:00
}}
2024-04-01 12:25:59 +08:00
{...props}
2023-10-23 18:02:42 +08:00
>
<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}
/>
2024-04-17 15:35:44 +08:00
<Paper className="KT-draggable-body" elevation={4}>
<Pointer
className="KT-draggable-header"
direction="Header"
style={{ cursor: "move" }}
{...opts}
>
2023-10-23 18:02:42 +08:00
{header}
</Pointer>
2024-04-17 15:35:44 +08:00
<Box
className="KT-draggable-container"
style={
autoHeight
? {
width: size.w,
maxHeight: size.h,
overflow: "hidden auto",
}
: {
width: size.w,
height: size.h,
overflow: "hidden auto",
}
}
2023-10-23 18:02:42 +08:00
>
{children}
2024-04-17 15:35:44 +08:00
</Box>
2023-10-23 18:02:42 +08:00
</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>
);
}