@patternfly/react-core 4.264.0 → 4.265.0

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 (123) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/esm/components/Badge/Badge.d.ts +2 -0
  3. package/dist/esm/components/Badge/Badge.d.ts.map +1 -1
  4. package/dist/esm/components/Badge/Badge.js +4 -2
  5. package/dist/esm/components/Badge/Badge.js.map +1 -1
  6. package/dist/esm/components/TimePicker/TimePicker.d.ts +0 -1
  7. package/dist/esm/components/TimePicker/TimePicker.d.ts.map +1 -1
  8. package/dist/esm/components/TimePicker/TimePicker.js +1 -9
  9. package/dist/esm/components/TimePicker/TimePicker.js.map +1 -1
  10. package/dist/esm/next/components/Dropdown/DropdownItem.d.ts +2 -0
  11. package/dist/esm/next/components/Dropdown/DropdownItem.d.ts.map +1 -1
  12. package/dist/esm/next/components/Dropdown/DropdownItem.js +2 -2
  13. package/dist/esm/next/components/Dropdown/DropdownItem.js.map +1 -1
  14. package/dist/esm/next/components/Wizard/Wizard.d.ts +1 -1
  15. package/dist/esm/next/components/Wizard/Wizard.d.ts.map +1 -1
  16. package/dist/esm/next/components/Wizard/WizardContext.d.ts +2 -2
  17. package/dist/esm/next/components/Wizard/WizardContext.d.ts.map +1 -1
  18. package/dist/esm/next/components/Wizard/WizardFooter.d.ts +2 -2
  19. package/dist/esm/next/components/Wizard/WizardFooter.d.ts.map +1 -1
  20. package/dist/esm/next/components/Wizard/WizardNavInternal.js +2 -2
  21. package/dist/esm/next/components/Wizard/WizardNavInternal.js.map +1 -1
  22. package/dist/esm/next/components/Wizard/WizardNavItem.js +1 -1
  23. package/dist/esm/next/components/Wizard/WizardNavItem.js.map +1 -1
  24. package/dist/esm/next/components/Wizard/WizardStep.d.ts +2 -0
  25. package/dist/esm/next/components/Wizard/WizardStep.d.ts.map +1 -1
  26. package/dist/esm/next/components/Wizard/WizardStep.js.map +1 -1
  27. package/dist/esm/next/components/Wizard/types.d.ts +4 -2
  28. package/dist/esm/next/components/Wizard/types.d.ts.map +1 -1
  29. package/dist/esm/next/components/Wizard/types.js.map +1 -1
  30. package/dist/js/components/Badge/Badge.d.ts +2 -0
  31. package/dist/js/components/Badge/Badge.d.ts.map +1 -1
  32. package/dist/js/components/Badge/Badge.js +4 -2
  33. package/dist/js/components/Badge/Badge.js.map +1 -1
  34. package/dist/js/components/TimePicker/TimePicker.d.ts +0 -1
  35. package/dist/js/components/TimePicker/TimePicker.d.ts.map +1 -1
  36. package/dist/js/components/TimePicker/TimePicker.js +1 -9
  37. package/dist/js/components/TimePicker/TimePicker.js.map +1 -1
  38. package/dist/js/next/components/Dropdown/DropdownItem.d.ts +2 -0
  39. package/dist/js/next/components/Dropdown/DropdownItem.d.ts.map +1 -1
  40. package/dist/js/next/components/Dropdown/DropdownItem.js +2 -2
  41. package/dist/js/next/components/Dropdown/DropdownItem.js.map +1 -1
  42. package/dist/js/next/components/Wizard/Wizard.d.ts +1 -1
  43. package/dist/js/next/components/Wizard/Wizard.d.ts.map +1 -1
  44. package/dist/js/next/components/Wizard/WizardContext.d.ts +2 -2
  45. package/dist/js/next/components/Wizard/WizardContext.d.ts.map +1 -1
  46. package/dist/js/next/components/Wizard/WizardFooter.d.ts +2 -2
  47. package/dist/js/next/components/Wizard/WizardFooter.d.ts.map +1 -1
  48. package/dist/js/next/components/Wizard/WizardNavInternal.js +2 -2
  49. package/dist/js/next/components/Wizard/WizardNavInternal.js.map +1 -1
  50. package/dist/js/next/components/Wizard/WizardNavItem.js +1 -1
  51. package/dist/js/next/components/Wizard/WizardNavItem.js.map +1 -1
  52. package/dist/js/next/components/Wizard/WizardStep.d.ts +2 -0
  53. package/dist/js/next/components/Wizard/WizardStep.d.ts.map +1 -1
  54. package/dist/js/next/components/Wizard/WizardStep.js.map +1 -1
  55. package/dist/js/next/components/Wizard/types.d.ts +4 -2
  56. package/dist/js/next/components/Wizard/types.d.ts.map +1 -1
  57. package/dist/js/next/components/Wizard/types.js.map +1 -1
  58. package/dist/umd/react-core.min.css +80 -80
  59. package/dist/umd/react-core.min.js +2 -2
  60. package/package.json +14 -7
  61. package/src/components/Badge/Badge.tsx +4 -0
  62. package/src/components/Badge/__tests__/Badge.test.tsx +10 -0
  63. package/src/components/Badge/examples/BadgeUnread.tsx +12 -1
  64. package/src/components/Menu/examples/MenuWithDrilldownBreadcrumbs.tsx +60 -22
  65. package/src/components/TimePicker/TimePicker.tsx +0 -11
  66. package/src/components/Tooltip/examples/Tooltip.md +5 -285
  67. package/src/components/Tooltip/examples/TooltipBasic.tsx +16 -0
  68. package/src/components/Tooltip/examples/TooltipIcon.tsx +24 -0
  69. package/src/components/Tooltip/examples/TooltipOptions.tsx +197 -0
  70. package/src/components/Tooltip/examples/TooltipReactRef.tsx +22 -0
  71. package/src/components/Tooltip/examples/TooltipSelectorRef.tsx +19 -0
  72. package/src/next/components/Dropdown/DropdownItem.tsx +4 -1
  73. package/src/next/components/Wizard/Wizard.tsx +1 -1
  74. package/src/next/components/Wizard/WizardContext.tsx +2 -2
  75. package/src/next/components/Wizard/WizardFooter.tsx +2 -2
  76. package/src/next/components/Wizard/WizardNavInternal.tsx +1 -1
  77. package/src/next/components/Wizard/WizardNavItem.tsx +1 -1
  78. package/src/next/components/Wizard/WizardStep.tsx +2 -0
  79. package/src/next/components/Wizard/__tests__/Wizard.test.tsx +33 -1
  80. package/src/next/components/Wizard/__tests__/WizardStep.test.tsx +1 -2
  81. package/src/next/components/Wizard/examples/Wizard.md +1 -1
  82. package/src/next/components/Wizard/examples/WizardKitchenSink.tsx +21 -2
  83. package/src/next/components/Wizard/types.tsx +9 -4
  84. package/dist/esm/components/Button/__mocks__/Button.d.ts +0 -8
  85. package/dist/esm/components/Button/__mocks__/Button.d.ts.map +0 -1
  86. package/dist/esm/components/Button/__mocks__/Button.js +0 -14
  87. package/dist/esm/components/Button/__mocks__/Button.js.map +0 -1
  88. package/dist/esm/components/Button/__mocks__/index.d.ts +0 -2
  89. package/dist/esm/components/Button/__mocks__/index.d.ts.map +0 -1
  90. package/dist/esm/components/Button/__mocks__/index.js +0 -2
  91. package/dist/esm/components/Button/__mocks__/index.js.map +0 -1
  92. package/dist/esm/components/HelperText/__mocks__/HelperText.d.ts +0 -4
  93. package/dist/esm/components/HelperText/__mocks__/HelperText.d.ts.map +0 -1
  94. package/dist/esm/components/HelperText/__mocks__/HelperText.js +0 -5
  95. package/dist/esm/components/HelperText/__mocks__/HelperText.js.map +0 -1
  96. package/dist/esm/components/HelperText/__mocks__/HelperTextItem.d.ts +0 -4
  97. package/dist/esm/components/HelperText/__mocks__/HelperTextItem.d.ts.map +0 -1
  98. package/dist/esm/components/HelperText/__mocks__/HelperTextItem.js +0 -5
  99. package/dist/esm/components/HelperText/__mocks__/HelperTextItem.js.map +0 -1
  100. package/dist/esm/components/HelperText/__mocks__/index.d.ts +0 -3
  101. package/dist/esm/components/HelperText/__mocks__/index.d.ts.map +0 -1
  102. package/dist/esm/components/HelperText/__mocks__/index.js +0 -3
  103. package/dist/esm/components/HelperText/__mocks__/index.js.map +0 -1
  104. package/dist/js/components/Button/__mocks__/Button.d.ts +0 -8
  105. package/dist/js/components/Button/__mocks__/Button.d.ts.map +0 -1
  106. package/dist/js/components/Button/__mocks__/Button.js +0 -18
  107. package/dist/js/components/Button/__mocks__/Button.js.map +0 -1
  108. package/dist/js/components/Button/__mocks__/index.d.ts +0 -2
  109. package/dist/js/components/Button/__mocks__/index.d.ts.map +0 -1
  110. package/dist/js/components/Button/__mocks__/index.js +0 -5
  111. package/dist/js/components/Button/__mocks__/index.js.map +0 -1
  112. package/dist/js/components/HelperText/__mocks__/HelperText.d.ts +0 -4
  113. package/dist/js/components/HelperText/__mocks__/HelperText.d.ts.map +0 -1
  114. package/dist/js/components/HelperText/__mocks__/HelperText.js +0 -10
  115. package/dist/js/components/HelperText/__mocks__/HelperText.js.map +0 -1
  116. package/dist/js/components/HelperText/__mocks__/HelperTextItem.d.ts +0 -4
  117. package/dist/js/components/HelperText/__mocks__/HelperTextItem.d.ts.map +0 -1
  118. package/dist/js/components/HelperText/__mocks__/HelperTextItem.js +0 -10
  119. package/dist/js/components/HelperText/__mocks__/HelperTextItem.js.map +0 -1
  120. package/dist/js/components/HelperText/__mocks__/index.d.ts +0 -3
  121. package/dist/js/components/HelperText/__mocks__/index.d.ts.map +0 -1
  122. package/dist/js/components/HelperText/__mocks__/index.js +0 -6
  123. package/dist/js/components/HelperText/__mocks__/index.js.map +0 -1
