import React, { forwardRef } from 'react' import Block from '../Primitives/Block/Block' import { ButtonV2, ButtonV2SubType, ButtonV2Type } from '../ButtonV2' import type { ModalV2Props } from './modalV2.types' import { type SkeletonVariant } from '../Skeleton' import { useResponsiveTokens } from '../../hooks/useResponsiveTokens' import type { ModalV2TokensType } from './modalV2.tokens.types' import ModalV2Skeleton from './ModalV2Skeleton' import { DrawerV2, DrawerV2Body, DrawerV2Close, DrawerV2Content, DrawerV2Description, DrawerV2Footer, DrawerV2Header, DrawerV2Overlay, DrawerV2Portal, DrawerV2Title, } from '../DrawerV2' import { XIcon } from '@phosphor-icons/react' type MobileModalV2Props = ModalV2Props const formatLineHeight = (value: string | number | undefined) => typeof value === 'number' ? `${value}px` : value const visuallyHiddenStyle: React.CSSProperties = { position: 'absolute', width: 1, height: 1, padding: 0, margin: -1, overflow: 'hidden', clip: 'rect(0, 0, 0, 0)', clipPath: 'inset(50%)', whiteSpace: 'nowrap', borderWidth: 0, } const MobileModalV2 = forwardRef( ( { isOpen, onClose, title, subtitle, children, primaryAction, secondaryAction, showCloseButton = true, showHeader = true, showFooter = true, closeOnBackdropClick = true, customHeader, customFooter, headerSlot, skeleton, showDivider = true, ...props }, ref ) => { const modalTokens = useResponsiveTokens('MODALV2') const shouldShowSkeleton = skeleton?.show const skeletonVariant: SkeletonVariant = (skeleton?.variant as SkeletonVariant) || 'pulse' const bodySkeletonWidth = skeleton?.bodySkeletonProps?.width || '100%' const bodySkeletonHeight = skeleton?.bodySkeletonProps?.height || 200 const headerPaddingStyle = { paddingTop: modalTokens.header.paddingTop, paddingRight: modalTokens.header.paddingRight, paddingBottom: modalTokens.header.paddingBottom, paddingLeft: modalTokens.header.paddingLeft, } const bodyPaddingStyle = { paddingTop: modalTokens.body.paddingTop, paddingRight: modalTokens.body.paddingRight, paddingBottom: modalTokens.body.paddingBottom, paddingLeft: modalTokens.body.paddingLeft, } const footerPaddingStyle = { paddingTop: modalTokens.footer.paddingTop, paddingRight: modalTokens.footer.paddingRight, paddingBottom: modalTokens.footer.paddingBottom, paddingLeft: modalTokens.footer.paddingLeft, } const contentClassName = 'fixed z-[1001] outline-none flex flex-col overflow-hidden max-h-[85vh]' const contentStyle = { left: modalTokens.overlay.offset, right: modalTokens.overlay.offset, bottom: modalTokens.overlay.offset, backgroundColor: modalTokens.backgroundColor, boxShadow: modalTokens.boxShadow, borderRadius: modalTokens.borderRadius, border: `1px solid ${modalTokens.divider.borderColor}`, height: 'auto', } const shouldShowBodySkeleton = Boolean( shouldShowSkeleton && skeleton?.bodySkeletonProps?.show ) const hasFooterContent = Boolean( customFooter || primaryAction || secondaryAction || shouldShowSkeleton ) const { 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, ...contentProps } = props const shouldUseGeneratedTitle = Boolean( showHeader && !customHeader && title ) const effectiveAriaLabel = ariaLabel ?? (ariaLabelledBy || shouldUseGeneratedTitle ? undefined : title || 'Modal dialog') const hiddenTitle = ariaLabel || title || 'Modal dialog' return ( { if (!open) onClose() }} direction="bottom" modal={true} dismissible={closeOnBackdropClick} > {!shouldUseGeneratedTitle && ( {hiddenTitle} )} ) } ) MobileModalV2.displayName = 'MobileModalV2' export default MobileModalV2