@patternfly/react-core 6.5.0-prerelease.27 → 6.5.0-prerelease.29

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 (145) 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/ClipboardCopy/package.json +1 -1
  21. package/dist/dynamic/components/CodeBlock/package.json +1 -1
  22. package/dist/dynamic/components/Compass/package.json +1 -1
  23. package/dist/dynamic/components/Content/package.json +1 -1
  24. package/dist/dynamic/components/DataList/package.json +1 -1
  25. package/dist/dynamic/components/DatePicker/package.json +1 -1
  26. package/dist/dynamic/components/DescriptionList/package.json +1 -1
  27. package/dist/dynamic/components/Divider/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/Hero/package.json +1 -1
  38. package/dist/dynamic/components/Hint/package.json +1 -1
  39. package/dist/dynamic/components/Icon/package.json +1 -1
  40. package/dist/dynamic/components/InputGroup/package.json +1 -1
  41. package/dist/dynamic/components/JumpLinks/package.json +1 -1
  42. package/dist/dynamic/components/Label/package.json +1 -1
  43. package/dist/dynamic/components/List/package.json +1 -1
  44. package/dist/dynamic/components/LoginPage/package.json +1 -1
  45. package/dist/dynamic/components/Masthead/package.json +1 -1
  46. package/dist/dynamic/components/Menu/package.json +1 -1
  47. package/dist/dynamic/components/MenuToggle/package.json +1 -1
  48. package/dist/dynamic/components/Modal/package.json +1 -1
  49. package/dist/dynamic/components/MultipleFileUpload/package.json +1 -1
  50. package/dist/dynamic/components/Nav/package.json +1 -1
  51. package/dist/dynamic/components/NotificationBadge/package.json +1 -1
  52. package/dist/dynamic/components/NotificationDrawer/package.json +1 -1
  53. package/dist/dynamic/components/NumberInput/package.json +1 -1
  54. package/dist/dynamic/components/OverflowMenu/package.json +1 -1
  55. package/dist/dynamic/components/Page/package.json +1 -1
  56. package/dist/dynamic/components/Pagination/package.json +1 -1
  57. package/dist/dynamic/components/Panel/package.json +1 -1
  58. package/dist/dynamic/components/Popover/package.json +1 -1
  59. package/dist/dynamic/components/Progress/package.json +1 -1
  60. package/dist/dynamic/components/ProgressStepper/package.json +1 -1
  61. package/dist/dynamic/components/Radio/package.json +1 -1
  62. package/dist/dynamic/components/SearchInput/package.json +1 -1
  63. package/dist/dynamic/components/Select/package.json +1 -1
  64. package/dist/dynamic/components/Sidebar/package.json +1 -1
  65. package/dist/dynamic/components/SimpleList/package.json +1 -1
  66. package/dist/dynamic/components/Skeleton/package.json +1 -1
  67. package/dist/dynamic/components/SkipToContent/package.json +1 -1
  68. package/dist/dynamic/components/Slider/package.json +1 -1
  69. package/dist/dynamic/components/Spinner/package.json +1 -1
  70. package/dist/dynamic/components/Switch/package.json +1 -1
  71. package/dist/dynamic/components/Tabs/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/TimePicker/package.json +1 -1
  76. package/dist/dynamic/components/Timestamp/package.json +1 -1
  77. package/dist/dynamic/components/Title/package.json +1 -1
  78. package/dist/dynamic/components/ToggleGroup/package.json +1 -1
  79. package/dist/dynamic/components/Toolbar/package.json +1 -1
  80. package/dist/dynamic/components/Tooltip/package.json +1 -1
  81. package/dist/dynamic/components/TreeView/package.json +1 -1
  82. package/dist/dynamic/components/Truncate/package.json +1 -1
  83. package/dist/dynamic/components/Wizard/hooks/package.json +1 -1
  84. package/dist/dynamic/components/Wizard/package.json +1 -1
  85. package/dist/dynamic/deprecated/components/Chip/package.json +1 -1
  86. package/dist/dynamic/deprecated/components/DragDrop/package.json +1 -1
  87. package/dist/dynamic/deprecated/components/DualListSelector/package.json +1 -1
  88. package/dist/dynamic/deprecated/components/Modal/package.json +1 -1
  89. package/dist/dynamic/deprecated/components/Tile/package.json +1 -1
  90. package/dist/dynamic/deprecated/components/Wizard/package.json +1 -1
  91. package/dist/dynamic/deprecated/components/package.json +1 -1
  92. package/dist/dynamic/helpers/AnimationsProvider/AnimationsProvider/package.json +1 -1
  93. package/dist/dynamic/helpers/AnimationsProvider/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/fileUtils/package.json +1 -1
  102. package/dist/dynamic/helpers/htmlConstants/package.json +1 -1
  103. package/dist/dynamic/helpers/package.json +1 -1
  104. package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
  105. package/dist/dynamic/helpers/typeUtils/package.json +1 -1
  106. package/dist/dynamic/helpers/useInterval/package.json +1 -1
  107. package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
  108. package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
  109. package/dist/dynamic/helpers/util/package.json +1 -1
  110. package/dist/dynamic/layouts/Bullseye/package.json +1 -1
  111. package/dist/dynamic/layouts/Flex/package.json +1 -1
  112. package/dist/dynamic/layouts/Gallery/package.json +1 -1
  113. package/dist/dynamic/layouts/Grid/package.json +1 -1
  114. package/dist/dynamic/layouts/Level/package.json +1 -1
  115. package/dist/dynamic/layouts/Split/package.json +1 -1
  116. package/dist/dynamic/layouts/Stack/package.json +1 -1
  117. package/dist/dynamic/styles/package.json +1 -1
  118. package/dist/esm/components/TreeView/TreeView.d.ts +4 -0
  119. package/dist/esm/components/TreeView/TreeView.d.ts.map +1 -1
  120. package/dist/esm/components/TreeView/TreeView.js +1 -1
  121. package/dist/esm/components/TreeView/TreeView.js.map +1 -1
  122. package/dist/esm/components/TreeView/TreeViewListItem.d.ts +4 -0
  123. package/dist/esm/components/TreeView/TreeViewListItem.d.ts.map +1 -1
  124. package/dist/esm/components/TreeView/TreeViewListItem.js +15 -11
  125. package/dist/esm/components/TreeView/TreeViewListItem.js.map +1 -1
  126. package/dist/js/components/TreeView/TreeView.d.ts +4 -0
  127. package/dist/js/components/TreeView/TreeView.d.ts.map +1 -1
  128. package/dist/js/components/TreeView/TreeView.js +1 -1
  129. package/dist/js/components/TreeView/TreeView.js.map +1 -1
  130. package/dist/js/components/TreeView/TreeViewListItem.d.ts +4 -0
  131. package/dist/js/components/TreeView/TreeViewListItem.d.ts.map +1 -1
  132. package/dist/js/components/TreeView/TreeViewListItem.js +15 -11
  133. package/dist/js/components/TreeView/TreeViewListItem.js.map +1 -1
  134. package/dist/umd/assets/{output-k590n8-M.css → output-BimuzWMQ.css} +21326 -21111
  135. package/dist/umd/react-core.min.js +1 -1
  136. package/helpers/package.json +1 -1
  137. package/layouts/package.json +1 -1
  138. package/next/package.json +1 -1
  139. package/package.json +7 -7
  140. package/src/components/TreeView/TreeView.tsx +6 -0
  141. package/src/components/TreeView/TreeViewListItem.tsx +27 -9
  142. package/src/components/TreeView/__tests__/TreeViewListItem.test.tsx +243 -0
  143. package/src/demos/DatePicker/DatePicker.md +1 -47
  144. package/src/demos/DatePicker/examples/DatePickerRange.tsx +46 -0
  145. package/src/demos/Wizard/WizardDemo.md +6 -6
