@availity/mui-stepper 0.2.4 → 0.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@availity/mui-stepper",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "description": "Availity MUI Stepper Component - part of the @availity/element design system",
5
5
  "keywords": [
6
6
  "react",
@@ -32,13 +32,13 @@
32
32
  "publish:canary": "yarn npm publish --access public --tag canary"
33
33
  },
34
34
  "dependencies": {
35
- "@availity/mui-icon": "^0.12.1"
35
+ "@availity/mui-icon": "^0.12.1",
36
+ "@availity/mui-typography": "^0.2.1"
36
37
  },
37
38
  "devDependencies": {
38
39
  "@availity/mui-button": "^0.6.14",
39
40
  "@availity/mui-layout": "^0.2.0",
40
41
  "@availity/mui-paper": "^0.1.9",
41
- "@availity/mui-typography": "^0.2.1",
42
42
  "@mui/material": "^5.15.15",
43
43
  "react": "18.2.0",
44
44
  "react-dom": "18.2.0",
@@ -21,13 +21,13 @@ export const _Step: StoryObj<typeof Step> = {
21
21
  <Box>
22
22
  <Paper sx={{ padding: '2rem' }}>
23
23
  <Stepper>
24
- <Step {...args}/>
24
+ <Step {...args} />
25
25
  </Stepper>
26
26
  </Paper>
27
27
  </Box>
28
28
  ),
29
29
  args: {
30
- children: 'Children'
30
+ children: 'Children',
31
31
  },
32
32
  };
33
33
 
@@ -1,7 +1,14 @@
1
1
  import MuiStepButton, { StepButtonProps as MuiStepButtonProps } from '@mui/material/StepButton';
2
2
 
3
- export type StepButtonProps = MuiStepButtonProps;
3
+ export type StepButtonProps = Omit<
4
+ MuiStepButtonProps,
5
+ 'centerRipple' | 'disableRipple' | 'disableTouchRipple' | 'focusRipple' | 'TouchRippleProps' | 'touchRippleRef'
6
+ >;
4
7
 
5
8
  export const StepButton = ({ children, ...rest }: StepButtonProps): JSX.Element => {
6
- return <MuiStepButton {...rest}>{children}</MuiStepButton>;
9
+ return (
10
+ <MuiStepButton {...rest} disableRipple disableTouchRipple>
11
+ {children}
12
+ </MuiStepButton>
13
+ );
7
14
  };
@@ -1,12 +1,22 @@
1
1
  import MuiStepLabel, { StepLabelProps as MuiStepLabelProps } from '@mui/material/StepLabel';
2
2
 
3
3
  import { StepIcon, StepIconProps } from './StepIcon';
4
+ import { Typography } from '@availity/mui-typography';
4
5
 
5
6
  export type StepLabelProps = Pick<StepIconProps, 'warning'> & MuiStepLabelProps;
6
7
 
7
- const StepLabel = ({ children, error, warning, ...rest }: StepLabelProps): JSX.Element => {
8
+ const StepLabel = ({ children, error, optional, warning, ...rest }: StepLabelProps): JSX.Element => {
9
+ if (typeof optional === 'string') {
10
+ optional = <Typography variant="caption" children={optional} />;
11
+ }
8
12
  return (
9
- <MuiStepLabel StepIconProps={{ error, warning }} StepIconComponent={StepIcon} error={error} {...rest}>
13
+ <MuiStepLabel
14
+ StepIconProps={{ error, warning }}
15
+ StepIconComponent={StepIcon}
16
+ error={error}
17
+ optional={optional}
18
+ {...rest}
19
+ >
10
20
  {children}
11
21
  </MuiStepLabel>
12
22
  );
@@ -174,7 +174,73 @@ export const _Stepper: StoryObj<typeof Stepper> = {
174
174
  </Box>
175
175
  );
176
176
  },
177
- args: {},
177
+ };
178
+
179
+ export const _StepperScrollButtons: StoryObj<typeof Stepper> = {
180
+ render: (args) => (
181
+ <Box>
182
+ <Paper sx={{ padding: '2rem' }}>
183
+ <Stepper {...args}>
184
+ <Step>
185
+ <StepLabel optional="Optional Sub-label">Label</StepLabel>
186
+ </Step>
187
+ <Step>
188
+ <StepLabel>Label</StepLabel>
189
+ </Step>
190
+ <Step>
191
+ <StepLabel>Label</StepLabel>
192
+ </Step>
193
+ <Step>
194
+ <StepLabel>Label</StepLabel>
195
+ </Step>
196
+ <Step>
197
+ <StepLabel>Label</StepLabel>
198
+ </Step>
199
+ <Step>
200
+ <StepLabel>Label</StepLabel>
201
+ </Step>
202
+ <Step>
203
+ <StepLabel>Label</StepLabel>
204
+ </Step>
205
+ <Step>
206
+ <StepLabel>Label</StepLabel>
207
+ </Step>
208
+ <Step>
209
+ <StepLabel>Label</StepLabel>
210
+ </Step>
211
+ <Step>
212
+ <StepLabel>Label</StepLabel>
213
+ </Step>
214
+ </Stepper>
215
+ </Paper>
216
+ </Box>
217
+ ),
218
+ args: {
219
+ scrollButtons: true,
220
+ },
221
+ };
222
+
223
+ /**
224
+ * To remove the connector, set the `connector` prop to `null`.
225
+ * */
226
+ export const _StepperWithoutConnectors: StoryObj<typeof Stepper> = {
227
+ render: (args) => (
228
+ <Box>
229
+ <Paper sx={{ padding: '2rem' }}>
230
+ <Stepper {...args} connector={null}>
231
+ <Step>
232
+ <StepLabel>Label</StepLabel>
233
+ </Step>
234
+ <Step>
235
+ <StepLabel>Label</StepLabel>
236
+ </Step>
237
+ </Stepper>
238
+ </Paper>
239
+ </Box>
240
+ ),
241
+ args: {
242
+ connector: null,
243
+ },
178
244
  };
