@patternfly/react-core 4.227.6 → 4.227.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/esm/components/Menu/MenuItem.d.ts +3 -1
  3. package/dist/esm/components/Menu/MenuItem.d.ts.map +1 -1
  4. package/dist/esm/components/Menu/MenuItem.js +2 -2
  5. package/dist/esm/components/Menu/MenuItem.js.map +1 -1
  6. package/dist/esm/components/MenuToggle/MenuToggle.d.ts +6 -12
  7. package/dist/esm/components/MenuToggle/MenuToggle.d.ts.map +1 -1
  8. package/dist/esm/components/MenuToggle/MenuToggle.js +12 -8
  9. package/dist/esm/components/MenuToggle/MenuToggle.js.map +1 -1
  10. package/dist/esm/components/TextInputGroup/TextInputGroup.d.ts +2 -0
  11. package/dist/esm/components/TextInputGroup/TextInputGroup.d.ts.map +1 -1
  12. package/dist/esm/components/TextInputGroup/TextInputGroup.js +2 -2
  13. package/dist/esm/components/TextInputGroup/TextInputGroup.js.map +1 -1
  14. package/dist/esm/components/TextInputGroup/TextInputGroupMain.d.ts +1 -1
  15. package/dist/esm/components/TextInputGroup/TextInputGroupMain.d.ts.map +1 -1
  16. package/dist/js/components/Menu/MenuItem.d.ts +3 -1
  17. package/dist/js/components/Menu/MenuItem.d.ts.map +1 -1
  18. package/dist/js/components/Menu/MenuItem.js +2 -2
  19. package/dist/js/components/Menu/MenuItem.js.map +1 -1
  20. package/dist/js/components/MenuToggle/MenuToggle.d.ts +6 -12
  21. package/dist/js/components/MenuToggle/MenuToggle.d.ts.map +1 -1
  22. package/dist/js/components/MenuToggle/MenuToggle.js +12 -8
  23. package/dist/js/components/MenuToggle/MenuToggle.js.map +1 -1
  24. package/dist/js/components/TextInputGroup/TextInputGroup.d.ts +2 -0
  25. package/dist/js/components/TextInputGroup/TextInputGroup.d.ts.map +1 -1
  26. package/dist/js/components/TextInputGroup/TextInputGroup.js +2 -2
  27. package/dist/js/components/TextInputGroup/TextInputGroup.js.map +1 -1
  28. package/dist/js/components/TextInputGroup/TextInputGroupMain.d.ts +1 -1
  29. package/dist/js/components/TextInputGroup/TextInputGroupMain.d.ts.map +1 -1
  30. package/dist/umd/react-core.css +46 -49
  31. package/dist/umd/react-core.js +17 -12
  32. package/dist/umd/react-core.min.css +84 -87
  33. package/dist/umd/react-core.min.js +5 -5
  34. package/package.json +6 -6
  35. package/src/components/Menu/MenuItem.tsx +4 -0
  36. package/src/components/MenuToggle/MenuToggle.tsx +63 -25
  37. package/src/components/Page/examples/Page.md +10 -615
  38. package/src/components/Page/examples/PageCenteredSection.tsx +76 -0
  39. package/src/components/Page/examples/PageGroupSection.tsx +106 -0
  40. package/src/components/Page/examples/PageHorizontalNav.tsx +43 -0
  41. package/src/components/Page/examples/PageMainSectionPadding.tsx +72 -0
  42. package/src/components/Page/examples/PageTertiaryNav.tsx +42 -0
  43. package/src/components/Page/examples/PageUncontrolledNav.tsx +53 -0
  44. package/src/components/Page/examples/PageVerticalNav.tsx +65 -0
  45. package/src/components/Page/examples/PageVerticalNavUsingPageHeaderComponent.tsx +44 -0
  46. package/src/components/Page/examples/PageWithOrWithoutFill.tsx +67 -0
  47. package/src/components/Pagination/examples/Pagination.md +8 -355
  48. package/src/components/Pagination/examples/PaginationBottom.tsx +33 -0
  49. package/src/components/Pagination/examples/PaginationCompact.tsx +33 -0
  50. package/src/components/Pagination/examples/PaginationDisabled.tsx +33 -0
  51. package/src/components/Pagination/examples/PaginationIndeterminate.tsx +40 -0
  52. package/src/components/Pagination/examples/PaginationNoItems.tsx +32 -0
  53. package/src/components/Pagination/examples/PaginationOnePage.tsx +32 -0
  54. package/src/components/Pagination/examples/PaginationSticky.tsx +81 -0
  55. package/src/components/Pagination/examples/PaginationTop.tsx +32 -0
  56. package/src/components/Switch/examples/Switch.md +6 -153
  57. package/src/components/Switch/examples/SwitchBasic.tsx +20 -0
  58. package/src/components/Switch/examples/SwitchCheckedWithLabel.tsx +22 -0
  59. package/src/components/Switch/examples/SwitchDisabled.tsx +28 -0
  60. package/src/components/Switch/examples/SwitchReversed.tsx +21 -0
  61. package/src/components/Switch/examples/SwitchUncontrolled.tsx +14 -0
  62. package/src/components/Switch/examples/SwitchWithoutLabel.tsx +12 -0
  63. package/src/components/TextInputGroup/TextInputGroup.tsx +9 -1
  64. package/src/components/TextInputGroup/TextInputGroupMain.tsx +1 -1
  65. package/src/demos/ComposableMenu/ComposableMenu.md +8 -0
  66. package/src/demos/ComposableMenu/examples/ComposableTypeaheadSelect.tsx +196 -0
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import { Pagination } from '@patternfly/react-core';
3
+
4
+ export const PaginationTop: React.FunctionComponent = () => {
5
+ const [page, setPage] = React.useState(1);
6
+ const [perPage, setPerPage] = React.useState(20);
7
+
8
+ const onSetPage = (_event: React.MouseEvent | React.KeyboardEvent | MouseEvent, newPage: number) => {
9
+ setPage(newPage);
10
+ };
11
+
12
+ const onPerPageSelect = (
13
+ _event: React.MouseEvent | React.KeyboardEvent | MouseEvent,
14
+ newPerPage: number,
15
+ newPage: number
16
+ ) => {
17
+ setPerPage(newPerPage);
18
+ setPage(newPage);
19
+ };
20
+
21
+ return (
22
+ <Pagination
23
+ perPageComponent="button"
24
+ itemCount={523}
25
+ perPage={perPage}
26
+ page={page}
27
+ onSetPage={onSetPage}
28
+ widgetId="pagination-options-menu-top"
29
+ onPerPageSelect={onPerPageSelect}
30
+ />
31
+ );
32
+ };
@@ -10,177 +10,30 @@ ouia: true
10
10
 
