diff --git a/lib/components/display/modal.jsx b/lib/components/display/modal.jsx index 55f0c354..386e2063 100644 --- a/lib/components/display/modal.jsx +++ b/lib/components/display/modal.jsx @@ -6,59 +6,149 @@ import { DialogBackdrop, } from "@headlessui/react"; import gwMerge from "../../gw-merge"; -import { WIDTH_OPTIONS } from "../../utils/sizes"; +import { useRef, useState, useEffect } from "react"; + +const WIDTH_OPTIONS = { + xs: "max-w-xs", + sm: "max-w-sm", + md: "max-w-md", + lg: "max-w-lg", + xl: "max-w-xl", + "2xl": "max-w-2xl", + "3xl": "max-w-3xl", + "4xl": "max-w-4xl", + "5xl": "max-w-5xl", +}; function Modal({ opened = false, onClose, dialogTitle, dialogDescription, - buttons, + footer, size = "2xl", className, children, }) { - // Check if the size exists + const widthClass = WIDTH_OPTIONS[size] ?? WIDTH_OPTIONS["2xl"]; if (!WIDTH_OPTIONS[size]) { - console.error( - `Invalid size prop: ${size}. Must be one of: 'sx', 'sm', 'md', 'lg', 'xl', '2xl', '4xl', 'full'` - ); console.warn( - `Defaulting to '2xl' for size of ` + `Modal: invalid size "${size}" passed. Falling back to "2xl".` ); - size = "2xl"; } + const panelRef = useRef(null); + // Modal Defaults + const [dimensions, setDimensions] = useState({ width: 600, height: 400 }); + const [position, setPosition] = useState({ x: 0, y: 0 }); + const [dragging, setDragging] = useState(false); + const [offset, setOffset] = useState({ x: 0, y: 0 }); + const [resizing, setResizing] = useState(false); + + const handleMouseDown = (e) => { + const rect = panelRef.current.getBoundingClientRect(); + setOffset({ x: e.clientX - rect.left, y: e.clientY - rect.top }); + setDragging(true); + }; + + const handleMouseMove = (e) => { + if (dragging) { + setPosition({ + x: e.clientX - offset.x, + y: e.clientY - offset.y, + }); + } else if (resizing) { + const rect = panelRef.current.getBoundingClientRect(); + setDimensions({ + width: Math.max(300, e.clientX - rect.left), + height: Math.max(200, e.clientY - rect.top), + }); + } + }; + + const handleMouseUp = () => { + setDragging(false); + setResizing(false); + }; + + useEffect(() => { + if (dragging || resizing) { + window.addEventListener("mousemove", handleMouseMove); + window.addEventListener("mouseup", handleMouseUp); + } + return () => { + window.removeEventListener("mousemove", handleMouseMove); + window.removeEventListener("mouseup", handleMouseUp); + }; + }, [dragging, resizing, offset]); + return (
-
+
- {dialogTitle && ( - +
+ {dialogTitle} - )} +
{dialogDescription && ( - {dialogDescription} + + {dialogDescription} + )} - {children} - {buttons} +
+ {children} +
+
+
{footer}
+
{ + e.preventDefault(); + e.stopPropagation(); + setResizing(true); + }} + className="gw-w-6 gw-h-6 gw-cursor-se-resize gw-ml-auto gw-mt-8" + style={{ + backgroundImage: + "linear-gradient(135deg, transparent 45%, #4b5563 45%, #4b5563 55%, transparent 55%)," + + "linear-gradient(135deg, transparent 65%, #4b5563 65%, #4b5563 75%, transparent 75%)", + backgroundRepeat: "no-repeat", + backgroundPosition: "bottom right", + backgroundSize: "100% 100%", + }} + title="Resize" + /> +
diff --git a/lib/utils/sizes.js b/lib/utils/sizes.js deleted file mode 100644 index 3652a5e0..00000000 --- a/lib/utils/sizes.js +++ /dev/null @@ -1,13 +0,0 @@ -const WIDTH_OPTIONS = { - xs: "max-w-xs", - sm: "max-w-sm", - md: "max-w-md", - lg: "max-w-lg", - xl: "max-w-xl", - "2xl": "max-w-2xl", - "3xl": "max-w-3xl", - "4xl": "max-w-4xl", - "5xl": "max-w-5xl", -}; - -export { WIDTH_OPTIONS }; diff --git a/src/app-pages/documentation/display/modal.jsx b/src/app-pages/documentation/display/modal.jsx index 9fb7e745..bd684a12 100644 --- a/src/app-pages/documentation/display/modal.jsx +++ b/src/app-pages/documentation/display/modal.jsx @@ -41,10 +41,10 @@ const componentProps = [ desc: "Description of the modal dialog.", }, { - name: "buttons", + name: "footer", type: "ReactNode", default: "null", - desc: "Button components to display at the bottom of the modal.", + desc: "Footer components to display at the bottom of the modal.", }, { name: "children", @@ -92,7 +92,7 @@ function ModalDocs() { dialogDescription="1-7 Day Quantitative Precipitation Forecast" size="2xl" staticWidth={true} - buttons={ + footer={