UNPKG

@react95/core

Version:
162 lines (161 loc) 4.68 kB
import { nanoid } from "nanoid"; import React, { useState, useEffect, useRef, useImperativeHandle } from "react"; import { useDraggable } from "@neodrag/react"; import { Button } from "../Button/Button.mjs"; import { fixedForwardRef, Frame } from "../Frame/Frame.mjs"; import { TitleBar } from "../TitleBar/TitleBar.mjs"; import { content, modalWrapper, menuWrapper, menuItem, buttonWrapper } from "./Modal.css.mjs"; import cn from "classnames"; import { useOnClickOutside } from "usehooks-ts"; import { modals, ModalEvents } from "../shared/events.mjs"; const ModalContent = fixedForwardRef( (rest, ref) => /* @__PURE__ */ React.createElement(Frame, { ...rest, ref, className: cn(content, rest.className) }) ); const ModalMinimize = fixedForwardRef( (props, ref) => { const [id, setId] = useState(""); useEffect(() => { const handleVisibilityChange = ({ id: activeId }) => { setId(activeId); }; modals.on(ModalEvents.ModalVisibilityChanged, handleVisibilityChange); return () => { modals.off(ModalEvents.ModalVisibilityChanged, handleVisibilityChange); }; }, []); const handleMinimize = () => { modals.emit(ModalEvents.MinimizeModal, { id }); modals.emit(ModalEvents.ModalVisibilityChanged, { id: "no id" }); }; return /* @__PURE__ */ React.createElement(TitleBar.Minimize, { ...props, ref, onClick: handleMinimize }); } ); const ModalRenderer = ({ hasWindowButton: hasButton = true, buttons = [], buttonsAlignment = "flex-end", children, icon, menu = [], title, dragOptions, titleBarOptions, className, ...rest }, ref) => { const [id] = useState(nanoid()); const [menuOpened, setMenuOpened] = useState(""); const [isActive, setIsActive] = useState(false); const [isModalMinimized, setIsModalMinimized] = useState(false); const draggableRef = useRef(null); useDraggable(draggableRef, { ...dragOptions, handle: ".draggable" }); const menuRef = useRef(null); useOnClickOutside(menuRef, () => { setMenuOpened(""); }); useEffect(() => { modals.emit(ModalEvents.AddModal, { icon, title, id, hasButton }); modals.on(ModalEvents.ModalVisibilityChanged, ({ id: activeId }) => { setIsActive(activeId === id); }); modals.emit(ModalEvents.ModalVisibilityChanged, { id }); return () => { modals.emit(ModalEvents.RemoveModal, { id }); }; }, []); useEffect(() => { modals.on(ModalEvents.MinimizeModal, ({ id: activeId }) => { if (activeId === id) { setIsModalMinimized(true); } }); modals.on(ModalEvents.RestoreModal, ({ id: activeId }) => { if (activeId === id) { setIsModalMinimized(false); } }); return () => { modals.off(ModalEvents.MinimizeModal, () => { }); modals.off(ModalEvents.RestoreModal, () => { }); }; }, [id]); useImperativeHandle(ref, () => { return draggableRef.current; }); return /* @__PURE__ */ React.createElement( Frame, { ...rest, className: cn( modalWrapper({ active: isActive, minimized: isModalMinimized }), className ), role: "dialog", "aria-hidden": isModalMinimized, ref: draggableRef, onMouseDown: () => { modals.emit(ModalEvents.ModalVisibilityChanged, { id }); } }, /* @__PURE__ */ React.createElement( TitleBar, { active: isActive, icon, title, className: "draggable" }, titleBarOptions && /* @__PURE__ */ React.createElement(TitleBar.OptionsBox, null, titleBarOptions) ), menu && menu.length > 0 && /* @__PURE__ */ React.createElement("ul", { className: menuWrapper, ref: menuRef }, menu.map(({ name, list }) => { const active = menuOpened === name; return /* @__PURE__ */ React.createElement( "li", { key: name, onMouseDown: () => setMenuOpened(name), className: menuItem({ active }) }, name, active && list ); })), children, buttons && buttons.length > 0 && /* @__PURE__ */ React.createElement( Frame, { className: buttonWrapper, justifyContent: buttonsAlignment }, buttons.map((button) => /* @__PURE__ */ React.createElement( Button, { key: button.value, onClick: button.onClick, value: button.value }, button.value )) ) ); }; const Modal = Object.assign( fixedForwardRef(ModalRenderer), { Content: ModalContent, Minimize: ModalMinimize } ); export { Modal };