179
245
 
180
246
  export const _StepLabel: StoryObj<typeof StepLabel> = {
@@ -1,10 +1,18 @@
1
+ /* eslint-disable @typescript-eslint/no-empty-function */
1
2
  import { render, screen } from '@testing-library/react';
2
3
 
3
4
  import { Stepper } from './Stepper';
4
5
  import { Step } from './Step';
5
6
  import { StepLabel } from './StepLabel';
6
7
 
8
+ class ResizeObserver {
9
+ observe() {}
10
+ unobserve() {}
11
+ disconnect() {}
12
+ }
13
+
7
14
  describe('Stepper', () => {
15
+ window.ResizeObserver = ResizeObserver;
8
16
  test('should render successfully', () => {
9
17
  render(
10
18
  <Stepper activeStep={0}>
@@ -1,13 +1,109 @@
1
+ import { useRef, useState, useEffect } from 'react';
1
2
  import MuiStepper, { StepperProps as MuiStepperProps } from '@mui/material/Stepper';
3
+ import { IconButton } from '@availity/mui-button';
4
+ import { NavigatePreviousIcon, NavigateNextIcon } from '@availity/mui-icon';
5
+ import { Grid } from '@availity/mui-layout';
6
+ import { styled } from '@mui/material/styles';
2
7
 
3
- export type StepperProps = Omit<MuiStepperProps, 'alternativeLabel' | 'elevation'>;
8
+ export type StepperProps = {
9
+ scrollButtons?: boolean;
10
+ } & Omit<MuiStepperProps, 'alternativeLabel' | 'elevation'>;
4
11
 
5
- export const Stepper = ({ children, orientation, ...rest }: StepperProps): JSX.Element => {
12
+ export const Stepper = ({ children, connector, orientation, scrollButtons, ...rest }: StepperProps): JSX.Element => {
6
13
  const alternativeLabel = orientation !== 'vertical';
7
14
 
8
- return (
9
- <MuiStepper {...rest} orientation={orientation} alternativeLabel={alternativeLabel}>
10
- {children}
11
- </MuiStepper>
15
+ const stepperRef = useRef<HTMLDivElement>(null);
16
+ const [showLeftButton, setShowLeftButton] = useState(true);
17
+ const [showRightButton, setShowRightButton] = useState(true);
18
+
19
+ useEffect(() => {
20
+ const stepper = stepperRef.current;
21
+
22
+ const handleScroll = () => {
23
+ if (stepper) {
24
+ setShowLeftButton(stepper.scrollLeft > 0);
25
+
26
+ // Check if scrolled to right
27
+ const isRight = Math.abs(stepper.scrollWidth - stepper.clientWidth - stepper.scrollLeft) <= 1; // Using 1px threshold for floating point precision
28
+ setShowRightButton(!isRight);
29
+ }
30
+ };
31
+
32
+ const resizeObserver = new ResizeObserver(() => {
33
+ handleScroll();
34
+ });
35
+
36
+ if (stepper) {
37
+ stepper.addEventListener('scroll', handleScroll);
38
+ resizeObserver.observe(stepper);
39
+ // Initial check
40
+ handleScroll();
41
+ }
42
+
43
+ return () => {
44
+ if (stepper) {
45
+ stepper.removeEventListener('scroll', handleScroll);
46
+ resizeObserver.disconnect();
47
+ }
48
+ };
49
+ }, []);
50
+
51
+ const showScrollButtons = scrollButtons && orientation !== 'vertical';
52
+
53
+ const ScrollIconContainer = styled('div')({
54
+ width: '50px',
55
+ flexShrink: 0,
56
+ paddingTop: '15px',
57
+ });
58
+
59
+ return showScrollButtons ? (
60
+ <Grid container direction="row" justifyContent="space-between" wrap="nowrap">
61
+ <ScrollIconContainer style={{ paddingRight: '8px' }}>
62
+ {showLeftButton && (
63
+ <IconButton
64
+ title="Previous"
65
+ variant="outlined"
66
+ onClick={() => stepperRef.current?.scrollTo({ left: 0, behavior: 'smooth' })}
67
+ >
68
+ <NavigatePreviousIcon fontSize="xsmall" />
69
+ </IconButton>
70
+ )}
71
+ </ScrollIconContainer>
72
+
73
+ <MuiStepper
74
+ {...rest}
75
+ connector={connector}
76
+ orientation={orientation}
77
+ alternativeLabel={alternativeLabel}
78
+ ref={stepperRef}
79
+ children={children}
80
+ />
81
+
82
+ <ScrollIconContainer style={{ paddingLeft: '8px' }}>
83
+ {showRightButton && (
84
+ <IconButton
85
+ title="Next"
86
+ variant="outlined"
87
+ onClick={() => {
88
+ stepperRef.current?.scrollTo({
89
+ left: stepperRef.current.scrollWidth - stepperRef.current.clientWidth,
90
+ behavior: 'smooth',
91
+ });
92
+ }}
93
+ >
94
+ <NavigateNextIcon fontSize="xsmall" />
95
+ </IconButton>
96
+ )}
97
+ </ScrollIconContainer>
98
+ </Grid>
99
+ ) : (
100
+ <MuiStepper
101
+ {...rest}
102
+ connector={connector}
103
+ orientation={orientation}
104
+ alternativeLabel={alternativeLabel}
105
+ ref={stepperRef}
106
+ children={children}
107
+ />
12
108
  );
13
109
  };