|
1 | | -import { FC } from 'react'; |
| 1 | +import { FC, useEffect } from 'react'; |
2 | 2 | import { SearchInput, SearchInputProps, ToolbarFilter, ToolbarFilterProps } from '@patternfly/react-core'; |
3 | 3 |
|
4 | 4 | /** extends SearchInputProps */ |
@@ -29,26 +29,55 @@ export const DataViewTextFilter: FC<DataViewTextFilterProps> = ({ |
29 | 29 | trimValue = true, |
30 | 30 | ouiaId = 'DataViewTextFilter', |
31 | 31 | ...props |
32 | | -}: DataViewTextFilterProps) => ( |
33 | | - <ToolbarFilter |
34 | | - key={ouiaId} |
35 | | - data-ouia-component-id={ouiaId} |
36 | | - labels={value.length > 0 ? [ { key: title, node: value } ] : []} |
37 | | - deleteLabel={() => onChange?.(undefined, '')} |
38 | | - categoryName={title} |
39 | | - showToolbarItem={showToolbarItem} |
40 | | - > |
41 | | - <SearchInput |
42 | | - searchInputId={filterId} |
43 | | - value={value} |
44 | | - onChange={(e, inputValue) => onChange?.(e, trimValue ? inputValue.trim() : inputValue)} |
45 | | - onClear={onClear} |
46 | | - placeholder={`Filter by ${title}`} |
47 | | - aria-label={`${title ?? filterId} filter`} |
48 | | - data-ouia-component-id={`${ouiaId}-input`} |
49 | | - {...props} |
50 | | - /> |
51 | | - </ToolbarFilter> |
52 | | -); |
| 32 | +}: DataViewTextFilterProps) => { |
| 33 | + useEffect(() => { |
| 34 | + const handleKeyDown = (event: KeyboardEvent) => { |
| 35 | + // Only handle "/" key when not typing in an input, textarea, or contenteditable element |
| 36 | + if (event.key === '/' && !event.ctrlKey && !event.metaKey && !event.altKey) { |
| 37 | + const target = event.target as HTMLElement; |
| 38 | + const isInputElement = target.tagName === 'INPUT' || |
| 39 | + target.tagName === 'TEXTAREA' || |
| 40 | + target.isContentEditable; |
| 41 | + |
| 42 | + // Only focus if the filter is visible and we're not already in an input field |
| 43 | + if (showToolbarItem && !isInputElement) { |
| 44 | + // Find the input element by its ID (searchInputId prop) |
| 45 | + const inputElement = document.getElementById(filterId) as HTMLInputElement; |
| 46 | + if (inputElement) { |
| 47 | + event.preventDefault(); |
| 48 | + inputElement.focus(); |
| 49 | + } |
| 50 | + } |
| 51 | + } |
| 52 | + }; |
| 53 | + |
| 54 | + window.addEventListener('keydown', handleKeyDown); |
| 55 | + return () => { |
| 56 | + window.removeEventListener('keydown', handleKeyDown); |
| 57 | + }; |
| 58 | + }, [showToolbarItem, filterId]); |
| 59 | + |
| 60 | + return ( |
| 61 | + <ToolbarFilter |
| 62 | + key={ouiaId} |
| 63 | + data-ouia-component-id={ouiaId} |
| 64 | + labels={value.length > 0 ? [ { key: title, node: value } ] : []} |
| 65 | + deleteLabel={() => onChange?.(undefined, '')} |
| 66 | + categoryName={title} |
| 67 | + showToolbarItem={showToolbarItem} |
| 68 | + > |
| 69 | + <SearchInput |
| 70 | + searchInputId={filterId} |
| 71 | + value={value} |
| 72 | + onChange={(e, inputValue) => onChange?.(e, trimValue ? inputValue.trim() : inputValue)} |
| 73 | + onClear={onClear} |
| 74 | + placeholder={`Filter by ${title}`} |
| 75 | + aria-label={`${title ?? filterId} filter`} |
| 76 | + data-ouia-component-id={`${ouiaId}-input`} |
| 77 | + {...props} |
| 78 | + /> |
| 79 | + </ToolbarFilter> |
| 80 | + ); |
| 81 | +}; |
53 | 82 |
|
54 | 83 | export default DataViewTextFilter; |
0 commit comments