{"version":3,"file":"Drawer.cjs","names":[],"sources":["../../../src/components/Drawer/Drawer.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count, function-lines — placement plus mobilePlacement is\n * the whole point — a drawer that comes from the side on desktop and from the bottom\n * on a phone — and the rest is the dialog contract the SDK's Modal also has (open,\n * onClose, title, children, footer, closeOnBackdrop, closeOnEsc, hideCloseButton)\n * plus showHandle for the sheet affordance.\n */\nimport { useEffect } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"@/utils/cn\";\nimport { useBreakpoint } from \"@/hooks/use-breakpoint\";\nimport styles from \"./Drawer.module.css\";\nimport { usePortalHost } from \"../Portal/portal-host\";\n\nexport type DrawerPlacement = \"right\" | \"left\" | \"top\" | \"bottom\";\n\nexport interface DrawerProps {\n    open: boolean;\n    onClose: () => void;\n    placement?: DrawerPlacement;\n    title?: ReactNode;\n    children?: ReactNode;\n    footer?: ReactNode;\n    closeOnBackdrop?: boolean;\n    closeOnEsc?: boolean;\n    hideCloseButton?: boolean;\n    className?: string;\n    /**\n     * Auto-switch to bottom-sheet placement on mobile viewports (< md).\n     * Modern mobile apps default to bottom drawers; on desktop the original\n     * `placement` is preserved.\n     */\n    mobilePlacement?: DrawerPlacement;\n    /** Render a drag handle indicator at the leading edge (bottom-sheet style). */\n    showHandle?: boolean;\n}\n\n/**\n * Sliding side panel. Same building blocks as {@link Modal} but anchored to\n * an edge. Locks body scroll while open.\n */\nexport function Drawer({\n    open,\n    onClose,\n    placement = \"right\",\n    title,\n    children,\n    footer,\n    closeOnBackdrop = true,\n    closeOnEsc = true,\n    hideCloseButton = false,\n    className,\n    mobilePlacement,\n    showHandle = false,\n}: DrawerProps) {\n    const { isMobile } = useBreakpoint();\n    const effectivePlacement: DrawerPlacement =\n        isMobile && mobilePlacement ? mobilePlacement : placement;\n\n    useEffect(() => {\n        if (!open) return;\n        const previousOverflow = document.body.style.overflow;\n        document.body.style.overflow = \"hidden\";\n        const handleKey = (event: KeyboardEvent): void => {\n            if (closeOnEsc && event.key === \"Escape\") onClose();\n        };\n        window.addEventListener(\"keydown\", handleKey);\n        return () => {\n            document.body.style.overflow = previousOverflow;\n            window.removeEventListener(\"keydown\", handleKey);\n        };\n    }, [open, closeOnEsc, onClose]);\n\n    const portalHost = usePortalHost();\n\n    if (!open || !portalHost) return null;\n\n    return createPortal(\n        <>\n            <div\n                className={styles.overlay}\n                onClick={() => {\n                    if (closeOnBackdrop) onClose();\n                }}\n            />\n            <aside\n                role=\"dialog\"\n                aria-modal=\"true\"\n                className={cn(styles.panel, styles[effectivePlacement], className)}\n            >\n                {showHandle &&\n                    (effectivePlacement === \"bottom\" || effectivePlacement === \"top\") && (\n                        <div\n                            className={cn(\n                                styles.handle,\n                                effectivePlacement === \"top\" && styles.handleTop,\n                            )}\n                            aria-hidden\n                        />\n                    )}\n                {(title || !hideCloseButton) && (\n                    <header className={styles.header}>\n                        <h3 className={styles.title}>{title}</h3>\n                        {!hideCloseButton && (\n                            <button\n                                type=\"button\"\n                                aria-label=\"Fechar\"\n                                className={styles.close}\n                                onClick={onClose}\n                            >\n                                <CloseIcon />\n                            </button>\n                        )}\n                    </header>\n                )}\n                <div className={styles.body}>{children}</div>\n                {footer && <footer className={styles.footer}>{footer}</footer>}\n            </aside>\n        </>,\n        portalHost,\n    );\n}\n\nfunction CloseIcon() {\n    return (\n        <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\">\n            <path\n                d=\"M6 6l12 12M6 18L18 6\"\n                stroke=\"currentColor\"\n                strokeWidth=\"2\"\n                strokeLinecap=\"round\"\n            />\n        </svg>\n    );\n}\n"],"mappings":"uOA0CA,SAAgB,EAAO,CACnB,OACA,UACA,YAAY,QACZ,QACA,WACA,SACA,kBAAkB,GAClB,aAAa,GACb,kBAAkB,GAClB,YACA,kBACA,aAAa,IACD,CACZ,GAAM,CAAE,YAAa,EAAA,cAAc,EAC7B,EACF,GAAY,EAAkB,EAAkB,GAEpD,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,CAAC,EAAM,OACX,IAAM,EAAmB,SAAS,KAAK,MAAM,SAC7C,SAAS,KAAK,MAAM,SAAW,SAC/B,IAAM,EAAa,GAA+B,CAC1C,GAAc,EAAM,MAAQ,UAAU,EAAQ,CACtD,EAEA,OADA,OAAO,iBAAiB,UAAW,CAAS,MAC/B,CACT,SAAS,KAAK,MAAM,SAAW,EAC/B,OAAO,oBAAoB,UAAW,CAAS,CACnD,CACJ,EAAG,CAAC,EAAM,EAAY,CAAO,CAAC,EAE9B,IAAM,EAAa,EAAA,cAAc,EAIjC,MAFI,CAAC,GAAQ,CAAC,EAAmB,MAEjC,EAAO,EAAA,aAAA,EACH,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,UAAW,EAAA,QAAO,QAClB,YAAe,CACP,GAAiB,EAAQ,CACjC,CACH,CAAA,GACD,EAAA,EAAA,KAAA,CAAC,QAAD,CACI,KAAK,SACL,aAAW,OACX,UAAW,EAAA,GAAG,EAAA,QAAO,MAAO,EAAA,QAAO,GAAqB,CAAS,EAHrE,SAAA,CAKK,IACI,IAAuB,UAAY,IAAuB,SACvD,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,UAAW,EAAA,GACP,EAAA,QAAO,OACP,IAAuB,OAAS,EAAA,QAAO,SAC3C,EACA,cAAA,EACH,CAAA,GAEP,GAAS,CAAC,KACR,EAAA,EAAA,KAAA,CAAC,SAAD,CAAQ,UAAW,EAAA,QAAO,OAA1B,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAU,CAAA,EACvC,CAAC,IACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,aAAW,SACX,UAAW,EAAA,QAAO,MAClB,QAAS,EAET,UAAA,EAAA,EAAA,IAAA,CAAC,EAAD,CAAY,CAAA,CACR,CAAA,CAER,KAEZ,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAO,UAAc,CAAA,EAC3C,IAAU,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,UAAW,EAAA,QAAO,OAAS,SAAA,CAAe,CAAA,CAC1D,CACT,CAAA,CAAA,CAAA,CAAA,EACF,CACJ,CACJ,CAEA,SAAS,GAAY,CACjB,OACI,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OACjD,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,EAAE,uBACF,OAAO,eACP,YAAY,IACZ,cAAc,OACjB,CAAA,CACA,CAAA,CAEb"}