'use client' import classNames from 'classnames' import { ForwardedRef, forwardRef, HTMLAttributes, ReactNode, Ref, useCallback, useEffect, useRef, } from 'react' import { PktButton } from '../button/Button' export interface IPktModal extends Omit, 'onClose' | 'open'> { open?: boolean headingText?: string hideCloseButton?: boolean closeOnBackdropClick?: boolean size?: 'small' | 'medium' | 'large' | 'fit-content' removePadding?: boolean closeButtonSkin?: 'blue' | 'yellow-filled' variant?: 'dialog' | 'drawer' drawerPosition?: 'left' | 'right' transparentBackdrop?: boolean onClose?: () => void children?: ReactNode ref?: Ref } export const PktModal = forwardRef( ( { children, className, open = false, headingText = '', hideCloseButton = false, closeOnBackdropClick = false, size = 'medium', removePadding = false, closeButtonSkin = 'blue', variant = 'dialog', drawerPosition = 'right', transparentBackdrop = false, onClose, ...props }: IPktModal, ref: ForwardedRef, ) => { const internalRef = useRef(null) const dialogRef = (ref as React.RefObject) || internalRef const close = useCallback(() => { if (!dialogRef.current?.open) return dialogRef.current?.close() onClose?.() }, [dialogRef, onClose]) // Synkroniser scroll-lock med dialogens faktiske åpen/lukket-tilstand useEffect(() => { const dialog = dialogRef.current if (!dialog) return const observer = new MutationObserver(() => { if (dialog.open) { document.body.classList.add('pkt-modal--open') } else { document.body.classList.remove('pkt-modal--open') } }) observer.observe(dialog, { attributes: true, attributeFilter: ['open'] }) return () => observer.disconnect() }, [dialogRef]) // Deklarativ åpne/lukke via open-prop useEffect(() => { if (open) { if (!dialogRef.current?.open) { dialogRef.current?.showModal() } } else { if (dialogRef.current?.open) { dialogRef.current?.close() } } }, [open, dialogRef]) const handleBackdropClick = useCallback( (event: React.MouseEvent) => { if (closeOnBackdropClick && event.target === dialogRef.current) { close() } }, [closeOnBackdropClick, dialogRef, close], ) const handleNativeClose = useCallback(() => { onClose?.() }, [onClose]) const isCloseButtonSkinDefault = closeButtonSkin === 'blue' const classes = classNames( { 'pkt-modal': true, 'pkt-modal--removePadding': removePadding, 'pkt-modal--noHeadingText': !headingText, 'pkt-modal--noShadow': closeButtonSkin === 'yellow-filled', 'pkt-modal--transparentBackdrop': transparentBackdrop, [`pkt-modal--${size}`]: size, [`pkt-modal__${variant}`]: variant, [`pkt-modal__drawer--${drawerPosition}`]: variant === 'drawer', }, className, ) return (
{(headingText || !hideCloseButton) && (
{headingText ? (

{headingText}

) : (
)} {!hideCloseButton ? (
Lukk
) : (
)}
)}
{children}
) }, ) PktModal.displayName = 'PktModal'