import { forwardRef, useMemo } from 'react'; import type { ContainerRef } from '@cleartrip/ct-design-container'; import { ActionButtonAlignment, ActionButtonVariant, Modal, ModalWithCloseOverlay, type ActionButtonAlignmentType, type ActionButtonVariantsType, } from '@cleartrip/ct-design-modal'; import type { IDialogProps } from './type'; /** * Web implementation of `Dialog`. * * Migrated from aldenui (`core/components/components/Dialog`) per * Migration.MD. The yagami Dialog is a thin wrapper around `Modal` * that translates the legacy `overlayCloseIcon` flag set into the * Modal-level `actionButtonType` + `actionButtonAlignment` contract: * * - `isBack` → `actionButtonType=BACK`, alignment `LEFT` * - `showCloseIcon`→ `actionButtonType=CLOSE` * - `isCenter` → alignment `CENTER` * - default → `actionButtonType=NONE`, alignment `RIGHT` * * The public API surface is preserved 1:1 with aldenui; the only * implementation difference on web is that the underlying `Modal` * does not yet implement the `actionButton*` slots directly, so we * delegate the close-overlay rendering to `ModalWithCloseOverlay` * whenever a visible close affordance is requested. The `NONE` case * falls through to plain `Modal`. */ const Dialog = forwardRef( ( { children, open, variant, placement, blur, allowBackdropClose, overlayCloseIcon, onClose, styleConfig, size, insidePortal = true, actionButtonType: actionButtonTypeFromProps, actionButtonAlignment: actionButtonAlignmentFromProps, }, forwardedRef, ) => { const { root: customRootStyles = [], modalWrapperStyles = [] } = styleConfig || {}; const { show = false, isBack = false, showCloseIcon = false, isCenter = false, isTop = true, } = overlayCloseIcon || {}; // Translate legacy `overlayCloseIcon` flags to the new // Modal-level `actionButton*` contract. Explicit `actionButton*` // props take precedence so consumers can opt into the new API // directly without touching `overlayCloseIcon`. const actionButtonAlignment = useMemo(() => { if (actionButtonAlignmentFromProps) return actionButtonAlignmentFromProps; if (isBack) return ActionButtonAlignment.LEFT; if (isCenter) return ActionButtonAlignment.CENTER; return ActionButtonAlignment.RIGHT; }, [actionButtonAlignmentFromProps, isBack, isCenter]); const actionButtonType = useMemo(() => { if (actionButtonTypeFromProps) return actionButtonTypeFromProps; if (isBack) return ActionButtonVariant.BACK; if (showCloseIcon || show) return ActionButtonVariant.CLOSE; return ActionButtonVariant.NONE; }, [actionButtonTypeFromProps, isBack, showCloseIcon, show]); const needsOverlay = actionButtonType !== ActionButtonVariant.NONE; if (needsOverlay) { return ( // `ModalWithCloseOverlay` expects an `HTMLDivElement` ref while // the public Dialog ref signature is `ContainerRef` for // cross-platform parity with native. The cast keeps the public // type stable until web Modal adopts the new ref shape. {children} ); } return ( {children} ); }, ); Dialog.displayName = 'Dialog'; export default Dialog;