@@ -0,0 +1,197 @@
1
+ import React from 'react';
2
+ import { Button, Tooltip, Checkbox, Select, SelectOption, TextInput, TooltipPosition } from '@patternfly/react-core';
3
+
4
+ export const TooltipOptions: React.FunctionComponent = () => {
5
+ const [trigger, setTrigger] = React.useState(['mouseenter', 'focus']);
6
+ const [isVisible, setIsVisible] = React.useState(true);
7
+ const [contentLeftAligned, setContentLeftAligned] = React.useState(false);
8
+ const [enableFlip, setEnableFlip] = React.useState(true);
9
+ const [position, setPosition] = React.useState<TooltipPosition>(TooltipPosition.top);
10
+ const [positionSelectOpen, setPositionSelectOpen] = React.useState(false);
11
+ const [flipSelectOpen, setFlipSelectOpen] = React.useState(false);
12
+ const [flipBehavior, setFlipBehavior] = React.useState('flip');
13
+ const [entryDelayInput, setEntryDelayInput] = React.useState(0);
14
+ const [exitDelayInput, setExitDelayInput] = React.useState(0);
15
+ const [animationDuration, setAnimationDuration] = React.useState(300);
16
+ const tipBoxRef = React.useRef(null);
17
+
18
+ const scrollToRef = (ref: React.RefObject<any>) => {
19
+ if (ref && ref.current) {
20
+ ref.current.scrollTop = 400;
21
+ ref.current.scrollLeft = 300;
22
+ }
23
+ };
24
+
25
+ React.useEffect(() => {
26
+ scrollToRef(tipBoxRef);
27
+ }, []);
28
+
29
+ return (
30
+ <>
31
+ <div>
32
+ <div style={{ border: '1px solid' }}>
33
+ <Checkbox
34
+ label="trigger: mouseenter"
35
+ isChecked={trigger.includes('mouseenter')}
36
+ onChange={checked => {
37
+ const updatedTrigger = checked ? trigger.concat('mouseenter') : trigger.filter(t => t !== 'mouseenter');
38
+ setIsVisible(false);
39
+ setTrigger(updatedTrigger);
40
+ }}
41
+ aria-label="trigger: mouseenter"
42
+ id="trigger_mouseenter"
43
+ />
44
+ <Checkbox
45
+ label="trigger: focus"
46
+ isChecked={trigger.includes('focus')}
47
+ onChange={checked => {
48
+ const updatedTrigger = checked ? trigger.concat('focus') : trigger.filter(t => t !== 'focus');
49
+ setIsVisible(false);
50
+ setTrigger(updatedTrigger);
51
+ }}
52
+ aria-label="trigger: focus"
53
+ id="trigger_focus"
54
+ />
55
+ <Checkbox
56
+ label="trigger: click"
57
+ isChecked={trigger.includes('click')}
58
+ onChange={checked => {
59
+ const updatedTrigger = checked ? trigger.concat('click') : trigger.filter(t => t !== 'click');
60
+ setIsVisible(false);
61
+ setTimeout(() => setTrigger(updatedTrigger));
62
+ }}
63
+ aria-label="trigger: click"
64
+ id="trigger_click"
65
+ />
66
+ <Checkbox
67
+ label="trigger: manual"
68
+ isChecked={trigger.includes('manual')}
69
+ onChange={checked => {
70
+ const updatedTrigger = checked ? trigger.concat('manual') : trigger.filter(t => t !== 'manual');
71
+ setIsVisible(false);
72
+ setTrigger(updatedTrigger);
73
+ }}
74
+ aria-label="trigger: manual"
75
+ id="trigger_manual"
76
+ />
77
+ </div>
78
+ <div style={{ border: '1px solid' }}>
79
+ <Checkbox
80
+ label="content left-aligned"
81
+ isChecked={contentLeftAligned}
82
+ onChange={checked => setContentLeftAligned(checked)}
83
+ aria-label="content left-aligned"
84
+ id="content_left_aligned"
85
+ />
86
+ </div>
87
+ <div style={{ border: '1px solid' }}>
88
+ <Checkbox
89
+ label="enableFlip"
90
+ isChecked={enableFlip}
91
+ onChange={checked => setEnableFlip(checked)}
92
+ aria-label="enableFlip"
93
+ id="enable_flip"
94
+ />
95
+ </div>
96
+ <div style={{ border: '1px solid' }}>
97
+ position (will flip if enableFlip is true). The 'auto' position requires enableFlip to be set to true.
98
+ <Select
99
+ onToggle={() => setPositionSelectOpen(!positionSelectOpen)}
100
+ onSelect={(_event, selection) => {
101
+ setPosition(selection.toString() as TooltipPosition);
102
+ setPositionSelectOpen(false);
103
+ }}
104
+ isOpen={positionSelectOpen}
105
+ selections={position}
106
+ menuAppendTo={() => document.body}
107
+ >
108
+ <SelectOption value={TooltipPosition.auto} />
109
+ <SelectOption value={TooltipPosition.top} />
110
+ <SelectOption value={TooltipPosition.bottom} />
111
+ <SelectOption value={TooltipPosition.left} />
112
+ <SelectOption value={TooltipPosition.right} />
113
+ <SelectOption value={TooltipPosition.topStart} />
114
+ <SelectOption value={TooltipPosition.topEnd} />
115
+ <SelectOption value={TooltipPosition.bottomStart} />
116
+ <SelectOption value={TooltipPosition.bottomEnd} />
117
+ <SelectOption value={TooltipPosition.leftStart} />
118
+ <SelectOption value={TooltipPosition.leftEnd} />
119
+ <SelectOption value={TooltipPosition.rightStart} />
120
+ <SelectOption value={TooltipPosition.rightEnd} />
121
+ </Select>
122
+ </div>
123
+ <div style={{ border: '1px solid' }}>
124
+ <Checkbox
125
+ label="isVisible (also set trigger to only manual to programmatically control it)"
126
+ isChecked={isVisible}
127
+ onChange={checked => setIsVisible(checked)}
128
+ aria-label="isVisible"
129
+ id="is_visible"
130
+ />
131
+ </div>
132
+ <div style={{ border: '1px solid' }}>
133
+ Entry delay (ms){' '}
134
+ <TextInput
135
+ value={entryDelayInput}
136
+ type="number"
137
+ onChange={val => setEntryDelayInput(Number(val))}
138
+ aria-label="entry delay"
139
+ />
140
+ Exit delay (ms){' '}
141
+ <TextInput
142
+ value={exitDelayInput}
143
+ type="number"
144
+ onChange={val => setExitDelayInput(Number(val))}
145
+ aria-label="exit delay"
146
+ />
147
+ Animation duration (ms){' '}
148
+ <TextInput
149
+ value={animationDuration}
150
+ type="number"
151
+ onChange={val => setAnimationDuration(Number(val))}
152
+ aria-label="animation duration"
153
+ />
154
+ </div>
155
+ <div style={{ border: '1px solid' }}>
156
+ flip behavior examples (enableFlip has to be true). "flip" will try to flip the tooltip to the opposite of the
157
+ starting position. The second option ensures that there are 3 escape positions for every possible starting
158
+ position (default). This setting is ignored if position prop is set to 'auto'.
159
+ <Select
160
+ onToggle={() => setFlipSelectOpen(!flipSelectOpen)}
161
+ onSelect={(_event, selection) => {
162
+ setFlipBehavior(selection.toString());
163
+ setFlipSelectOpen(false);
164
+ }}
165
+ isOpen={flipSelectOpen}
166
+ selections={flipBehavior}
167
+ menuAppendTo={() => document.body}
168
+ >
169
+ <SelectOption value="flip" />
170
+ <SelectOption value="clockwise">['top', 'right', 'bottom', 'left', 'top', 'right', 'bottom']</SelectOption>
171
+ </Select>
172
+ </div>
173
+ </div>
174
+ <div id="tooltip-boundary" className="tooltip-box" ref={tipBoxRef}>
175
+ <Tooltip
176
+ content={
177
+ <div>
178
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.
179
+ </div>
180
+ }
181
+ trigger={trigger.join(' ')}
182
+ enableFlip={enableFlip}
183
+ flipBehavior={flipBehavior === 'flip' ? 'flip' : ['top', 'right', 'bottom', 'left', 'top', 'right', 'bottom']}
184
+ position={position}
185
+ isVisible={isVisible}
186
+ entryDelay={entryDelayInput}
187
+ exitDelay={exitDelayInput}
188
+ animationDuration={animationDuration}
189
+ isContentLeftAligned={contentLeftAligned}
190
+ appendTo={() => document.getElementById('tooltip-boundary') as HTMLElement}
191
+ >
192
+ <Button className="tooltip-button">Tooltip</Button>
193
+ </Tooltip>
194
+ </div>
195
+ </>
196
+ );
197
+ };
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { Tooltip } from '@patternfly/react-core';
3
+
4
+ export const TooltipReactRef: React.FunctionComponent = () => {
5
+ const tooltipRef = React.useRef<HTMLButtonElement>(null);
6
+ return (
7
+ <div style={{ margin: '100px' }}>
8
+ <button aria-describedby="tooltip-ref1" ref={tooltipRef}>
9
+ Tooltip attached via react ref
10
+ </button>
11
+ <Tooltip
12
+ id="tooltip-ref1"
13
+ content={
14
+ <div>
15
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.
16
+ </div>
17
+ }
18
+ reference={tooltipRef}
19
+ />
20
+ </div>
21
+ );
22
+ };
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { Tooltip } from '@patternfly/react-core';
3
+
4
+ export const TooltipSelectorRef: React.FunctionComponent = () => (
5
+ <div style={{ margin: '100px' }}>
6
+ <button aria-describedby="tooltip-ref2" id="tooltip-selector">
7
+ Tooltip attached via selector ref
8
+ </button>
9
+ <Tooltip
10
+ id="tooltip-ref2"
11
+ content={
12
+ <div>
13
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.
14
+ </div>
15
+ }
16
+ reference={() => document.getElementById('tooltip-selector') as HTMLButtonElement}
17
+ />
18
+ </div>
19
+ );
@@ -10,6 +10,8 @@ export interface DropdownItemProps extends Omit<MenuItemProps, 'ref'>, OUIAProps
10
10
  className?: string;
