@@ -7,7 +7,7 @@ import type {
77 ReactNode ,
88 Ref ,
99} from 'react' ;
10- import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
10+ import React , { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
1111
1212import { createRovingFocusKeyDownHandler } from '../../a11y/a11yUtils' ;
1313import {
@@ -18,6 +18,11 @@ import {
1818const DEFAULT_DROPDOWN_ITEM_SELECTOR =
1919 '[role="option"]:not(:disabled), [role="menuitem"]:not(:disabled), button:not(:disabled), a:not(:disabled)' ;
2020
21+ const isEditableTarget = ( target : EventTarget | null ) =>
22+ target instanceof HTMLInputElement ||
23+ target instanceof HTMLTextAreaElement ||
24+ ( target instanceof HTMLElement && target . isContentEditable ) ;
25+
2126type DropdownContextValue = {
2227 close ( ) : void ;
2328} ;
@@ -47,6 +52,7 @@ export type DropdownTriggerProps = Pick<
4752
4853export type DropdownProps = PropsWithChildren < {
4954 className ?: string ;
55+ matchReferenceWidth ?: boolean ;
5056 onClose ?: ( ) => void ;
5157 onOpen ?: ( ) => void ;
5258 placement ?: PopperLikePlacement ;
@@ -58,6 +64,7 @@ export type DropdownProps = PropsWithChildren<{
5864export const Dropdown = ( {
5965 children,
6066 className,
67+ matchReferenceWidth = false ,
6168 onClose,
6269 onOpen,
6370 placement = 'bottom' ,
@@ -142,18 +149,32 @@ export const Dropdown = ({
142149 [ ] ,
143150 ) ;
144151
152+ const escapeConsumedRef = useRef ( false ) ;
153+
145154 const handleKeyDown = useCallback (
146155 ( event : React . KeyboardEvent < HTMLElement > ) => {
147156 if ( event . key === 'Escape' ) {
148157 event . preventDefault ( ) ;
158+ event . stopPropagation ( ) ;
159+ escapeConsumedRef . current = true ;
149160 close ( ) ;
150161 return ;
151162 }
163+ if ( isEditableTarget ( event . target ) ) {
164+ return ;
165+ }
152166 rovingFocusKeyDownHandler ( event ) ;
153167 } ,
154168 [ close , rovingFocusKeyDownHandler ] ,
155169 ) ;
156170
171+ const suppressEscapeKeyUp = useCallback ( ( event : React . KeyboardEvent < HTMLElement > ) => {
172+ if ( event . key === 'Escape' && escapeConsumedRef . current ) {
173+ escapeConsumedRef . current = false ;
174+ event . stopPropagation ( ) ;
175+ }
176+ } , [ ] ) ;
177+
157178 const DropdownTriggerComponent = TriggerComponent ;
158179
159180 const trigger = DropdownTriggerComponent ? (
@@ -173,10 +194,14 @@ export const Dropdown = ({
173194 className = { clsx ( 'str-chat__dropdown__items' , className ) }
174195 onClick = { close }
175196 onKeyDown = { handleKeyDown }
197+ onKeyUpCapture = { suppressEscapeKeyUp }
176198 ref = { setFloatingElement }
177199 role = 'menu'
178200 style = { {
179201 left : x ?? 0 ,
202+ minWidth : matchReferenceWidth
203+ ? resolvedReferenceElement . getBoundingClientRect ( ) . width
204+ : undefined ,
180205 position : strategy ,
181206 top : y ?? 0 ,
182207 } }
0 commit comments