@@ -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.5.0-prerelease.26","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.5.0-prerelease.28","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.5.0-prerelease.26","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.5.0-prerelease.28","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.5.0-prerelease.26","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.5.0-prerelease.28","private":true}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "6.5.0-prerelease.27",
3
+ "version": "6.5.0-prerelease.29",
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",
@@ -46,22 +46,22 @@
46
46
  "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json"
47
47
  },
48
48
  "dependencies": {
49
- "@patternfly/react-icons": "^6.5.0-prerelease.12",
50
- "@patternfly/react-styles": "^6.5.0-prerelease.10",
51
- "@patternfly/react-tokens": "^6.5.0-prerelease.9",
49
+ "@patternfly/react-icons": "^6.5.0-prerelease.13",
50
+ "@patternfly/react-styles": "^6.5.0-prerelease.11",
51
+ "@patternfly/react-tokens": "^6.5.0-prerelease.10",
52
52
  "focus-trap": "7.6.6",
53
53
  "react-dropzone": "^14.3.5",
54
54
  "tslib": "^2.8.1"
55
55
  },
56
56
  "devDependencies": {
57
- "@patternfly/patternfly": "6.5.0-prerelease.33",
57
+ "@patternfly/patternfly": "6.5.0-prerelease.34",
58
58
  "case-anything": "^3.1.2",
59
59
  "css": "^3.0.0",
60
- "fs-extra": "^11.3.0"
60
+ "fs-extra": "^11.3.3"
61
61
  },