11
11
  ### Basic
12
12
 
13
- ```js
14
- import React from 'react';
15
- import { Switch } from '@patternfly/react-core';
16
-
17
- class SimpleSwitch extends React.Component {
18
- constructor(props) {
19
- super(props);
20
- this.state = {
21
- isChecked: true
22
- };
23
- this.handleChange = isChecked => {
24
- this.setState({ isChecked });
25
- };
26
- }
27
-
28
- render() {
29
- const { isChecked } = this.state;
30
- return (
31
- <Switch
32
- id="simple-switch"
33
- label="Message when on"
34
- labelOff="Message when off"
35
- isChecked={isChecked}
36
- onChange={this.handleChange}
37
- />
38
- );
39
- }
40
- }
13
+ ```ts file="./SwitchBasic.tsx"
41
14
  ```
42
15
 
43
16
  ### Reversed Layout
44
17
 
45
- ```js
46
- import React from 'react';
47
- import { Switch } from '@patternfly/react-core';
48
-
49
- class ReversedSwitch extends React.Component {
50
- constructor(props) {
51
- super(props);
52
- this.state = {
53
- isChecked: true
54
- };
55
- this.handleChange = isChecked => {
56
- this.setState({ isChecked });
57
- };
58
- }
59
-
60
- render() {
61
- const { isChecked } = this.state;
62
- return (
63
- <Switch
64
- id="reversed-switch"
65
- label="Message when on"
66
- labelOff="Message when off"
67
- isChecked={isChecked}
68
- onChange={this.handleChange}
69
- isReversed
70
- />
71
- );
72
- }
73
- }
18
+ ```ts file="./SwitchReversed.tsx"
74
19
  ```
75
20
 
76
21
  ### Without label
77
22
 
