import type { Child } from 'hono/jsx' import { define } from '@because/forge' import { theme } from '../themes' let modalTitle: string | null = null let modalContent: (() => Child) | null = null let renderFn: (() => void) | null = null export const initModal = (render: () => void) => { renderFn = render } export const openModal = (title: string, content: () => Child) => { modalTitle = title modalContent = content renderFn?.() requestAnimationFrame(() => { document.querySelector('[data-modal-body] input')?.focus() }) } export const closeModal = () => { modalTitle = null modalContent = null renderFn?.() } export const rerenderModal = () => { renderFn?.() } // ESC key handler document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && modalContent) { closeModal() } }) const ModalBackdrop = define('ModalBackdrop', { position: 'fixed', inset: 0, background: 'rgba(0, 0, 0, 0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1000, }) const ModalBox = define('ModalBox', { background: theme('colors-bg'), borderRadius: theme('radius-md'), border: `1px solid ${theme('colors-border')}`, boxShadow: '0 4px 24px rgba(0, 0, 0, 0.2)', maxWidth: 500, width: '90%', maxHeight: '80vh', overflow: 'auto', }) const ModalHeader = define('ModalHeader', { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '16px 20px', borderBottom: `1px solid ${theme('colors-border')}`, }) const ModalTitle = define('ModalTitle', { fontSize: 16, fontWeight: 600, margin: 0, }) const ModalCloseButton = define('ModalCloseButton', { base: 'button', background: 'none', border: 'none', cursor: 'pointer', padding: 4, fontSize: 18, color: theme('colors-textMuted'), lineHeight: 1, selectors: { '&:hover': { color: theme('colors-text') }, }, }) const ModalBody = define('ModalBody', { padding: 20, }) export const Modal = () => { if (!modalContent) return null return ( e.stopPropagation()}> {modalTitle} × {modalContent()} ) }