@patternfly/react-core 6.1.0-prerelease.8 → 6.1.0-prerelease.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 (165) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/components/package.json +1 -1
  3. package/deprecated/package.json +1 -1
  4. package/dist/dynamic/components/AboutModal/package.json +1 -1
  5. package/dist/dynamic/components/Accordion/package.json +1 -1
  6. package/dist/dynamic/components/ActionList/package.json +1 -1
  7. package/dist/dynamic/components/Alert/package.json +1 -1
  8. package/dist/dynamic/components/Avatar/package.json +1 -1
  9. package/dist/dynamic/components/BackToTop/package.json +1 -1
  10. package/dist/dynamic/components/Backdrop/package.json +1 -1
  11. package/dist/dynamic/components/BackgroundImage/package.json +1 -1
  12. package/dist/dynamic/components/Badge/package.json +1 -1
  13. package/dist/dynamic/components/Banner/package.json +1 -1
  14. package/dist/dynamic/components/Brand/package.json +1 -1
  15. package/dist/dynamic/components/Breadcrumb/package.json +1 -1
  16. package/dist/dynamic/components/Button/package.json +1 -1
  17. package/dist/dynamic/components/CalendarMonth/package.json +1 -1
  18. package/dist/dynamic/components/Card/package.json +1 -1
  19. package/dist/dynamic/components/Checkbox/package.json +1 -1
  20. package/dist/dynamic/components/ClipboardCopy/package.json +1 -1
  21. package/dist/dynamic/components/CodeBlock/package.json +1 -1
  22. package/dist/dynamic/components/Content/package.json +1 -1
  23. package/dist/dynamic/components/DataList/package.json +1 -1
  24. package/dist/dynamic/components/DatePicker/package.json +1 -1
  25. package/dist/dynamic/components/DescriptionList/package.json +1 -1
  26. package/dist/dynamic/components/Divider/package.json +1 -1
  27. package/dist/dynamic/components/Drawer/package.json +1 -1
  28. package/dist/dynamic/components/Dropdown/package.json +1 -1
  29. package/dist/dynamic/components/DualListSelector/package.json +1 -1
  30. package/dist/dynamic/components/EmptyState/package.json +1 -1
  31. package/dist/dynamic/components/ExpandableSection/package.json +1 -1
  32. package/dist/dynamic/components/FileUpload/package.json +1 -1
  33. package/dist/dynamic/components/Form/package.json +1 -1
  34. package/dist/dynamic/components/FormSelect/package.json +1 -1
  35. package/dist/dynamic/components/HelperText/package.json +1 -1
  36. package/dist/dynamic/components/Hint/package.json +1 -1
  37. package/dist/dynamic/components/Icon/package.json +1 -1
  38. package/dist/dynamic/components/InputGroup/package.json +1 -1
  39. package/dist/dynamic/components/JumpLinks/package.json +1 -1
  40. package/dist/dynamic/components/Label/package.json +1 -1
  41. package/dist/dynamic/components/List/package.json +1 -1
  42. package/dist/dynamic/components/LoginPage/package.json +1 -1
  43. package/dist/dynamic/components/Masthead/package.json +1 -1
  44. package/dist/dynamic/components/Menu/package.json +1 -1
  45. package/dist/dynamic/components/MenuToggle/package.json +1 -1
  46. package/dist/dynamic/components/Modal/package.json +1 -1
  47. package/dist/dynamic/components/MultipleFileUpload/package.json +1 -1
  48. package/dist/dynamic/components/Nav/package.json +1 -1
  49. package/dist/dynamic/components/NotificationBadge/package.json +1 -1
  50. package/dist/dynamic/components/NotificationDrawer/package.json +1 -1
  51. package/dist/dynamic/components/NumberInput/package.json +1 -1
  52. package/dist/dynamic/components/OverflowMenu/package.json +1 -1
  53. package/dist/dynamic/components/Page/package.json +1 -1
  54. package/dist/dynamic/components/Pagination/package.json +1 -1
  55. package/dist/dynamic/components/Panel/package.json +1 -1
  56. package/dist/dynamic/components/Popover/package.json +1 -1
  57. package/dist/dynamic/components/Progress/package.json +1 -1
  58. package/dist/dynamic/components/ProgressStepper/package.json +1 -1
  59. package/dist/dynamic/components/Radio/package.json +1 -1
  60. package/dist/dynamic/components/SearchInput/package.json +1 -1
  61. package/dist/dynamic/components/Select/package.json +1 -1
  62. package/dist/dynamic/components/Sidebar/package.json +1 -1
  63. package/dist/dynamic/components/SimpleList/package.json +1 -1
  64. package/dist/dynamic/components/Skeleton/package.json +1 -1
  65. package/dist/dynamic/components/SkipToContent/package.json +1 -1
  66. package/dist/dynamic/components/Slider/package.json +1 -1
  67. package/dist/dynamic/components/Spinner/package.json +1 -1
  68. package/dist/dynamic/components/Switch/package.json +1 -1
  69. package/dist/dynamic/components/Tabs/package.json +1 -1
  70. package/dist/dynamic/components/TextArea/package.json +1 -1
  71. package/dist/dynamic/components/TextInput/package.json +1 -1
  72. package/dist/dynamic/components/TextInputGroup/package.json +1 -1
  73. package/dist/dynamic/components/TimePicker/package.json +1 -1
  74. package/dist/dynamic/components/Timestamp/package.json +1 -1
  75. package/dist/dynamic/components/Title/package.json +1 -1
  76. package/dist/dynamic/components/ToggleGroup/package.json +1 -1
  77. package/dist/dynamic/components/Toolbar/package.json +1 -1
  78. package/dist/dynamic/components/Tooltip/package.json +1 -1
  79. package/dist/dynamic/components/TreeView/package.json +1 -1
  80. package/dist/dynamic/components/Truncate/package.json +1 -1
  81. package/dist/dynamic/components/Wizard/hooks/package.json +1 -1
  82. package/dist/dynamic/components/Wizard/package.json +1 -1
  83. package/dist/dynamic/deprecated/components/Chip/package.json +1 -1
  84. package/dist/dynamic/deprecated/components/DragDrop/package.json +1 -1
  85. package/dist/dynamic/deprecated/components/DualListSelector/package.json +1 -1
  86. package/dist/dynamic/deprecated/components/Modal/package.json +1 -1
  87. package/dist/dynamic/deprecated/components/Tile/package.json +1 -1
  88. package/dist/dynamic/deprecated/components/Wizard/package.json +1 -1
  89. package/dist/dynamic/deprecated/components/package.json +1 -1
  90. package/dist/dynamic/helpers/FocusTrap/FocusTrap/package.json +1 -1
  91. package/dist/dynamic/helpers/GenerateId/GenerateId/package.json +1 -1
  92. package/dist/dynamic/helpers/KeyboardHandler/package.json +1 -1
  93. package/dist/dynamic/helpers/OUIA/ouia/package.json +1 -1
  94. package/dist/dynamic/helpers/Popper/Popper/package.json +1 -1
  95. package/dist/dynamic/helpers/constants/package.json +1 -1
  96. package/dist/dynamic/helpers/datetimeUtils/package.json +1 -1
  97. package/dist/dynamic/helpers/fileUtils/package.json +1 -1
  98. package/dist/dynamic/helpers/htmlConstants/package.json +1 -1
  99. package/dist/dynamic/helpers/package.json +1 -1
  100. package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
  101. package/dist/dynamic/helpers/typeUtils/package.json +1 -1
  102. package/dist/dynamic/helpers/useInterval/package.json +1 -1
  103. package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
  104. package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
  105. package/dist/dynamic/helpers/util/package.json +1 -1
  106. package/dist/dynamic/layouts/Bullseye/package.json +1 -1
  107. package/dist/dynamic/layouts/Flex/package.json +1 -1
  108. package/dist/dynamic/layouts/Gallery/package.json +1 -1
  109. package/dist/dynamic/layouts/Grid/package.json +1 -1
  110. package/dist/dynamic/layouts/Level/package.json +1 -1
  111. package/dist/dynamic/layouts/Split/package.json +1 -1
  112. package/dist/dynamic/layouts/Stack/package.json +1 -1
  113. package/dist/dynamic/styles/package.json +1 -1
  114. package/dist/dynamic-modules.json +1 -0
  115. package/dist/esm/components/Dropdown/Dropdown.d.ts +2 -0
  116. package/dist/esm/components/Dropdown/Dropdown.d.ts.map +1 -1
  117. package/dist/esm/components/Dropdown/Dropdown.js +12 -3
  118. package/dist/esm/components/Dropdown/Dropdown.js.map +1 -1
  119. package/dist/esm/components/Menu/MenuContainer.d.ts +2 -0
  120. package/dist/esm/components/Menu/MenuContainer.d.ts.map +1 -1
  121. package/dist/esm/components/Menu/MenuContainer.js +21 -4
  122. package/dist/esm/components/Menu/MenuContainer.js.map +1 -1
  123. package/dist/esm/components/Select/Select.d.ts +4 -0
  124. package/dist/esm/components/Select/Select.d.ts.map +1 -1
  125. package/dist/esm/components/Select/Select.js +12 -3
  126. package/dist/esm/components/Select/Select.js.map +1 -1
  127. package/dist/esm/helpers/KeyboardHandler.d.ts +7 -0
  128. package/dist/esm/helpers/KeyboardHandler.d.ts.map +1 -1
  129. package/dist/esm/helpers/KeyboardHandler.js +25 -0
  130. package/dist/esm/helpers/KeyboardHandler.js.map +1 -1
  131. package/dist/js/components/Dropdown/Dropdown.d.ts +2 -0
  132. package/dist/js/components/Dropdown/Dropdown.d.ts.map +1 -1
  133. package/dist/js/components/Dropdown/Dropdown.js +11 -2
  134. package/dist/js/components/Dropdown/Dropdown.js.map +1 -1
  135. package/dist/js/components/Menu/MenuContainer.d.ts +2 -0
  136. package/dist/js/components/Menu/MenuContainer.d.ts.map +1 -1
  137. package/dist/js/components/Menu/MenuContainer.js +22 -5
  138. package/dist/js/components/Menu/MenuContainer.js.map +1 -1
  139. package/dist/js/components/Select/Select.d.ts +4 -0
  140. package/dist/js/components/Select/Select.d.ts.map +1 -1
  141. package/dist/js/components/Select/Select.js +11 -2
  142. package/dist/js/components/Select/Select.js.map +1 -1
  143. package/dist/js/helpers/KeyboardHandler.d.ts +7 -0
  144. package/dist/js/helpers/KeyboardHandler.d.ts.map +1 -1
  145. package/dist/js/helpers/KeyboardHandler.js +27 -1
  146. package/dist/js/helpers/KeyboardHandler.js.map +1 -1
  147. package/dist/umd/assets/{output-Df7FMwYL.css → output-B0G4u0sM.css} +3114 -3114
  148. package/dist/umd/react-core.min.js +3 -3
  149. package/helpers/package.json +1 -1
  150. package/layouts/package.json +1 -1
  151. package/next/package.json +1 -1
  152. package/package.json +3 -3
  153. package/src/components/DataList/examples/DataList.md +16 -4
  154. package/src/components/Dropdown/Dropdown.tsx +13 -1
  155. package/src/components/DualListSelector/examples/DualListSelector.md +16 -14
  156. package/src/components/FileUpload/__tests__/__snapshots__/FileUpload.test.tsx.snap +1 -1
  157. package/src/components/Menu/MenuContainer.tsx +24 -3
  158. package/src/components/MultipleFileUpload/__tests__/__snapshots__/MultipleFileUpload.test.tsx.snap +3 -3
  159. package/src/components/Select/Select.tsx +16 -1
  160. package/src/components/Select/examples/SelectMultiTypeahead.tsx +1 -1
  161. package/src/components/Select/examples/SelectMultiTypeaheadCheckbox.tsx +1 -1
  162. package/src/components/Select/examples/SelectMultiTypeaheadCreatable.tsx +1 -1
  163. package/src/components/Select/examples/SelectTypeahead.tsx +1 -1
  164. package/src/components/Select/examples/SelectTypeaheadCreatable.tsx +1 -1
  165. package/src/helpers/KeyboardHandler.tsx +27 -0
