Skip to content

Commit 57d663c

Browse files
committed
config object for navigation component added
1 parent cf9ba68 commit 57d663c

File tree

4 files changed

+130
-25
lines changed

4 files changed

+130
-25
lines changed

README.md

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,34 @@ Example:
4141

4242
<br />
4343

44+
# Config Object
45+
46+
`Steps` component accepts an optional `config` object for configuring the common navigation component. The `Navigation` component provided in the config object will be rendered along with every step component. Here is an example:
47+
48+
```javascript
49+
const Navigation = (props) => {
50+
return (
51+
<div>
52+
<button onClick={props.prev}>Previous</button>
53+
<button onClick={props.next}>Next</button>
54+
</div>
55+
);
56+
}
57+
58+
const config = {
59+
navigation: {
60+
component: Navigation // a React component with special props provided automatically
61+
location: "before" // or after
62+
}
63+
}
64+
65+
<Steps config={config}>
66+
<Step title="My First Step" component={Step1} />
67+
<Step title="My Second Step" component={Step2} />
68+
<Step title="My Third Step" component={Step3} />
69+
</Steps>
70+
```
71+
4472
# Documentation
4573

4674
## Wrapper Components
@@ -49,7 +77,7 @@ Example:
4977

5078
| Component | Description |
5179
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
52-
| `<Steps />` | Wrapper component for Step components. |
80+
| `<Steps />` | Wrapper component for Step components. Accepts a `config` object for rendering a common navigation component. |
5381
| `<Step />` | `title`: takes a title for the step, which can be accessed in `props` object of the step component. <br />`component`: takes a React component that you would like to show in that step. <br />`beforeStepChange`: takes a callback function to run right before the current step changes. |
5482

5583
<br />
@@ -78,6 +106,22 @@ The React component that is passed to each `Step` wrapper component will be inje
78106
| `props.getState` | `function<key, defaultValue>` | Function to retrieve a state value by key |
79107
| `props.handleChange` | `function<event>` | `onChange` event handler for form elements |
80108

