11import { clsx } from 'clsx' ;
22import { useComposeRef } from '@rc-component/util/lib/ref' ;
3+ import { useLockFocus } from '@rc-component/util/lib/Dom/focus' ;
34import React , { useMemo , useRef } from 'react' ;
45import { RefContext } from '../../context' ;
56import type { IDialogPropTypes } from '../../IDialogPropTypes' ;
67import MemoChildren from './MemoChildren' ;
78import pickAttrs from '@rc-component/util/lib/pickAttrs' ;
89
9- const sentinelStyle : React . CSSProperties = {
10- width : 0 ,
11- height : 0 ,
12- overflow : 'hidden' ,
13- outline : 'none' ,
14- } ;
15-
16- const entityStyle : React . CSSProperties = {
17- outline : 'none' ,
18- } ;
19-
2010export interface PanelProps extends Omit < IDialogPropTypes , 'getOpenCount' > {
2111 prefixCls : string ;
2212 ariaId ?: string ;
2313 onMouseDown ?: React . MouseEventHandler ;
2414 onMouseUp ?: React . MouseEventHandler ;
2515 holderRef ?: React . Ref < HTMLDivElement > ;
16+ /** Used for focus lock. When true and open, focus will lock into the panel */
17+ isFixedPos ?: boolean ;
2618}
2719
2820export type PanelRef = {
2921 focus : ( ) => void ;
30- changeActive : ( next : boolean ) => void ;
3122} ;
3223
3324const Panel = React . forwardRef < PanelRef , PanelProps > ( ( props , ref ) => {
@@ -54,27 +45,23 @@ const Panel = React.forwardRef<PanelRef, PanelProps>((props, ref) => {
5445 height,
5546 classNames : modalClassNames ,
5647 styles : modalStyles ,
48+ isFixedPos,
49+ focusTrap,
5750 } = props ;
5851
5952 // ================================= Refs =================================
6053 const { panel : panelRef } = React . useContext ( RefContext ) ;
54+ const internalRef = useRef < HTMLDivElement > ( null ) ;
55+ const mergedRef = useComposeRef ( holderRef , panelRef , internalRef ) ;
6156
62- const mergedRef = useComposeRef ( holderRef , panelRef ) ;
63-
64- const sentinelStartRef = useRef < HTMLDivElement > ( null ) ;
65- const sentinelEndRef = useRef < HTMLDivElement > ( null ) ;
57+ const [ ignoreElement ] = useLockFocus (
58+ visible && isFixedPos && focusTrap !== false ,
59+ ( ) => internalRef . current ,
60+ ) ;
6661
6762 React . useImperativeHandle ( ref , ( ) => ( {
6863 focus : ( ) => {
69- sentinelStartRef . current ?. focus ( { preventScroll : true } ) ;
70- } ,
71- changeActive : ( next ) => {
72- const { activeElement } = document ;
73- if ( next && activeElement === sentinelEndRef . current ) {
74- sentinelStartRef . current . focus ( { preventScroll : true } ) ;
75- } else if ( ! next && activeElement === sentinelStartRef . current ) {
76- sentinelEndRef . current . focus ( { preventScroll : true } ) ;
77- }
64+ internalRef . current ?. focus ( { preventScroll : true } ) ;
7865 } ,
7966 } ) ) ;
8067
@@ -168,13 +155,14 @@ const Panel = React.forwardRef<PanelRef, PanelProps>((props, ref) => {
168155 className = { clsx ( prefixCls , className ) }
169156 onMouseDown = { onMouseDown }
170157 onMouseUp = { onMouseUp }
158+ tabIndex = { - 1 }
159+ onFocus = { ( e ) => {
160+ ignoreElement ( e . target ) ;
161+ } }
171162 >
172- < div ref = { sentinelStartRef } tabIndex = { 0 } style = { entityStyle } >
173- < MemoChildren shouldUpdate = { visible || forceRender } >
174- { modalRender ? modalRender ( content ) : content }
175- </ MemoChildren >
176- </ div >
177- < div tabIndex = { 0 } ref = { sentinelEndRef } style = { sentinelStyle } />
163+ < MemoChildren shouldUpdate = { visible || forceRender } >
164+ { modalRender ? modalRender ( content ) : content }
165+ </ MemoChildren >
178166 </ div >
179167 ) ;
180168} ) ;
0 commit comments