@availity/mui-stepper 0.1.4 → 0.2.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/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [0.2.0](https://github.com/Availity/element/compare/@availity/mui-stepper@0.1.4...@availity/mui-stepper@0.2.0) (2024-10-04)
6
+
7
+
8
+ ### Features
9
+
10
+ * **mui-stepper:** legacy styles and docs ([9bad3a1](https://github.com/Availity/element/commit/9bad3a13300857e3d13e5b21bc11e20c492c69e7))
11
+
5
12
  ## [0.1.4](https://github.com/Availity/element/compare/@availity/mui-stepper@0.1.3...@availity/mui-stepper@0.1.4) (2024-09-09)
6
13
 
7
14
 
package/dist/index.d.mts CHANGED
@@ -1,6 +1,44 @@
1
+ import { StepProps as StepProps$1 } from '@mui/material/Step';
2
+ import { StepButtonProps as StepButtonProps$1 } from '@mui/material/StepButton';
3
+ import { StepConnectorProps as StepConnectorProps$1 } from '@mui/material/StepConnector';
4
+ import { StepContentProps as StepContentProps$1 } from '@mui/material/StepContent';
5
+ import { StepIconProps as StepIconProps$1 } from '@mui/material/StepIcon';
6
+ import { SvgIconProps } from '@mui/material/SvgIcon';
7
+ import { StepLabelProps as StepLabelProps$1 } from '@mui/material/StepLabel';
1
8
  import { StepperProps as StepperProps$1 } from '@mui/material/Stepper';
2
9
 
10
+ type StepProps = StepProps$1;
11
+ declare const Step: ({ children, ...rest }: StepProps) => JSX.Element;
12
+
13
+ type StepButtonProps = StepButtonProps$1;
14
+ declare const StepButton: ({ children, ...rest }: StepButtonProps) => JSX.Element;
15
+
16
+ type StepConnectorProps = StepConnectorProps$1;
17
+ declare const StepConnector: (props: StepConnectorProps) => JSX.Element;
18
+
19
+ type StepContentProps = StepContentProps$1;
20
+ declare const StepContent: ({ children, ...rest }: StepContentProps) => JSX.Element;
21
+
22
+ type Tag = ((props: SvgIconProps) => JSX.Element) | null;
23
+ declare module '@mui/material/StepIcon' {
24
+ interface StepIconProps {
25
+ as?: Tag;
26
+ warning?: boolean;
27
+ }
28
+ }
29
+ type StepIconProps = {
30
+ /** If `true`, the step will have a warning icon. */
31
+ warning?: boolean;
32
+ } & StepIconProps$1;
33
+ declare const StepIcon: ({ error, completed, warning, ...rest }: StepIconProps) => JSX.Element;
34
+
35
+ type StepLabelProps = Pick<StepIconProps, 'warning'> & StepLabelProps$1;
36
+ declare const StepLabel: {
37
+ ({ children, error, warning, ...rest }: StepLabelProps): JSX.Element;
38
+ muiName: string;
39
+ };
40
+
3
41
  type StepperProps = Omit<StepperProps$1, 'alternativeLabel' | 'elevation'>;
4
42
  declare const Stepper: ({ children, orientation, ...rest }: StepperProps) => JSX.Element;
5
43
 
6
- export { Stepper, type StepperProps };
44
+ export { Step, StepButton, type StepButtonProps, StepConnector, type StepConnectorProps, StepContent, type StepContentProps, StepIcon, type StepIconProps, StepLabel, type StepLabelProps, type StepProps, Stepper, type StepperProps };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,44 @@
1
+ import { StepProps as StepProps$1 } from '@mui/material/Step';
2
+ import { StepButtonProps as StepButtonProps$1 } from '@mui/material/StepButton';
3
+ import { StepConnectorProps as StepConnectorProps$1 } from '@mui/material/StepConnector';
4
+ import { StepContentProps as StepContentProps$1 } from '@mui/material/StepContent';
5
+ import { StepIconProps as StepIconProps$1 } from '@mui/material/StepIcon';
6
+ import { SvgIconProps } from '@mui/material/SvgIcon';
7
+ import { StepLabelProps as StepLabelProps$1 } from '@mui/material/StepLabel';
1
8
  import { StepperProps as StepperProps$1 } from '@mui/material/Stepper';
2
9
 
10
+ type StepProps = StepProps$1;
11
+ declare const Step: ({ children, ...rest }: StepProps) => JSX.Element;
12
+
13
+ type StepButtonProps = StepButtonProps$1;
14
+ declare const StepButton: ({ children, ...rest }: StepButtonProps) => JSX.Element;
15
+
16
+ type StepConnectorProps = StepConnectorProps$1;
17
+ declare const StepConnector: (props: StepConnectorProps) => JSX.Element;
18
+
19
+ type StepContentProps = StepContentProps$1;
20
+ declare const StepContent: ({ children, ...rest }: StepContentProps) => JSX.Element;
21
+
22
+ type Tag = ((props: SvgIconProps) => JSX.Element) | null;
23
+ declare module '@mui/material/StepIcon' {
24
+ interface StepIconProps {
25
+ as?: Tag;
26
+ warning?: boolean;
27
+ }
28
+ }
29
+ type StepIconProps = {
30
+ /** If `true`, the step will have a warning icon. */
31
+ warning?: boolean;
32
+ } & StepIconProps$1;
33
+ declare const StepIcon: ({ error, completed, warning, ...rest }: StepIconProps) => JSX.Element;
34
+
35
+ type StepLabelProps = Pick<StepIconProps, 'warning'> & StepLabelProps$1;
36
+ declare const StepLabel: {
37
+ ({ children, error, warning, ...rest }: StepLabelProps): JSX.Element;
38
+ muiName: string;
39
+ };
40
+
3
41
  type StepperProps = Omit<StepperProps$1, 'alternativeLabel' | 'elevation'>;
4
42
  declare const Stepper: ({ children, orientation, ...rest }: StepperProps) => JSX.Element;
5
43
 
6
- export { Stepper, type StepperProps };
44
+ export { Step, StepButton, type StepButtonProps, StepConnector, type StepConnectorProps, StepContent, type StepContentProps, StepIcon, type StepIconProps, StepLabel, type StepLabelProps, type StepProps, Stepper, type StepperProps };
package/dist/index.js CHANGED
@@ -59,19 +59,87 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
59
59
  // src/index.ts
60
60
  var src_exports = {};
61
61
  __export(src_exports, {
62
+ Step: () => Step,
63
+ StepButton: () => StepButton,
64
+ StepConnector: () => StepConnector,
65
+ StepContent: () => StepContent,
66
+ StepIcon: () => StepIcon,
67
+ StepLabel: () => StepLabel,
62
68
  Stepper: () => Stepper
63
69
  });
64
70
  module.exports = __toCommonJS(src_exports);
65
71
 
72
+ // src/lib/Step.tsx
73
+ var import_Step = __toESM(require("@mui/material/Step"));
74
+ var import_jsx_runtime = require("react/jsx-runtime");
75
+ var Step = (_a) => {
76
+ var _b = _a, { children } = _b, rest = __objRest(_b, ["children"]);
77
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Step.default, __spreadProps(__spreadValues({}, rest), { children }));
78
+ };
79
+
80
+ // src/lib/StepButton.tsx
81
+ var import_StepButton = __toESM(require("@mui/material/StepButton"));
82
+ var import_jsx_runtime2 = require("react/jsx-runtime");
83
+ var StepButton = (_a) => {
84
+ var _b = _a, { children } = _b, rest = __objRest(_b, ["children"]);
85
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_StepButton.default, __spreadProps(__spreadValues({}, rest), { children }));
86
+ };
87
+
88
+ // src/lib/StepConnector.tsx
89
+ var import_StepConnector = __toESM(require("@mui/material/StepConnector"));
90
+ var import_jsx_runtime3 = require("react/jsx-runtime");
91
+ var StepConnector = (props) => {
92
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_StepConnector.default, __spreadValues({}, props));
93
+ };
94
+
95
+ // src/lib/StepContent.tsx
96
+ var import_StepContent = __toESM(require("@mui/material/StepContent"));
97
+ var import_jsx_runtime4 = require("react/jsx-runtime");
98
+ var StepContent = (_a) => {
99
+ var _b = _a, { children } = _b, rest = __objRest(_b, ["children"]);
100
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_StepContent.default, __spreadProps(__spreadValues({}, rest), { children }));
101
+ };
102
+
103
+ // src/lib/StepIcon.tsx
104
+ var import_StepIcon = __toESM(require("@mui/material/StepIcon"));
105
+ var import_mui_icon = require("@availity/mui-icon");
106
+ var import_jsx_runtime5 = require("react/jsx-runtime");
107
+ var StepIcon = (_a) => {
108
+ var _b = _a, { error, completed, warning } = _b, rest = __objRest(_b, ["error", "completed", "warning"]);
109
+ let tag = null;
110
+ if (error)
111
+ tag = import_mui_icon.WarningCircleIcon;
112
+ if (warning)
113
+ tag = (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_icon.WarningCircleIcon, __spreadValues({ color: "warning" }, props));
114
+ if (completed)
115
+ tag = import_mui_icon.SuccessCircleIcon;
116
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_StepIcon.default, __spreadProps(__spreadValues({}, rest), { error, completed, as: tag }));
117
+ };
118
+
119
+ // src/lib/StepLabel.tsx
120
+ var import_StepLabel = __toESM(require("@mui/material/StepLabel"));
121
+ var import_jsx_runtime6 = require("react/jsx-runtime");
122
+ var StepLabel = (_a) => {
123
+ var _b = _a, { children, error, warning } = _b, rest = __objRest(_b, ["children", "error", "warning"]);
124
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_StepLabel.default, __spreadProps(__spreadValues({ StepIconProps: { error, warning }, StepIconComponent: StepIcon, error }, rest), { children }));
125
+ };
126
+ StepLabel.muiName = import_StepLabel.default.muiName;
127
+
66
128
  // src/lib/Stepper.tsx
