1
1
import classNames from 'classnames' ;
2
2
import CSSMotion from 'rc-motion' ;
3
3
import KeyCode from '@rc-component/util/lib/KeyCode' ;
4
- import React from 'react' ;
4
+ import React , { useMemo } from 'react' ;
5
5
import type { CollapsePanelProps } from './interface' ;
6
6
import PanelContent from './PanelContent' ;
7
7
@@ -32,6 +32,15 @@ const CollapsePanel = React.forwardRef<HTMLDetailsElement, CollapsePanelProps>((
32
32
33
33
const ifExtraExist = extra !== null && extra !== undefined && typeof extra !== 'boolean' ;
34
34
35
+ // ? 用于判断浏览器是否支持::details-content 否则使用CSSMotion
36
+ const supportsDetailsContentSelector = useMemo (
37
+ ( ) =>
38
+ typeof document !== 'undefined' && typeof document . createElement === 'function'
39
+ ? CSS . supports ( 'selector(details::details-content)' )
40
+ : false ,
41
+ [ ] ,
42
+ ) ;
43
+
35
44
const collapsibleProps = {
36
45
onClick : ( e : React . MouseEvent ) => {
37
46
onItemClick ?.( panelKey ) ;
@@ -68,6 +77,8 @@ const CollapsePanel = React.forwardRef<HTMLDetailsElement, CollapsePanelProps>((
68
77
[ `${ prefixCls } -item-disabled` ] : disabled ,
69
78
} ,
70
79
className ,
80
+ // ? 修改为details实现后动画是作用在details元素上 需要将motionName设置在details上
81
+ supportsDetailsContentSelector && openMotion ?. motionName ,
71
82
) ;
72
83
73
84
const headerClassName = classNames (
@@ -87,6 +98,68 @@ const CollapsePanel = React.forwardRef<HTMLDetailsElement, CollapsePanelProps>((
87
98
} ;
88
99
89
100
// ======================== Render ========================
101
+
102
+ const leavedClassName = `${ prefixCls } -panel-hidden` ;
103
+ const createPanelContent = (
104
+ props : Partial < {
105
+ className : string ;
106
+ style : React . CSSProperties ;
107
+ motionRef : ( node : HTMLDivElement ) => void ;
108
+ } > ,
109
+ ) => {
110
+ const { className, style, motionRef } = props ;
111
+
112
+ return (
113
+ < PanelContent
114
+ ref = { motionRef }
115
+ prefixCls = { prefixCls }
116
+ className = { className }
117
+ classNames = { customizeClassNames }
118
+ style = { style }
119
+ styles = { styles }
120
+ isActive = { isActive }
121
+ forceRender = { forceRender }
122
+ role = { accordion ? 'tabpanel' : void 0 }
123
+ >
124
+ { children }
125
+ </ PanelContent >
126
+ ) ;
127
+ } ;
128
+ let detailsChildren = (
129
+ < CSSMotion
130
+ visible = { isActive }
131
+ leavedClassName = { leavedClassName }
132
+ { ...openMotion }
133
+ forceRender = { forceRender }
134
+ removeOnLeave = { destroyInactivePanel }
135
+ >
136
+ { ( { className, style } , motionRef ) =>
137
+ createPanelContent ( {
138
+ className,
139
+ style,
140
+ motionRef,
141
+ } )
142
+ }
143
+ </ CSSMotion >
144
+ ) ;
145
+
146
+ // ? 模拟CSSMotion子元素生命周期管理
147
+ if ( supportsDetailsContentSelector ) {
148
+ if ( isActive ) {
149
+ detailsChildren = createPanelContent ( { } ) ;
150
+ } else if ( ! destroyInactivePanel && leavedClassName ) {
151
+ detailsChildren = createPanelContent ( {
152
+ className : leavedClassName ,
153
+ } ) ;
154
+ } else if ( forceRender || ( ! destroyInactivePanel && ! leavedClassName ) ) {
155
+ detailsChildren = createPanelContent ( {
156
+ style : { display : 'none' } ,
157
+ } ) ;
158
+ } else {
159
+ detailsChildren = null ;
160
+ }
161
+ }
162
+
90
163
return (
91
164
< details { ...resetProps } ref = { ref } className = { collapsePanelClassNames } open = { isActive } >
92
165
< summary { ...headerProps } >
@@ -100,31 +173,7 @@ const CollapsePanel = React.forwardRef<HTMLDetailsElement, CollapsePanelProps>((
100
173
</ span >
101
174
{ ifExtraExist && < div className = { `${ prefixCls } -extra` } > { extra } </ div > }
102
175
</ summary >
103
- < CSSMotion
104
- visible = { isActive }
105
- leavedClassName = { `${ prefixCls } -panel-hidden` }
106
- { ...openMotion }
107
- forceRender = { forceRender }
108
- removeOnLeave = { destroyInactivePanel }
109
- >
110
- { ( { className : motionClassName , style : motionStyle } , motionRef ) => {
111
- return (
112
- < PanelContent
113
- ref = { motionRef }
114
- prefixCls = { prefixCls }
115
- className = { motionClassName }
116
- classNames = { customizeClassNames }
117
- style = { motionStyle }
118
- styles = { styles }
119
- isActive = { isActive }
120
- forceRender = { forceRender }
121
- role = { accordion ? 'tabpanel' : void 0 }
122
- >
123
- { children }
124
- </ PanelContent >
125
- ) ;
126
- } }
127
- </ CSSMotion >
176
+ { detailsChildren }
128
177
</ details >
129
178
) ;
130
179
} ) ;
0 commit comments