128 lines
4.7 KiB
TypeScript
128 lines
4.7 KiB
TypeScript
![]() |
import PointsIcon from "@icons/questionsPage/PointsIcon";
|
||
|
import { Box, IconButton, Paper, keyframes } from "@mui/material";
|
||
|
import { toggleQuizPreview, useQuizPreviewStore } from "@root/quizPreview";
|
||
|
import { useEffect, useLayoutEffect, useRef } from "react";
|
||
|
import { Rnd } from "react-rnd";
|
||
|
import QuizPreviewContent from "./QuizPreviewContent";
|
||
|
import ResizeIcon from "./ResizeIcon";
|
||
|
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||
|
|
||
|
|
||
|
const DRAG_PARENT_MARGIN = 25;
|
||
|
const NAVBAR_HEIGHT = 81;
|
||
|
const DRAG_PARENT_BOTTOM_MARGIN = 25;
|
||
|
|
||
|
interface RndPositionAndSize {
|
||
|
x: number;
|
||
|
y: number;
|
||
|
width: string;
|
||
|
height: string;
|
||
|
}
|
||
|
|
||
|
export default function QuizPreview() {
|
||
|
const isPreviewShown = useQuizPreviewStore(state => state.isPreviewShown);
|
||
|
const rndParentRef = useRef<HTMLDivElement>(null);
|
||
|
const rndRef = useRef<Rnd | null>(null);
|
||
|
const rndPositionAndSizeRef = useRef<RndPositionAndSize>({ x: 0, y: 0, width: "0", height: "0" });
|
||
|
const isFirstShowRef = useRef<boolean>(true);
|
||
|
|
||
|
useLayoutEffect(function stickPreviewToBottomRight() {
|
||
|
const rnd = rndRef.current;
|
||
|
const rndSelfElement = rnd?.getSelfElement();
|
||
|
if (!rnd || !rndSelfElement || !rndParentRef.current || !isFirstShowRef.current) return;
|
||
|
|
||
|
const rndParentRect = rndParentRef.current.getBoundingClientRect();
|
||
|
const rndRect = rndSelfElement.getBoundingClientRect();
|
||
|
|
||
|
const x = rndParentRect.width - rndRect.width;
|
||
|
const y = rndParentRect.height - rndRect.height;
|
||
|
|
||
|
rnd.updatePosition({ x, y });
|
||
|
rndPositionAndSizeRef.current.x = x;
|
||
|
rndPositionAndSizeRef.current.y = y;
|
||
|
|
||
|
isFirstShowRef.current = false;
|
||
|
}, [isPreviewShown]);
|
||
|
|
||
|
return (
|
||
|
<Box
|
||
|
ref={rndParentRef}
|
||
|
sx={{
|
||
|
position: "fixed",
|
||
|
top: NAVBAR_HEIGHT + DRAG_PARENT_MARGIN,
|
||
|
left: DRAG_PARENT_MARGIN,
|
||
|
bottom: DRAG_PARENT_BOTTOM_MARGIN,
|
||
|
right: DRAG_PARENT_MARGIN,
|
||
|
// backgroundColor: "rgba(0, 100, 0, 0.2)",
|
||
|
pointerEvents: "none",
|
||
|
}}
|
||
|
>
|
||
|
{isPreviewShown &&
|
||
|
<Rnd
|
||
|
minHeight={480}
|
||
|
minWidth={300}
|
||
|
bounds="parent"
|
||
|
ref={rndRef}
|
||
|
dragHandleClassName="quiz-preview-draghandle"
|
||
|
default={{
|
||
|
x: rndPositionAndSizeRef.current.x,
|
||
|
y: rndPositionAndSizeRef.current.y,
|
||
|
width: rndPositionAndSizeRef.current.width,
|
||
|
height: rndPositionAndSizeRef.current.height
|
||
|
}}
|
||
|
onResizeStop={(e, direction, ref, delta, position) => {
|
||
|
rndPositionAndSizeRef.current.x = position.x;
|
||
|
rndPositionAndSizeRef.current.y = position.y;
|
||
|
rndPositionAndSizeRef.current.width = ref.style.width;
|
||
|
rndPositionAndSizeRef.current.height = ref.style.height;
|
||
|
}}
|
||
|
onDragStop={(e, d) => {
|
||
|
rndPositionAndSizeRef.current.x = d.x;
|
||
|
rndPositionAndSizeRef.current.y = d.y;
|
||
|
}}
|
||
|
enableResizing={{
|
||
|
topLeft: isPreviewShown,
|
||
|
}}
|
||
|
resizeHandleComponent={{
|
||
|
topLeft: <ResizeIcon />
|
||
|
}}
|
||
|
style={{
|
||
|
pointerEvents: "auto",
|
||
|
display: "flex",
|
||
|
flexDirection: "column",
|
||
|
}}
|
||
|
>
|
||
|
<Paper sx={{
|
||
|
flexGrow: 1,
|
||
|
borderRadius: "12px",
|
||
|
mb: 1,
|
||
|
}}>
|
||
|
<QuizPreviewContent />
|
||
|
</Paper>
|
||
|
<Box sx={{
|
||
|
alignSelf: "end",
|
||
|
mt: "auto",
|
||
|
mr: "45px",
|
||
|
display: "flex",
|
||
|
}}>
|
||
|
<IconButton className="quiz-preview-draghandle">
|
||
|
<PointsIcon />
|
||
|
</IconButton>
|
||
|
</Box>
|
||
|
</Rnd>
|
||
|
}
|
||
|
<IconButton
|
||
|
onClick={toggleQuizPreview}
|
||
|
sx={{
|
||
|
pointerEvents: "auto",
|
||
|
position: "absolute",
|
||
|
right: 4,
|
||
|
bottom: 4,
|
||
|
}}
|
||
|
>
|
||
|
<VisibilityIcon />
|
||
|
</IconButton>
|
||
|
</Box>
|
||
|
);
|
||
|
}
|