1
- import { inject , cloneVNode , defineComponent } from 'vue' ;
1
+ import { inject , cloneVNode , defineComponent , ref , ExtractPropTypes } from 'vue' ;
2
2
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined' ;
3
3
import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined' ;
4
4
import ExclamationCircleOutlined from '@ant-design/icons-vue/ExclamationCircleOutlined' ;
@@ -9,15 +9,18 @@ import ExclamationCircleFilled from '@ant-design/icons-vue/ExclamationCircleFill
9
9
import InfoCircleFilled from '@ant-design/icons-vue/InfoCircleFilled' ;
10
10
import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled' ;
11
11
import classNames from '../_util/classNames' ;
12
- import BaseMixin from '../_util/BaseMixin' ;
13
12
import PropTypes from '../_util/vue-types' ;
14
13
import { getTransitionProps , Transition } from '../_util/transition' ;
15
- import { getComponent , isValidElement , findDOMNode } from '../_util/props-util' ;
14
+ import { isValidElement } from '../_util/props-util' ;
16
15
import { defaultConfigProvider } from '../config-provider' ;
17
16
import { tuple , withInstall } from '../_util/type' ;
18
17
19
18
function noop ( ) { }
20
19
20
+ function getDefaultSlot ( slots : Record < string , any > , props : Record < string , any > , prop : string ) {
21
+ return slots [ prop ] ?.( ) ?? props [ prop ] ;
22
+ }
23
+
21
24
const iconMapFilled = {
22
25
success : CheckCircleFilled ,
23
26
info : InfoCircleFilled ,
@@ -32,11 +35,15 @@ const iconMapOutlined = {
32
35
warning : ExclamationCircleOutlined ,
33
36
} ;
34
37
35
- export const AlertProps = {
38
+ const AlertTypes = tuple ( 'success' , 'info' , 'warning' , 'error' ) ;
39
+
40
+ export type AlertType = typeof AlertTypes [ number ] ;
41
+
42
+ const alertProps = ( ) => ( {
36
43
/**
37
44
* Type of Alert styles, options: `success`, `info`, `warning`, `error`
38
45
*/
39
- type : PropTypes . oneOf ( tuple ( 'success' , 'info' , 'warning' , 'error' ) ) ,
46
+ type : PropTypes . oneOf ( AlertTypes ) ,
40
47
/** Whether Alert can be closed */
41
48
closable : PropTypes . looseBool ,
42
49
/** Close text to show */
@@ -55,114 +62,114 @@ export const AlertProps = {
55
62
banner : PropTypes . looseBool ,
56
63
icon : PropTypes . VNodeChild ,
57
64
onClose : PropTypes . VNodeChild ,
58
- } ;
65
+ } ) ;
66
+
67
+ export type AlertProps = Partial < ExtractPropTypes < ReturnType < typeof alertProps > > > ;
59
68
60
69
const Alert = defineComponent ( {
61
70
name : 'AAlert' ,
62
- mixins : [ BaseMixin ] ,
71
+ props : alertProps ( ) ,
63
72
inheritAttrs : false ,
64
- props : AlertProps ,
65
73
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 ) => {
79
81
e . preventDefault ( ) ;
80
- const dom = findDOMNode ( this ) ;
82
+
83
+ const dom = alertNode . value ;
84
+
81
85
dom . style . height = `${ dom . offsetHeight } px` ;
82
86
// Magic code
83
87
// 重复一次后才能正确设置 height
84
88
dom . style . height = `${ dom . offsetHeight } px` ;
85
89
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 ,
95
131
} ) ;
96
- this . afterClose ( ) ;
97
- } ,
98
- } ,
99
132
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
+ } ;
166
173
} ,
167
174
} ) ;
168
175
0 commit comments