@@ -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":"6.1.0-prerelease.7","private":true}
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":"6.1.0-prerelease.8","private":true}
@@ -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":"6.1.0-prerelease.7","private":true}
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":"6.1.0-prerelease.8","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":"6.1.0-prerelease.7","private":true}
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":"6.1.0-prerelease.8","private":true}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "6.1.0-prerelease.8",
3
+ "version": "6.1.0-prerelease.9",
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",
@@ -50,7 +50,7 @@
50
50
  "@patternfly/react-styles": "^6.1.0-prerelease.3",
51
51
  "@patternfly/react-tokens": "^6.1.0-prerelease.3",
52
52
  "focus-trap": "7.6.2",
53
- "react-dropzone": "^14.2.3",
53
+ "react-dropzone": "^14.3.5",
54
54
  "tslib": "^2.8.1"
55
55
  },
56
56
  "devDependencies": {
@@ -63,5 +63,5 @@
63
63
  "react": "^17 || ^18",
64
64
  "react-dom": "^17 || ^18"
65
65
  },
66
- "gitHead": "0f9245023fb9bdf860c9eee91b6fe160b6c261c5"
66
+ "gitHead": "adb27fc981481c31bf249fb185ebc1850929cd87"
67
67
  }
@@ -23,7 +23,7 @@ import AngleDownIcon from '@patternfly/react-icons/dist/esm/icons/angle-down-ico
23
23
  import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
