@patternfly/react-core 5.4.0-prerelease.1 → 5.4.0-prerelease.3

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 (187) hide show
  1. package/CHANGELOG.md +10 -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/Chip/package.json +1 -1
  21. package/dist/dynamic/components/ClipboardCopy/package.json +1 -1
  22. package/dist/dynamic/components/CodeBlock/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/DragDrop/package.json +1 -1
  28. package/dist/dynamic/components/Drawer/package.json +1 -1
  29. package/dist/dynamic/components/Dropdown/package.json +1 -1
  30. package/dist/dynamic/components/DualListSelector/package.json +1 -1
  31. package/dist/dynamic/components/EmptyState/package.json +1 -1
  32. package/dist/dynamic/components/ExpandableSection/package.json +1 -1
  33. package/dist/dynamic/components/FileUpload/package.json +1 -1
  34. package/dist/dynamic/components/Form/package.json +1 -1
  35. package/dist/dynamic/components/FormSelect/package.json +1 -1
  36. package/dist/dynamic/components/HelperText/package.json +1 -1
  37. package/dist/dynamic/components/Hint/package.json +1 -1
  38. package/dist/dynamic/components/Icon/package.json +1 -1
  39. package/dist/dynamic/components/InputGroup/package.json +1 -1
  40. package/dist/dynamic/components/JumpLinks/package.json +1 -1
  41. package/dist/dynamic/components/Label/package.json +1 -1
  42. package/dist/dynamic/components/List/package.json +1 -1
  43. package/dist/dynamic/components/LoginPage/package.json +1 -1
  44. package/dist/dynamic/components/Masthead/package.json +1 -1
  45. package/dist/dynamic/components/Menu/package.json +1 -1
  46. package/dist/dynamic/components/MenuToggle/package.json +1 -1
  47. package/dist/dynamic/components/Modal/package.json +1 -1
  48. package/dist/dynamic/components/MultipleFileUpload/package.json +1 -1
  49. package/dist/dynamic/components/Nav/package.json +1 -1
  50. package/dist/dynamic/components/NotificationBadge/package.json +1 -1
  51. package/dist/dynamic/components/NotificationDrawer/package.json +1 -1
  52. package/dist/dynamic/components/NumberInput/package.json +1 -1
  53. package/dist/dynamic/components/OverflowMenu/package.json +1 -1
  54. package/dist/dynamic/components/Page/package.json +1 -1
  55. package/dist/dynamic/components/Pagination/package.json +1 -1
  56. package/dist/dynamic/components/Panel/package.json +1 -1
  57. package/dist/dynamic/components/Popover/package.json +1 -1
  58. package/dist/dynamic/components/Progress/package.json +1 -1
  59. package/dist/dynamic/components/ProgressStepper/package.json +1 -1
  60. package/dist/dynamic/components/Radio/package.json +1 -1
  61. package/dist/dynamic/components/SearchInput/package.json +1 -1
  62. package/dist/dynamic/components/Select/package.json +1 -1
  63. package/dist/dynamic/components/Sidebar/package.json +1 -1
  64. package/dist/dynamic/components/SimpleList/package.json +1 -1
  65. package/dist/dynamic/components/Skeleton/package.json +1 -1
  66. package/dist/dynamic/components/SkipToContent/package.json +1 -1
  67. package/dist/dynamic/components/Slider/package.json +1 -1
  68. package/dist/dynamic/components/Spinner/package.json +1 -1
  69. package/dist/dynamic/components/Switch/package.json +1 -1
  70. package/dist/dynamic/components/Tabs/package.json +1 -1
  71. package/dist/dynamic/components/Text/package.json +1 -1
  72. package/dist/dynamic/components/TextArea/package.json +1 -1
  73. package/dist/dynamic/components/TextInput/package.json +1 -1
  74. package/dist/dynamic/components/TextInputGroup/package.json +1 -1
  75. package/dist/dynamic/components/Tile/package.json +1 -1
  76. package/dist/dynamic/components/TimePicker/package.json +1 -1
  77. package/dist/dynamic/components/Timestamp/package.json +1 -1
  78. package/dist/dynamic/components/Title/package.json +1 -1
  79. package/dist/dynamic/components/ToggleGroup/package.json +1 -1
  80. package/dist/dynamic/components/Toolbar/package.json +1 -1
  81. package/dist/dynamic/components/Tooltip/package.json +1 -1
  82. package/dist/dynamic/components/TreeView/package.json +1 -1
  83. package/dist/dynamic/components/Truncate/package.json +1 -1
  84. package/dist/dynamic/components/Wizard/hooks/package.json +1 -1
  85. package/dist/dynamic/components/Wizard/package.json +1 -1
  86. package/dist/dynamic/deprecated/components/ApplicationLauncher/package.json +1 -1
  87. package/dist/dynamic/deprecated/components/ContextSelector/package.json +1 -1
  88. package/dist/dynamic/deprecated/components/Dropdown/package.json +1 -1
  89. package/dist/dynamic/deprecated/components/OptionsMenu/package.json +1 -1
  90. package/dist/dynamic/deprecated/components/PageHeader/package.json +1 -1
  91. package/dist/dynamic/deprecated/components/Select/package.json +1 -1
  92. package/dist/dynamic/deprecated/components/Wizard/package.json +1 -1
  93. package/dist/dynamic/deprecated/components/package.json +1 -1
  94. package/dist/dynamic/helpers/FocusTrap/FocusTrap/package.json +1 -1
  95. package/dist/dynamic/helpers/GenerateId/GenerateId/package.json +1 -1
  96. package/dist/dynamic/helpers/KeyboardHandler/package.json +1 -1
  97. package/dist/dynamic/helpers/OUIA/ouia/package.json +1 -1
  98. package/dist/dynamic/helpers/Popper/Popper/package.json +1 -1
  99. package/dist/dynamic/helpers/constants/package.json +1 -1
  100. package/dist/dynamic/helpers/datetimeUtils/package.json +1 -1
  101. package/dist/dynamic/helpers/favorites/package.json +1 -1
  102. package/dist/dynamic/helpers/fileUtils/package.json +1 -1
  103. package/dist/dynamic/helpers/htmlConstants/package.json +1 -1
  104. package/dist/dynamic/helpers/package.json +1 -1
  105. package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
  106. package/dist/dynamic/helpers/typeUtils/package.json +1 -1
  107. package/dist/dynamic/helpers/useInterval/package.json +1 -1
  108. package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
  109. package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
  110. package/dist/dynamic/helpers/util/package.json +1 -1
  111. package/dist/dynamic/layouts/Bullseye/package.json +1 -1
  112. package/dist/dynamic/layouts/Flex/package.json +1 -1
  113. package/dist/dynamic/layouts/Gallery/package.json +1 -1
  114. package/dist/dynamic/layouts/Grid/package.json +1 -1
  115. package/dist/dynamic/layouts/Level/package.json +1 -1
  116. package/dist/dynamic/layouts/Split/package.json +1 -1
  117. package/dist/dynamic/layouts/Stack/package.json +1 -1
  118. package/dist/dynamic/next/components/DualListSelector/package.json +1 -1
  119. package/dist/dynamic/next/components/Modal/package.json +1 -1
  120. package/dist/dynamic/next/components/package.json +1 -1
  121. package/dist/dynamic/styles/package.json +1 -1
  122. package/dist/dynamic-modules.json +772 -0
  123. package/dist/esm/components/NumberInput/NumberInput.d.ts.map +1 -1
  124. package/dist/esm/components/NumberInput/NumberInput.js +4 -3
  125. package/dist/esm/components/NumberInput/NumberInput.js.map +1 -1
  126. package/dist/esm/components/Pagination/Navigation.d.ts +3 -3
  127. package/dist/esm/components/Pagination/Navigation.d.ts.map +1 -1
  128. package/dist/esm/components/Pagination/Navigation.js.map +1 -1
  129. package/dist/esm/components/Pagination/Pagination.d.ts +1 -1
  130. package/dist/esm/components/Pagination/Pagination.d.ts.map +1 -1
  131. package/dist/esm/components/TreeView/TreeView.d.ts +13 -0
  132. package/dist/esm/components/TreeView/TreeView.d.ts.map +1 -1
  133. package/dist/esm/components/TreeView/TreeView.js +2 -2
  134. package/dist/esm/components/TreeView/TreeView.js.map +1 -1
  135. package/dist/esm/components/TreeView/TreeViewList.d.ts +13 -0
  136. package/dist/esm/components/TreeView/TreeViewList.d.ts.map +1 -1
  137. package/dist/esm/components/TreeView/TreeViewList.js +2 -2
  138. package/dist/esm/components/TreeView/TreeViewList.js.map +1 -1
  139. package/dist/esm/components/TreeView/TreeViewListItem.d.ts.map +1 -1
  140. package/dist/esm/components/TreeView/TreeViewListItem.js +8 -8
  141. package/dist/esm/components/TreeView/TreeViewListItem.js.map +1 -1
  142. package/dist/js/components/NumberInput/NumberInput.d.ts.map +1 -1
  143. package/dist/js/components/NumberInput/NumberInput.js +4 -3
  144. package/dist/js/components/NumberInput/NumberInput.js.map +1 -1
  145. package/dist/js/components/Pagination/Navigation.d.ts +3 -3
  146. package/dist/js/components/Pagination/Navigation.d.ts.map +1 -1
  147. package/dist/js/components/Pagination/Navigation.js.map +1 -1
  148. package/dist/js/components/Pagination/Pagination.d.ts +1 -1
  149. package/dist/js/components/Pagination/Pagination.d.ts.map +1 -1
  150. package/dist/js/components/TreeView/TreeView.d.ts +13 -0
  151. package/dist/js/components/TreeView/TreeView.d.ts.map +1 -1
  152. package/dist/js/components/TreeView/TreeView.js +2 -2
  153. package/dist/js/components/TreeView/TreeView.js.map +1 -1
  154. package/dist/js/components/TreeView/TreeViewList.d.ts +13 -0
  155. package/dist/js/components/TreeView/TreeViewList.d.ts.map +1 -1
  156. package/dist/js/components/TreeView/TreeViewList.js +2 -2
  157. package/dist/js/components/TreeView/TreeViewList.js.map +1 -1
  158. package/dist/js/components/TreeView/TreeViewListItem.d.ts.map +1 -1
  159. package/dist/js/components/TreeView/TreeViewListItem.js +8 -8
  160. package/dist/js/components/TreeView/TreeViewListItem.js.map +1 -1
  161. package/dist/umd/react-core.min.js +8 -8
  162. package/helpers/package.json +1 -1
  163. package/layouts/package.json +1 -1
  164. package/next/package.json +1 -1
  165. package/package.json +6 -7
  166. package/src/components/NumberInput/NumberInput.tsx +5 -3
  167. package/src/components/Pagination/Navigation.tsx +12 -12
  168. package/src/components/Pagination/Pagination.tsx +1 -1
  169. package/src/components/TreeView/TreeView.tsx +23 -1
  170. package/src/components/TreeView/TreeViewList.tsx +24 -1
  171. package/src/components/TreeView/TreeViewListItem.tsx +13 -7
  172. package/src/components/TreeView/__tests__/__snapshots__/TreeViewList.test.tsx.snap +2 -0
  173. package/src/components/TreeView/__tests__/__snapshots__/TreeViewListItem.test.tsx.snap +2 -0
  174. package/src/components/TreeView/examples/TreeView.md +12 -2
  175. package/src/components/TreeView/examples/TreeViewCompact.tsx +1 -1
  176. package/src/components/TreeView/examples/TreeViewCompactNoBackground.tsx +1 -1
  177. package/src/components/TreeView/examples/TreeViewGuides.tsx +1 -1
  178. package/src/components/TreeView/examples/TreeViewMultiselectable.tsx +86 -0
  179. package/src/components/TreeView/examples/TreeViewSelectionExpansion.tsx +9 -1
  180. package/src/components/TreeView/examples/{TreeViewDefault.tsx → TreeViewSingleSelectable.tsx} +8 -2
  181. package/src/components/TreeView/examples/TreeViewWithActionItems.tsx +8 -1
  182. package/src/components/TreeView/examples/TreeViewWithBadges.tsx +9 -1
  183. package/src/components/TreeView/examples/TreeViewWithCheckboxes.tsx +1 -1
  184. package/src/components/TreeView/examples/TreeViewWithCustomBadges.tsx +9 -1
  185. package/src/components/TreeView/examples/TreeViewWithIcons.tsx +1 -0
  186. package/src/components/TreeView/examples/TreeViewWithMemoization.tsx +8 -1
  187. package/src/components/TreeView/examples/TreeViewWithSearch.tsx +1 -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":"5.4.0-prerelease.0","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":"5.4.0-prerelease.2","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":"5.4.0-prerelease.0","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":"5.4.0-prerelease.2","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.0-prerelease.0","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":"5.4.0-prerelease.2","private":true}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "5.4.0-prerelease.1",
