import { useTranslate } from "@workspace/i18n" import { Button } from "@workspace/ui/components/button" import { createDialogHandle, Dialog, DialogClose, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@workspace/ui/components/dialog" import { XIcon } from "@workspace/ui/components/icon" import { OverlayController, type OverlayRequest } from "./internal/controller" import { renderOverlayContent } from "./internal/render-content" import { useOverlayController } from "./internal/use-controller" import { overlayMessages } from "./messages" import { globalOverlayScope, type OverlayScope } from "./scope" import type { ModalOptions } from "./types" type ModalRequestOptions = Omit, "scope"> const modalChannel = Symbol("overlay.modal") function getModalController(scope: OverlayScope) { return scope.getChannel(modalChannel, () => { const handle = createDialogHandle>() return new OverlayController({ handle, isDismissible: (options) => options.dismissible !== false, scope, }) }) } export function openModal(options: ModalOptions) { const { scope = globalOverlayScope, ...modalOptions } = options return getModalController(scope).open( modalOptions as ModalRequestOptions, undefined ) } export interface ModalHostProps { scope?: OverlayScope } export function ModalHost({ scope }: ModalHostProps) { const controller = useOverlayController(scope, getModalController) const activeOptions = controller.getActive()?.options return ( > disablePointerDismissal={activeOptions?.dismissible === false} handle={controller.handle} modal={activeOptions?.modal} onOpenChange={(open, details) => { if (!open) controller.handleCloseRequest(details) }} onOpenChangeComplete={(open) => { if (!open) controller.handleCloseComplete() }} > {({ payload }) => payload ? ( controller.resolve(value)} /> ) : null } ) } function ModalContent({ onDismiss, onResolve, options, }: { onDismiss: () => void onResolve: (value: unknown) => void options: ModalRequestOptions }) { const t = useTranslate() const dismissible = options.dismissible !== false return ( {options.title} {options.description != null && ( {options.description} )} {renderOverlayContent(options.content, { close: onResolve, dismiss: onDismiss, })} {dismissible && ( } > )} ) } export type { ModalOptions } from "./types"