24
24
  import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
25
25
  import { css } from '@patternfly/react-styles';
26
- import { DragDrop, Draggable, Droppable } from '@patternfly/react-core/deprecated';
26
+ import { DragDropSort, DragDropContainer, Droppable as NewDroppable } from '@patternfly/react-drag-drop';
27
27
 
28
28
  ## Examples
29
29
 
@@ -83,11 +83,23 @@ import { DragDrop, Draggable, Droppable } from '@patternfly/react-core/deprecate
83
83
 
84
84
  ### Draggable
85
85
 
86
- Note: There is a new recommended drag and drop implementation with full keyboard functionality, which replaces this implementation. To adhere to our new recommendations, refer to the [drag and drop demos](/components/drag-and-drop/react-demos).
86
+ To enable drag and drop, wrap the `<DataList>` component with `<DragDropSort>`, define the `variant` property as "DataList", and pass both the sortable items and `onDrop` callback to `<DragDropSort>`. `<DragDropSort>` will create the component's usual children internally based on the items property, so children should not be passed to the wrapped component.
87
87
 
88
- Previously, draggable data lists had their own API for the [drag and drop component](/components/drag-and-drop), which wasn't flexible enough to allow custom styling for items as they are dragged. To address this disparity, `<DragDrop>`, `<Draggable>`, and `<Droppable>` components were added to replace our now deprecated HTML5-based API. Keyboard and screen reader accessibility for the `<DragDrop>` component is still in development.
88
+ Full drag and drop details can be found on the [drag and drop](/components/drag-and-drop) component page.
89
89
 