62
62
  "peerDependencies": {
63
63
  "react": "^17 || ^18 || ^19",
64
64
  "react-dom": "^17 || ^18 || ^19"
65
65
  },
66
- "gitHead": "097dae1319f634100648d173b0334f97308dc4d2"
66
+ "gitHead": "937bd3eb560199de65ed28f12ec59b91226f6341"
67
67
  }
@@ -35,6 +35,10 @@ export interface TreeViewDataItem {
35
35
  name: React.ReactNode;
36
36
  /** Title of a tree view item. Only used in compact presentations. */
37
37
  title?: React.ReactNode;
38
+ /** Flag indicating if the tree view item is disabled. */
39
+ isDisabled?: boolean;
40
+ /** Flag indicating if the tree view item toggle is disabled. */
41
+ isToggleDisabled?: boolean;
38
42
  }
39
43
 
40
44
  /** The main tree view component. */
@@ -158,6 +162,8 @@ export const TreeView: React.FunctionComponent<TreeViewProps> = ({
158
162
  id={item.id}
159
163
  isExpanded={allExpanded}
160
164
  isSelectable={hasSelectableNodes}
165
+ isDisabled={item.isDisabled}
166
+ isToggleDisabled={item.isToggleDisabled}
161
167
  defaultExpanded={item.defaultExpanded !== undefined ? item.defaultExpanded : defaultAllExpanded}
162
168
  onSelect={onSelect}
163
169
  onCheck={onCheck}
@@ -46,6 +46,10 @@ export interface TreeViewListItemProps {
46
46
  * children.
47
47
  */
48
48
  isSelectable?: boolean;
49
+ /** Flag indicating if the tree view item is disabled. */
50
+ isDisabled?: boolean;
51
+ /** Flag indicating if the tree view item toggle is disabled. */
52
+ isToggleDisabled?: boolean;
49
53
  /** Data structure of tree view item. */
50
54
  itemData?: TreeViewDataItem;
51
55
  /** Internal content of a tree view item. */
@@ -81,6 +85,8 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
81
85
  title,
82
86
  id,
83
87
  isExpanded,
88
+ isDisabled = false,
89
+ isToggleDisabled = false,
84
90
  defaultExpanded = false,
85
91
  children = null,
86
92
  onSelect,
@@ -125,12 +131,13 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
125
131
  }
126
132
 
127
133
  const ToggleComponent = hasCheckbox || isSelectable ? 'button' : 'span';
134
+ const hasDisabledToggleClass = isToggleDisabled || (Component === 'button' && isDisabled);
128
135
 
129
136
  const renderToggle = (randomId: string) => (
130
137
  <ToggleComponent
131
- className={css(styles.treeViewNodeToggle)}
138
+ className={css(styles.treeViewNodeToggle, hasDisabledToggleClass && styles.modifiers.disabled)}
132
139
  onClick={(evt: React.MouseEvent) => {
133
- if (isSelectable || hasCheckbox) {
140
+ if (!isToggleDisabled && (isSelectable || hasCheckbox)) {
134
141
  if (internalIsExpanded) {
135
142
  onCollapse && onCollapse(evt, itemData, parentItem);
136
143
  } else {
@@ -138,12 +145,12 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
138
145
  }
139
146
  setIsExpanded(!internalIsExpanded);
140
147
  }
141
- if (isSelectable) {
148
+ if (!isToggleDisabled && isSelectable) {
142
149
  evt.stopPropagation();
143
150
  }
144
151
  }}
145
152
  {...((hasCheckbox || isSelectable) && { 'aria-labelledby': `label-${randomId}` })}
146
- {...(ToggleComponent === 'button' && { type: 'button' })}
153
+ {...(ToggleComponent === 'button' && { disabled: isToggleDisabled, type: 'button' })}
147
154
  tabIndex={-1}
148
155
  >
149
156
  <span className={css(styles.treeViewNodeToggleIcon)}>
@@ -162,6 +169,7 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
162
169
  ref={(elem) => {
163
170
  elem && (elem.indeterminate = checkProps.checked === null);
164
171
  }}
172
+ disabled={isDisabled || checkProps.disabled}
165
173
  {...checkProps}
166
174
  checked={isCheckboxChecked}
167
175
  id={randomId}
@@ -180,7 +188,7 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
180
188
  <>
181
189
  {isCompact && title && <span className={css(styles.treeViewNodeTitle)}>{title}</span>}
182
190
  {isSelectable ? (
183
- <button tabIndex={-1} className={css(styles.treeViewNodeText)} type="button">
191
+ <button tabIndex={-1} className={css(styles.treeViewNodeText)} type="button" disabled={isDisabled}>
184
192
  {name}
185
193
  </button>
186
194
  ) : (
@@ -220,6 +228,9 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
220
228
  })
221
229
  );
222
230
 
231
+ const isFullyDisabled =
232
+ (Component === 'button' && isDisabled) || (Component !== 'button' && isDisabled && isToggleDisabled);
233
+
223
234
  return (
224
235
  <li
225
236
  id={id}
@@ -229,16 +240,21 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
229
240
  tabIndex={-1}
230
241
  {...(hasCheckbox && { 'aria-checked': isCheckboxChecked })}
231
242
  {...(!hasCheckbox && { 'aria-selected': isSelected })}
243
+ {...(isFullyDisabled && { 'aria-disabled': true })}
232
244
  >
233
245
  <div className={css(styles.treeViewContent)}>
234
246
  <GenerateId prefix={isSelectable ? 'selectable-id' : 'checkbox-id'}>
235
247
  {(randomId) => (
236
248
  <Component
237
- className={css(styles.treeViewNode, isSelected && styles.modifiers.current)}
249
+ className={css(
250
+ styles.treeViewNode,
251
+ isSelected && styles.modifiers.current,
252
+ isDisabled && styles.modifiers.disabled
253
+ )}
238
254
  onClick={(evt: React.MouseEvent) => {
239
255
  if (!hasCheckbox) {
240
- onSelect && onSelect(evt, itemData, parentItem);
241
- if (!isSelectable && children && evt.isDefaultPrevented() !== true) {
256
+ !isDisabled && onSelect && onSelect(evt, itemData, parentItem);
257
+ if (!isDisabled && !isSelectable && children && evt.isDefaultPrevented() !== true) {
242
258
  if (internalIsExpanded) {
243
259
  onCollapse && onCollapse(evt, itemData, parentItem);
244
260
  } else {
@@ -250,7 +266,7 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
250
266
  }}
251
267
  {...(hasCheckbox && { htmlFor: randomId })}
252
268
  {...((hasCheckbox || (isSelectable && children)) && { id: `label-${randomId}` })}
253
- {...(Component === 'button' && { type: 'button' })}
269
+ {...(Component === 'button' && { type: 'button', disabled: isDisabled })}
254
270
  >
255
271
  <span className={css(styles.treeViewNodeContainer)}>
256
272
  {children && renderToggle(randomId)}
@@ -297,6 +313,8 @@ export const TreeViewListItem = memo(TreeViewListItemBase, (prevProps, nextProps
297
313
  prevProps.id !== nextProps.id ||
298
314
  prevProps.isExpanded !== nextProps.isExpanded ||
299
315
  prevProps.defaultExpanded !== nextProps.defaultExpanded ||
316
+ prevProps.isDisabled !== nextProps.isDisabled ||
317
+ prevProps.isToggleDisabled !== nextProps.isToggleDisabled ||
300
318
  prevProps.onSelect !== nextProps.onSelect ||
301
319
  prevProps.onCheck !== nextProps.onCheck ||
302
320
  prevProps.onExpand !== nextProps.onExpand ||
@@ -415,6 +415,249 @@ test(`Does not render ${styles.treeViewNode} element with ${styles.modifiers.cur
415
415
  expect(treeViewNode).not.toHaveClass(styles.modifiers.current);
416
416
  });
417
417
 
418
+ // Assisted by Cursor AI
419
+ describe('isDisabled prop', () => {
420
+ const user = userEvent.setup();
421
+ const onSelectMock = jest.fn();
422
+ const onExpandMock = jest.fn();
423
+ const onCollapseMock = jest.fn();
424
+
425
+ beforeEach(() => {
426
+ jest.clearAllMocks();
427
+ });
428
+
429
+ test(`Renders button with disabled attribute and ${styles.modifiers.disabled} class when isDisabled is true`, () => {
430
+ render(<TreeViewListItem isDisabled {...requiredProps} />);
431
+
432
+ const button = screen.getByRole('button', { name: requiredProps.name });
433
+ expect(button).toBeDisabled();
434
+ expect(button).toHaveClass(styles.modifiers.disabled);
435
+ });
436
+
437
+ test('Does not render button with disabled attribute when isDisabled is false', () => {
438
+ render(<TreeViewListItem isDisabled={false} {...requiredProps} />);
439
+
440
+ expect(screen.getByRole('button', { name: requiredProps.name })).not.toBeDisabled();
441
+ });
442
+
443
+ test('Does not call onSelect when isDisabled is true', async () => {
444
+ render(<TreeViewListItem isDisabled onSelect={onSelectMock} {...requiredProps} />);
445
+
446
+ await user.click(screen.getByRole('button', { name: requiredProps.name }));
447
+
448
+ expect(onSelectMock).not.toHaveBeenCalled();
449
+ });
450
+
451
+ test('Does not call onExpand when isDisabled is true and item is collapsed', async () => {
452
+ render(
453
+ <TreeViewListItem isDisabled onExpand={onExpandMock} {...requiredProps}>
454
+ Content
455
+ </TreeViewListItem>
456
+ );
457
+
458
+ await user.click(screen.getByRole('button', { name: requiredProps.name }));
459
+
460
+ expect(onExpandMock).not.toHaveBeenCalled();
461
+ });
462
+
463
+ test('Does not call onCollapse when isDisabled is true and item is expanded', async () => {
464
+ render(
465
+ <TreeViewListItem isDisabled isExpanded onCollapse={onCollapseMock} {...requiredProps}>
466
+ Content
467
+ </TreeViewListItem>
468
+ );
469
+
470
+ await user.click(screen.getByRole('button', { name: requiredProps.name }));
471
+
472
+ expect(onCollapseMock).not.toHaveBeenCalled();
473
+ });
474
+
475
+ test(`Renders toggle with ${styles.modifiers.disabled} class when isDisabled is true for default TreeViewListItem`, () => {
476
+ render(
477
+ <TreeViewListItem isDisabled {...requiredProps}>
478
+ Content
479
+ </TreeViewListItem>
480
+ );
481
+
482
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling;
483
+ expect(toggle).toHaveClass(styles.modifiers.disabled);
484
+ });
485
+
486
+ test('Renders treeitem with aria-disabled when isDisabled is true for default TreeViewListItem', () => {
487
+ render(<TreeViewListItem isDisabled {...requiredProps} />);
488
+
489
+ expect(screen.getByRole('treeitem')).toHaveAttribute('aria-disabled', 'true');
490
+ });
491
+
492
+ test('Renders treeitem with aria-disabled when isDisabled and isToggleDisabled are true and isSelectable is true', () => {
493
+ render(
494
+ <TreeViewListItem isSelectable isDisabled isToggleDisabled {...requiredProps}>
495
+ Content
496
+ </TreeViewListItem>
497
+ );
498
+
499
+ expect(screen.getByRole('treeitem')).toHaveAttribute('aria-disabled', 'true');
500
+ });
501
+
502
+ test('Renders treeitem with aria-disabled when isDisabled and isToggleDisabled are true and hasCheckbox is true', () => {
503
+ render(
504
+ <TreeViewListItem hasCheckbox isDisabled isToggleDisabled {...requiredProps}>
505
+ Content
506
+ </TreeViewListItem>
507
+ );
508
+
509
+ expect(screen.getByRole('treeitem')).toHaveAttribute('aria-disabled', 'true');
510
+ });
511
+
512
+ test('Does not render treeitem with aria-disabled when isDisabled is true, isToggleDisabled is false, and isSelectable is true', () => {
513
+ render(
514
+ <TreeViewListItem isSelectable isDisabled {...requiredProps}>
515
+ Content
516
+ </TreeViewListItem>
517
+ );
518
+
519
+ expect(screen.getByRole('treeitem')).not.toHaveAttribute('aria-disabled');
520
+ });
521
+
522
+ test('Does not render treeitem with aria-disabled when isDisabled is false', () => {
523
+ render(<TreeViewListItem isDisabled={false} {...requiredProps} />);
524
+
525
+ expect(screen.getByRole('treeitem')).not.toHaveAttribute('aria-disabled');
526
+ });
527
+ });
528
+
529
+ // Assisted by Cursor AI
530
+ describe('isToggleDisabled prop', () => {
531
+ const user = userEvent.setup();
532
+ const onExpandMock = jest.fn();
533
+ const onCollapseMock = jest.fn();
534
+
535
+ beforeEach(() => {
536
+ jest.clearAllMocks();
537
+ });
538
+
539
+ test(`Renders toggle button with disabled attribute and ${styles.modifiers.disabled} class when isToggleDisabled is true and hasCheckbox is passed`, () => {
540
+ render(
541
+ <TreeViewListItem hasCheckbox isToggleDisabled {...requiredProps}>
542
+ Content
543
+ </TreeViewListItem>
544
+ );
545
+
546
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling?.previousElementSibling;
547
+ expect(toggle).toBeDisabled();
548
+ expect(toggle).toHaveClass(styles.modifiers.disabled);
549
+ });
550
+
551
+ test(`Renders toggle button with disabled attribute and ${styles.modifiers.disabled} class when isToggleDisabled is true and isSelectable is passed`, () => {
552
+ render(
553
+ <TreeViewListItem isSelectable isToggleDisabled {...requiredProps}>
554
+ Content
555
+ </TreeViewListItem>
556
+ );
557
+
558
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling;
559
+ expect(toggle).toBeDisabled();
560
+ expect(toggle).toHaveClass(styles.modifiers.disabled);
561
+ });
562
+
563
+ test('Does not render toggle span with disabled attribute when isToggleDisabled is true (toggle is span by default)', () => {
564
+ render(
565
+ <TreeViewListItem isToggleDisabled {...requiredProps}>
566
+ Content
567
+ </TreeViewListItem>
568
+ );
569
+
570
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling;
571
+ expect(toggle?.tagName).toBe('SPAN');
572
+ expect(toggle).not.toHaveAttribute('disabled');
573
+ });
574
+
575
+ test('Does not call onExpand when isToggleDisabled is true and hasCheckbox is passed', async () => {
576
+ render(
577
+ <TreeViewListItem hasCheckbox isToggleDisabled onExpand={onExpandMock} {...requiredProps}>
578
+ Content
579
+ </TreeViewListItem>
580
+ );
581
+
582
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling?.previousElementSibling;
583
+ await user.click(toggle as Element);
584
+
585
+ expect(onExpandMock).not.toHaveBeenCalled();
586
+ });
587
+
588
+ test('Does not call onCollapse when isToggleDisabled is true and hasCheckbox is passed', async () => {
589
+ render(
590
+ <TreeViewListItem hasCheckbox isToggleDisabled isExpanded onCollapse={onCollapseMock} {...requiredProps}>
591
+ Content
592
+ </TreeViewListItem>
593
+ );
594
+
595
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling?.previousElementSibling;
596
+ await user.click(toggle as Element);
597
+
598
+ expect(onCollapseMock).not.toHaveBeenCalled();
599
+ });
600
+
601
+ test('Does not call onExpand when isToggleDisabled is true and isSelectable is passed', async () => {
602
+ render(
603
+ <TreeViewListItem isSelectable isToggleDisabled onExpand={onExpandMock} {...requiredProps}>
604
+ Content
605
+ </TreeViewListItem>
606
+ );
607
+
608
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling;
609
+ await user.click(toggle as Element);
610
+
611
+ expect(onExpandMock).not.toHaveBeenCalled();
612
+ });
613
+
614
+ test('Does not call onCollapse when isToggleDisabled is true and isSelectable is passed', async () => {
615
+ render(
616
+ <TreeViewListItem isSelectable isToggleDisabled isExpanded onCollapse={onCollapseMock} {...requiredProps}>
617
+ Content
618
+ </TreeViewListItem>
619
+ );
620
+
621
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling;
622
+ await user.click(toggle as Element);
623
+
624
+ expect(onCollapseMock).not.toHaveBeenCalled();
625
+ });
626
+
627
+ test(`Renders toggle span with ${styles.modifiers.disabled} class when isDisabled is true for default TreeViewListItem`, () => {
628
+ render(
629
+ <TreeViewListItem isDisabled {...requiredProps}>
630
+ Content
631
+ </TreeViewListItem>
632
+ );
633
+
634
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling;
635
+ expect(toggle).toHaveClass(styles.modifiers.disabled);
636
+ });
637
+
638
+ test(`Does not render toggle with ${styles.modifiers.disabled} class when isDisabled is true and hasCheckbox is true`, () => {
639
+ render(
640
+ <TreeViewListItem hasCheckbox isDisabled {...requiredProps}>
641
+ Content
642
+ </TreeViewListItem>
643
+ );
644
+
645
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling?.previousElementSibling;
646
+ expect(toggle).not.toHaveClass(styles.modifiers.disabled);
647
+ });
648
+
649
+ test(`Does not render toggle with ${styles.modifiers.disabled} class when isDisabled is true and isSelectable is true`, () => {
650
+ render(
651
+ <TreeViewListItem isSelectable isDisabled {...requiredProps}>
652
+ Content
653
+ </TreeViewListItem>
654
+ );
655
+
656
+ const toggle = screen.getByText(requiredProps.name).previousElementSibling;
657
+ expect(toggle).not.toHaveClass(styles.modifiers.disabled);
658
+ });
659
+ });
660
+
418
661
  describe('Callback props', () => {
419
662
  const user = userEvent.setup();
420
663
  const compareItemsMock = jest.fn();
@@ -13,53 +13,7 @@ import { Modal as ModalDeprecated, ModalVariant as ModalVariantDeprecated } from
13
13
 
14
14
  This is intended to be used as a filter. After selecting a start date, the next date is automatically selected.
15
15
 
16
- ```js
17
- import { useState } from 'react';
18
- import { Split, SplitItem, DatePicker, isValidDate, yyyyMMddFormat } from '@patternfly/react-core';
19
-
20
- DateRangePicker = () => {
21
- const [from, setFrom] = useState();
22
- const [to, setTo] = useState();
23
-
24
- const toValidator = (date) =>
25
- isValidDate(from) && date >= from ? '' : 'The "to" date must be after the "from" date';
26
-
27
- const onFromChange = (_event, _value, date) => {
28
- setFrom(new Date(date));
29
- if (isValidDate(date)) {
30
- date.setDate(date.getDate() + 1);
31
- setTo(yyyyMMddFormat(date));
32
- } else {
33
- setTo('');
34
- }
35
- };
36
-
37
- const onToChange = (_event, _value, date) => {
38
- if (isValidDate(date)) {
39
- setTo(yyyyMMddFormat(date));
40
- }
41
- };
42
-
43
- return (
44
- <Split>
45
- <SplitItem>
46
- <DatePicker onChange={onFromChange} aria-label="Start date" placeholder="YYYY-MM-DD" />
47
- </SplitItem>
48
- <SplitItem style={{ padding: '6px 12px 0 12px' }}>to</SplitItem>
49
- <SplitItem>
50
- <DatePicker
51
- value={to}
52
- onChange={onToChange}
53
- isDisabled={!isValidDate(from)}
54
- rangeStart={from}
55
- validators={[toValidator]}
56
- aria-label="End date"
57
- placeholder="YYYY-MM-DD"
58
- />
59
- </SplitItem>
60
- </Split>
61
- );
62
- };
16
+ ```ts file="./examples/DatePickerRange.tsx"
63
17
  ```
64
18
 
65
19
  ### Date and time pickers in modal
@@ -0,0 +1,46 @@
1
+ import { useState } from 'react';
2
+ import { Split, SplitItem, DatePicker, isValidDate, yyyyMMddFormat } from '@patternfly/react-core';
3
+
4
+ export const DatePickerRange: React.FunctionComponent = () => {
5
+ const [from, setFrom] = useState<Date | undefined>();
6
+ const [to, setTo] = useState<string>('');
7
+
8
+ const toValidator = (date: Date) =>
9
+ isValidDate(from) && date >= from ? '' : 'The "to" date must be after the "from" date';
10
+
11
+ const onFromChange = (_event: React.MouseEvent<HTMLElement>, _value: string, date: Date) => {
12
+ setFrom(new Date(date));
13
+ if (isValidDate(date)) {
14
+ date.setDate(date.getDate() + 1);
15
+ setTo(yyyyMMddFormat(date));
16
+ } else {
17
+ setTo('');
18
+ }
19
+ };
20
+
21
+ const onToChange = (_event: React.MouseEvent<HTMLElement>, _value: string, date: Date) => {
22
+ if (isValidDate(date)) {
23
+ setTo(yyyyMMddFormat(date));
24
+ }
25
+ };
26
+
27
+ return (
28
+ <Split>
29
+ <SplitItem>
30
+ <DatePicker onChange={onFromChange} aria-label="Start date" placeholder="YYYY-MM-DD" />
31
+ </SplitItem>
32
+ <SplitItem style={{ padding: '6px 12px 0 12px' }}>to</SplitItem>
33
+ <SplitItem>
34
+ <DatePicker
35
+ value={to}
36
+ onChange={onToChange}
37
+ isDisabled={!isValidDate(from)}
38
+ rangeStart={from}
39
+ validators={[toValidator]}
40
+ aria-label="End date"
41
+ placeholder="YYYY-MM-DD"
42
+ />
43
+ </SplitItem>
44
+ </Split>
45
+ );
46
+ };
@@ -14,30 +14,30 @@ import { DashboardWrapper } from '@patternfly/react-core/dist/js/demos/Dashboard
14
14
 
15
15
  ### In modal
16
16
 
17
- ```js file="../examples/Wizard/InModal.tsx" isFullscreen
17
+ ```ts file="../examples/Wizard/InModal.tsx" isFullscreen
18
18
  ```
19
19
 
20
20
  ### In modal, with drawer
21
21
 
22
- ```js file="../examples/Wizard/InModalWithDrawer.tsx" isFullscreen
22
+ ```ts file="../examples/Wizard/InModalWithDrawer.tsx" isFullscreen
23
23
  ```
24
24
 
25
25
  ### In modal, with drawer and informational step
26
26
 
27
- ```js file="../examples/Wizard/InModalWithDrawerInformationalStep.tsx" isFullscreen
27
+ ```ts file="../examples/Wizard/InModalWithDrawerInformationalStep.tsx" isFullscreen
28
28
  ```
29
29
 
30
30
  ### In page
31
31
 
32
- ```js file="../examples/Wizard/InPage.tsx" isFullscreen
32
+ ```ts file="../examples/Wizard/InPage.tsx" isFullscreen
33
33
  ```
34
34
 
35
35
  ### In page, with drawer
36
36
 
37
- ```js file="../examples/Wizard/InPageWithDrawer.tsx" isFullscreen
37
+ ```ts file="../examples/Wizard/InPageWithDrawer.tsx" isFullscreen
38
38
  ```
39
39
 
40
40
  ### In page, with drawer and informational step
41
41
 
42
- ```js file="../examples/Wizard/InPageWithDrawerInformationalStep.tsx" isFullscreen
42
+ ```ts file="../examples/Wizard/InPageWithDrawerInformationalStep.tsx" isFullscreen
43
43
  ```