@patternfly/react-core 5.4.10 → 5.4.12
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 +12 -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/DualListSelector/DualListSelector.d.ts +4 -4
- package/dist/esm/components/DualListSelector/DualListSelector.d.ts.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelector.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/DualListSelector/DualListSelector.d.ts +4 -4
- package/dist/js/components/DualListSelector/DualListSelector.d.ts.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelector.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-CWjj_LpR.css} +14576 -14576
- 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/DualListSelector/DualListSelector.tsx +20 -20
- 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.11","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.11","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.11","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.12",
|
|
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": "0eb8f37580f7c68fec72396572aec0a8025881fd"
|
|
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
|
|
@@ -59,7 +59,7 @@ export interface DualListSelectorProps {
|
|
|
59
59
|
addSelectedAriaLabel?: string;
|
|
60
60
|
/** Tooltip content for the dynamically built add selected button */
|
|
61
61
|
addSelectedTooltip?: React.ReactNode;
|
|
62
|
-
/**
|
|
62
|
+
/** Additional tooltip properties for the dynamically built add selected tooltip */
|
|
63
63
|
addSelectedTooltipProps?: any;
|
|
64
64
|
/** Callback fired every time dynamically built options are chosen or removed */
|
|
65
65
|
onListChange?: (
|
|
@@ -73,7 +73,7 @@ export interface DualListSelectorProps {
|
|
|
73
73
|
addAllAriaLabel?: string;
|
|
74
74
|
/** Tooltip content for the dynamically built add all button */
|
|
75
75
|
addAllTooltip?: React.ReactNode;
|
|
76
|
-
/**
|
|
76
|
+
/** Additional tooltip properties for the dynamically built add all tooltip */
|
|
77
77
|
addAllTooltipProps?: any;
|
|
78
78
|
/** Optional callback for the dynamically built remove selected button */
|
|
79
79
|
removeSelected?: (newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void;
|
|
@@ -81,7 +81,7 @@ export interface DualListSelectorProps {
|
|
|
81
81
|
removeSelectedAriaLabel?: string;
|
|
82
82
|
/** Tooltip content for the dynamically built remove selected button */
|
|
83
83
|
removeSelectedTooltip?: React.ReactNode;
|
|
84
|
-
/**
|
|
84
|
+
/** Additional tooltip properties for the dynamically built remove selected tooltip */
|
|
85
85
|
removeSelectedTooltipProps?: any;
|
|
86
86
|
/** Optional callback for the dynamically built remove all button */
|
|
87
87
|
removeAll?: (newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void;
|
|
@@ -89,7 +89,7 @@ export interface DualListSelectorProps {
|
|
|
89
89
|
removeAllAriaLabel?: string;
|
|
90
90
|
/** Tooltip content for the dynamically built remove all button */
|
|
91
91
|
removeAllTooltip?: React.ReactNode;
|
|
92
|
-
/**
|
|
92
|
+
/** Additional tooltip properties for the dynamically built remove all tooltip */
|
|
93
93
|
removeAllTooltipProps?: any;
|
|
94
94
|
/** Optional callback fired when a dynamically built option is selected */
|
|
95
95
|
onOptionSelect?: (
|
|
@@ -286,8 +286,8 @@ class DualListSelector extends React.Component<DualListSelectorProps, DualListSe
|
|
|
286
286
|
chosenFilteredOptions: newChosen,
|
|
287
287
|
availableOptions: newAvailable,
|
|
288
288
|
availableFilteredOptions: newAvailable,
|
|
289
|
-
chosenOptionsSelected: [],
|
|
290
|
-
availableOptionsSelected: []
|
|
289
|
+
chosenOptionsSelected: [] as number[],
|
|
290
|
+
availableOptionsSelected: [] as number[]
|
|
291
291
|
};
|
|
292
292
|
});
|
|
293
293
|
};
|
|
@@ -319,8 +319,8 @@ class DualListSelector extends React.Component<DualListSelectorProps, DualListSe
|
|
|
319
319
|
chosenFilteredOptions: newChosen,
|
|
320
320
|
availableOptions: newAvailable,
|
|
321
321
|
availableFilteredOptions: newAvailable,
|
|
322
|
-
availableTreeOptionsChecked: [],
|
|
323
|
-
chosenTreeOptionsChecked: []
|
|
322
|
+
availableTreeOptionsChecked: [] as string[],
|
|
323
|
+
chosenTreeOptionsChecked: [] as string[]
|
|
324
324
|
};
|
|
325
325
|
});
|
|
326
326
|
};
|
|
@@ -342,8 +342,8 @@ class DualListSelector extends React.Component<DualListSelectorProps, DualListSe
|
|
|
342
342
|
this.props.onListChange && this.props.onListChange(event, newAvailable, newChosen);
|
|
343
343
|
|
|
344
344
|
return {
|
|
345
|
-
chosenOptionsSelected: [],
|
|
346
|
-
availableOptionsSelected: [],
|
|
345
|
+
chosenOptionsSelected: [] as number[],
|
|
346
|
+
availableOptionsSelected: [] as number[],
|
|
347
347
|
chosenOptions: newChosen,
|
|
348
348
|
chosenFilteredOptions: newChosen,
|
|
349
349
|
availableOptions: newAvailable,
|
|
@@ -374,8 +374,8 @@ class DualListSelector extends React.Component<DualListSelectorProps, DualListSe
|
|
|
374
374
|
this.props.onListChange && this.props.onListChange(event, newAvailable, newChosen);
|
|
375
375
|
|
|
376
376
|
return {
|
|
377
|
-
availableTreeOptionsChecked: [],
|
|
378
|
-
chosenTreeOptionsChecked: [],
|
|
377
|
+
availableTreeOptionsChecked: [] as string[],
|
|
378
|
+
chosenTreeOptionsChecked: [] as string[],
|
|
379
379
|
availableOptions: newAvailable,
|
|
380
380
|
chosenOptions: newChosen
|
|
381
381
|
};
|
|
@@ -404,8 +404,8 @@ class DualListSelector extends React.Component<DualListSelectorProps, DualListSe
|
|
|
404
404
|
chosenFilteredOptions: newChosen,
|
|
405
405
|
availableOptions: newAvailable,
|
|
406
406
|
availableFilteredOptions: newAvailable,
|
|
407
|
-
chosenOptionsSelected: [],
|
|
408
|
-
availableOptionsSelected: []
|
|
407
|
+
chosenOptionsSelected: [] as number[],
|
|
408
|
+
availableOptionsSelected: [] as number[]
|
|
409
409
|
};
|
|
410
410
|
});
|
|
411
411
|
};
|
|
@@ -433,8 +433,8 @@ class DualListSelector extends React.Component<DualListSelectorProps, DualListSe
|
|
|
433
433
|
return {
|
|
434
434
|
chosenOptions: newChosen,
|
|
435
435
|
availableOptions: newAvailable,
|
|
436
|
-
availableTreeOptionsChecked: [],
|
|
437
|
-
chosenTreeOptionsChecked: []
|
|
436
|
+
availableTreeOptionsChecked: [] as string[],
|
|
437
|
+
chosenTreeOptionsChecked: [] as string[]
|
|
438
438
|
};
|
|
439
439
|
});
|
|
440
440
|
};
|
|
@@ -456,8 +456,8 @@ class DualListSelector extends React.Component<DualListSelectorProps, DualListSe
|
|
|
456
456
|
this.props.onListChange && this.props.onListChange(event, newAvailable, newChosen);
|
|
457
457
|
|
|
458
458
|
return {
|
|
459
|
-
chosenOptionsSelected: [],
|
|
460
|
-
availableOptionsSelected: [],
|
|
459
|
+
chosenOptionsSelected: [] as number[],
|
|
460
|
+
availableOptionsSelected: [] as number[],
|
|
461
461
|
chosenOptions: newChosen,
|
|
462
462
|
chosenFilteredOptions: newChosen,
|
|
463
463
|
availableOptions: newAvailable,
|
|
@@ -488,8 +488,8 @@ class DualListSelector extends React.Component<DualListSelectorProps, DualListSe
|
|
|
488
488
|
this.props.onListChange && this.props.onListChange(event, newAvailable, newChosen);
|
|
489
489
|
|
|
490
490
|
return {
|
|
491
|
-
availableTreeOptionsChecked: [],
|
|
492
|
-
chosenTreeOptionsChecked: [],
|
|
491
|
+
availableTreeOptionsChecked: [] as string[],
|
|
492
|
+
chosenTreeOptionsChecked: [] as string[],
|
|
493
493
|
availableOptions: newAvailable,
|
|
494
494
|
chosenOptions: newChosen
|
|
495
495
|
};
|
|
@@ -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 = {
|