1- import { inject , cloneVNode , defineComponent } from 'vue' ;
1+ import { inject , cloneVNode , defineComponent , ref , ExtractPropTypes } from 'vue' ;
22import CloseOutlined from '@ant-design/icons-vue/CloseOutlined' ;
33import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined' ;
44import ExclamationCircleOutlined from '@ant-design/icons-vue/ExclamationCircleOutlined' ;
@@ -9,15 +9,18 @@ import ExclamationCircleFilled from '@ant-design/icons-vue/ExclamationCircleFill
99import InfoCircleFilled from '@ant-design/icons-vue/InfoCircleFilled' ;
1010import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled' ;
1111import classNames from '../_util/classNames' ;
12- import BaseMixin from '../_util/BaseMixin' ;
1312import PropTypes from '../_util/vue-types' ;
1413import { getTransitionProps , Transition } from '../_util/transition' ;
15- import { getComponent , isValidElement , findDOMNode } from '../_util/props-util' ;
14+ import { isValidElement } from '../_util/props-util' ;
1615import { defaultConfigProvider } from '../config-provider' ;
1716import { tuple , withInstall } from '../_util/type' ;
1817
1918function noop ( ) { }
2019
20+ function getDefaultSlot ( slots : Record < string , any > , props : Record < string , any > , prop : string ) {
21+ return slots [ prop ] ?.( ) ?? props [ prop ] ;
22+ }
23+
2124const iconMapFilled = {
2225 success : CheckCircleFilled ,
2326 info : InfoCircleFilled ,
@@ -32,11 +35,15 @@ const iconMapOutlined = {
3235 warning : ExclamationCircleOutlined ,
3336} ;
3437
35- export const AlertProps = {
38+ const AlertTypes = tuple ( 'success' , 'info' , 'warning' , 'error' ) ;
39+
40+ export type AlertType = typeof AlertTypes [ number ] ;
41+
42+ const alertProps = ( ) => ( {
3643 /**
3744 * Type of Alert styles, options: `success`, `info`, `warning`, `error`
3845 */
39- type : PropTypes . oneOf ( tuple ( 'success' , 'info' , 'warning' , 'error' ) ) ,
46+ type : PropTypes . oneOf ( AlertTypes ) ,
4047 /** Whether Alert can be closed */
4148 closable : PropTypes . looseBool ,
4249 /** Close text to show */
@@ -55,114 +62,114 @@ export const AlertProps = {
5562 banner : PropTypes . looseBool ,
5663 icon : PropTypes . VNodeChild ,
5764 onClose : PropTypes . VNodeChild ,
58- } ;
65+ } ) ;
66+
67+ export type AlertProps = Partial < ExtractPropTypes < ReturnType < typeof alertProps > > > ;
5968
6069const Alert = defineComponent ( {
6170 name : 'AAlert' ,
62- mixins : [ BaseMixin ] ,
71+ props : alertProps ( ) ,
6372 inheritAttrs : false ,
64- props : AlertProps ,
6573 emits : [ 'close' ] ,
66- setup ( ) {
67- return {
68- configProvider : inject ( 'configProvider' , defaultConfigProvider ) ,
69- } ;
70- } ,
71- data ( ) {
72- return {
73- closing : false ,
74- closed : false ,
75- } ;
76- } ,
77- methods : {
78- handleClose ( e : Event ) {
74+ setup ( props , { slots, emit, attrs } ) {
75+ const configProvider = inject ( 'configProvider' , defaultConfigProvider ) ;
76+ const closing = ref ( false ) ;
77+ const closed = ref ( false ) ;
78+ const alertNode = ref ( ) ;
79+
80+ const handleClose = ( e : MouseEvent ) => {
7981 e . preventDefault ( ) ;
80- const dom = findDOMNode ( this ) ;
82+
83+ const dom = alertNode . value ;
84+
8185 dom . style . height = `${ dom . offsetHeight } px` ;
8286 // Magic code
8387 // 重复一次后才能正确设置 height
8488 dom . style . height = `${ dom . offsetHeight } px` ;
8589
86- this . setState ( {
87- closing : true ,
88- } ) ;
89- this . $emit ( 'close' , e ) ;
90- } ,
91- animationEnd ( ) {
92- this . setState ( {
93- closing : false ,
94- closed : true ,
90+ closing . value = true ;
91+ emit ( 'close' , e ) ;
92+ } ;
93+
94+ const animationEnd = ( ) => {
95+ closing . value = false ;
96+ closed . value = true ;
97+ props . afterClose ?.( ) ;
98+ } ;
99+
100+ return ( ) => {
101+ const { prefixCls : customizePrefixCls , banner } = props ;
102+ const { getPrefixCls } = configProvider ;
103+ const prefixCls = getPrefixCls ( 'alert' , customizePrefixCls ) ;
104+
105+ let { closable, type, showIcon } = props ;
106+
107+ const closeText = getDefaultSlot ( slots , props , 'closeText' ) ;
108+ const description = getDefaultSlot ( slots , props , 'description' ) ;
109+ const message = getDefaultSlot ( slots , props , 'message' ) ;
110+ const icon = getDefaultSlot ( slots , props , 'icon' ) ;
111+
112+ // banner模式默认有 Icon
113+ showIcon = banner && showIcon === undefined ? true : showIcon ;
114+ // banner模式默认为警告
115+ type = banner && type === undefined ? 'warning' : type || 'info' ;
116+
117+ const IconType = ( description ? iconMapOutlined : iconMapFilled ) [ type ] || null ;
118+
119+ // closeable when closeText is assigned
120+ if ( closeText ) {
121+ closable = true ;
122+ }
123+
124+ const alertCls = classNames ( prefixCls , {
125+ [ `${ prefixCls } -${ type } ` ] : true ,
126+ [ `${ prefixCls } -closing` ] : closing . value ,
127+ [ `${ prefixCls } -with-description` ] : ! ! description ,
128+ [ `${ prefixCls } -no-icon` ] : ! showIcon ,
129+ [ `${ prefixCls } -banner` ] : ! ! banner ,
130+ [ `${ prefixCls } -closable` ] : closable ,
95131 } ) ;
96- this . afterClose ( ) ;
97- } ,
98- } ,
99132
100- render ( ) {
101- const { prefixCls : customizePrefixCls , banner, closing, closed, $attrs } = this ;
102- const { getPrefixCls } = this . configProvider ;
103- const prefixCls = getPrefixCls ( 'alert' , customizePrefixCls ) ;
104-
105- let { closable, type, showIcon } = this ;
106- const closeText = getComponent ( this , 'closeText' ) ;
107- const description = getComponent ( this , 'description' ) ;
108- const message = getComponent ( this , 'message' ) ;
109- const icon = getComponent ( this , 'icon' ) ;
110- // banner模式默认有 Icon
111- showIcon = banner && showIcon === undefined ? true : showIcon ;
112- // banner模式默认为警告
113- type = banner && type === undefined ? 'warning' : type || 'info' ;
114-
115- const IconType = ( description ? iconMapOutlined : iconMapFilled ) [ type ] || null ;
116-
117- // closeable when closeText is assigned
118- if ( closeText ) {
119- closable = true ;
120- }
121-
122- const alertCls = classNames ( prefixCls , {
123- [ `${ prefixCls } -${ type } ` ] : true ,
124- [ `${ prefixCls } -closing` ] : closing ,
125- [ `${ prefixCls } -with-description` ] : ! ! description ,
126- [ `${ prefixCls } -no-icon` ] : ! showIcon ,
127- [ `${ prefixCls } -banner` ] : ! ! banner ,
128- [ `${ prefixCls } -closable` ] : closable ,
129- } ) ;
130-
131- const closeIcon = closable ? (
132- < button
133- type = "button"
134- onClick = { this . handleClose }
135- class = { `${ prefixCls } -close-icon` }
136- tabindex = { 0 }
137- >
138- { closeText ? < span class = { `${ prefixCls } -close-text` } > { closeText } </ span > : < CloseOutlined /> }
139- </ button >
140- ) : null ;
141-
142- const iconNode = ( icon &&
143- ( isValidElement ( icon ) ? (
144- cloneVNode ( icon , {
145- class : `${ prefixCls } -icon` ,
146- } )
147- ) : (
148- < span class = { `${ prefixCls } -icon` } > { icon } </ span >
149- ) ) ) || < IconType class = { `${ prefixCls } -icon` } /> ;
150- // h(iconType, { class: `${prefixCls}-icon` });
151-
152- const transitionProps = getTransitionProps ( `${ prefixCls } -slide-up` , {
153- appear : false ,
154- onAfterLeave : this . animationEnd ,
155- } ) ;
156- return closed ? null : (
157- < Transition { ...transitionProps } >
158- < div { ...$attrs } v-show = { ! closing } class = { [ $attrs . class , alertCls ] } data-show = { ! closing } >
159- { showIcon ? iconNode : null }
160- < span class = { `${ prefixCls } -message` } > { message } </ span >
161- < span class = { `${ prefixCls } -description` } > { description } </ span >
162- { closeIcon }
163- </ div >
164- </ Transition >
165- ) ;
133+ const closeIcon = closable ? (
134+ < button type = "button" onClick = { handleClose } class = { `${ prefixCls } -close-icon` } tabindex = { 0 } >
135+ { closeText ? (
136+ < span class = { `${ prefixCls } -close-text` } > { closeText } </ span >
137+ ) : (
138+ < CloseOutlined />
139+ ) }
140+ </ button >
141+ ) : null ;
142+
143+ const iconNode = ( icon &&
144+ ( isValidElement ( icon ) ? (
145+ cloneVNode ( icon , {
146+ class : `${ prefixCls } -icon` ,
147+ } )
148+ ) : (
149+ < span class = { `${ prefixCls } -icon` } > { icon } </ span >
150+ ) ) ) || < IconType class = { `${ prefixCls } -icon` } /> ;
151+
152+ const transitionProps = getTransitionProps ( `${ prefixCls } -slide-up` , {
153+ appear : false ,
154+ onAfterLeave : animationEnd ,
155+ } ) ;
156+ return closed . value ? null : (
157+ < Transition { ...transitionProps } >
158+ < div
159+ { ...attrs }
160+ v-show = { ! closing . value }
161+ class = { [ attrs . class , alertCls ] }
162+ data-show = { ! closing . value }
163+ ref = { alertNode }
164+ >
165+ { showIcon ? iconNode : null }
166+ < span class = { `${ prefixCls } -message` } > { message } </ span >
167+ < span class = { `${ prefixCls } -description` } > { description } </ span >
168+ { closeIcon }
169+ </ div >
170+ </ Transition >
171+ ) ;
172+ } ;
166173 } ,
167174} ) ;
168175
0 commit comments