3
+ "version": "5.4.0-prerelease.3",
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",
@@ -40,15 +40,15 @@
40
40
  "scripts": {
41
41
  "build:umd": "rollup -c --environment IS_PRODUCTION",
42
42
  "build:single:packages": "node ../../scripts/build-single-packages.js --config single-packages.config.json",
43
- "clean": "rimraf dist components layouts helpers next deprecated node_modules",
43
+ "clean": "rimraf dist components layouts helpers next deprecated",
44
44
  "generate": "node scripts/copyStyles.js",
45
45
  "subpaths": "node ../../scripts/exportSubpaths.js --config subpaths.config.json",
46
46
  "clean:exports": "node scripts/cleanDistExports.js"
47
47
  },
48
48
  "dependencies": {
49
- "@patternfly/react-icons": "^5.4.0-prerelease.0",
50
- "@patternfly/react-styles": "^5.4.0-prerelease.0",
51
- "@patternfly/react-tokens": "^5.4.0-prerelease.0",
49
+ "@patternfly/react-icons": "^5.4.0-prerelease.1",
50
+ "@patternfly/react-styles": "^5.4.0-prerelease.1",
51
+ "@patternfly/react-tokens": "^5.4.0-prerelease.1",
52
52
  "focus-trap": "7.5.2",
53
53
  "react-dropzone": "^14.2.3",
54
54
  "tslib": "^2.5.0"
@@ -61,7 +61,6 @@
61
61
  "css": "^2.2.3",
62
62
  "fs-extra": "^11.1.1",
63
63
  "glob": "^7.1.2",
64
- "rimraf": "^3.0.2",
65
64
  "rollup": "^3.21.5",
66
65
  "rollup-plugin-scss": "^4.0.0",
67
66
  "rollup-plugin-svg": "2.0.0",
@@ -72,5 +71,5 @@
72
71
  "react": "^17 || ^18",
73
72
  "react-dom": "^17 || ^18"
74
73
  },