78
- ```js
79
- import React from 'react';
80
- import { Switch } from '@patternfly/react-core';
81
-
82
- class NoLabelSwitch extends React.Component {
83
- constructor(props) {
84
- super(props);
85
- this.state = {
86
- isChecked: true
87
- };
88
- this.handleChange = isChecked => {
89
- this.setState({ isChecked });
90
- };
91
- }
92
-
93
- render() {
94
- const { isChecked } = this.state;
95
- return (
96
- <Switch id="no-label-switch-on" aria-label="Message when on" isChecked={isChecked} onChange={this.handleChange} />
97
- );
98
- }
99
- }
23
+ ```ts file="./SwitchWithoutLabel.tsx"
100
24
  ```
101
25
 
102
26
  ### Checked with label
103
27
 
104
- ```js
105
- import React from 'react';
106
- import { Switch } from '@patternfly/react-core';
107
-
108
- class CheckedWithLabelSwitch extends React.Component {
109
- constructor(props) {
110
- super(props);
111
- this.state = {
112
- isChecked: true
113
- };
114
- this.handleChange = isChecked => {
115
- this.setState({ isChecked });
116
- };
117
- }
118
-
119
- render() {
120
- const { isChecked } = this.state;
121
- return (
122
- <Switch
123
- label="Message when on"
124
- labelOff="Message when off"
125
- id="checked-with-label-switch-on"
126
- aria-label="Message when on"
127
- isChecked={isChecked}
128
- hasCheckIcon
129
- onChange={this.handleChange}
130
- />
131
- );
132
- }
133
- }
28
+ ```ts file="./SwitchCheckedWithLabel.tsx"
134
29
  ```
135
30
 
136
31
  ### Disabled
137
32
 
