@patternfly/react-core 5.4.10 → 5.4.11
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.
- package/CHANGELOG.md +6 -0
- package/components/package.json +1 -1
- package/deprecated/package.json +1 -1
- package/dist/dynamic/components/AboutModal/package.json +1 -1
- package/dist/dynamic/components/Accordion/package.json +1 -1
- package/dist/dynamic/components/ActionList/package.json +1 -1
- package/dist/dynamic/components/Alert/package.json +1 -1
- package/dist/dynamic/components/Avatar/package.json +1 -1
- package/dist/dynamic/components/BackToTop/package.json +1 -1
- package/dist/dynamic/components/Backdrop/package.json +1 -1
- package/dist/dynamic/components/BackgroundImage/package.json +1 -1
- package/dist/dynamic/components/Badge/package.json +1 -1
- package/dist/dynamic/components/Banner/package.json +1 -1
- package/dist/dynamic/components/Brand/package.json +1 -1
- package/dist/dynamic/components/Breadcrumb/package.json +1 -1
- package/dist/dynamic/components/Button/package.json +1 -1
- package/dist/dynamic/components/CalendarMonth/package.json +1 -1
- package/dist/dynamic/components/Card/package.json +1 -1
- package/dist/dynamic/components/Checkbox/package.json +1 -1
- package/dist/dynamic/components/Chip/package.json +1 -1
- package/dist/dynamic/components/ClipboardCopy/package.json +1 -1
- package/dist/dynamic/components/CodeBlock/package.json +1 -1
- package/dist/dynamic/components/DataList/package.json +1 -1
- package/dist/dynamic/components/DatePicker/package.json +1 -1
- package/dist/dynamic/components/DescriptionList/package.json +1 -1
- package/dist/dynamic/components/Divider/package.json +1 -1
- package/dist/dynamic/components/DragDrop/package.json +1 -1
- package/dist/dynamic/components/Drawer/package.json +1 -1
- package/dist/dynamic/components/Dropdown/package.json +1 -1
- package/dist/dynamic/components/DualListSelector/package.json +1 -1
- package/dist/dynamic/components/EmptyState/package.json +1 -1
- package/dist/dynamic/components/ExpandableSection/package.json +1 -1
- package/dist/dynamic/components/FileUpload/package.json +1 -1
- package/dist/dynamic/components/Form/package.json +1 -1
- package/dist/dynamic/components/FormSelect/package.json +1 -1
- package/dist/dynamic/components/HelperText/package.json +1 -1
- package/dist/dynamic/components/Hint/package.json +1 -1
- package/dist/dynamic/components/Icon/package.json +1 -1
- package/dist/dynamic/components/InputGroup/package.json +1 -1
- package/dist/dynamic/components/JumpLinks/package.json +1 -1
- package/dist/dynamic/components/Label/package.json +1 -1
- package/dist/dynamic/components/List/package.json +1 -1
- package/dist/dynamic/components/LoginPage/package.json +1 -1
- package/dist/dynamic/components/Masthead/package.json +1 -1
- package/dist/dynamic/components/Menu/package.json +1 -1
- package/dist/dynamic/components/MenuToggle/package.json +1 -1
- package/dist/dynamic/components/Modal/package.json +1 -1
- package/dist/dynamic/components/MultipleFileUpload/package.json +1 -1
- package/dist/dynamic/components/Nav/package.json +1 -1
- package/dist/dynamic/components/NotificationBadge/package.json +1 -1
- package/dist/dynamic/components/NotificationDrawer/package.json +1 -1
- package/dist/dynamic/components/NumberInput/package.json +1 -1
- package/dist/dynamic/components/OverflowMenu/package.json +1 -1
- package/dist/dynamic/components/Page/package.json +1 -1
- package/dist/dynamic/components/Pagination/package.json +1 -1
- package/dist/dynamic/components/Panel/package.json +1 -1
- package/dist/dynamic/components/Popover/package.json +1 -1
- package/dist/dynamic/components/Progress/package.json +1 -1
- package/dist/dynamic/components/ProgressStepper/package.json +1 -1
- package/dist/dynamic/components/Radio/package.json +1 -1
- package/dist/dynamic/components/SearchInput/package.json +1 -1
- package/dist/dynamic/components/Select/package.json +1 -1
- package/dist/dynamic/components/Sidebar/package.json +1 -1
- package/dist/dynamic/components/SimpleList/package.json +1 -1
- package/dist/dynamic/components/Skeleton/package.json +1 -1
- package/dist/dynamic/components/SkipToContent/package.json +1 -1
- package/dist/dynamic/components/Slider/package.json +1 -1
- package/dist/dynamic/components/Spinner/package.json +1 -1
- package/dist/dynamic/components/Switch/package.json +1 -1
- package/dist/dynamic/components/Tabs/package.json +1 -1
- package/dist/dynamic/components/Text/package.json +1 -1
- package/dist/dynamic/components/TextArea/package.json +1 -1
- package/dist/dynamic/components/TextInput/package.json +1 -1
- package/dist/dynamic/components/TextInputGroup/package.json +1 -1
- package/dist/dynamic/components/Tile/package.json +1 -1
- package/dist/dynamic/components/TimePicker/package.json +1 -1
- package/dist/dynamic/components/Timestamp/package.json +1 -1
- package/dist/dynamic/components/Title/package.json +1 -1
- package/dist/dynamic/components/ToggleGroup/package.json +1 -1
- package/dist/dynamic/components/Toolbar/package.json +1 -1
- package/dist/dynamic/components/Tooltip/package.json +1 -1
- package/dist/dynamic/components/TreeView/package.json +1 -1
- package/dist/dynamic/components/Truncate/package.json +1 -1
- package/dist/dynamic/components/Wizard/hooks/package.json +1 -1
- package/dist/dynamic/components/Wizard/package.json +1 -1
- package/dist/dynamic/deprecated/components/ApplicationLauncher/package.json +1 -1
- package/dist/dynamic/deprecated/components/ContextSelector/package.json +1 -1
- package/dist/dynamic/deprecated/components/Dropdown/package.json +1 -1
- package/dist/dynamic/deprecated/components/OptionsMenu/package.json +1 -1
- package/dist/dynamic/deprecated/components/PageHeader/package.json +1 -1
- package/dist/dynamic/deprecated/components/Select/package.json +1 -1
- package/dist/dynamic/deprecated/components/Wizard/package.json +1 -1
- package/dist/dynamic/deprecated/components/package.json +1 -1
- package/dist/dynamic/helpers/FocusTrap/FocusTrap/package.json +1 -1
- package/dist/dynamic/helpers/GenerateId/GenerateId/package.json +1 -1
- package/dist/dynamic/helpers/KeyboardHandler/package.json +1 -1
- package/dist/dynamic/helpers/OUIA/ouia/package.json +1 -1
- package/dist/dynamic/helpers/Popper/Popper/package.json +1 -1
- package/dist/dynamic/helpers/constants/package.json +1 -1
- package/dist/dynamic/helpers/datetimeUtils/package.json +1 -1
- package/dist/dynamic/helpers/favorites/package.json +1 -1
- package/dist/dynamic/helpers/fileUtils/package.json +1 -1
- package/dist/dynamic/helpers/htmlConstants/package.json +1 -1
- package/dist/dynamic/helpers/package.json +1 -1
- package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
- package/dist/dynamic/helpers/typeUtils/package.json +1 -1
- package/dist/dynamic/helpers/useInterval/package.json +1 -1
- package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
- package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
- package/dist/dynamic/helpers/util/package.json +1 -1
- package/dist/dynamic/layouts/Bullseye/package.json +1 -1
- package/dist/dynamic/layouts/Flex/package.json +1 -1
- package/dist/dynamic/layouts/Gallery/package.json +1 -1
- package/dist/dynamic/layouts/Grid/package.json +1 -1
- package/dist/dynamic/layouts/Level/package.json +1 -1
- package/dist/dynamic/layouts/Split/package.json +1 -1
- package/dist/dynamic/layouts/Stack/package.json +1 -1
- package/dist/dynamic/next/components/DualListSelector/package.json +1 -1
- package/dist/dynamic/next/components/Modal/package.json +1 -1
- package/dist/dynamic/next/components/package.json +1 -1
- package/dist/dynamic/styles/package.json +1 -1
- package/dist/dynamic-modules.json +1 -0
- package/dist/esm/components/Dropdown/Dropdown.d.ts +2 -0
- package/dist/esm/components/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/esm/components/Dropdown/Dropdown.js +12 -3
- package/dist/esm/components/Dropdown/Dropdown.js.map +1 -1
- package/dist/esm/components/Menu/MenuContainer.d.ts +4 -0
- package/dist/esm/components/Menu/MenuContainer.d.ts.map +1 -1
- package/dist/esm/components/Menu/MenuContainer.js +37 -15
- package/dist/esm/components/Menu/MenuContainer.js.map +1 -1
- package/dist/esm/components/Select/Select.d.ts +4 -0
- package/dist/esm/components/Select/Select.d.ts.map +1 -1
- package/dist/esm/components/Select/Select.js +12 -3
- package/dist/esm/components/Select/Select.js.map +1 -1
- package/dist/esm/helpers/KeyboardHandler.d.ts +7 -0
- package/dist/esm/helpers/KeyboardHandler.d.ts.map +1 -1
- package/dist/esm/helpers/KeyboardHandler.js +25 -0
- package/dist/esm/helpers/KeyboardHandler.js.map +1 -1
- package/dist/js/components/Dropdown/Dropdown.d.ts +2 -0
- package/dist/js/components/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/js/components/Dropdown/Dropdown.js +11 -2
- package/dist/js/components/Dropdown/Dropdown.js.map +1 -1
- package/dist/js/components/Menu/MenuContainer.d.ts +4 -0
- package/dist/js/components/Menu/MenuContainer.d.ts.map +1 -1
- package/dist/js/components/Menu/MenuContainer.js +38 -16
- package/dist/js/components/Menu/MenuContainer.js.map +1 -1
- package/dist/js/components/Select/Select.d.ts +4 -0
- package/dist/js/components/Select/Select.d.ts.map +1 -1
- package/dist/js/components/Select/Select.js +11 -2
- package/dist/js/components/Select/Select.js.map +1 -1
- package/dist/js/helpers/KeyboardHandler.d.ts +7 -0
- package/dist/js/helpers/KeyboardHandler.d.ts.map +1 -1
- package/dist/js/helpers/KeyboardHandler.js +27 -1
- package/dist/js/helpers/KeyboardHandler.js.map +1 -1
- package/dist/umd/assets/{output-DxbNpZVR.css → output-CT5USS28.css} +2354 -2354
- package/dist/umd/react-core.min.js +1 -1
- package/helpers/package.json +1 -1
- package/layouts/package.json +1 -1
- package/next/package.json +1 -1
- package/package.json +2 -2
- package/src/components/Dropdown/Dropdown.tsx +13 -1
- package/src/components/Menu/MenuContainer.tsx +42 -12
- package/src/components/Select/Select.tsx +16 -1
- package/src/components/Select/examples/SelectMultiTypeahead.tsx +1 -1
- package/src/components/Select/examples/SelectMultiTypeaheadCheckbox.tsx +1 -1
- package/src/components/Select/examples/SelectMultiTypeaheadCreatable.tsx +1 -1
- package/src/components/Select/examples/SelectTypeahead.tsx +1 -1
- package/src/components/Select/examples/SelectTypeaheadCreatable.tsx +1 -1
- package/src/helpers/KeyboardHandler.tsx +27 -0
package/helpers/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"5.4.
|
|
1
|
+
{"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"5.4.10","private":true}
|
package/layouts/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"5.4.
|
|
1
|
+
{"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"5.4.10","private":true}
|
package/next/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"5.4.
|
|
1
|
+
{"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"5.4.10","private":true}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/react-core",
|
|
3
|
-
"version": "5.4.
|
|
3
|
+
"version": "5.4.11",
|
|
4
4
|
"description": "This library provides a set of common React components for use with the PatternFly reference implementation.",
|
|
5
5
|
"main": "dist/js/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"react": "^17 || ^18",
|
|
63
63
|
"react-dom": "^17 || ^18"
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "2c6037ef6cfae35bdd0377fdc0f59020729b5138"
|
|
66
66
|
}
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { css } from '@patternfly/react-styles';
|
|
3
3
|
import { Menu, MenuContent, MenuProps } from '../Menu';
|
|
4
4
|
import { Popper } from '../../helpers/Popper/Popper';
|
|
5
|
-
import { useOUIAProps, OUIAProps } from '../../helpers';
|
|
5
|
+
import { useOUIAProps, OUIAProps, onToggleArrowKeydownDefault } from '../../helpers';
|
|
6
6
|
|
|
7
7
|
export interface DropdownPopperProps {
|
|
8
8
|
/** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */
|
|
@@ -51,6 +51,8 @@ export interface DropdownProps extends MenuProps, OUIAProps {
|
|
|
51
51
|
onOpenChange?: (isOpen: boolean) => void;
|
|
52
52
|
/** @beta Keys that trigger onOpenChange, defaults to tab and escape. It is highly recommended to include Escape in the array, while Tab may be omitted if the menu contains non-menu items that are focusable. */
|
|
53
53
|
onOpenChangeKeys?: string[];
|
|
54
|
+
/** Callback to override the toggle keydown behavior. By default, when the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key. */
|
|
55
|
+
onToggleKeydown?: (event: KeyboardEvent) => void;
|
|
54
56
|
/** Indicates if the menu should be without the outer box-shadow. */
|
|
55
57
|
isPlain?: boolean;
|
|
56
58
|
/** Indicates if the menu should be scrollable. */
|
|
@@ -85,6 +87,7 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
|
|
|
85
87
|
toggle,
|
|
86
88
|
shouldFocusToggleOnSelect = false,
|
|
87
89
|
onOpenChange,
|
|
90
|
+
onToggleKeydown,
|
|
88
91
|
isPlain,
|
|
89
92
|
isScrollable,
|
|
90
93
|
innerRef,
|
|
@@ -123,6 +126,14 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
|
|
|
123
126
|
toggleRef.current?.focus();
|
|
124
127
|
}
|
|
125
128
|
}
|
|
129
|
+
|
|
130
|
+
if (toggleRef.current?.contains(event.target as Node)) {
|
|
131
|
+
if (onToggleKeydown) {
|
|
132
|
+
onToggleKeydown(event);
|
|
133
|
+
} else if (isOpen) {
|
|
134
|
+
onToggleArrowKeydownDefault(event, menuRef);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
126
137
|
};
|
|
127
138
|
|
|
128
139
|
const handleClick = (event: MouseEvent) => {
|
|
@@ -157,6 +168,7 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
|
|
|
157
168
|
toggleRef,
|
|
158
169
|
onOpenChange,
|
|
159
170
|
onOpenChangeKeys,
|
|
171
|
+
onToggleKeydown,
|
|
160
172
|
shouldPreventScrollOnItemFocus,
|
|
161
173
|
shouldFocusFirstItemOnOpen,
|
|
162
174
|
focusTimeoutDelay
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Popper } from '../../helpers
|
|
2
|
+
import { onToggleArrowKeydownDefault, Popper } from '../../helpers';
|
|
3
3
|
|
|
4
4
|
export interface MenuPopperProps {
|
|
5
5
|
/** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */
|
|
@@ -17,6 +17,7 @@ export interface MenuPopperProps {
|
|
|
17
17
|
/** Flag to prevent the popper from overflowing its container and becoming partially obscured. */
|
|
18
18
|
preventOverflow?: boolean;
|
|
19
19
|
}
|
|
20
|
+
|
|
20
21
|
export interface MenuContainerProps {
|
|
21
22
|
/** Menu to be rendered */
|
|
22
23
|
menu: React.ReactElement<any, string | React.JSXElementConstructor<any>>;
|
|
@@ -33,10 +34,14 @@ export interface MenuContainerProps {
|
|
|
33
34
|
onOpenChange?: (isOpen: boolean) => void;
|
|
34
35
|
/** Keys that trigger onOpenChange, defaults to tab and escape. It is highly recommended to include Escape in the array, while Tab may be omitted if the menu contains non-menu items that are focusable. */
|
|
35
36
|
onOpenChangeKeys?: string[];
|
|
37
|
+
/** Callback to override the toggle keydown behavior. By default, when the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key. */
|
|
38
|
+
onToggleKeydown?: (event: KeyboardEvent) => void;
|
|
36
39
|
/** z-index of the dropdown menu */
|
|
37
40
|
zIndex?: number;
|
|
38
41
|
/** Additional properties to pass to the Popper */
|
|
39
42
|
popperProps?: MenuPopperProps;
|
|
43
|
+
/** @beta Flag indicating the first menu item should be focused after opening the dropdown. */
|
|
44
|
+
shouldFocusFirstItemOnOpen?: boolean;
|
|
40
45
|
/** Flag indicating if scroll on focus of the first menu item should occur. */
|
|
41
46
|
shouldPreventScrollOnItemFocus?: boolean;
|
|
42
47
|
/** Time in ms to wait before firing the toggles' focus event. Defaults to 0 */
|
|
@@ -54,12 +59,30 @@ export const MenuContainer: React.FunctionComponent<MenuContainerProps> = ({
|
|
|
54
59
|
toggle,
|
|
55
60
|
toggleRef,
|
|
56
61
|
onOpenChange,
|
|
62
|
+
onToggleKeydown,
|
|
57
63
|
zIndex = 9999,
|
|
58
64
|
popperProps,
|
|
59
65
|
onOpenChangeKeys = ['Escape', 'Tab'],
|
|
66
|
+
shouldFocusFirstItemOnOpen = false,
|
|
60
67
|
shouldPreventScrollOnItemFocus = true,
|
|
61
68
|
focusTimeoutDelay = 0
|
|
62
69
|
}: MenuContainerProps) => {
|
|
70
|
+
const prevIsOpen = React.useRef<boolean>(isOpen);
|
|
71
|
+
React.useEffect(() => {
|
|
72
|
+
// menu was opened, focus on first menu item
|
|
73
|
+
if (prevIsOpen.current === false && isOpen === true && shouldFocusFirstItemOnOpen) {
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
const firstElement = menuRef?.current?.querySelector(
|
|
76
|
+
'li button:not(:disabled),li input:not(:disabled),li a:not([aria-disabled="true"])'
|
|
77
|
+
);
|
|
78
|
+
firstElement && (firstElement as HTMLElement).focus({ preventScroll: shouldPreventScrollOnItemFocus });
|
|
79
|
+
}, focusTimeoutDelay);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
prevIsOpen.current = isOpen;
|
|
83
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
84
|
+
}, [isOpen]);
|
|
85
|
+
|
|
63
86
|
React.useEffect(() => {
|
|
64
87
|
const handleMenuKeys = (event: KeyboardEvent) => {
|
|
65
88
|
// Close the menu on tab or escape if onOpenChange is provided
|
|
@@ -72,19 +95,17 @@ export const MenuContainer: React.FunctionComponent<MenuContainerProps> = ({
|
|
|
72
95
|
toggleRef.current?.focus();
|
|
73
96
|
}
|
|
74
97
|
}
|
|
75
|
-
};
|
|
76
98
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
);
|
|
84
|
-
firstElement && (firstElement as HTMLElement).focus({ preventScroll: shouldPreventScrollOnItemFocus });
|
|
85
|
-
}, focusTimeoutDelay);
|
|
99
|
+
if (toggleRef.current?.contains(event.target as Node)) {
|
|
100
|
+
if (onToggleKeydown) {
|
|
101
|
+
onToggleKeydown(event);
|
|
102
|
+
} else if (isOpen) {
|
|
103
|
+
onToggleArrowKeydownDefault(event, menuRef);
|
|
104
|
+
}
|
|
86
105
|
}
|
|
106
|
+
};
|
|
87
107
|
|
|
108
|
+
const handleClick = (event: MouseEvent) => {
|
|
88
109
|
// If the event is not on the toggle and onOpenChange callback is provided, close the menu
|
|
89
110
|
if (isOpen && onOpenChange && !toggleRef?.current?.contains(event.target as Node)) {
|
|
90
111
|
if (isOpen && !menuRef.current?.contains(event.target as Node)) {
|
|
@@ -100,7 +121,16 @@ export const MenuContainer: React.FunctionComponent<MenuContainerProps> = ({
|
|
|
100
121
|
window.removeEventListener('keydown', handleMenuKeys);
|
|
101
122
|
window.removeEventListener('click', handleClick);
|
|
102
123
|
};
|
|
103
|
-
}, [
|
|
124
|
+
}, [
|
|
125
|
+
focusTimeoutDelay,
|
|
126
|
+
isOpen,
|
|
127
|
+
menuRef,
|
|
128
|
+
onOpenChange,
|
|
129
|
+
onOpenChangeKeys,
|
|
130
|
+
onToggleKeydown,
|
|
131
|
+
shouldPreventScrollOnItemFocus,
|
|
132
|
+
toggleRef
|
|
133
|
+
]);
|
|
104
134
|
|
|
105
135
|
return (
|
|
106
136
|
<Popper
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { css } from '@patternfly/react-styles';
|
|
3
3
|
import { Menu, MenuContent, MenuProps } from '../Menu';
|
|
4
4
|
import { Popper } from '../../helpers/Popper/Popper';
|
|
5
|
-
import { getOUIAProps, OUIAProps, getDefaultOUIAId } from '../../helpers';
|
|
5
|
+
import { getOUIAProps, OUIAProps, getDefaultOUIAId, onToggleArrowKeydownDefault } from '../../helpers';
|
|
6
6
|
|
|
7
7
|
export interface SelectPopperProps {
|
|
8
8
|
/** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */
|
|
@@ -62,6 +62,10 @@ export interface SelectProps extends MenuProps, OUIAProps {
|
|
|
62
62
|
onOpenChange?: (isOpen: boolean) => void;
|
|
63
63
|
/** @beta Keys that trigger onOpenChange, defaults to tab and escape. It is highly recommended to include Escape in the array, while Tab may be omitted if the menu contains non-menu items that are focusable. */
|
|
64
64
|
onOpenChangeKeys?: string[];
|
|
65
|
+
/** Callback to override the toggle keydown behavior. By default, when the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key. */
|
|
66
|
+
onToggleKeydown?: (event: KeyboardEvent) => void;
|
|
67
|
+
/** Select variant. For typeahead variant focus won't shift to menu items when pressing up/down arrows. */
|
|
68
|
+
variant?: 'default' | 'typeahead';
|
|
65
69
|
/** Indicates if the select should be without the outer box-shadow */
|
|
66
70
|
isPlain?: boolean;
|
|
67
71
|
/** @hide Forwarded ref */
|
|
@@ -95,6 +99,8 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
|
|
|
95
99
|
shouldFocusFirstItemOnOpen = false,
|
|
96
100
|
onOpenChange,
|
|
97
101
|
onOpenChangeKeys = ['Escape', 'Tab'],
|
|
102
|
+
onToggleKeydown,
|
|
103
|
+
variant,
|
|
98
104
|
isPlain,
|
|
99
105
|
innerRef,
|
|
100
106
|
zIndex = 9999,
|
|
@@ -130,6 +136,14 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
|
|
|
130
136
|
toggleRef.current?.focus();
|
|
131
137
|
}
|
|
132
138
|
}
|
|
139
|
+
|
|
140
|
+
if (toggleRef.current?.contains(event.target as Node)) {
|
|
141
|
+
if (onToggleKeydown) {
|
|
142
|
+
onToggleKeydown(event);
|
|
143
|
+
} else if (isOpen && variant !== 'typeahead') {
|
|
144
|
+
onToggleArrowKeydownDefault(event, menuRef);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
133
147
|
};
|
|
134
148
|
|
|
135
149
|
const handleClick = (event: MouseEvent) => {
|
|
@@ -162,6 +176,7 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
|
|
|
162
176
|
toggleRef,
|
|
163
177
|
onOpenChange,
|
|
164
178
|
onOpenChangeKeys,
|
|
179
|
+
onToggleKeydown,
|
|
165
180
|
shouldPreventScrollOnItemFocus,
|
|
166
181
|
shouldFocusFirstItemOnOpen,
|
|
167
182
|
focusTimeoutDelay
|
|
@@ -245,7 +245,7 @@ export const SelectMultiTypeahead: React.FunctionComponent = () => {
|
|
|
245
245
|
!isOpen && closeMenu();
|
|
246
246
|
}}
|
|
247
247
|
toggle={toggle}
|
|
248
|
-
|
|
248
|
+
variant="typeahead"
|
|
249
249
|
>
|
|
250
250
|
<SelectList isAriaMultiselectable id="select-multi-typeahead-listbox">
|
|
251
251
|
{selectOptions.map((option, index) => (
|
|
@@ -238,7 +238,7 @@ export const SelectMultiTypeaheadCheckbox: React.FunctionComponent = () => {
|
|
|
238
238
|
!isOpen && closeMenu();
|
|
239
239
|
}}
|
|
240
240
|
toggle={toggle}
|
|
241
|
-
|
|
241
|
+
variant="typeahead"
|
|
242
242
|
>
|
|
243
243
|
<SelectList isAriaMultiselectable id="select-multi-typeahead-checkbox-listbox">
|
|
244
244
|
{selectOptions.map((option, index) => (
|
|
@@ -256,7 +256,7 @@ export const SelectMultiTypeaheadCreatable: React.FunctionComponent = () => {
|
|
|
256
256
|
!isOpen && closeMenu();
|
|
257
257
|
}}
|
|
258
258
|
toggle={toggle}
|
|
259
|
-
|
|
259
|
+
variant="typeahead"
|
|
260
260
|
>
|
|
261
261
|
<SelectList isAriaMultiselectable id="select-multi-create-typeahead-listbox">
|
|
262
262
|
{selectOptions.map((option, index) => (
|
|
@@ -241,7 +241,7 @@ export const SelectTypeahead: React.FunctionComponent = () => {
|
|
|
241
241
|
!isOpen && closeMenu();
|
|
242
242
|
}}
|
|
243
243
|
toggle={toggle}
|
|
244
|
-
|
|
244
|
+
variant="typeahead"
|
|
245
245
|
>
|
|
246
246
|
<SelectList id="select-typeahead-listbox">
|
|
247
247
|
{selectOptions.map((option, index) => (
|
|
@@ -248,7 +248,7 @@ export const SelectTypeaheadCreatable: React.FunctionComponent = () => {
|
|
|
248
248
|
!isOpen && closeMenu();
|
|
249
249
|
}}
|
|
250
250
|
toggle={toggle}
|
|
251
|
-
|
|
251
|
+
variant="typeahead"
|
|
252
252
|
>
|
|
253
253
|
<SelectList id="select-create-typeahead-listbox">
|
|
254
254
|
{selectOptions.map((option, index) => (
|
|
@@ -170,6 +170,33 @@ export const setTabIndex = (options: HTMLElement[]) => {
|
|
|
170
170
|
}
|
|
171
171
|
};
|
|
172
172
|
|
|
173
|
+
/**
|
|
174
|
+
* This function is used in Dropdown, Select and MenuContainer as a default toggle keydown behavior. When the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key.
|
|
175
|
+
*
|
|
176
|
+
* @param event Event triggered by the keyboard
|
|
177
|
+
* @param menuRef Menu reference
|
|
178
|
+
*/
|
|
179
|
+
export const onToggleArrowKeydownDefault = (event: KeyboardEvent, menuRef: React.RefObject<HTMLDivElement>) => {
|
|
180
|
+
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
event.preventDefault();
|
|
185
|
+
|
|
186
|
+
const listItems = Array.from(menuRef.current?.querySelectorAll('li'));
|
|
187
|
+
const focusableElements = listItems
|
|
188
|
+
.map((li) => li.querySelector('button:not(:disabled),input:not(:disabled),a:not([aria-disabled="true"])'))
|
|
189
|
+
.filter((el) => el !== null);
|
|
190
|
+
|
|
191
|
+
let focusableElement: Element;
|
|
192
|
+
if (event.key === 'ArrowDown') {
|
|
193
|
+
focusableElement = focusableElements[0];
|
|
194
|
+
} else {
|
|
195
|
+
focusableElement = focusableElements[focusableElements.length - 1];
|
|
196
|
+
}
|
|
197
|
+
focusableElement && (focusableElement as HTMLElement).focus();
|
|
198
|
+
};
|
|
199
|
+
|
|
173
200
|
class KeyboardHandler extends React.Component<KeyboardHandlerProps> {
|
|
174
201
|
static displayName = 'KeyboardHandler';
|
|
175
202
|
static defaultProps: KeyboardHandlerProps = {
|