11
11
  /** Description of the dropdown item */
12
12
  description?: React.ReactNode;
13
+ /** Identifies the component in the dropdown onSelect callback */
14
+ itemId?: any;
13
15
  /** Value to overwrite the randomly generated data-ouia-component-id.*/
14
16
  ouiaId?: number | string;
15
17
  /** Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */
@@ -20,13 +22,14 @@ export const DropdownItem: React.FunctionComponent<MenuItemProps> = ({
20
22
  children,
21
23
  className,
22
24
  description,
25
+ itemId,
23
26
  ouiaId,
24
27
  ouiaSafe,
25
28
  ...props
26
29
  }: DropdownItemProps) => {
27
30
  const ouiaProps = useOUIAProps(DropdownItem.displayName, ouiaId, ouiaSafe);
28
31
  return (
29
- <MenuItem className={css(className)} description={description} {...ouiaProps} {...props}>
32
+ <MenuItem className={css(className)} description={description} itemId={itemId} {...ouiaProps} {...props}>
30
33
  {children}
31
34
  </MenuItem>
32
35
  );
@@ -49,7 +49,7 @@ export interface WizardProps extends React.HTMLProps<HTMLDivElement> {
49
49
  /** Callback function after back button is clicked */
50
50
  onBack?: WizardNavStepFunction;
51
51
  /** Callback function to save at the end of the wizard, if not specified uses onClose */
52
- onSave?: () => void;
52
+ onSave?: () => void | Promise<void>;
53
53
  /** Callback function to close the wizard */
54
54
  onClose?: () => void;
55
55
  }
@@ -12,9 +12,9 @@ export interface WizardContextProps {
12
12
  /** Footer element */
13
13
  footer: React.ReactElement;
14
14
  /** Navigate to the next step */
15
- onNext: () => void;
15
+ onNext: () => void | Promise<void>;
16
16
  /** Navigate to the previous step */
17
- onBack: () => void;
17
+ onBack: () => void | Promise<void>;
18
18
  /** Close the wizard */
19
19
  onClose: () => void;
20
20
  /** Navigate to step by ID */
@@ -14,9 +14,9 @@ export interface WizardFooterProps {
14
14
  /** The active step */
15
15
  activeStep: WizardControlStep;
16
16
  /** Next button callback */
17
- onNext: () => WizardNavStepFunction | void;
17
+ onNext: () => WizardNavStepFunction | void | Promise<void>;
18
18
  /** Back button callback */
19
- onBack: () => WizardNavStepFunction | void;
19
+ onBack: () => WizardNavStepFunction | void | Promise<void>;
20
20
  /** Cancel link callback */
21
21
  onClose: () => void;
22
22
  /** Custom text for the Next button. The current step's nextButtonText takes precedence. */
@@ -97,7 +97,7 @@ export const WizardNavInternal = ({ nav, isStepVisitRequired, isNavExpanded }: W
97
97
  key={step.id}
98
98
  id={step.id}
99
99
  content={step.name}
100
- isExpandable={true}
100
+ isExpandable={step.isCollapsible ?? true}
101
101
  isCurrent={hasActiveChild}
102
102
  isDisabled={!hasEnabledChildren}
103
103
  isVisited={step.isVisited}
@@ -109,7 +109,7 @@ export const WizardNavItem: React.FunctionComponent<WizardNavItemProps> = ({
109
109
  <span className={css(styles.wizardNavLinkText)}>{content}</span>
110
110
  <span className={css(styles.wizardNavLinkToggle)}>
111
111
  <span className={css(styles.wizardNavLinkToggleIcon)}>
112
- <AngleRightIcon />
112
+ <AngleRightIcon aria-label={`${isCurrent ? 'Collapse' : 'Expand'} step icon`} />
113
113
  </span>
114
114
  </span>
115
115
  </>
@@ -30,6 +30,8 @@ export interface WizardStepProps {
30
30
  footer?: React.ReactElement | Partial<WizardFooterProps>;
31
31
  /** Used to determine icon next to the step's navigation item */
32
32
  status?: 'default' | 'error';
33
+ /** Flag to determine whether sub-steps can collapse or not */
34
+ isCollapsible?: boolean;
33
35
  }
34
36
 
35
37
  export const WizardStep = ({ children, steps: _subSteps, ...props }: WizardStepProps) => {
@@ -278,7 +278,7 @@ test('calls onClose on cancel link click', async () => {
278
278
  expect(onClose).toHaveBeenCalled();
279
279
  });
280
280
 
281
- test('unmounts inactive steps by default', async () => {
281
+ test('does not render inactive step content', async () => {
282
282
  const user = userEvent.setup();
283
283
 
284
284
  render(
@@ -297,3 +297,35 @@ test('unmounts inactive steps by default', async () => {
297
297
  expect(screen.queryByText('Step 1 content')).toBeNull();
298
298
  expect(screen.getByText('Step 2 content')).toBeVisible();
299
299
  });
300
+
301
+ test('parent steps have collapsed sub-steps by default unless the step is active', async () => {
302
+ const user = userEvent.setup();
303
+
304
+ render(
305
+ <Wizard startIndex={2}>
306
+ <WizardStep id="step-1" name="Test step 1" />
307
+ <WizardStep id="step-2" name="Test step 2" steps={[<WizardStep id="sub-step-1" name="Test sub step 1" />]} />
308
+ </Wizard>
309
+ );
310
+
311
+ expect(screen.getByLabelText('Expand step icon')).toBeVisible();
312
+
313
+ await user.click(screen.getByRole('button', { name: 'Next' }));
314
+
315
+ expect(screen.getByLabelText('Collapse step icon')).toBeVisible();
316
+ });
317
+
318
+ test('parent step can be non-collapsible by setting isCollapsible to false', () => {
319
+ render(
320
+ <Wizard>
321
+ <WizardStep
322
+ id="step-1"
323
+ name="Test step 1"
324
+ isCollapsible={false}
325
+ steps={[<WizardStep id="sub-step-1" name="Sub step 1" />]}
326
+ />
327
+ </Wizard>
328
+ );
329
+
330
+ expect(screen.queryByLabelText('step icon', { exact: false })).toBeNull();
331
+ });
@@ -31,8 +31,7 @@ const wizardContext: WizardContext.WizardContextProps = {
31
31
  goToStepByName: jest.fn(),
32
32
  goToStepByIndex: jest.fn(),
33
33
  setFooter: jest.fn(),
34
- getStep: jest.fn(),
35
- setSteps: jest.fn()
34
+ getStep: jest.fn()
36
35
  };
37
36
 
38
37
  const useWizardContextSpy = jest.spyOn(WizardContext, 'useWizardContext');
@@ -96,7 +96,7 @@ Custom operations when navigating between steps can be achieved by utilizing `on
96
96
 
97
97
  ```noLive
98
98
  /** Callback for the Wizard's 'onNext', 'onBack', and 'onNavByIndex' properties */
99
- type WizardNavStepFunction = (currentStep: WizardNavStepData, previousStep: WizardNavStepData) => void;
99
+ type WizardNavStepFunction = (currentStep: WizardNavStepData, previousStep: WizardNavStepData) => void | Promise<void>;
100
100
 
101
101
  /** Data returned for either parameter of WizardNavStepFunction */
102
102
  type WizardNavStepData = Pick<WizardControlStep, 'id' | 'name'>;
@@ -161,6 +161,16 @@ const StepContentWithActions = () => {
161
161
 
162
162
  export const WizardKitchenSink: React.FunctionComponent = () => {
163
163
  const onNext: WizardNavStepFunction = (_currentStep: WizardNavStepData, _previousStep: WizardNavStepData) => {};
164
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
165
+
166
+ async function onSubmit(): Promise<void> {
167
+ setIsSubmitting(true);
168
+
169
+ await new Promise(resolve => setTimeout(resolve, 5000));
170
+
171
+ setIsSubmitting(false);
172
+ alert('50 points to Gryffindor!');
173
+ }
164
174
 
165
175
  return (
166
176
  <SomeContextProvider>
@@ -207,8 +217,17 @@ export const WizardKitchenSink: React.FunctionComponent = () => {
207
217
  >
208
218
  Step 3 content w/ custom async footer
209
219
  </WizardStep>
210
- <WizardStep id={StepId.ReviewStep} name="Review" footer={{ nextButtonText: 'Submit' }}>
211
- Review step content
220
+ <WizardStep
221
+ id={StepId.ReviewStep}
222
+ name="Review"
223
+ footer={{
224
+ nextButtonText: 'Submit',
225
+ onNext: onSubmit,
226
+ isNextDisabled: isSubmitting,
227
+ isBackDisabled: isSubmitting
228
+ }}
229
+ >
230
+ {isSubmitting ? 'Calculating wizard score...' : 'Review step content'}
212
231
  </WizardStep>
213
232
  </Wizard>
214
233
  )}
@@ -34,6 +34,8 @@ export enum WizardNavItemStatus {
34
34
  export interface WizardParentStep extends WizardBasicStep {
35
35
  /** Nested step IDs */
36
36
  subStepIds: (string | number)[];
37
+ /** Flag to determine whether sub-steps can collapse or not */
38
+ isCollapsible?: boolean;
37
39
  }
38
40
 
39
41
  /** Type used to define sub-steps. */
@@ -46,7 +48,10 @@ export interface WizardSubStep extends WizardBasicStep {
46
48
  export type WizardControlStep = WizardBasicStep | WizardParentStep | WizardSubStep;
47
49
 
48
50
  /** Callback for the Wizard's 'onNext', 'onBack', and 'onNavByIndex' properties. */
49
- export type WizardNavStepFunction = (currentStep: WizardNavStepData, previousStep: WizardNavStepData) => void;
51
+ export type WizardNavStepFunction = (
52
+ currentStep: WizardNavStepData,
53
+ previousStep: WizardNavStepData
54
+ ) => void | Promise<void>;
50
55
 
51
56
  /** Data returned for either parameter of WizardNavStepFunction. */
52
57
  export interface WizardNavStepData {
@@ -81,9 +86,9 @@ export type CustomWizardNavItemFunction = (
81
86
  /** Callback for the Wizard's 'footer' property. Returns element which replaces the Wizard's default footer. */
82
87
  export type CustomWizardFooterFunction = (
83
88
  activeStep: WizardControlStep,
84
- onNext: () => void,
85
- onBack: () => void,
86
- onClose: () => void
89
+ onNext: () => void | Promise<void>,
90
+ onBack: () => void | Promise<void>,
91
+ onClose: () => void | Promise<void>
87
92
  ) => React.ReactElement<WizardFooterProps>;
88
93
 
89
94
  export function isCustomWizardNav(nav: WizardNavType): nav is CustomWizardNavFunction | React.ReactElement {
@@ -1,8 +0,0 @@
1
- /// <reference types="react" />
2
- import { ButtonProps } from '../';
3
- export declare const Button: ({ children, variant, isInline, onClick, iconPosition, icon, ...props }: ButtonProps) => JSX.Element;
4
- export declare const ButtonVariant: {
5
- plain: string;
6
- link: string;
7
- };
8
- //# sourceMappingURL=Button.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../../../src/components/Button/__mocks__/Button.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAElC,eAAO,MAAM,MAAM,2EAA4E,WAAW,gBAWzG,CAAC;AAEF,eAAO,MAAM,aAAa;;;CAAmC,CAAC"}
@@ -1,14 +0,0 @@
1
- import { __rest } from "tslib";
2
- import React from 'react';
3
- export const Button = (_a) => {
4
- var { children, variant, isInline, onClick, iconPosition, icon } = _a, props = __rest(_a, ["children", "variant", "isInline", "onClick", "iconPosition", "icon"]);
5
- return (React.createElement(React.Fragment, null,
6
- React.createElement("button", Object.assign({ onClick: onClick }, props), children),
7
- React.createElement("p", null, `variant: ${variant}`),
8
- React.createElement("p", { id: "labelling-id" }, "Test label"),
9
- React.createElement("p", null, `isInline: ${isInline}`),
10
- React.createElement("p", null, `iconPosition: ${iconPosition}`),
11
- React.createElement("div", { "data-testid": "icon" }, icon)));
12
- };
13
- export const ButtonVariant = { plain: 'plain', link: 'link' };
14
- //# sourceMappingURL=Button.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../../../src/components/Button/__mocks__/Button.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,EAAmF,EAAE,EAAE;QAAvF,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,OAAyB,EAApB,KAAK,cAApE,sEAAsE,CAAF;IAAoB,OAAA,CAC7G;QACE,8CAAQ,OAAO,EAAE,OAAO,IAAM,KAAK,GAChC,QAAQ,CACF;QACT,+BAAI,YAAY,OAAO,EAAE,CAAK;QAC9B,2BAAG,EAAE,EAAC,cAAc,iBAAe;QACnC,+BAAI,aAAa,QAAQ,EAAE,CAAK;QAChC,+BAAI,iBAAiB,YAAY,EAAE,CAAK;QACxC,4CAAiB,MAAM,IAAE,IAAI,CAAO,CACnC,CACJ,CAAA;CAAA,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './Button';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Button/__mocks__/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './Button';
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/components/Button/__mocks__/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
@@ -1,4 +0,0 @@
1
- /// <reference types="react" />
2
- import { HelperTextProps } from '../';
3
- export declare const HelperText: ({ children, isLiveRegion }: HelperTextProps) => JSX.Element;
4
- //# sourceMappingURL=HelperText.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HelperText.d.ts","sourceRoot":"","sources":["../../../../../src/components/HelperText/__mocks__/HelperText.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,eAAe,EAAE,MAAM,KAAK,CAAC;AAEtC,eAAO,MAAM,UAAU,+BAAgC,eAAe,gBAKrE,CAAC"}
@@ -1,5 +0,0 @@
1
- import React from 'react';
2
- export const HelperText = ({ children, isLiveRegion }) => (React.createElement(React.Fragment, null,
3
- React.createElement("div", { "data-testid": "helper-text-children-container" }, children),
4
- React.createElement("p", null, `isLiveRegion: ${isLiveRegion}`)));
5
- //# sourceMappingURL=HelperText.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HelperText.js","sourceRoot":"","sources":["../../../../../src/components/HelperText/__mocks__/HelperText.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAmB,EAAE,EAAE,CAAC,CACzE;IACE,4CAAiB,gCAAgC,IAAE,QAAQ,CAAO;IAClE,+BAAI,iBAAiB,YAAY,EAAE,CAAK,CACvC,CACJ,CAAC"}
@@ -1,4 +0,0 @@
1
- /// <reference types="react" />
2
- import { HelperTextItemProps } from '../';
3
- export declare const HelperTextItem: ({ children, variant }: HelperTextItemProps) => JSX.Element;
4
- //# sourceMappingURL=HelperTextItem.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HelperTextItem.d.ts","sourceRoot":"","sources":["../../../../../src/components/HelperText/__mocks__/HelperTextItem.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,KAAK,CAAC;AAE1C,eAAO,MAAM,cAAc,0BAA2B,mBAAmB,gBAKxE,CAAC"}
@@ -1,5 +0,0 @@
1
- import React from 'react';
2
- export const HelperTextItem = ({ children, variant }) => (React.createElement(React.Fragment, null,
3
- React.createElement("div", { "data-testid": "helper-text-item-children-container" }, children),
4
- React.createElement("p", null, `variant: ${variant}`)));
5
- //# sourceMappingURL=HelperTextItem.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HelperTextItem.js","sourceRoot":"","sources":["../../../../../src/components/HelperText/__mocks__/HelperTextItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAuB,EAAE,EAAE,CAAC,CAC5E;IACE,4CAAiB,qCAAqC,IAAE,QAAQ,CAAO;IACvE,+BAAI,YAAY,OAAO,EAAE,CAAK,CAC7B,CACJ,CAAC"}
@@ -1,3 +0,0 @@
1
- export * from './HelperText';
2
- export * from './HelperTextItem';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/HelperText/__mocks__/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC"}
@@ -1,3 +0,0 @@
1
- export * from './HelperText';
2
- export * from './HelperTextItem';
3
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/components/HelperText/__mocks__/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC"}
@@ -1,8 +0,0 @@
1
- /// <reference types="react" />
2
- import { ButtonProps } from '../';
3
- export declare const Button: ({ children, variant, isInline, onClick, iconPosition, icon, ...props }: ButtonProps) => JSX.Element;
4
- export declare const ButtonVariant: {
5
- plain: string;
6
- link: string;
7
- };
8
- //# sourceMappingURL=Button.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../../../src/components/Button/__mocks__/Button.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAElC,eAAO,MAAM,MAAM,2EAA4E,WAAW,gBAWzG,CAAC;AAEF,eAAO,MAAM,aAAa;;;CAAmC,CAAC"}
@@ -1,18 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ButtonVariant = exports.Button = void 0;
4
- const tslib_1 = require("tslib");
5
- const react_1 = tslib_1.__importDefault(require("react"));
6
- const Button = (_a) => {
7
- var { children, variant, isInline, onClick, iconPosition, icon } = _a, props = tslib_1.__rest(_a, ["children", "variant", "isInline", "onClick", "iconPosition", "icon"]);
8
- return (react_1.default.createElement(react_1.default.Fragment, null,
9
- react_1.default.createElement("button", Object.assign({ onClick: onClick }, props), children),
10
- react_1.default.createElement("p", null, `variant: ${variant}`),
11
- react_1.default.createElement("p", { id: "labelling-id" }, "Test label"),
12
- react_1.default.createElement("p", null, `isInline: ${isInline}`),
13
- react_1.default.createElement("p", null, `iconPosition: ${iconPosition}`),
14
- react_1.default.createElement("div", { "data-testid": "icon" }, icon)));
15
- };
16
- exports.Button = Button;
17
- exports.ButtonVariant = { plain: 'plain', link: 'link' };
18
- //# sourceMappingURL=Button.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../../../src/components/Button/__mocks__/Button.tsx"],"names":[],"mappings":";;;;AAAA,0DAA0B;AAGnB,MAAM,MAAM,GAAG,CAAC,EAAmF,EAAE,EAAE;QAAvF,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,OAAyB,EAApB,KAAK,sBAApE,sEAAsE,CAAF;IAAoB,OAAA,CAC7G;QACE,wDAAQ,OAAO,EAAE,OAAO,IAAM,KAAK,GAChC,QAAQ,CACF;QACT,yCAAI,YAAY,OAAO,EAAE,CAAK;QAC9B,qCAAG,EAAE,EAAC,cAAc,iBAAe;QACnC,yCAAI,aAAa,QAAQ,EAAE,CAAK;QAChC,yCAAI,iBAAiB,YAAY,EAAE,CAAK;QACxC,sDAAiB,MAAM,IAAE,IAAI,CAAO,CACnC,CACJ,CAAA;CAAA,CAAC;AAXW,QAAA,MAAM,UAWjB;AAEW,QAAA,aAAa,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './Button';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Button/__mocks__/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./Button"), exports);
5
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/components/Button/__mocks__/index.ts"],"names":[],"mappings":";;;AAAA,mDAAyB"}