import 'react-resizable/css/styles.css';
import React, { useRef, useState } from 'react';
import Draggable from 'react-draggable';
import { Resizable } from 'react-resizable';
interface FloatingModalProps {
title: string;
subTitle?: string;
children: React.ReactNode;
onClose: () => void;
defaultPosition?: { x: number; y: number };
defaultSize?: { width: number; height: number };
}
const FloatingModal: React.FC<FloatingModalProps> = ({
title,
subTitle,
children,
onClose,
defaultPosition = { x: 0, y: 0 },
defaultSize = { width: 400, height: 300 },
}) => {
const [position, setPosition] = useState(defaultPosition);
const [size, setSize] = useState(defaultSize);
const [isDragging, setIsDragging] = useState(false);
const dragRef = useRef<HTMLDivElement>(null);
const handleDrag = (_: any, data: { x: number; y: number }) => {
setPosition({ x: data.x, y: Math.max(data.y, 0) });
};
const handleStart = () => {
setIsDragging(true);
};
const handleStop = () => {
setIsDragging(false);
};
const handleResize = (_: any, { size }: { size: { width: number; height: number } }) => {
setSize(size);
};
return (
<Draggable
nodeRef={dragRef}
position={position}
onDrag={handleDrag}
onStart={handleStart}
onStop={handleStop}
handle=".floating-modal-header"
bounds="parent"
>
<Resizable
width={size.width}
height={size.height}
onResize={handleResize}
resizeHandles={['s', 'w', 'e', 'n', 'sw', 'nw', 'se', 'ne']}
>
<div
ref={dragRef}
style={{
position: 'fixed',
width: `${size.width}px`,
height: `${size.height}px`,
zIndex: 100000,
boxShadow: '0 4px 20px rgba(0, 0, 0, 0.15)',
borderRadius: '8px',
overflow: 'hidden',
backgroundColor: '#242424',
display: 'flex',
flexDirection: 'column',
pointerEvents: isDragging ? 'none' : 'auto',
cursor: isDragging ? 'grabbing' : 'default',
}}
>
{}
<div
className="floating-modal-header"
style={{
padding: '8px 15px',
backgroundColor: '#242424',
borderBottom: '1px solid rgba(255, 255, 255, 0.05)',
cursor: 'move',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<div style={{ display: 'flex', alignItems: 'flex-end' }}>
<h3 style={{
margin: 0,
paddingRight: 15,
borderRight: '1px solid rgba(255, 255, 255, 0.08)',
fontSize: '14px', color: '#FCFCFC', fontWeight: 600, userSelect: 'none',
}}>{title}</h3>
{subTitle && <div
style={{ fontSize: 12, opacity: 0.6, paddingLeft: 15 }}
>{subTitle}</div>}
</div>
</div>
<button
onClick={onClose}
style={{
position: 'absolute',
right: '16px',
top: '6px',
background: 'none',
border: 'none',
cursor: 'pointer',
fontSize: '18px',
lineHeight: 1,
padding: '4px',
color: '#fff',
}}
>
×
</button>
{}
<div
style={{
flex: 1,
padding: '10px',
overflow: 'auto',
}}
>
{children}
</div>
</div>
</Resizable>
</Draggable>
);
};
export default FloatingModal;