import React, { useContext, useRef, useState } from "react" import PropTypes from "prop-types" import classNames from "classnames" import Icon, { IconNames } from "../icon" import ICON_INTENTS from "./iconIntents" import { ConfigContext, getComputedSize } from "../config-provider" import "./style" const prefix = "adui-alert" export interface IAlertProps { [key: string]: any /** * 关闭后的 handler,参数 node */ afterClose?: () => void /** * 附加类名 */ className?: string /** * 是否可关闭 */ closable?: boolean /** * 关闭文字 */ closeText?: React.ReactNode /** * 是否展开,内部驱动 */ defaultExpanded?: boolean | null /** * 展开内容 */ expandContent?: React.ReactNode /** * 是否展开,外部控制 */ expanded?: boolean | null /** * 设置图标 */ icon?: IconNames | null /** * 设置类型 */ intent?: "normal" | "primary" | "success" | "info" | "warning" | "danger" /** * 关闭时的 handler */ onClose?: () => void /** * 展开状态变化时的 handler,参数为 bool */ onExpandChange?: (expanded: boolean) => void /** * 设置尺寸 */ size?: "mini" | "small" | "medium" /** * 提醒内容 */ text: React.ReactNode /** * 设置主题 */ theme?: null | "light" /** * 提醒标题 */ title?: React.ReactNode } /** * 提醒是内容的常态、即时性提示,展示需要用户即时关注的信息。 * 与对话框 Dialog 或气泡提示 Popover 不同,提醒 Alert 通常常驻在页面中,与页面内容有更强的关联性。 */ const Alert: React.FC = ({ afterClose, className, closable, closeText, defaultExpanded, expandContent, expanded: expandedProp, icon, intent, onClose, onExpandChange, size, text, title, theme, ...otherProps }: IAlertProps) => { const ref = useRef(null) const [expanded, setExpanded] = useState( expandedProp !== null && expandedProp !== undefined ? expandedProp : !!defaultExpanded ) const [closing, setClosing] = useState(false) // 相当于生命周期 getDerivedStateFromProps if ( expandedProp !== null && expandedProp !== undefined && expanded !== expandedProp ) { setExpanded(expandedProp) } const { size: sizeContext } = useContext(ConfigContext) const computedSize = getComputedSize(size, sizeContext) const handleClose = () => { if (onClose) { onClose() } if (ref.current) { ref.current.style.height = `${ref.current.offsetHeight}px` setTimeout(() => { if (ref.current) { ref.current.style.marginTop = "0" ref.current.style.marginBottom = "0" ref.current.style.paddingTop = "0" ref.current.style.paddingBottom = "0" ref.current.style.height = "0" ref.current.style.opacity = "0" } setTimeout(() => { setClosing(true) if (afterClose) { afterClose() } }, 300) }, 0) } } const handleExpand = () => { if (expandedProp === null) { setExpanded(!expanded) } if (onExpandChange) { onExpandChange(!expanded) } } const classSet = classNames( className, `${prefix}-base`, `${prefix}-${intent}`, `${prefix}-${computedSize}`, { [`${prefix}-${theme}`]: theme, } ) if (closing) { return null } return (
{icon !== null && ( )}
{!!title &&
{title}
}
{text}
{!!expandContent && expanded && (
{expandContent}
)}
{closable && (
{closeText ? (
{closeText}
) : ( )}
)} {!!expandContent && (
{expanded ? "收起" : "展开"}
)}
) } Alert.displayName = "Alert" Alert.propTypes = { /** * 关闭后的 handler,参数 node */ afterClose: PropTypes.func, /** * 附加类名 */ className: PropTypes.string, /** * 是否可关闭 */ closable: PropTypes.bool, /** * 关闭文字 */ closeText: PropTypes.node, /** * 是否展开,内部驱动 */ defaultExpanded: PropTypes.bool, /** * 展开内容 */ expandContent: PropTypes.node, /** * 是否展开,外部控制 */ expanded: PropTypes.bool, /** * 设置图标 */ icon: PropTypes.any, /** * 设置类型 */ intent: PropTypes.oneOf([ "normal", "primary", "success", "info", "warning", "danger", ]), /** * 关闭时的 handler,参数 node */ onClose: PropTypes.func, /** * 展开状态变化时的 handler,参数为 bool */ onExpandChange: PropTypes.func, /** * 设置尺寸 */ size: PropTypes.oneOf(["mini", "small", "medium"]), /** * 提醒内容 */ text: PropTypes.node.isRequired, /** * 设置主题 */ theme: PropTypes.oneOf([null, "light"]), /** * 提醒标题 */ title: PropTypes.node, } Alert.defaultProps = { afterClose: () => {}, className: undefined, closable: false, closeText: null, defaultExpanded: null, expandContent: null, expanded: null, icon: undefined, intent: "normal", onClose: () => {}, onExpandChange: () => {}, size: "small", theme: null, title: null, } export default Alert