90
- ```ts isDeprecated file="./DataListDraggable.tsx"
90
+ ```ts file="../../../../../react-drag-drop/src/components/DragDrop/examples/DataListDraggable.tsx"
91
+
92
+ ```
93
+
94
+ ### Draggable with multiple drop zones
95
+
96
+ To enable multiple drop zones, and create the desired amount of `<Droppable>` components within a `<DragDropContainer>`.
97
+
98
+ Each `<Droppable>` should define the `wrapper` property as the component that acts as the drop zone, `<DataList>`, and the `items` property of their respective draggable items as an array of `<DraggableObject>` data. `<DragDropContainer>` should be passed the `onDrop`, `onContainerMove`, and `onCancel` callbacks to handle items being dropped, items moving between droppable containers, and what happens if the drag is cancelled respectively. `<DragDropContainer>` should also be given a `Record` representing all sortable drop zones' items. Both components should define the `variant` property as "DataList".
99
+
100
+ Full drag and drop details can be found on the [drag and drop](/components/drag-and-drop) component page.
101
+
102
+ ```ts file="../../../../../react-drag-drop/src/components/DragDrop/examples/DragDropContainerDataList.tsx"
91
103
 
92
104
  ```
93
105
 
@@ -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
  /** 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,
@@ -139,6 +142,14 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
139
142
  toggleRef.current?.focus();
140
143
  }
141
144
  }
145
+
146
+ if (toggleRef.current?.contains(event.target as Node)) {
147
+ if (onToggleKeydown) {
148
+ onToggleKeydown(event);
149
+ } else if (isOpen) {
150
+ onToggleArrowKeydownDefault(event, menuRef);
151
+ }
152
+ }
142
153
  };
143
154
 
144
155
  const handleClick = (event: MouseEvent) => {
@@ -163,6 +174,7 @@ const DropdownBase: React.FunctionComponent<DropdownProps> = ({
163
174
  toggleRef,
164
175
  onOpenChange,
165
176
  onOpenChangeKeys,
177
+ onToggleKeydown,
166
178
  shouldPreventScrollOnItemFocus,
167
179
  shouldFocusFirstItemOnOpen,
168
180
  focusTimeoutDelay
@@ -22,7 +22,7 @@ import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-i
22
22
  import PficonSortCommonAscIcon from '@patternfly/react-icons/dist/esm/icons/pficon-sort-common-asc-icon';
23
23
  import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
24
24
  import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
25
- import { DragDrop, Draggable, Droppable } from '@patternfly/react-core/deprecated';
25
+ import { DragDropSort, DragDropContainer, Droppable as NewDroppable } from '@patternfly/react-drag-drop';
26
26
 
27
27
  ## Examples
28
28
 
@@ -78,22 +78,24 @@ The dual list selector is built in a composable manner to make customization eas
78
78
 
79
79
  ```
