-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Expand file tree
/
Copy pathmenu-title-search.tsx
More file actions
100 lines (88 loc) · 2.6 KB
/
menu-title-search.tsx
File metadata and controls
100 lines (88 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* WordPress dependencies
*/
import { useEffect, useRef } from '@wordpress/element';
import { __, _n, sprintf } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import withSpokenMessages from '../../higher-order/with-spoken-messages';
import { useNavigationMenuContext } from './context';
import { useNavigationContext } from '../context';
import { SEARCH_FOCUS_DELAY } from '../constants';
import type { NavigationMenuTitleSearchProps } from '../types';
import SearchControl from '../../search-control';
import { MenuTitleSearchControlWrapper } from '../styles/navigation-styles';
function MenuTitleSearch( {
debouncedSpeak,
onCloseSearch,
onSearch,
search,
title,
}: NavigationMenuTitleSearchProps ) {
const {
navigationTree: { items },
} = useNavigationContext();
const { menu } = useNavigationMenuContext();
const inputRef = useRef< HTMLInputElement >( null );
// Wait for the slide-in animation to complete before autofocusing the input.
// This prevents scrolling to the input during the animation.
useEffect( () => {
const delayedFocus = setTimeout( () => {
inputRef.current?.focus();
}, SEARCH_FOCUS_DELAY );
return () => {
clearTimeout( delayedFocus );
};
}, [] );
useEffect( () => {
if ( ! search ) {
return;
}
const count = Object.values( items ).filter(
( item ) => item._isVisible
).length;
const resultsFoundMessage = sprintf(
/* translators: %d: number of results. */
_n( '%d result found.', '%d results found.', count ),
count
);
debouncedSpeak( resultsFoundMessage );
// Not adding deps for now, as it would require either a larger refactor.
// See https://github.com/WordPress/gutenberg/pull/44090
}, [ items, search ] );
const onClose = () => {
onSearch?.( '' );
onCloseSearch();
};
const onKeyDown: React.KeyboardEventHandler< HTMLInputElement > = (
event
) => {
if ( event.code === 'Escape' && ! event.defaultPrevented ) {
event.preventDefault();
onClose();
}
};
const inputId = `components-navigation__menu-title-search-${ menu }`;
const placeholder = sprintf(
/* translators: placeholder for menu search box. %s: menu title */
__( 'Search %s' ),
title?.toLowerCase()
).trim();
return (
<MenuTitleSearchControlWrapper>
<SearchControl
__nextHasNoMarginBottom
className="components-navigation__menu-search-input"
id={ inputId }
onChange={ ( value ) => onSearch?.( value ) }
onKeyDown={ onKeyDown }
placeholder={ placeholder }
onClose={ onClose }
ref={ inputRef }
value={ search }
/>
</MenuTitleSearchControlWrapper>
);
}
export default withSpokenMessages( MenuTitleSearch );