67
129
  var import_Stepper = __toESM(require("@mui/material/Stepper"));
68
- var import_jsx_runtime = require("react/jsx-runtime");
130
+ var import_jsx_runtime7 = require("react/jsx-runtime");
69
131
  var Stepper = (_a) => {
70
132
  var _b = _a, { children, orientation } = _b, rest = __objRest(_b, ["children", "orientation"]);
71
133
  const alternativeLabel = orientation !== "vertical";
72
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Stepper.default, __spreadProps(__spreadValues({}, rest), { orientation, alternativeLabel, children }));
134
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Stepper.default, __spreadProps(__spreadValues({}, rest), { orientation, alternativeLabel, children }));
73
135
  };
74
136
  // Annotate the CommonJS export names for ESM import in node:
75
137
  0 && (module.exports = {
138
+ Step,
139
+ StepButton,
140
+ StepConnector,
141
+ StepContent,
142
+ StepIcon,
143
+ StepLabel,
76
144
  Stepper
77
145
  });
package/dist/index.mjs CHANGED
@@ -30,14 +30,76 @@ var __objRest = (source, exclude) => {
30
30
  return target;
31
31
  };
32
32
 
33
+ // src/lib/Step.tsx
34
+ import MuiStep from "@mui/material/Step";
35
+ import { jsx } from "react/jsx-runtime";
36
+ var Step = (_a) => {
37
+ var _b = _a, { children } = _b, rest = __objRest(_b, ["children"]);
38
+ return /* @__PURE__ */ jsx(MuiStep, __spreadProps(__spreadValues({}, rest), { children }));
39
+ };
40
+
41
+ // src/lib/StepButton.tsx
42
+ import MuiStepButton from "@mui/material/StepButton";
43
+ import { jsx as jsx2 } from "react/jsx-runtime";
44
+ var StepButton = (_a) => {
45
+ var _b = _a, { children } = _b, rest = __objRest(_b, ["children"]);
46
+ return /* @__PURE__ */ jsx2(MuiStepButton, __spreadProps(__spreadValues({}, rest), { children }));
47
+ };
48
+
49
+ // src/lib/StepConnector.tsx
50
+ import MuiStepConnector from "@mui/material/StepConnector";
51
+ import { jsx as jsx3 } from "react/jsx-runtime";
52
+ var StepConnector = (props) => {
53
+ return /* @__PURE__ */ jsx3(MuiStepConnector, __spreadValues({}, props));
54
+ };
55
+
56
+ // src/lib/StepContent.tsx
57
+ import MuiStepContent from "@mui/material/StepContent";
58
+ import { jsx as jsx4 } from "react/jsx-runtime";
59
+ var StepContent = (_a) => {
60
+ var _b = _a, { children } = _b, rest = __objRest(_b, ["children"]);
61
+ return /* @__PURE__ */ jsx4(MuiStepContent, __spreadProps(__spreadValues({}, rest), { children }));
62
+ };
63
+
64
+ // src/lib/StepIcon.tsx
65
+ import MuiStepIcon from "@mui/material/StepIcon";
66
+ import { SuccessCircleIcon, WarningCircleIcon } from "@availity/mui-icon";
67
+ import { jsx as jsx5 } from "react/jsx-runtime";
68
+ var StepIcon = (_a) => {
69
+ var _b = _a, { error, completed, warning } = _b, rest = __objRest(_b, ["error", "completed", "warning"]);
70
+ let tag = null;
71
+ if (error)
72
+ tag = WarningCircleIcon;
73
+ if (warning)
74
+ tag = (props) => /* @__PURE__ */ jsx5(WarningCircleIcon, __spreadValues({ color: "warning" }, props));
75
+ if (completed)
76
+ tag = SuccessCircleIcon;
77
+ return /* @__PURE__ */ jsx5(MuiStepIcon, __spreadProps(__spreadValues({}, rest), { error, completed, as: tag }));
78
+ };
79
+
80
+ // src/lib/StepLabel.tsx
81
+ import MuiStepLabel from "@mui/material/StepLabel";
82
+ import { jsx as jsx6 } from "react/jsx-runtime";
83
+ var StepLabel = (_a) => {
84
+ var _b = _a, { children, error, warning } = _b, rest = __objRest(_b, ["children", "error", "warning"]);
85
+ return /* @__PURE__ */ jsx6(MuiStepLabel, __spreadProps(__spreadValues({ StepIconProps: { error, warning }, StepIconComponent: StepIcon, error }, rest), { children }));
86
+ };
87
+ StepLabel.muiName = MuiStepLabel.muiName;
88
+
33
89
  // src/lib/Stepper.tsx