80
80
 
81
- ### Drag and drop
81
+ ### Draggable
82
82
 
83
- This example only allows reordering the contents of the "chosen" pane with drag and drop. To make a pane able to be reordered:
83
+ To enable drag and drop, wrap the `<DualListSelectorList>` component with `<DragDropSort>`, define the `variant` property as "DualListSelectorList", and pass both the sortable items and `onDrop` callback to `<DragDropSort>`. `<DragDropSort>` will create the component's usual children internally based on the items property, so children inside the `<DualListSelectorList>` should not be passed to the wrapped component.
84
84
 
85
- - wrap the `DualListSelectorPane` in a `DragDrop` component
86
- - wrap the `DualListSelectorList` in a `Droppable` component
87
- - wrap the `DualListSelectorListItem` components in a `Draggable` component
88
- - define an `onDrop` callback which reorders the sortable options.
89
- - The `onDrop` function provides the starting location and destination location for a dragged item. It should return
90
- true to enable the 'drop' animation in the new location and false to enable the 'drop' animation back to the item's
91
- old position.
92
- - define an `onDrag` callback which ensures that the drag event will not cross hairs with the `onOptionSelect` click
93
- event set on the option. Note: the `ignoreNextOptionSelect` state value is used to prevent selection while dragging.
85
+ Full drag and drop details can be found on the [drag and drop](/components/drag-and-drop) component page.
94
86
 
95
- Note: Keyboard accessibility and screen reader accessibility for the `DragDrop` component are still in development.
87
+ ```ts file="../../../../../react-drag-drop/src/components/DragDrop/examples/DualListSelectorDraggable.tsx"
96
88
 
97
- ```ts file="DualListSelectorDragDrop.tsx"
89
+ ```
90
+
91
+ ### Draggable with multiple drop zones
92
+
93
+ To enable multiple drop zones, wrap the `<DualListSelector>` component with `<DragDropContainer>`, and create the desired amount of `<Droppable>` components within `<DragDropContainer>`. `<Droppable>` components should be located where `<DualListSelectorList>` usually would go for each pane to be made draggable.
94
+
95
+ Each `<Droppable>` should define the `wrapper` property as the component that acts as the drop zone, `<DualListSelectorList>`, and the `items` property of their respective draggable items as an array of `<DraggableObject>` data. `<DragDropContainer>` should be passed the `onDrop`, `onContainerMove`, and `onCancel` callbacks to handle items being dropped, items moving between droppable containers, and what happens if the drag is cancelled respectively. `<DragDropContainer>` should also be given a `Record` representing all sortable drop zones' items. Both components should define the `variant` property as "DualListSelectorList".
96
+
97
+ Full drag and drop details can be found on the [drag and drop](/components/drag-and-drop) component page.
98
+
99
+ ```ts file="../../../../../react-drag-drop/src/components/DragDrop/examples/DragDropContainerDualListSelector.tsx"
98
100
 
99
101
  ```
@@ -87,7 +87,7 @@ exports[`simple fileupload 1`] = `
87
87
  </span>
88
88
  </div>
89
89
  <input
90
- style="display: none;"
90
+ style="border: 0px; clip: rect(0px, 0px, 0px, 0px); clip-path: inset(50%); height: 1px; margin: 0px -1px -1px 0px; overflow: hidden; padding: 0px; position: absolute; width: 1px; white-space: nowrap;"
91
91
  tabindex="-1"