109+
## Navigation Component `props`
110+
111+
| Property | Type | Description |
112+
| -------------------- | ----------------------------- | ---------------------------------------------------- |
113+
| `props.size` | `number` | Total number of steps |
114+
| `props.current` | `string` | Current step number |
115+
| `props.progress` | `number` | Progress of the current step, value between 0 and 1 |
116+
| `props.next` | `function` | Function to move to the next step |
117+
| `props.prev` | `function` | Function to move to the previous step |
118+
| `props.jump` | `function<step>` | Function to jump to the given step |
119+
| `props.allSteps` | `Array<{order, title}>` | Array of all available steps' title and order number |
120+
| `props.state` | `object` | Combined state value of all steps |
121+
| `props.setState` | `function<key, value>` | Function to set/update state by key |
122+
| `props.getState` | `function<key, defaultValue>` | Function to retrieve a state value by key |
123+
| `props.handleChange` | `function<event>` | `onChange` event handler for form elements |
124+
81125
<br />
82126
<hr />
83127
<br />
@@ -113,3 +157,18 @@ const Step1 = (props: StepComponentProps) => {
113157

114158
export default Step1;
115159
```
160+
161+
## Component Type of Example Navigation Component
162+
163+
If you'd like to add a persistent navigation component to be shown on every step, you may utilize `NavigationComponentProps` type for your custom `Navigation` component. Here is an example:
164+
165+
```javascript
166+
const Navigation = (props: NavigationComponentProps) => {
167+
return (
168+
<div>
169+
<button onClick={props.prev}>Previous</button>
170+
<button onClick={props.next}>Next</button>
171+
</div>
172+
);
173+
};
174+
```

src/App.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11
import React from "react";
2-
import { Steps, Step } from "./lib-ts/index";
2+
import { Steps, Step, NavigationComponentProps } from "./lib-ts/index";
33
import Step1 from "./stepComponents/Step1";
44
import Step2 from "./stepComponents/Step2";
55
import Step3 from "./stepComponents/Step3";
66
import Step4 from "./stepComponents/Step4";
77

8+
const Navigation = (props: NavigationComponentProps) => {
9+
console.log(props);
10+
return (
11+
<div>
12+
<button onClick={props.prev}>Previous</button>
13+
<button onClick={props.next}>Next</button>
14+
</div>
15+
);
16+
};
17+
818
const App = () => {
919
return (
1020
<div className="steps_wrapper">
1121
<h1>React Step Builder v1.1.0</h1>
12-
<Steps>
22+
<Steps
23+
config={{
24+
navigation: {
25+
component: Navigation,
26+
location: "before",
27+
},
28+
}}
29+
>
1330
<Step title="Hello" component={Step1} deneme={"deneme"} />
1431
<Step component={Step2} />
1532
<Step title="Contact Info" component={Step3} />

src/lib-ts/index.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ interface State {
2424

2525
type StepsProps = {
2626
children: ReactElement<StepProps> | ReactElement<StepProps>[];
27+
config?: {
28+
navigation?: {
29+
component: (props: any) => JSX.Element;
30+
location?: "before" | "after";
31+
};
32+
};
2733
};
2834

2935
type BeforeStepChange = () => any;
@@ -98,6 +104,10 @@ interface StepContext {
98104
order: number;
99105
}
100106

107+
export interface NavigationComponentProps extends StepsContext {
108+
[name: string]: any;
109+
}
110+
101111
const StepsContext = React.createContext<StepsContext>({
102112
// Dummy values for satisfying the type checker
103113
// Gets updated before being passed down
@@ -119,9 +129,18 @@ const StepContext = React.createContext<StepContext>({ order: 0 });
119129
/**
120130
* Wrapper component for `Step` components.
121131
*/
122-
export function Steps({ children }: StepsProps) {
132+
export function Steps({ children, config }: StepsProps) {
123133
const childSteps = React.Children.toArray(children);
124134

135+
const NavigationComponent = (context: NavigationComponentProps) => {
136+
if (config?.navigation?.component) {
137+
const NavComponent = config?.navigation?.component;
138+
return <NavComponent {...context} />;
139+
} else {
140+
return null;
141+
}
142+
};
143+
125144
const allSteps: AllSteps = childSteps.map((child, order) => {
126145
return {
127146
title:
@@ -210,11 +229,14 @@ export function Steps({ children }: StepsProps) {
210229

211230
return (
212231
<StepsContext.Provider value={context}>
232+
{config?.navigation?.location === "before" &&
233+
NavigationComponent(context)}
213234
{React.Children.map(children, (child, order) => (
214235
<StepContext.Provider value={{ order: order + 1 }}>
215236
{child}
216237
</StepContext.Provider>
217238
))}
239+
{config?.navigation?.location === "after" && NavigationComponent(context)}
218240
</StepsContext.Provider>
219241
);
220242
}

tsconfig.json

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
11
{
2-
"compilerOptions": {
3-
"target": "es6",
4-
"module": "esnext",
5-
"jsx": "react",
6-
"declaration": true,
7-
"declarationMap": true,
8-
"sourceMap": true,
9-
"outDir": "src/lib",
10-
"strict": true,
11-
"esModuleInterop": true,
12-
"skipLibCheck": true,
13-
"forceConsistentCasingInFileNames": true,
14-
"lib": ["dom", "dom.iterable", "esnext"],
15-
"allowJs": true,
16-
"allowSyntheticDefaultImports": true,
17-
"moduleResolution": "node",
18-
"resolveJsonModule": true,
19-
"isolatedModules": true,
20-
"noEmit": false
21-
},
22-
"include": ["src/lib-ts/**/*.ts", "src/lib-ts/**/*.tsx"]
2+
"compilerOptions": {
3+
"target": "es6",
4+
"module": "esnext",
5+
"jsx": "react",
6+
"declaration": true,
7+
"declarationMap": true,
8+
"sourceMap": true,
9+
"outDir": "src/lib",
10+
"strict": true,
11+
"esModuleInterop": true,
12+
"skipLibCheck": true,
13+
"forceConsistentCasingInFileNames": true,
14+
"lib": [
15+
"dom",
16+
"dom.iterable",
17+
"esnext"
18+
],
19+
"allowJs": true,
20+
"allowSyntheticDefaultImports": true,
21+
"moduleResolution": "node",
22+
"resolveJsonModule": true,
23+
"isolatedModules": true,
24+
"noEmit": true
25+
},
26+
"include": [
27+
"src/lib-ts/**/*.ts",
28+
"src/lib-ts/**/*.tsx"
29+
]
2330
}

0 commit comments

Comments
 (0)