138
- ```js
139
- import React from 'react';
140
- import { Switch } from '@patternfly/react-core';
141
-
142
- <React.Fragment>
143
- <Switch
144
- id="disabled-switch-on"
145
- aria-label="Message when on"
146
- label="Message when on"
147
- labelOff="Message when off"
148
- isChecked
149
- isDisabled
150
- />
151
- <br />
152
- <Switch
153
- id="disabled-switch-off"
154
- aria-label="Message when on"
155
- label="Message when on"
156
- labelOff="Message when off"
157
- isChecked={false}
158
- isDisabled
159
- />
160
- <br />
161
- <Switch id="disabled-no-label-switch-on" aria-label="Message when on" isChecked isDisabled />
162
- <br />
163
- <Switch id="disabled-no-label-switch-off" aria-label="Message when on" isChecked={false} isDisabled />
164
- </React.Fragment>;
33
+ ```ts file="./SwitchDisabled.tsx"
165
34
  ```
166
35
 
167
36
  ### Uncontrolled
168
37
 
169
- ```js
170
- import React from 'react';
171
- import { Switch } from '@patternfly/react-core';
172
-
173
- <React.Fragment>
174
- <Switch
175
- id="uncontrolled-switch-no-label"
176
- aria-label="An uncontrolled switch with no label"
177
- defaultChecked={false}
178
- />
179
- <br />
180
- <Switch
181
- id="uncontrolled-switch-with-label"
182
- label="An uncontrolled switch"
183
- defaultChecked={false}
184
- />
185
- </React.Fragment>;
38
+ ```ts file="./SwitchUncontrolled.tsx"
186
39
  ```
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { Switch } from '@patternfly/react-core';
3
+
4
+ export const SwitchBasic: React.FunctionComponent = () => {
5
+ const [isChecked, setIsChecked] = React.useState<boolean>(true);
6
+
7
+ const handleChange = (checked: boolean, _event: React.FormEvent<HTMLInputElement>) => {
8
+ setIsChecked(checked);
9
+ };
10
+
11
+ return (
12
+ <Switch
13
+ id="simple-switch"
14
+ label="Message when on"
15
+ labelOff="Message when off"
16
+ isChecked={isChecked}
17
+ onChange={handleChange}
18
+ />
19
+ );
20
+ };
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { Switch } from '@patternfly/react-core';
3
+
4
+ export const SwitchCheckedWithLabel: React.FunctionComponent = () => {
5
+ const [isChecked, setIsChecked] = React.useState<boolean>(true);
6
+
7
+ const handleChange = (checked: boolean, _event: React.FormEvent<HTMLInputElement>) => {
8
+ setIsChecked(checked);
9
+ };
10
+
11
+ return (
12
+ <Switch
13
+ label="Message when on"
14
+ labelOff="Message when off"
15
+ id="checked-with-label-switch-on"
16
+ aria-label="Message when on"
17
+ isChecked={isChecked}
18
+ hasCheckIcon
19
+ onChange={handleChange}
20
+ />
21
+ );
22
+ };
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import { Switch } from '@patternfly/react-core';
3
+
4
+ export const SwitchDisabled: React.FunctionComponent = () => (
5
+ <React.Fragment>
6
+ <Switch
7
+ id="disabled-switch-on"
8
+ aria-label="Message when on"
9
+ label="Message when on"
10
+ labelOff="Message when off"
11
+ isChecked
12
+ isDisabled
13
+ />
14
+ <br />
15
+ <Switch
16
+ id="disabled-switch-off"
17
+ aria-label="Message when on"
18
+ label="Message when on"
19
+ labelOff="Message when off"
20
+ isChecked={false}
21
+ isDisabled
22
+ />
23
+ <br />
24
+ <Switch id="disabled-no-label-switch-on" aria-label="Message when on" isChecked isDisabled />
25
+ <br />
26
+ <Switch id="disabled-no-label-switch-off" aria-label="Message when on" isChecked={false} isDisabled />
27
+ </React.Fragment>
28
+ );
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import { Switch } from '@patternfly/react-core';
3
+
4
+ export const SwitchReversed: React.FunctionComponent = () => {
5
+ const [isChecked, setIsChecked] = React.useState<boolean>(true);
6
+
7
+ const handleChange = (checked: boolean, _event: React.FormEvent<HTMLInputElement>) => {
8
+ setIsChecked(checked);
9
+ };
10
+
11
+ return (
12
+ <Switch
13
+ id="reversed-switch"
14
+ label="Message when on"
15
+ labelOff="Message when off"
16
+ isChecked={isChecked}
17
+ onChange={handleChange}
18
+ isReversed
19
+ />
20
+ );
21
+ };
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { Switch } from '@patternfly/react-core';
3
+
4
+ export const SwitchUncontrolled: React.FunctionComponent = () => (
5
+ <React.Fragment>
6
+ <Switch
7
+ id="uncontrolled-switch-no-label"
8
+ aria-label="An uncontrolled switch with no label"
9
+ defaultChecked={false}
10
+ />
11
+ <br />
12
+ <Switch id="uncontrolled-switch-with-label" label="An uncontrolled switch" defaultChecked={false} />
13
+ </React.Fragment>
14
+ );
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { Switch } from '@patternfly/react-core';
3
+
4
+ export const SwitchWithoutLabel: React.FunctionComponent = () => {
5
+ const [isChecked, setIsChecked] = React.useState<boolean>(true);
6
+
7
+ const handleChange = (checked: boolean, _event: React.FormEvent<HTMLInputElement>) => {
8
+ setIsChecked(checked);
9
+ };
10
+
11
+ return <Switch id="no-label-switch-on" aria-label="Message when on" isChecked={isChecked} onChange={handleChange} />;
12
+ };
@@ -9,6 +9,8 @@ export interface TextInputGroupProps extends React.HTMLProps<HTMLDivElement> {
9
9
  className?: string;
10
10
  /** Adds disabled styling and a disabled context value which text input group main hooks into for the input itself */
11
11
  isDisabled?: boolean;
12
+ /** Flag to indicate the toggle has no border or background */
13
+ isPlain?: boolean;
12
14
  /** @hide A reference object to attach to the input box */
13
15
  innerRef?: React.RefObject<any>;
14
16
  }
