11import classNames from 'classnames' ;
22import CSSMotion from 'rc-motion' ;
33import KeyCode from '@rc-component/util/lib/KeyCode' ;
4- import React from 'react' ;
4+ import React , { useMemo } from 'react' ;
55import type { CollapsePanelProps } from './interface' ;
66import PanelContent from './PanelContent' ;
77
@@ -32,6 +32,15 @@ const CollapsePanel = React.forwardRef<HTMLDetailsElement, CollapsePanelProps>((
3232
3333 const ifExtraExist = extra !== null && extra !== undefined && typeof extra !== 'boolean' ;
3434
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+
3544 const collapsibleProps = {
3645 onClick : ( e : React . MouseEvent ) => {
3746 onItemClick ?.( panelKey ) ;
@@ -68,6 +77,8 @@ const CollapsePanel = React.forwardRef<HTMLDetailsElement, CollapsePanelProps>((
6877 [ `${ prefixCls } -item-disabled` ] : disabled ,
6978 } ,
7079 className ,
80+ // ? 修改为details实现后动画是作用在details元素上 需要将motionName设置在details上
81+ supportsDetailsContentSelector && openMotion ?. motionName ,
7182 ) ;
7283
7384 const headerClassName = classNames (
@@ -87,6 +98,68 @@ const CollapsePanel = React.forwardRef<HTMLDetailsElement, CollapsePanelProps>((
8798 } ;
8899
89100 // ======================== 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+
90163 return (
91164 < details { ...resetProps } ref = { ref } className = { collapsePanelClassNames } open = { isActive } >
92165 < summary { ...headerProps } >
@@ -100,31 +173,7 @@ const CollapsePanel = React.forwardRef<HTMLDetailsElement, CollapsePanelProps>((
100173 </ span >
101174 { ifExtraExist && < div className = { `${ prefixCls } -extra` } > { extra } </ div > }
102175 </ 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 }
128177 </ details >
129178 ) ;
130179} ) ;
0 commit comments