75
- "gitHead": "593832e72c7bbad4096109cba7d7a79a5d135635"
74
+ "gitHead": "75849b05bb14b3d8f50535a92a65136b4a2cb13b"
76
75
  }
@@ -67,8 +67,10 @@ const defaultKeyDownHandler = (args: DefaultKeyDownHandlerArgs) => (event: React
67
67
  }
68
68
  };
69
69
 
70
+ const DEFAULT_VALUE = 0;
71
+
70
72
  export const NumberInput: React.FunctionComponent<NumberInputProps> = ({
71
- value = 0,
73
+ value = DEFAULT_VALUE,
72
74
  className,
73
75
  widthChars,
74
76
  isDisabled = false,
@@ -121,7 +123,7 @@ export const NumberInput: React.FunctionComponent<NumberInputProps> = ({
121
123
  <Button
122
124
  variant="control"
123
125
  aria-label={minusBtnAriaLabel}
124
- isDisabled={isDisabled || value <= min}
126
+ isDisabled={isDisabled || (typeof value === 'number' ? value : DEFAULT_VALUE) <= min}
125
127
  onClick={(evt) => onMinus(evt, inputName)}
126
128
  {...minusBtnProps}
127
129
  >
@@ -149,7 +151,7 @@ export const NumberInput: React.FunctionComponent<NumberInputProps> = ({
149
151
  <Button
150
152
  variant="control"
151
153
  aria-label={plusBtnAriaLabel}
152
- isDisabled={isDisabled || value >= max}
154
+ isDisabled={isDisabled || (typeof value === 'number' ? value : DEFAULT_VALUE) >= max}
153
155
  onClick={(evt) => onPlus(evt, inputName)}
154
156
  {...plusBtnProps}
155
157
  >
@@ -29,7 +29,7 @@ export interface NavigationProps extends React.HTMLProps<HTMLElement> {
29
29
  /** Label for the English word "of". */
30
30
  ofWord?: string;
31
31
  /** The number of the current page. */
32
- page: string | number;
32
+ page: number;
33
33
  /** The title of a page displayed beside the page number. */
34
34
  pagesTitle?: string;
35
35
  /** The title of a page displayed beside the page number (the plural form). */
@@ -55,13 +55,13 @@ export interface NavigationProps extends React.HTMLProps<HTMLElement> {
55
55
  /** Function called when user clicks to navigate to previous page. */
56
56
  onPreviousClick?: (event: React.SyntheticEvent<HTMLButtonElement>, page: number) => void;
57
57
  /** Function called when user inputs page number. */
58
- onPageInput?: (event: React.SyntheticEvent<HTMLButtonElement>, page: number) => void;
58
+ onPageInput?: (event: React.KeyboardEvent<HTMLInputElement>, page: number) => void;
59
59
  /** Function called when page is changed. */
60
60
  onSetPage: OnSetPage;
61
61
  }
62
62
 
63
63
  export interface NavigationState {
64
- userInputPage?: React.ReactText;
64
+ userInputPage?: number | string;
65
65
  }
66
66
 
67
67
  class Navigation extends React.Component<NavigationProps, NavigationState> {
@@ -93,7 +93,7 @@ class Navigation extends React.Component<NavigationProps, NavigationState> {
93
93
  onPageInput: () => undefined as any
94
94
  };
95
95
 
96
- private static parseInteger(input: React.ReactText, lastPage: number): number {
96
+ private static parseInteger(input: number | string, lastPage: number): number {
97
97
  // eslint-disable-next-line radix
98
98
  let inputPage = Number.parseInt(input as string, 10);
99
99
  if (!Number.isNaN(inputPage)) {
@@ -105,14 +105,14 @@ class Navigation extends React.Component<NavigationProps, NavigationState> {
105
105
 
106
106
  private onChange(event: React.FormEvent<HTMLInputElement>, lastPage: number): void {
107
107
  const inputPage = Navigation.parseInteger(event.currentTarget.value, lastPage);
108
- this.setState({ userInputPage: Number.isNaN(inputPage as number) ? event.currentTarget.value : inputPage });
108
+ this.setState({ userInputPage: Number.isNaN(inputPage) ? event.currentTarget.value : inputPage });
109
109
  }
110
110
 
111
111
  private onKeyDown(
112
112
  event: React.KeyboardEvent<HTMLInputElement>,
113
- page: number | string,
113
+ page: number,
114
114
  lastPage: number,
115
- onPageInput: (event: React.SyntheticEvent<HTMLButtonElement>, page: number) => void
115
+ onPageInput: (event: React.KeyboardEvent<HTMLInputElement>, page: number) => void
116
116
  ): void {
117
117
  const allowedKeys = [
118
118
  'Tab',
@@ -126,9 +126,9 @@ class Navigation extends React.Component<NavigationProps, NavigationState> {
126
126
  'ArrowDown'
127
127
  ];
128
128
  if (event.key === KeyTypes.Enter) {
129
- const inputPage = Navigation.parseInteger(this.state.userInputPage, lastPage) as number;
130
- onPageInput(event, Number.isNaN(inputPage) ? (page as number) : inputPage);
131
- this.handleNewPage(event, Number.isNaN(inputPage) ? (page as number) : inputPage);
129
+ const inputPage = Navigation.parseInteger(this.state.userInputPage, lastPage);
130
+ onPageInput(event, Number.isNaN(inputPage) ? page : inputPage);
131
+ this.handleNewPage(event, Number.isNaN(inputPage) ? page : inputPage);
132
132
  } else if (!/^\d*$/.test(event.key) && !allowedKeys.includes(event.key)) {
133
133
  event.preventDefault();
134
134
  }
@@ -206,7 +206,7 @@ class Navigation extends React.Component<NavigationProps, NavigationState> {
206
206
  isDisabled={isDisabled || page === firstPage || page === 0}
207
207
  data-action="previous"
208
208
  onClick={(event) => {
209
- const newPage = (page as number) - 1 >= 1 ? (page as number) - 1 : 1;
209
+ const newPage = page - 1 >= 1 ? page - 1 : 1;
210
210
  onPreviousClick(event, newPage);
211
211
  this.handleNewPage(event, newPage);
212
212
  this.setState({ userInputPage: newPage });
@@ -244,7 +244,7 @@ class Navigation extends React.Component<NavigationProps, NavigationState> {
244
244
  aria-label={toNextPageAriaLabel}
245
245
  data-action="next"
246
246
  onClick={(event) => {
247
- const newPage = (page as number) + 1 <= lastPage ? (page as number) + 1 : lastPage;
247
+ const newPage = page + 1 <= lastPage ? page + 1 : lastPage;
248
248
  onNextClick(event, newPage);
249
249
  this.handleNewPage(event, newPage);
250
250
  this.setState({ userInputPage: newPage });
@@ -148,7 +148,7 @@ export interface PaginationProps extends React.HTMLProps<HTMLDivElement>, OUIAPr
148
148
  /** Function called when user clicks on navigate to next page. */
149
149
  onNextClick?: (event: React.SyntheticEvent<HTMLButtonElement>, page: number) => void;
150
150
  /** Function called when user inputs page number. */
151
- onPageInput?: (event: React.SyntheticEvent<HTMLButtonElement>, page: number) => void;
151
+ onPageInput?: (event: React.KeyboardEvent<HTMLInputElement>, page: number) => void;
152
152
  /** Function called when user selects number of items per page. */
153
153
  onPerPageSelect?: OnPerPageSelect;
154
154
  /** Function called when user clicks on navigate to previous page. */
@@ -46,6 +46,14 @@ export interface TreeViewProps {
46
46
  * internal state.
47
47
  */
48
48
  allExpanded?: boolean;
49
+ /** A text string that sets the accessible name of the tree view list. Either this or the aria-labelledby property must
50
+ * be passed in.
51
+ */
52
+ 'aria-label'?: string;
53
+ /** A space separated list of element id's that sets the accessible name of the tree view list. Either
54
+ * this or the aria-label property must be passed in.
55
+ */
56
+ 'aria-labelledby'?: string;
49
57
  /** Class to add if not passed a parentItem property. */
50
58
  className?: string;
51
59
  /** Comparison function for determining active items. */
@@ -72,6 +80,11 @@ export interface TreeViewProps {
72
80
  icon?: React.ReactNode;
73
81
  /** ID of the tree view. */
74
82
  id?: string;
83
+ /** Flag indicating whether multiple nodes can be selected in the tree view. This will also set the
84
+ * aria-multiselectable attribute on the tree view list which is required to be true when multiple selection is intended.
85
+ * Can only be applied to the root tree view list.
86
+ */
87
+ isMultiSelectable?: boolean;
75
88
  /** Callback for item checkbox selection. */
76
89
  onCheck?: (event: React.ChangeEvent<HTMLInputElement>, item: TreeViewDataItem, parentItem: TreeViewDataItem) => void;
77
90
  /** Callback for item selection. */
@@ -104,6 +117,7 @@ export const TreeView: React.FunctionComponent<TreeViewProps> = ({
104
117
  defaultAllExpanded = false,
105
118
  allExpanded,
106
119
  icon,
120
+ isMultiSelectable = false,
107
121
  expandedIcon,
108
122
  parentItem,
109
123
  onSelect,
@@ -115,10 +129,18 @@ export const TreeView: React.FunctionComponent<TreeViewProps> = ({
115
129
  compareItems = (item, itemToCheck) => item.id === itemToCheck.id,
116
130
  className,
117
131
  useMemo,
132
+ 'aria-label': ariaLabel,
133
+ 'aria-labelledby': ariaLabelledby,
118
134
  ...props
119
135
  }: TreeViewProps) => {
120
136
  const treeViewList = (
121
- <TreeViewList isNested={isNested} toolbar={toolbar}>
137
+ <TreeViewList
138
+ isNested={isNested}
139
+ toolbar={toolbar}
140
+ isMultiSelectable={isMultiSelectable}
141
+ aria-label={ariaLabel}
142
+ aria-labelledby={ariaLabelledby}
143
+ >
122
144
  {data.map((item) => (
123
145
  <TreeViewListItem
124
146
  key={item.id?.toString() || item.name?.toString()}
@@ -10,12 +10,28 @@ export interface TreeViewListProps extends React.HTMLProps<HTMLUListElement> {
10
10
  isNested?: boolean;
11
11
  /** Toolbar to display above the tree view. */
12
12
  toolbar?: React.ReactNode;
13
+ /** Flag indicating whether multiple nodes can be selected in the tree view. This will also set the
14
+ * aria-multiselectable attribute on the tree view list which is required to be true when multiple selection is intended.
15
+ * Can only be applied to the root tree view list.
16
+ */
17
+ isMultiSelectable?: boolean;
18
+ /** A text string that sets the accessible name of the tree view list. Either this or the aria-labelledby property must
19
+ * be passed in.
20
+ */
21
+ 'aria-label'?: string;
22
+ /** A space separated list of element id's that sets the accessible name of the tree view list. Either
23
+ * this or the aria-label property must be passed in.
24
+ */
25
+ 'aria-labelledby'?: string;
13
26
  }
14
27
 
15
28
  export const TreeViewList: React.FunctionComponent<TreeViewListProps> = ({
16
29
  isNested = false,
30
+ isMultiSelectable = false,
17
31
  toolbar,
18
32
  children,
33
+ 'aria-label': ariaLabel,
34
+ 'aria-labelledby': ariaLabelledby,
19
35
  ...props
20
36
  }: TreeViewListProps) => (
21
37
  <>
@@ -25,7 +41,14 @@ export const TreeViewList: React.FunctionComponent<TreeViewListProps> = ({
25
41
  <Divider />
26
42
  </React.Fragment>
27
43
  )}
28
- <ul className={css(`${styles.treeView}__list`)} role={isNested ? 'group' : 'tree'} {...props}>
44
+ <ul
45
+ className={css(`${styles.treeView}__list`)}
46
+ role={isNested ? 'group' : 'tree'}
47
+ aria-multiselectable={isNested ? undefined : isMultiSelectable}
48
+ aria-label={ariaLabel}
49
+ aria-labelledby={ariaLabelledby}
50
+ {...props}
51
+ >
29
52
  {children}
30
53
  </ul>
31
54
  </>
@@ -143,6 +143,8 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
143
143
  </span>
144
144
  </ToggleComponent>
145
145
  );
146
+
147
+ const isCheckboxChecked = checkProps.checked === null ? false : checkProps.checked;
146
148
  const renderCheck = (randomId: string) => (
147
149
  <span className={css(styles.treeViewNodeCheck)}>
148
150
  <input
@@ -151,7 +153,7 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
151
153
  onClick={(evt) => evt.stopPropagation()}
152
154
  ref={(elem) => elem && (elem.indeterminate = checkProps.checked === null)}
153
155
  {...checkProps}
154
- checked={checkProps.checked === null ? false : checkProps.checked}
156
+ checked={isCheckboxChecked}
155
157
  id={randomId}
156
158
  tabIndex={-1}
157
159
  />
@@ -194,6 +196,13 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
194
196
  )}
195
197
  </>
196
198
  );
199
+
200
+ const isSelected =
201
+ (!children || isSelectable) &&
202
+ activeItems &&
203
+ activeItems.length > 0 &&
204
+ activeItems.some((item) => compareItems && item && compareItems(item, itemData));
205
+
197
206
  return (
198
207
  <li
199
208
  id={id}
@@ -201,6 +210,8 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
201
210
  aria-expanded={internalIsExpanded}
202
211
  role="treeitem"
203
212
  tabIndex={-1}
213
+ {...(hasCheckbox && { 'aria-checked': isCheckboxChecked })}
214
+ {...(!hasCheckbox && { 'aria-selected': isSelected })}
204
215
  >
205
216
  <div className={css(styles.treeViewContent)}>
206
217
  <GenerateId prefix={isSelectable ? 'selectable-id' : 'checkbox-id'}>
@@ -209,12 +220,7 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
209
220
  className={css(
210
221
  styles.treeViewNode,
211
222
  children && (isSelectable || hasCheckbox) && styles.modifiers.selectable,
212
- (!children || isSelectable) &&
213
- activeItems &&
214
- activeItems.length > 0 &&
215
- activeItems.some((item) => compareItems && item && compareItems(item, itemData))
216
- ? styles.modifiers.current
217
- : ''
223
+ isSelected && styles.modifiers.current
218
224
  )}
219
225
  onClick={(evt: React.MouseEvent) => {
220
226
  if (!hasCheckbox) {
@@ -3,6 +3,7 @@
3
3
  exports[`Matches snapshot by default 1`] = `
4
4
  <DocumentFragment>
5
5
  <ul
6
+ aria-multiselectable="false"
6
7
  class="pf-v5-c-tree-view__list"
7
8
  role="tree"
8
9
  >
@@ -20,6 +21,7 @@ exports[`Matches snapshot when toolbar is passed 1`] = `
20
21
  class="pf-v5-c-divider"
21
22
  />
22
23
  <ul
24
+ aria-multiselectable="false"
23
25
  class="pf-v5-c-tree-view__list"
24
26
  role="tree"
25
27
  >
@@ -4,6 +4,7 @@ exports[`Matches snapshot with children 1`] = `
4
4
  <DocumentFragment>
5
5
  <li
6
6
  aria-expanded="false"
7
+ aria-selected="false"
7
8
  class="pf-v5-c-tree-view__list-item"
8
9
  role="treeitem"
9
10
  tabindex="-1"
@@ -56,6 +57,7 @@ exports[`Matches snapshot without children 1`] = `
56
57
  <DocumentFragment>
57
58
  <li
58
59
  aria-expanded="false"
60
+ aria-selected="false"
59
61
  class="pf-v5-c-tree-view__list-item"
60
62
  role="treeitem"
61
63
  tabindex="-1"
@@ -9,9 +9,17 @@ import { FolderIcon, FolderOpenIcon, EllipsisVIcon, ClipboardIcon, HamburgerIcon
9
9
 
10
10
  ## Examples
11
11
 
12
- ### Default
12
+ ### Single selectable
13
13
 
14
- ```ts file='./TreeViewDefault.tsx'
14
+ ```ts file='./TreeViewSingleSelectable.tsx'
15
+
16
+ ```
17
+
18
+ ### Multiselectable
19
+
20
+ A tree view can be setup to allow multiple nodes to be selected. When a tree view is intended to allow multiple selection, the `isMultiSelectable` property must be passed.
21
+
22
+ ```ts file='./TreeViewMultiselectable.tsx'
15
23
 
16
24
  ```
17
25
 
@@ -25,6 +33,8 @@ The `hasSelectableNodes` modifier will separate the expansion and selection beha
25
33
 
26
34
  ### With search
27
35
 
36
+ A search input can be used to filter tree view items. It is recommended that a tree view with more than 7 nodes includes a search input.
37
+
28
38
  ```ts file='./TreeViewWithSearch.tsx'
29
39
 
30
40
  ```
@@ -55,5 +55,5 @@ export const TreeViewCompact: React.FunctionComponent = () => {
55
55
  ]
56
56
  }
57
57
  ];
58
- return <TreeView data={options} variant="compact" />;
58
+ return <TreeView aria-label="Tree View compact example" data={options} variant="compact" />;
59
59
  };
@@ -55,5 +55,5 @@ export const TreeViewCompactNoBackground: React.FunctionComponent = () => {
55
55
  ]
56
56
  }
57
57
  ];
58
- return <TreeView data={options} variant="compactNoBackground" />;
58
+ return <TreeView aria-label="Tree View compact no background example" data={options} variant="compactNoBackground" />;
59
59
  };
@@ -61,5 +61,5 @@ export const GuidesTreeView: React.FunctionComponent = () => {
61
61
  children: [{ name: 'Application 5', id: 'example8-App5' }]
62
62
  }
63
63
  ];
64
- return <TreeView data={options} hasGuides={true} />;
64
+ return <TreeView aria-label="Tree View guides example" data={options} hasGuides={true} />;
65
65
  };
@@ -0,0 +1,86 @@
1
+ import React from 'react';
2
+ import { TreeView, TreeViewDataItem } from '@patternfly/react-core';
3
+
4
+ export const TreeViewMultiselectable: React.FunctionComponent = () => {
5
+ const [activeItems, setActiveItems] = React.useState<TreeViewDataItem[]>([]);
6
+
7
+ const onSelect = (_event: React.MouseEvent, treeViewItem: TreeViewDataItem) => {
8
+ // Ignore folders for selection
9
+ if (treeViewItem && !treeViewItem.children) {
10
+ setActiveItems((prevActiveItems) => [...prevActiveItems, treeViewItem]);
11
+ }
12
+ };
13
+
14
+ const options = [
15
+ {
16
+ name: 'Application launcher',
17
+ id: 'multiselectExample-AppLaunch',
18
+ children: [
19
+ {
20
+ name: 'Application 1',
21
+ id: 'multiselectExample-App1',
22
+ children: [
23
+ { name: 'Settings', id: 'multiselectExample-App1Settings' },
24
+ { name: 'Current', id: 'multiselectExample-App1Current' }
25
+ ]
26
+ },
27
+ {
28
+ name: 'Application 2',
29
+ id: 'multiselectExample-App2',
30
+ children: [
31
+ { name: 'Settings', id: 'multiselectExample-App2Settings' },
32
+ {
33
+ name: 'Loader',
34
+ id: 'multiselectExample-App2Loader',
35
+ children: [
36
+ { name: 'Loading App 1', id: 'multiselectExample-LoadApp1' },
37
+ { name: 'Loading App 2', id: 'multiselectExample-LoadApp2' },
38
+ { name: 'Loading App 3', id: 'multiselectExample-LoadApp3' }
39
+ ]
40
+ }
41
+ ]
42
+ }
43
+ ],
44
+ defaultExpanded: true
45
+ },
46
+ {
47
+ name: 'Cost management',
48
+ id: 'multiselectExample-Cost',
49
+ children: [
50
+ {
51
+ name: 'Application 3',
52
+ id: 'multiselectExample-App3',
53
+ children: [
54
+ { name: 'Settings', id: 'multiselectExample-App3Settings' },
55
+ { name: 'Current', id: 'multiselectExample-App3Current' }
56
+ ]
57
+ }
58
+ ]
59
+ },
60
+ {
61
+ name: 'Sources',
62
+ id: 'multiselectExample-Sources',
63
+ children: [
64
+ {
65
+ name: 'Application 4',
66
+ id: 'multiselectExample-App4',
67
+ children: [{ name: 'Settings', id: 'multiselectExample-App4Settings' }]
68
+ }
69
+ ]
70
+ },
71
+ {
72
+ name: 'Really really really long folder name that overflows the container it is in',
73
+ id: 'multiselectExample-Long',
74
+ children: [{ name: 'Application 5', id: 'multiselectExample-App5' }]
75
+ }
76
+ ];
77
+ return (
78
+ <TreeView
79
+ aria-label="Tree View multiselectable example"
80
+ isMultiSelectable
81
+ data={options}
82
+ activeItems={activeItems}
83
+ onSelect={onSelect}
84
+ />
85
+ );
86
+ };
@@ -71,5 +71,13 @@ export const TreeViewSelectableNodes: React.FunctionComponent = () => {
71
71
  children: [{ name: 'Application 5', id: 'SelNodesTreeView-App5' }]
72
72
  }
73
73
  ];
74
- return <TreeView hasSelectableNodes data={options} activeItems={activeItems} onSelect={onSelect} />;
74
+ return (
75
+ <TreeView
76
+ aria-label="Tree View separate selection and expansion example"
77
+ hasSelectableNodes
78
+ data={options}
79
+ activeItems={activeItems}
80
+ onSelect={onSelect}
81
+ />
82
+ );
75
83
  };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { TreeView, Button, TreeViewDataItem } from '@patternfly/react-core';
3
3
 
4
- export const TreeViewDefault: React.FunctionComponent = () => {
4
+ export const TreeViewSingleSelectable: React.FunctionComponent = () => {
5
5
  const [activeItems, setActiveItems] = React.useState<TreeViewDataItem[]>();
6
6
  const [allExpanded, setAllExpanded] = React.useState<boolean>();
7
7
 
@@ -81,7 +81,13 @@ export const TreeViewDefault: React.FunctionComponent = () => {
81
81
  {allExpanded && 'Collapse all'}
82
82
  {!allExpanded && 'Expand all'}
83
83
  </Button>
84
- <TreeView data={options} activeItems={activeItems} onSelect={onSelect} allExpanded={allExpanded} />
84
+ <TreeView
85
+ aria-label="Tree View single selectable example"
86
+ data={options}
87
+ activeItems={activeItems}
88
+ onSelect={onSelect}
89
+ allExpanded={allExpanded}
90
+ />
85
91
  </React.Fragment>
86
92
  );
87
93
  };
@@ -136,5 +136,12 @@ export const TreeViewWithActionItems: React.FunctionComponent = () => {
136
136
  children: [{ name: 'Application 5', id: 'example7-App5' }]
137
137
  }
138
138
  ];
139
- return <TreeView data={options} activeItems={activeItems} onSelect={onSelect} />;
139
+ return (
140
+ <TreeView
141
+ aria-label="Tree View with actions example"
142
+ data={options}
143
+ activeItems={activeItems}
144
+ onSelect={onSelect}
145
+ />
146
+ );
140
147
  };
@@ -75,5 +75,13 @@ export const TreeViewBadges: React.FunctionComponent = () => {
75
75
  }
76
76
  ];
77
77
 
78
- return <TreeView data={options} activeItems={activeItems} onSelect={onSelect} hasBadges />;
78
+ return (
79
+ <TreeView
80
+ aria-label="Tree View with badges example"
81
+ data={options}
82
+ activeItems={activeItems}
83
+ onSelect={onSelect}
84
+ hasBadges
85
+ />
86
+ );
79
87
  };
@@ -194,5 +194,5 @@ export const TreeViewWithCheckboxes: React.FunctionComponent = () => {
194
194
  }
195
195
  };
196
196
  const mapped = options.map((item) => mapTree(item));
197
- return <TreeView data={mapped} onCheck={onCheck} hasCheckboxes />;
197
+ return <TreeView aria-label="Tree View with checkboxes example" data={mapped} onCheck={onCheck} hasCheckboxes />;
198
198
  };
@@ -82,5 +82,13 @@ export const TreeViewCustomBadges: React.FunctionComponent = () => {
82
82
  children: [{ name: 'Application 5', id: 'example6-App5' }]
83
83
  }
84
84
  ];
85
- return <TreeView data={options} activeItems={activeItems} onSelect={onSelect} hasBadges />;
85
+ return (
86
+ <TreeView
87
+ aria-label="Tree View with custom badges example"
88
+ data={options}
89
+ activeItems={activeItems}
90
+ onSelect={onSelect}
91
+ hasBadges
92
+ />
93
+ );
86
94
  };
@@ -73,6 +73,7 @@ export const TreeViewWithIcons: React.FunctionComponent = () => {
73
73
  ];
74
74
  return (
75
75
  <TreeView
76
+ aria-label="Tree View with icons example"
76
77
  data={options}
77
78
  activeItems={activeItems}
78
79
  onSelect={onSelect}
@@ -50,7 +50,14 @@ export const TreeViewWithMemoization: React.FunctionComponent = () => {
50
50
  options.push({ name: 'Option ' + i, id: i.toString(), children: childOptions });
51
51
  }
52
52
  const tree = (
53
- <TreeView data={options} activeItems={activeItems} onSelect={onSelect} allExpanded={allExpanded} useMemo />
53
+ <TreeView
54
+ aria-label="Tree View with memoization example"
55
+ data={options}
56
+ activeItems={activeItems}
57
+ onSelect={onSelect}
58
+ allExpanded={allExpanded}
59
+ useMemo
60
+ />
54
61
  );
55
62
 
56
63
  return (
@@ -118,6 +118,7 @@ export const TreeViewWithSearch: React.FunctionComponent = () => {
118
118
 
119
119
  return (
120
120
  <TreeView
121
+ aria-label="Tree View with search example"
121
122
  data={filteredItems}
122
123
  activeItems={activeItems}
123
124
  onSelect={onSelect}