@@ -21,6 +23,7 @@ export const TextInputGroup: React.FunctionComponent<TextInputGroupProps> = ({
21
23
  children,
22
24
  className,
23
25
  isDisabled,
26
+ isPlain,
24
27
  innerRef,
25
28
  ...props
26
29
  }: TextInputGroupProps) => {
@@ -30,7 +33,12 @@ export const TextInputGroup: React.FunctionComponent<TextInputGroupProps> = ({
30
33
  <TextInputGroupContext.Provider value={{ isDisabled }}>
31
34
  <div
32
35
  ref={textInputGroupRef}
33
- className={css(styles.textInputGroup, isDisabled && styles.modifiers.disabled, className)}
36
+ className={css(
37
+ styles.textInputGroup,
38
+ isDisabled && styles.modifiers.disabled,
39
+ isPlain && styles.modifiers.plain,
40
+ className
41
+ )}
34
42
  {...props}
35
43
  >
36
44
  {children}
@@ -37,7 +37,7 @@ export interface TextInputGroupMainProps extends Omit<React.HTMLProps<HTMLDivEle
37
37
  value?: string | number;
38
38
  /** Placeholder value for the input */
39
39
  placeholder?: string;
40
- /** @hide A reference object to attach to the input box */
40
+ /** A reference object to attach to the input box */
41
41
  innerRef?: React.RefObject<any>;
42
42
  }
43
43
 
@@ -20,6 +20,9 @@ import pfIcon from './examples/pf-logo-small.svg';
20
20
  import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
21
21
  import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon';
22
22
  import avatarImg from './examples/avatarImg.svg';
23
+ import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
24
+ import { css } from '@patternfly/react-styles';
25
+ import styles from '@patternfly/react-styles/css/components/Menu/menu';
23
26
 
24
27
  ## Demos
25
28
 
@@ -45,6 +48,11 @@ Composable menus currently require consumer keyboard handling and use of our und
45
48
  ```ts isBeta file="./examples/ComposableSimpleCheckboxSelect.tsx"
46
49
  ```
47
50
 
51
+ ### Composable typeahead select
52
+
53
+ ```ts file="./examples/ComposableTypeaheadSelect.tsx"
54
+ ```
55
+
48
56
  ### Composable drilldown menu
49
57
 
50
58
  ```ts isBeta file="./examples/ComposableDrilldownMenu.tsx"
@@ -0,0 +1,196 @@
1
+ import React from 'react';
2
+
3
+ import {
4
+ Menu,
5
+ MenuContent,
6
+ MenuList,
7
+ MenuItem,
8
+ Popper,
9
+ MenuToggle,
10
+ TextInputGroup,
11
+ MenuItemProps,
12
+ Button,
13
+ TextInputGroupUtilities,
14
+ TextInputGroupMain,
15
+ MenuToggleElement
16
+ } from '@patternfly/react-core';
17
+ import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
18
+ import TableIcon from '@patternfly/react-icons/dist/esm/icons/table-icon';
19
+
20
+ const intitalMenuItems: MenuItemProps[] = [
21
+ { itemId: 'Option 1', children: 'Option 1' },
22
+ { itemId: 'Option 2', children: 'Option 2' },
23
+ { itemId: 'Option 3', children: 'Option 3', icon: <TableIcon aria-hidden /> }
24
+ ];
25
+
26
+ export const ComposableTypeaheadSelect: React.FunctionComponent = () => {
27
+ const [isMenuOpen, setIsMenuOpen] = React.useState(false);
28
+ const [inputValue, setInputValue] = React.useState<string>('');
29
+ const [menuItems, setMenuItems] = React.useState<MenuItemProps[]>(intitalMenuItems);
30
+ const [focusedItemIndex, setFocusedItemIndex] = React.useState<number | null>(null);
31
+ const [isSelected, setIsSelected] = React.useState(false);
32
+
33
+ const menuToggleRef = React.useRef<MenuToggleElement>({} as MenuToggleElement);
34
+ const textInputRef = React.useRef<HTMLInputElement>();
35
+
36
+ React.useEffect(() => {
37
+ let newMenuItems: MenuItemProps[] = intitalMenuItems;
38
+
39
+ // Filter menu items based on the text input value when one exists
40
+ if (inputValue) {
41
+ newMenuItems = intitalMenuItems.filter(menuItem =>
42
+ String(menuItem.children)
43
+ .toLowerCase()
44
+ .includes(inputValue.toLowerCase())
45
+ );
46
+
47
+ // When no options are found after filtering, display 'No results found'
48
+ if (!newMenuItems.length) {
49
+ newMenuItems = [{ isDisabled: true, children: 'No results found' }];
50
+ }
51
+ }
52
+
53
+ setMenuItems(newMenuItems);
54
+ }, [inputValue]);
55
+
56
+ const focusOnInput = () => menuToggleRef.current?.querySelector('input')?.focus();
57
+
58
+ const onMenuSelect = (_event: React.MouseEvent<Element, MouseEvent>, itemId: string | number) => {
59
+ if (itemId) {
60
+ setInputValue(itemId.toString());
61
+ setIsSelected(true);
62
+ }
63
+
64
+ setIsMenuOpen(false);
65
+ setFocusedItemIndex(null);
66
+ focusOnInput();
67
+ };
68
+
69
+ const handleMenuArrowKeys = (key: string) => {
70
+ let indexToFocus;
71
+
72
+ if (isMenuOpen) {
73
+ if (key === 'ArrowUp') {
74
+ // When no index is set or at the first index, focus to the last, otherwise decrement focus index
75
+ if (focusedItemIndex === null || focusedItemIndex === 0) {
76
+ indexToFocus = menuItems.length - 1;
77
+ } else {
78
+ indexToFocus = focusedItemIndex - 1;
79
+ }
80
+ }
81
+
82
+ if (key === 'ArrowDown') {
83
+ // When no index is set or at the last index, focus to the first, otherwise increment focus index
84
+ if (focusedItemIndex === null || focusedItemIndex === menuItems.length - 1) {
85
+ indexToFocus = 0;
86
+ } else {
87
+ indexToFocus = focusedItemIndex + 1;
88
+ }
89
+ }
90
+
91
+ setFocusedItemIndex(indexToFocus);
92
+ }
93
+ };
94
+
95
+ const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
96
+ const enabledMenuItems = menuItems.filter(menuItem => !menuItem.isDisabled);
97
+ const [firstMenuItem] = enabledMenuItems;
98
+ const focusedItem = focusedItemIndex ? enabledMenuItems[focusedItemIndex] : firstMenuItem;
99
+
100
+ switch (event.key) {
101
+ // Select the first available option
102
+ case 'Enter':
103
+ if (isMenuOpen) {
104
+ setInputValue(String(focusedItem.children));
105
+ setIsSelected(true);
106
+ }
107
+
108
+ setIsMenuOpen(prevIsOpen => !prevIsOpen);
109
+ setFocusedItemIndex(null);
110
+ focusOnInput();
111
+
112
+ break;
113
+ case 'Tab':
114
+ case 'Escape':
115
+ setIsMenuOpen(false);
116
+ break;
117
+ case 'ArrowUp':
118
+ case 'ArrowDown':
119
+ handleMenuArrowKeys(event.key);
120
+ break;
121
+ default:
122
+ !isMenuOpen && setIsMenuOpen(true);
123
+ }
124
+ };
125
+
126
+ // Close the menu when a click occurs outside of the menu toggle content
127
+ const onDocumentClick = (event: MouseEvent) => {
128
+ if (!menuToggleRef.current?.contains(event?.target as HTMLElement)) {
129
+ setIsMenuOpen(false);
130
+ }
131
+ };
132
+
133
+ const toggleMenuOpen = () => {
134
+ setIsMenuOpen(prevIsOpen => !prevIsOpen);
135
+ textInputRef.current?.focus();
136
+ };
137
+
138
+ const onTextInputChange = (value: string) => {
139
+ setInputValue(value);
140
+ setIsSelected(false);
141
+ };
142
+
143
+ return (
144
+ <Popper
145
+ trigger={
146
+ <MenuToggle
147
+ variant="typeahead"
148
+ onClick={toggleMenuOpen}
149
+ innerRef={menuToggleRef}
150
+ isExpanded={isMenuOpen}
151
+ isFullWidth
152
+ >
153
+ <TextInputGroup isPlain>
154
+ <TextInputGroupMain
155
+ value={inputValue}
156
+ onClick={toggleMenuOpen}
157
+ onChange={onTextInputChange}
158
+ onKeyDown={onInputKeyDown}
159
+ id="typeahead-select-input"
160
+ autoComplete="off"
161
+ innerRef={textInputRef}
162
+ />
163
+
164
+ <TextInputGroupUtilities>
165
+ {!!inputValue && (
166
+ <Button variant="plain" onClick={() => setInputValue('')} aria-label="Clear input value">
167
+ <TimesIcon aria-hidden />
168
+ </Button>
169
+ )}
170
+ </TextInputGroupUtilities>
171
+ </TextInputGroup>
172
+ </MenuToggle>
173
+ }
174
+ popper={
175
+ <Menu id="select-menu" onSelect={onMenuSelect} selected={isSelected && inputValue}>
176
+ <MenuContent>
177
+ <MenuList>
178
+ {menuItems.map((itemProps, index) => (
179
+ <MenuItem
180
+ key={itemProps.itemId || itemProps.children}
181
+ isFocused={focusedItemIndex === index}
182
+ className={itemProps.className}
183
+ onClick={() => setIsSelected(true)}
184
+ {...itemProps}
185
+ ref={null}
186
+ />
187
+ ))}
188
+ </MenuList>
189
+ </MenuContent>
190
+ </Menu>
191
+ }
192
+ isVisible={isMenuOpen}
193
+ onDocumentClick={onDocumentClick}
194
+ />
195
+ );
196
+ };