92
92
  type="file"
93
93
  />
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { Popper } from '../../helpers/Popper/Popper';
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,6 +34,8 @@ 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 */
@@ -55,10 +58,11 @@ export const MenuContainer: React.FunctionComponent<MenuContainerProps> = ({
55
58
  toggle,
56
59
  toggleRef,
57
60
  onOpenChange,
61
+ onToggleKeydown,
58
62
  zIndex = 9999,
59
63
  popperProps,
60
64
  onOpenChangeKeys = ['Escape', 'Tab'],
61
- shouldFocusFirstItemOnOpen = true,
65
+ shouldFocusFirstItemOnOpen = false,
62
66
  shouldPreventScrollOnItemFocus = true,
63
67
  focusTimeoutDelay = 0
64
68
  }: MenuContainerProps) => {
@@ -90,6 +94,14 @@ export const MenuContainer: React.FunctionComponent<MenuContainerProps> = ({
90
94
  toggleRef.current?.focus();
91
95
  }
92
96
  }
97
+
98
+ if (toggleRef.current?.contains(event.target as Node)) {
99
+ if (onToggleKeydown) {
100
+ onToggleKeydown(event);
101
+ } else if (isOpen) {
102
+ onToggleArrowKeydownDefault(event, menuRef);
103
+ }
104
+ }
93
105
  };
94
106
 
95
107
  const handleClick = (event: MouseEvent) => {
@@ -108,7 +120,16 @@ export const MenuContainer: React.FunctionComponent<MenuContainerProps> = ({
108
120
  window.removeEventListener('keydown', handleMenuKeys);
109
121
  window.removeEventListener('click', handleClick);
110
122
  };
111
- }, [focusTimeoutDelay, isOpen, menuRef, onOpenChange, onOpenChangeKeys, shouldPreventScrollOnItemFocus, toggleRef]);
123
+ }, [
124
+ focusTimeoutDelay,
125
+ isOpen,
126
+ menuRef,
127
+ onOpenChange,
128
+ onOpenChangeKeys,
129
+ onToggleKeydown,
130
+ shouldPreventScrollOnItemFocus,
131
+ toggleRef
132
+ ]);
112
133
 