34
90
  import MuiStepper from "@mui/material/Stepper";
35
- import { jsx } from "react/jsx-runtime";
91
+ import { jsx as jsx7 } from "react/jsx-runtime";
36
92
  var Stepper = (_a) => {
37
93
  var _b = _a, { children, orientation } = _b, rest = __objRest(_b, ["children", "orientation"]);
38
94
  const alternativeLabel = orientation !== "vertical";
39
- return /* @__PURE__ */ jsx(MuiStepper, __spreadProps(__spreadValues({}, rest), { orientation, alternativeLabel, children }));
95
+ return /* @__PURE__ */ jsx7(MuiStepper, __spreadProps(__spreadValues({}, rest), { orientation, alternativeLabel, children }));
40
96
  };
41
97
  export {
98
+ Step,
99
+ StepButton,
100
+ StepConnector,
101
+ StepContent,
102
+ StepIcon,
103
+ StepLabel,
42
104
  Stepper
43
105
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@availity/mui-stepper",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "Availity MUI Stepper Component - part of the @availity/element design system",
5
5
  "keywords": [
6
6
  "react",
package/src/index.ts CHANGED
@@ -1 +1,7 @@
1
+ export * from './lib/Step';
2
+ export * from './lib/StepButton';
3
+ export * from './lib/StepConnector';
4
+ export * from './lib/StepContent';
5
+ export * from './lib/StepIcon';
6
+ export * from './lib/StepLabel';
1
7
  export * from './lib/Stepper';
@@ -0,0 +1,188 @@
1
+ // Each exported component in the package should have its own stories file
2
+ import { useState, useEffect } from 'react';
3
+ import type { Meta, StoryObj } from '@storybook/react';
4
+ import { Button } from '@availity/mui-button';
5
+ import { Typography } from '@availity/mui-typography';
6
+ import { Box } from '@availity/mui-layout';
7
+ import { Paper } from '@availity/mui-paper';
8
+
9
+ import { Stepper, Step, StepLabel, StepButton } from '..';
10
+
11
+ const meta: Meta<typeof Step> = {
12
+ title: 'Components/Stepper/Step',
13
+ component: Step,
14
+ tags: ['autodocs'],
15
+ };
16
+
17
+ export default meta;
18
+
19
+ export const _Step: StoryObj<typeof Step> = {
20
+ render: (args) => (
21
+ <Box>
22
+ <Paper sx={{ padding: '2rem' }}>
23
+ <Stepper>
24
+ <Step {...args}/>
25
+ </Stepper>
26
+ </Paper>
27
+ </Box>
28
+ ),
29
+ args: {
30
+ children: 'Children'
31
+ },
32
+ };
33
+
34
+ // credit: https://stackoverflow.com/questions/36862334/get-viewport-window-height-in-reactjs
35
+ function getWindowDimensions() {
36
+ const { innerWidth: width, innerHeight: height } = window;
37
+ return {
38
+ width,
39
+ height,
40
+ };
41
+ }
42
+
43
+ function useWindowDimensions() {
44
+ const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
45
+
46
+ useEffect(() => {
47
+ function handleResize() {
48
+ setWindowDimensions(getWindowDimensions());
49
+ }
50
+
51
+ window.addEventListener('resize', handleResize);
52
+ return () => window.removeEventListener('resize', handleResize);
53
+ }, []);
54
+
55
+ return windowDimensions;
56
+ }
57
+
58
+ const steps = ['First', 'Second', 'Third', 'Final'];
59
+
60
+ export const _Stepper: StoryObj<typeof Step> = {
61
+ render: (args) => {
62
+ const [activeStep, setActiveStep] = useState(0);
63
+ const [skipped, setSkipped] = useState(new Set<number>());
64
+
65
+ const { width } = useWindowDimensions();
66
+
67
+ const isStepOptional = (step: number) => {
68
+ return step > 1;
69
+ };
70
+
71
+ const isStepSkipped = (step: number) => {
72
+ return skipped.has(step);
73
+ };
74
+
75
+ const isStepError = (step: number) => {
76
+ return step === 2 && activeStep < 2;
77
+ };
78
+
79
+ const isStepWarning = (step: number) => {
80
+ return step === 3 && activeStep < 3;
81
+ };
82
+
83
+ const handleNext = () => {
84
+ let newSkipped = skipped;
85
+ if (isStepSkipped(activeStep)) {
86
+ newSkipped = new Set(newSkipped.values());
87
+ newSkipped.delete(activeStep);
88
+ }
89
+
90
+ setActiveStep((prevActiveStep) => prevActiveStep + 1);
91
+ setSkipped(newSkipped);
92
+ };
93
+
94
+ const handleBack = () => {
95
+ setActiveStep((prevActiveStep) => prevActiveStep - 1);
96
+ };
97
+
98
+ const handleStep = (step: number) => () => {
99
+ setActiveStep(step);
100
+ };
101
+
102
+ const handleSkip = () => {
103
+ if (!isStepOptional(activeStep)) {
104
+ // You probably want to guard against something like this,
105
+ // it should never occur unless someone's actively trying to break something.
106
+ throw new Error("You can't skip a step that isn't optional.");
107
+ }
108
+
109
+ setActiveStep((prevActiveStep) => prevActiveStep + 1);
110
+ setSkipped((prevSkipped) => {
111
+ const newSkipped = new Set(prevSkipped.values());
112
+ newSkipped.add(activeStep);
113
+ return newSkipped;
114
+ });
115
+ };
116
+
117
+ const handleReset = () => {
118
+ setActiveStep(0);
119
+ };
120
+
121
+ return (
122
+ <Box maxWidth="75vw" marginX="auto">
123
+ <Paper sx={{ padding: '2rem' }}>
124
+ <Stepper activeStep={activeStep} orientation={width < 600 ? 'vertical' : 'horizontal'}>
125
+ {steps.map((label, index) => {
126
+ const stepProps: { completed?: boolean } = {};
127
+ const labelProps: { optional?: React.ReactNode; error?: boolean; warning?: boolean } = {};
128
+
129
+ if (isStepOptional(index)) {
130
+ labelProps.optional = <Typography variant="caption">Optional</Typography>;
131
+ }
132
+
133
+ if (isStepSkipped(index)) {
134
+ stepProps.completed = false;
135
+ }
136
+
137
+ if (isStepError(index)) {
138
+ labelProps.error = true;
139
+ }
140
+
141
+ if (isStepWarning(index)) {
142
+ labelProps.warning = true;
143
+ }
144
+
145
+ return (
146
+ <Step key={label} {...stepProps} {...args}>
147
+ <StepButton color="inherit" onClick={handleStep(index)}>
148
+ <StepLabel {...labelProps}>{label}</StepLabel>
149
+ </StepButton>
150
+ </Step>
151
+ );
152
+ })}
153
+ </Stepper>
154
+ {activeStep === steps.length ? (
155
+ <>
156
+ <Typography sx={{ mt: 2, mb: 1 }}>All steps completed - you&apos;re finished</Typography>
157
+ <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
158
+ <Box sx={{ flex: '1 1 auto' }} />
159
+ <Button color="tertiary" onClick={handleReset}>
160
+ Reset
161
+ </Button>
162
+ </Box>
163
+ </>
164
+ ) : (
165
+ <>
166
+ <Typography sx={{ mt: 2, mb: 1 }}>Step {activeStep + 1}</Typography>
167
+ <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
168
+ <Button color="secondary" disabled={activeStep === 0} onClick={handleBack} sx={{ mr: 1 }}>
169
+ Back
170
+ </Button>
171
+ <Box sx={{ flex: '1 1 auto' }} />
172
+ {isStepOptional(activeStep) && (
173
+ <Button color="secondary" onClick={handleSkip} sx={{ mr: 1 }}>
174
+ Skip
175
+ </Button>
176
+ )}
177
+ <Button color={activeStep === steps.length - 1 ? 'primary' : 'secondary'} onClick={handleNext}>
178
+ {activeStep === steps.length - 1 ? 'Finish' : 'Next'}
179
+ </Button>
180
+ </Box>
181
+ </>
182
+ )}
183
+ </Paper>
184
+ </Box>
185
+ );
186
+ },
187
+ args: {},
188
+ };
@@ -0,0 +1,187 @@
1
+ // Each exported component in the package should have its own stories file
2
+ import { useState, useEffect } from 'react';
3
+ import type { Meta, StoryObj } from '@storybook/react';
4
+ import { Button } from '@availity/mui-button';
5
+ import { Typography } from '@availity/mui-typography';
6
+ import { Box } from '@availity/mui-layout';
7
+ import { Paper } from '@availity/mui-paper';
8
+
9
+ import { Stepper, Step, StepLabel, StepButton } from '..';
10
+
11
+ const meta: Meta<typeof StepButton> = {
12
+ title: 'Components/Stepper/StepButton',
13
+ component: StepButton,
14
+ tags: ['autodocs'],
15
+ };
16
+
17
+ export default meta;
18
+
19
+ export const _StepButton: StoryObj<typeof StepButton> = {
20
+ render: (args) => (
21
+ <Box>
22
+ <Paper sx={{ padding: '2rem' }}>
23
+ <Stepper>
24
+ <Step>
25
+ <StepButton {...args}/>
26
+ </Step>
27
+ </Stepper>
28
+ </Paper>
29
+ </Box>
30
+ ),
31
+ };
32
+
33
+ // credit: https://stackoverflow.com/questions/36862334/get-viewport-window-height-in-reactjs
34
+ function getWindowDimensions() {
35
+ const { innerWidth: width, innerHeight: height } = window;
36
+ return {
37
+ width,
38
+ height,
39
+ };
40
+ }
41
+
42
+ function useWindowDimensions() {
43
+ const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
44
+
45
+ useEffect(() => {
46
+ function handleResize() {
47
+ setWindowDimensions(getWindowDimensions());
48
+ }
49
+
50
+ window.addEventListener('resize', handleResize);
51
+ return () => window.removeEventListener('resize', handleResize);
52
+ }, []);
53
+
54
+ return windowDimensions;
55
+ }
56
+
57
+ const steps = ['First', 'Second', 'Third', 'Final'];
58
+
59
+ export const _Stepper: StoryObj<typeof StepButton> = {
60
+ render: (args) => {
61
+ const [activeStep, setActiveStep] = useState(0);
62
+ const [skipped, setSkipped] = useState(new Set<number>());
63
+
64
+ const { width } = useWindowDimensions();
65
+
66
+ const isStepOptional = (step: number) => {
67
+ return step > 1;
68
+ };
69
+
70
+ const isStepSkipped = (step: number) => {
71
+ return skipped.has(step);
72
+ };
73
+
74
+ const isStepError = (step: number) => {
75
+ return step === 2 && activeStep < 2;
76
+ };
77
+
78
+ const isStepWarning = (step: number) => {
79
+ return step === 3 && activeStep < 3;
80
+ };
81
+
82
+ const handleNext = () => {
83
+ let newSkipped = skipped;
84
+ if (isStepSkipped(activeStep)) {
85
+ newSkipped = new Set(newSkipped.values());
86
+ newSkipped.delete(activeStep);
87
+ }
88
+
89
+ setActiveStep((prevActiveStep) => prevActiveStep + 1);
90
+ setSkipped(newSkipped);
91
+ };
92
+
93
+ const handleBack = () => {
94
+ setActiveStep((prevActiveStep) => prevActiveStep - 1);
95
+ };
96
+
97
+ const handleStep = (step: number) => () => {
98
+ setActiveStep(step);
99
+ };
100
+
101
+ const handleSkip = () => {
102
+ if (!isStepOptional(activeStep)) {
103
+ // You probably want to guard against something like this,
104
+ // it should never occur unless someone's actively trying to break something.
105
+ throw new Error("You can't skip a step that isn't optional.");
106
+ }
107
+
108
+ setActiveStep((prevActiveStep) => prevActiveStep + 1);
109
+ setSkipped((prevSkipped) => {
110
+ const newSkipped = new Set(prevSkipped.values());
111
+ newSkipped.add(activeStep);
112
+ return newSkipped;
113
+ });
114
+ };
115
+
116
+ const handleReset = () => {
117
+ setActiveStep(0);
118
+ };
119
+
120
+ return (
121
+ <Box maxWidth="75vw" marginX="auto">
122
+ <Paper sx={{ padding: '2rem' }}>
123
+ <Stepper activeStep={activeStep} orientation={width < 600 ? 'vertical' : 'horizontal'}>
124
+ {steps.map((label, index) => {
125
+ const stepProps: { completed?: boolean } = {};
126
+ const labelProps: { optional?: React.ReactNode; error?: boolean; warning?: boolean } = {};
127
+
128
+ if (isStepOptional(index)) {
129
+ labelProps.optional = <Typography variant="caption">Optional</Typography>;
130
+ }
131
+
132
+ if (isStepSkipped(index)) {
133
+ stepProps.completed = false;
134
+ }
135
+
136
+ if (isStepError(index)) {
137
+ labelProps.error = true;
138
+ }
139
+
140
+ if (isStepWarning(index)) {
141
+ labelProps.warning = true;
142
+ }
143
+
144
+ return (
145
+ <Step key={label} {...stepProps}>
146
+ <StepButton color="inherit" onClick={handleStep(index)} {...args}>
147
+ <StepLabel {...labelProps}>{label}</StepLabel>
148
+ </StepButton>
149
+ </Step>
150
+ );
151
+ })}
152
+ </Stepper>
153
+ {activeStep === steps.length ? (
154
+ <>
155
+ <Typography sx={{ mt: 2, mb: 1 }}>All steps completed - you&apos;re finished</Typography>
156
+ <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
157
+ <Box sx={{ flex: '1 1 auto' }} />
158
+ <Button color="tertiary" onClick={handleReset}>
159
+ Reset
160
+ </Button>
161
+ </Box>
162
+ </>
163
+ ) : (
164
+ <>
165
+ <Typography sx={{ mt: 2, mb: 1 }}>Step {activeStep + 1}</Typography>
166
+ <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
167
+ <Button color="secondary" disabled={activeStep === 0} onClick={handleBack} sx={{ mr: 1 }}>
168
+ Back
169
+ </Button>
170
+ <Box sx={{ flex: '1 1 auto' }} />
171
+ {isStepOptional(activeStep) && (
172
+ <Button color="secondary" onClick={handleSkip} sx={{ mr: 1 }}>
173
+ Skip
174
+ </Button>
175
+ )}
176
+ <Button color={activeStep === steps.length - 1 ? 'primary' : 'secondary'} onClick={handleNext}>
177
+ {activeStep === steps.length - 1 ? 'Finish' : 'Next'}
178
+ </Button>
179
+ </Box>
180
+ </>
181
+ )}
182
+ </Paper>
183
+ </Box>
184
+ );
185
+ },
186
+ args: {},
187
+ };
@@ -11,7 +11,10 @@ declare module '@mui/material/StepIcon' {
11
11
  }
12
12
  }
13
13
 
14
- export type StepIconProps = { warning?: boolean } & MuiStepIconProps;
14
+ export type StepIconProps = {
15
+ /** If `true`, the step will have a warning icon. */
16
+ warning?: boolean
17
+ } & MuiStepIconProps;
15
18
 
16
19
  export const StepIcon = ({ error, completed, warning, ...rest }: StepIconProps): JSX.Element => {
17
20
  let tag: Tag = null;
@@ -0,0 +1,187 @@
1
+ // Each exported component in the package should have its own stories file
2
+ import { useState, useEffect } from 'react';
3
+ import type { Meta, StoryObj } from '@storybook/react';
4
+ import { Button } from '@availity/mui-button';
5
+ import { Typography } from '@availity/mui-typography';
6
+ import { Box } from '@availity/mui-layout';
7
+ import { Paper } from '@availity/mui-paper';
8
+
9
+ import { Stepper, Step, StepLabel, StepButton } from '..';
10
+
11
+ const meta: Meta<typeof StepLabel> = {
12
+ title: 'Components/Stepper/StepLabel',
13
+ component: StepLabel,
14
+ tags: ['autodocs'],
15
+ };
16
+
17
+ export default meta;
18
+
19
+ export const _Step: StoryObj<typeof StepLabel> = {
20
+ render: (args) => (
21
+ <Box>
22
+ <Paper sx={{ padding: '2rem' }}>
23
+ <Stepper>
24
+ <Step>
25
+ <StepLabel {...args}>Label</StepLabel>
26
+ </Step>
27
+ </Stepper>
28
+ </Paper>
29
+ </Box>
30
+ ),
31
+ };
32
+
33
+ // credit: https://stackoverflow.com/questions/36862334/get-viewport-window-height-in-reactjs
34
+ function getWindowDimensions() {
35
+ const { innerWidth: width, innerHeight: height } = window;
36
+ return {
37
+ width,
38
+ height,
39
+ };
40
+ }
41
+
42
+ function useWindowDimensions() {
43
+ const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
44
+
45
+ useEffect(() => {
46
+ function handleResize() {
47
+ setWindowDimensions(getWindowDimensions());
48
+ }
49
+
50
+ window.addEventListener('resize', handleResize);
51
+ return () => window.removeEventListener('resize', handleResize);
52
+ }, []);
53
+
54
+ return windowDimensions;
55
+ }
56
+
57
+ const steps = ['First', 'Second', 'Third', 'Final'];
58
+
59
+ export const _Stepper: StoryObj<typeof StepLabel> = {
60
+ render: (args) => {
61
+ const [activeStep, setActiveStep] = useState(0);
62
+ const [skipped, setSkipped] = useState(new Set<number>());
63
+
64
+ const { width } = useWindowDimensions();
65
+
66
+ const isStepOptional = (step: number) => {
67
+ return step > 1;
68
+ };
69
+
70
+ const isStepSkipped = (step: number) => {
71
+ return skipped.has(step);
72
+ };
73
+
74
+ const isStepError = (step: number) => {
75
+ return step === 2 && activeStep < 2;
76
+ };
77
+
78
+ const isStepWarning = (step: number) => {
79
+ return step === 3 && activeStep < 3;
80
+ };
81
+
82
+ const handleNext = () => {
83
+ let newSkipped = skipped;
84
+ if (isStepSkipped(activeStep)) {
85
+ newSkipped = new Set(newSkipped.values());
86
+ newSkipped.delete(activeStep);
87
+ }
88
+
89
+ setActiveStep((prevActiveStep) => prevActiveStep + 1);
90
+ setSkipped(newSkipped);
91
+ };
92
+
93
+ const handleBack = () => {
94
+ setActiveStep((prevActiveStep) => prevActiveStep - 1);
95
+ };
96
+
97
+ const handleStep = (step: number) => () => {
98
+ setActiveStep(step);
99
+ };
100
+
101
+ const handleSkip = () => {
102
+ if (!isStepOptional(activeStep)) {
103
+ // You probably want to guard against something like this,
104
+ // it should never occur unless someone's actively trying to break something.
105
+ throw new Error("You can't skip a step that isn't optional.");
106
+ }
107
+
108
+ setActiveStep((prevActiveStep) => prevActiveStep + 1);
109
+ setSkipped((prevSkipped) => {
110
+ const newSkipped = new Set(prevSkipped.values());
111
+ newSkipped.add(activeStep);
112
+ return newSkipped;
113
+ });
114
+ };
115
+
116
+ const handleReset = () => {
117
+ setActiveStep(0);
118
+ };
119
+
120
+ return (
121
+ <Box maxWidth="75vw" marginX="auto">
122
+ <Paper sx={{ padding: '2rem' }}>
123
+ <Stepper activeStep={activeStep} orientation={width < 600 ? 'vertical' : 'horizontal'}>
124
+ {steps.map((label, index) => {
125
+ const stepProps: { completed?: boolean } = {};
126
+ const labelProps: { optional?: React.ReactNode; error?: boolean; warning?: boolean } = {};
127
+
128
+ if (isStepOptional(index)) {
129
+ labelProps.optional = <Typography variant="caption">Optional</Typography>;
130
+ }
131
+
132
+ if (isStepSkipped(index)) {
133
+ stepProps.completed = false;
134
+ }
135
+
136
+ if (isStepError(index)) {
137
+ labelProps.error = true;
138
+ }
139
+
140
+ if (isStepWarning(index)) {
141
+ labelProps.warning = true;
142
+ }
143
+
144
+ return (
145
+ <Step key={label} {...stepProps}>
146
+ <StepButton color="inherit" onClick={handleStep(index)}>
147
+ <StepLabel {...labelProps} {...args}>{label}</StepLabel>
148
+ </StepButton>
149
+ </Step>
150
+ );
151
+ })}
152
+ </Stepper>
153
+ {activeStep === steps.length ? (
154
+ <>
155
+ <Typography sx={{ mt: 2, mb: 1 }}>All steps completed - you&apos;re finished</Typography>
156
+ <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
157
+ <Box sx={{ flex: '1 1 auto' }} />
158
+ <Button color="tertiary" onClick={handleReset}>
159
+ Reset
160
+ </Button>
161
+ </Box>
162
+ </>
163
+ ) : (
164
+ <>
165
+ <Typography sx={{ mt: 2, mb: 1 }}>Step {activeStep + 1}</Typography>
166
+ <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
167
+ <Button color="secondary" disabled={activeStep === 0} onClick={handleBack} sx={{ mr: 1 }}>
168
+ Back
169
+ </Button>
170
+ <Box sx={{ flex: '1 1 auto' }} />
171
+ {isStepOptional(activeStep) && (
172
+ <Button color="secondary" onClick={handleSkip} sx={{ mr: 1 }}>
173
+ Skip
174
+ </Button>
175
+ )}
176
+ <Button color={activeStep === steps.length - 1 ? 'primary' : 'secondary'} onClick={handleNext}>
177
+ {activeStep === steps.length - 1 ? 'Finish' : 'Next'}
178
+ </Button>
179
+ </Box>
180
+ </>
181
+ )}
182
+ </Paper>
183
+ </Box>
184
+ );
185
+ },
186
+ args: {},
187
+ };
@@ -1,15 +1,17 @@
1
1
  import MuiStepLabel, { StepLabelProps as MuiStepLabelProps } from '@mui/material/StepLabel';
2
2
 
3
- import { StepIcon } from './StepIcon';
3
+ import { StepIcon, StepIconProps } from './StepIcon';
4
4
 
5
- export type StepLabelProps = {
6
- warning?: boolean;
7
- } & MuiStepLabelProps;
5
+ export type StepLabelProps = Pick<StepIconProps, 'warning'> & MuiStepLabelProps;
8
6
 
9
- export const StepLabel = ({ children, error, warning, ...rest }: StepLabelProps): JSX.Element => {
7
+ const StepLabel = ({ children, error, warning, ...rest }: StepLabelProps): JSX.Element => {
10
8
  return (
11
9
  <MuiStepLabel StepIconProps={{ error, warning }} StepIconComponent={StepIcon} error={error} {...rest}>
12
10
  {children}
13
11
  </MuiStepLabel>
14
12
  );
15
13
  };
14
+
15
+ StepLabel.muiName = MuiStepLabel.muiName;
16
+
17
+ export { StepLabel };
@@ -6,9 +6,7 @@ import { Typography } from '@availity/mui-typography';
6
6
  import { Box } from '@availity/mui-layout';
7
7
  import { Paper } from '@availity/mui-paper';
8
8
 
9
- import { Stepper, StepperProps } from './Stepper';
10
- import { Step } from './Step';
11
- import { StepLabel } from './StepLabel';
9
+ import { Stepper, StepperProps, Step, StepLabel, StepButton } from '..';
12
10
 
13
11
  const meta: Meta<typeof Stepper> = {
14
12
  title: 'Components/Stepper/Stepper',
@@ -72,6 +70,10 @@ export const _Stepper: StoryObj<typeof Stepper> = {
72
70
  return step === 3 && activeStep < 3;
73
71
  };
74
72
 
73
+ const handleStep = (step: number) => () => {
74
+ setActiveStep(step);
75
+ };
76
+
75
77
  const handleNext = () => {
76
78
  let newSkipped = skipped;
77
79
  if (isStepSkipped(activeStep)) {
@@ -132,7 +134,9 @@ export const _Stepper: StoryObj<typeof Stepper> = {
132
134
 
133
135
  return (
134
136
  <Step key={label} {...stepProps}>
135
- <StepLabel {...labelProps}>{label}</StepLabel>
137
+ <StepButton color="inherit" onClick={handleStep(index)}>
138
+ <StepLabel {...labelProps}>{label}</StepLabel>
139
+ </StepButton>
136
140
  </Step>
137
141
  );
138
142
  })}