{"version":3,"file":"Modal.mjs","names":[],"sources":["../../../src/base-ui/Modal/Modal.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { Maximize2, Minimize2, X } from 'lucide-react';\nimport { useDragControls } from 'motion/react';\nimport type { MouseEvent, PointerEvent } from 'react';\nimport type React from 'react';\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { stopPropagation } from '@/utils/dom';\n\nimport {\n  ModalBackdrop,\n  ModalContent,\n  ModalFooter,\n  ModalHeader,\n  ModalPopup,\n  ModalPortal,\n  ModalRoot,\n  ModalTitle,\n} from './atoms';\nimport { styles } from './style';\nimport type { ModalComponentProps } from './type';\n\ninterface OkBtnProps {\n  confirmLoading?: boolean;\n  okButtonProps?: ModalComponentProps['okButtonProps'];\n  okText?: React.ReactNode;\n  onOk: (e: MouseEvent<HTMLButtonElement>) => void;\n}\n\nconst OkBtn: React.FC<OkBtnProps> = ({ confirmLoading, okButtonProps, okText, onOk }) => {\n  const {\n    className: userCls,\n    danger,\n    disabled: userDisabled,\n    onClick: userOnClick,\n    ...restOk\n  } = okButtonProps ?? {};\n  return (\n    <button\n      type=\"button\"\n      {...restOk}\n      className={cx(styles.buttonBase, danger ? styles.dangerOkButton : styles.okButton, userCls)}\n      disabled={confirmLoading || userDisabled}\n      onClick={(e) => {\n        onOk(e);\n        userOnClick?.(e);\n      }}\n    >\n      {confirmLoading && <span className={styles.loadingSpinner} />}\n      {okText}\n    </button>\n  );\n};\ninterface CancelBtnProps {\n  cancelButtonProps?: ModalComponentProps['cancelButtonProps'];\n  cancelText?: React.ReactNode;\n  onCancel: (e: MouseEvent<HTMLButtonElement>) => void;\n}\n\nconst CancelBtn: React.FC<CancelBtnProps> = ({ cancelButtonProps, cancelText, onCancel }) => {\n  const { className: userCls, onClick: userOnClick, ...restCancel } = cancelButtonProps ?? {};\n  return (\n    <button\n      type=\"button\"\n      {...restCancel}\n      className={cx(styles.buttonBase, styles.cancelButton, userCls)}\n      onClick={(e) => {\n        onCancel(e);\n        userOnClick?.(e);\n      }}\n    >\n      {cancelText}\n    </button>\n  );\n};\n\nconst Modal = memo<ModalComponentProps>(\n  ({\n    open,\n    title,\n    children,\n    onOk,\n    onCancel,\n    okText = 'OK',\n    cancelText = 'Cancel',\n    okButtonProps,\n    cancelButtonProps,\n    confirmLoading,\n    footer,\n    width,\n    height,\n    maskClosable = true,\n    closable = true,\n    closeIcon,\n    className,\n    style,\n    classNames,\n    styles: semanticStyles,\n    zIndex,\n    afterClose,\n    afterOpenChange,\n    loading,\n    getContainer,\n    mask = true,\n    keyboard,\n    draggable = true,\n    allowFullscreen = false,\n  }) => {\n    const dragControls = useDragControls();\n    const constraintsRef = useRef<HTMLDivElement>(null);\n    const [isFullscreen, setIsFullscreen] = useState(false);\n    const [isDragging, setIsDragging] = useState(false);\n    const [isDenying, setIsDenying] = useState(false);\n    const denyTimerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n    useEffect(() => () => clearTimeout(denyTimerRef.current), []);\n\n    const triggerDeny = useCallback(() => {\n      clearTimeout(denyTimerRef.current);\n      setIsDenying(true);\n      denyTimerRef.current = setTimeout(() => setIsDenying(false), 400);\n    }, []);\n\n    const handleOpenChange = useCallback(\n      (nextOpen: boolean, eventDetails: { reason: string }) => {\n        if (!open) return;\n        if (!nextOpen && keyboard === false && eventDetails.reason === 'escape-key') return;\n        if (!nextOpen && !maskClosable && eventDetails.reason === 'outside-press') {\n          triggerDeny();\n          return;\n        }\n        if (!nextOpen) {\n          onCancel?.(new MouseEvent('click') as unknown as MouseEvent<HTMLButtonElement>);\n        }\n      },\n      [onCancel, keyboard, maskClosable, open, triggerDeny],\n    );\n\n    const handleExitComplete = useCallback(() => {\n      setIsFullscreen(false);\n      afterClose?.();\n      afterOpenChange?.(false);\n    }, [afterClose, afterOpenChange]);\n\n    const handleAnimationComplete = useCallback(() => {\n      if (open) afterOpenChange?.(true);\n    }, [open, afterOpenChange]);\n\n    const handleDragStart = useCallback(\n      (e: PointerEvent) => {\n        if (draggable && !isFullscreen) {\n          dragControls.start(e);\n          setIsDragging(true);\n        }\n      },\n      [draggable, dragControls, isFullscreen],\n    );\n\n    const handleDragEnd = useCallback(() => {\n      setIsDragging(false);\n    }, []);\n\n    const handleOk = useCallback(\n      (e: MouseEvent<HTMLButtonElement>) => {\n        onOk?.(e);\n      },\n      [onOk],\n    );\n\n    const handleCancel = useCallback(\n      (e: MouseEvent<HTMLButtonElement>) => {\n        onCancel?.(e);\n      },\n      [onCancel],\n    );\n\n    const footerNode = useMemo(() => {\n      if (footer === false || footer === null) return null;\n      const cancelBtnNode = (\n        <CancelBtn\n          cancelButtonProps={cancelButtonProps}\n          cancelText={cancelText}\n          onCancel={handleCancel}\n        />\n      );\n      const okBtnNode = (\n        <OkBtn\n          confirmLoading={confirmLoading}\n          okButtonProps={okButtonProps}\n          okText={okText}\n          onOk={handleOk}\n        />\n      );\n      const defaultFooter = (\n        <>\n          {cancelBtnNode}\n          {okBtnNode}\n        </>\n      );\n\n      if (typeof footer === 'function') {\n        const BoundCancelBtn: React.FC = () => cancelBtnNode;\n        const BoundOkBtn: React.FC = () => okBtnNode;\n        return footer(defaultFooter, { CancelBtn: BoundCancelBtn, OkBtn: BoundOkBtn });\n      }\n\n      return footer ?? defaultFooter;\n    }, [\n      footer,\n      cancelButtonProps,\n      cancelText,\n      handleCancel,\n      confirmLoading,\n      okButtonProps,\n      okText,\n      handleOk,\n    ]);\n\n    const container = getContainer === false ? undefined : (getContainer ?? undefined);\n    const backdropZIndex = zIndex ? { zIndex } : undefined;\n    const popupZIndex = zIndex ? { zIndex: (zIndex || 1000) + 1 } : undefined;\n\n    const shouldDrag = draggable && !isFullscreen;\n    const dragProps = shouldDrag\n      ? {\n          drag: true as const,\n          dragConstraints: constraintsRef,\n          dragControls,\n          dragElastic: 0,\n          dragListener: false,\n          dragMomentum: false,\n          whileDrag: { cursor: 'grabbing' as const },\n        }\n      : {};\n\n    const showTitle = title !== undefined && title !== false && title !== null;\n    const showHeader = showTitle || closable || allowFullscreen;\n\n    const hasHeight = height !== undefined;\n    const panelStyle: React.CSSProperties = {\n      ...(hasHeight && !isFullscreen ? { height } : {}),\n      ...style,\n    };\n\n    return (\n      <ModalRoot\n        open={open ?? false}\n        onExitComplete={handleExitComplete}\n        onOpenChange={handleOpenChange}\n      >\n        <ModalPortal container={container}>\n          {mask && (\n            <ModalBackdrop\n              className={classNames?.mask}\n              style={{ ...backdropZIndex, ...semanticStyles?.mask }}\n            />\n          )}\n          <ModalPopup\n            className={classNames?.wrapper}\n            popupStyle={{ ...popupZIndex, ...semanticStyles?.wrapper }}\n            ref={constraintsRef}\n            style={panelStyle}\n            width={isFullscreen ? undefined : width}\n            motionProps={{\n              ...dragProps,\n              onAnimationComplete: handleAnimationComplete,\n            }}\n            panelClassName={cx(\n              className,\n              isFullscreen && styles.fullscreenPopupInner,\n              isDenying && styles.denyAnimation,\n            )}\n          >\n            {showHeader && (\n              <ModalHeader\n                className={cx(classNames?.header, shouldDrag && styles.headerDraggable)}\n                style={{\n                  ...(isDragging ? { cursor: 'grabbing' } : {}),\n                  ...semanticStyles?.header,\n                }}\n                onPointerCancel={handleDragEnd}\n                onPointerDown={handleDragStart}\n                onPointerUp={handleDragEnd}\n              >\n                {showTitle ? (\n                  <ModalTitle className={classNames?.title} style={semanticStyles?.title}>\n                    {title}\n                  </ModalTitle>\n                ) : (\n                  <span />\n                )}\n                <div className={styles.headerActions} onPointerDown={stopPropagation}>\n                  {allowFullscreen && (\n                    <button\n                      aria-label={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}\n                      className={styles.fullscreenToggle}\n                      type=\"button\"\n                      onClick={() => setIsFullscreen((prev) => !prev)}\n                    >\n                      {isFullscreen ? <Minimize2 size={14} /> : <Maximize2 size={14} />}\n                    </button>\n                  )}\n                  {closable && (\n                    <button\n                      aria-label=\"Close\"\n                      className={styles.closeInline}\n                      type=\"button\"\n                      onClick={handleCancel}\n                    >\n                      {closeIcon ?? <X size={18} />}\n                    </button>\n                  )}\n                </div>\n              </ModalHeader>\n            )}\n            <ModalContent\n              className={classNames?.body}\n              style={{\n                ...(hasHeight || isFullscreen ? { flex: 1 } : {}),\n                ...semanticStyles?.body,\n              }}\n            >\n              {loading ? (\n                <div\n                  style={{\n                    display: 'flex',\n                    justifyContent: 'center',\n                    padding: '32px 0',\n                  }}\n                >\n                  <span className={styles.loadingSpinner} style={{ height: 24, width: 24 }} />\n                </div>\n              ) : (\n                children\n              )}\n            </ModalContent>\n            {footerNode !== null && (\n              <ModalFooter className={classNames?.footer} style={semanticStyles?.footer}>\n                {footerNode}\n              </ModalFooter>\n            )}\n          </ModalPopup>\n        </ModalPortal>\n      </ModalRoot>\n    );\n  },\n);\n\nModal.displayName = 'Modal';\n\nexport default Modal;\n"],"mappings":"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"}