113
134
  return (
114
135
  <Popper
@@ -9,7 +9,7 @@ exports[`MultipleFileUpload renders custom class names 1`] = `
9
9
  >
10
10
  <input
11
11
  multiple=""
12
- style="display: none;"
12
+ style="border: 0px; clip: rect(0px, 0px, 0px, 0px); clip-path: inset(50%); height: 1px; margin: 0px -1px -1px 0px; overflow: hidden; padding: 0px; position: absolute; width: 1px; white-space: nowrap;"
13
13
  tabindex="-1"
14
14
  type="file"
15
15
  />
@@ -27,7 +27,7 @@ exports[`MultipleFileUpload renders with expected class names when horizontal 1`
27
27
  >
28
28
  <input
29
29
  multiple=""
30
- style="display: none;"
30
+ style="border: 0px; clip: rect(0px, 0px, 0px, 0px); clip-path: inset(50%); height: 1px; margin: 0px -1px -1px 0px; overflow: hidden; padding: 0px; position: absolute; width: 1px; white-space: nowrap;"
31
31
  tabindex="-1"
32
32
  type="file"
33
33
  />
@@ -45,7 +45,7 @@ exports[`MultipleFileUpload renders with expected class names when not horizonta
45
45
  >
46
46
  <input
47
47
  multiple=""
48
- style="display: none;"
48
+ style="border: 0px; clip: rect(0px, 0px, 0px, 0px); clip-path: inset(50%); height: 1px; margin: 0px -1px -1px 0px; overflow: hidden; padding: 0px; position: absolute; width: 1px; white-space: nowrap;"
49
49
  tabindex="-1"
50
50
  type="file"
51
51
  />
@@ -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
  /** 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,
@@ -144,6 +150,14 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
144
150
  toggleRef.current?.focus();
145
151
  }
146
152
  }
153
+
154
+ if (toggleRef.current?.contains(event.target as Node)) {
155
+ if (onToggleKeydown) {
156
+ onToggleKeydown(event);
157
+ } else if (isOpen && variant !== 'typeahead') {
158
+ onToggleArrowKeydownDefault(event, menuRef);
159
+ }
160
+ }
147
161
  };
148
162
 
149
163
  const handleClick = (event: MouseEvent) => {
@@ -168,6 +182,7 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
168
182
  toggleRef,
169
183
  onOpenChange,
170
184
  onOpenChangeKeys,
185
+ onToggleKeydown,
171
186
  shouldPreventScrollOnItemFocus,
172
187
  shouldFocusFirstItemOnOpen,
173
188
  focusTimeoutDelay
@@ -247,7 +247,7 @@ export const SelectMultiTypeahead: React.FunctionComponent = () => {
247
247
  !isOpen && closeMenu();
248
248
  }}
249
249
  toggle={toggle}
250
- shouldFocusFirstItemOnOpen={false}
250
+ variant="typeahead"
251
251
  >
252
252
  <SelectList isAriaMultiselectable id="select-multi-typeahead-listbox">
253
253
  {selectOptions.map((option, index) => (
@@ -241,7 +241,7 @@ export const SelectMultiTypeaheadCheckbox: React.FunctionComponent = () => {
241
241
  !isOpen && closeMenu();
242
242
  }}
243
243
  toggle={toggle}
244
- shouldFocusFirstItemOnOpen={false}
244
+ variant="typeahead"
245
245
  >
246
246
  <SelectList isAriaMultiselectable id="select-multi-typeahead-checkbox-listbox">
247
247
  {selectOptions.map((option, index) => (
@@ -260,7 +260,7 @@ export const SelectMultiTypeaheadCreatable: React.FunctionComponent = () => {
260
260
  !isOpen && closeMenu();
261
261
  }}
262
262
  toggle={toggle}
263
- shouldFocusFirstItemOnOpen={false}
263
+ variant="typeahead"
264
264
  >
265
265
  <SelectList isAriaMultiselectable id="select-multi-create-typeahead-listbox">
266
266
  {selectOptions.map((option, index) => (
@@ -244,7 +244,7 @@ export const SelectTypeahead: React.FunctionComponent = () => {
244
244
  !isOpen && closeMenu();
245
245
  }}
246
246
  toggle={toggle}
247
- shouldFocusFirstItemOnOpen={false}
247
+ variant="typeahead"
248
248
  >
249
249
  <SelectList id="select-typeahead-listbox">
250
250
  {selectOptions.map((option, index) => (
@@ -251,7 +251,7 @@ export const SelectTypeaheadCreatable: React.FunctionComponent = () => {
251
251
  !isOpen && closeMenu();
252
252
  }}
253
253
  toggle={toggle}
254
- shouldFocusFirstItemOnOpen={false}
254
+ variant="typeahead"
255
255
  >
256
256
  <SelectList id="select-create-typeahead-listbox">
257
257
  {selectOptions.map((option, index) => (
@@ -176,6 +176,33 @@ export const setTabIndex = (options: HTMLElement[]) => {
176
176
  }
177
177
  };
178
178
 
179
+ /**
180
+ * 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.
181
+ *
182
+ * @param event Event triggered by the keyboard
183
+ * @param menuRef Menu reference
184
+ */
185
+ export const onToggleArrowKeydownDefault = (event: KeyboardEvent, menuRef: React.RefObject<HTMLDivElement>) => {
186
+ if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
187
+ return;
188
+ }
189
+
190
+ event.preventDefault();
191
+
192
+ const listItems = Array.from(menuRef.current?.querySelectorAll('li'));
193
+ const focusableElements = listItems
194
+ .map((li) => li.querySelector('button:not(:disabled),input:not(:disabled),a:not([aria-disabled="true"])'))
195
+ .filter((el) => el !== null);
196
+
197
+ let focusableElement: Element;
198
+ if (event.key === 'ArrowDown') {
199
+ focusableElement = focusableElements[0];
200
+ } else {
201
+ focusableElement = focusableElements[focusableElements.length - 1];
202
+ }
203
+ focusableElement && (focusableElement as HTMLElement).focus();
204
+ };
205
+
179
206
  class KeyboardHandler extends React.Component<KeyboardHandlerProps> {
180
207
  static displayName = 'KeyboardHandler';
181
208
  static defaultProps: KeyboardHandlerProps = {