Skip to content

Commit 7d8b02e

Browse files
Merge pull request #90 from alexzhang1030/feat/vue-binding
feat: add Vue binding of Stepperize
2 parents 98c1eb1 + f070cd9 commit 7d8b02e

File tree

17 files changed

+1049
-18
lines changed

17 files changed

+1049
-18
lines changed

.changeset/old-waves-protect.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@stepperize/vue": major
3+
---
4+
5+
feat: add vue binding of Stepperize

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ jobs:
3535
- name: Install dependencies
3636
run: pnpm install --frozen-lockfile
3737

38-
- name: Build @stepperize/react
39-
run: pnpm turbo run build --filter=@stepperize/react
38+
- name: Build stepperize packages
39+
run: pnpm turbo run build --filter=@stepperize/react --filter=@stepperize/vue
4040

4141
- name: Create Release Pull Request or Publish to npm
4242
uses: changesets/action@v1
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
---
2+
title: Composable
3+
description: Access and control your stepper with the useStepper composable
4+
---
5+
6+
The `useStepper` composable provides methods to interact with and render your stepper. It can be used with or without the [`Scoped`](./scoped) component.
7+
8+
## Usage
9+
10+
```vue
11+
<script setup lang="ts">
12+
import { defineStepper } from "@stepperize/vue"
13+
14+
const { useStepper } = defineStepper(
15+
{ id: "first" },
16+
{ id: "second" },
17+
{ id: "last" },
18+
)
19+
20+
const stepper = useStepper()
21+
</script>
22+
```
23+
24+
## Rendering Methods
25+
26+
### when
27+
28+
The when method allows rendering content conditionally based on the current step.
29+
It can take an id of a step (either a string or an array of a step ID followed by booleans)
30+
and a whenFn (the function to execute if the step matches). Additionally, you can provide
31+
an optional elseFn (the function to execute if the step does not match).
32+
33+
<Tabs groupId="components" items={['SFC', 'JSX']} defaultValue="sfc">
34+
<Tab value="sfc">
35+
```vue
36+
<script setup lang="ts">
37+
import { defineStepper, StepperWhen } from '@stepperize/vue'
38+
39+
const stepper = useStepper()
40+
</script>
41+
42+
<template>
43+
44+
<StepperWhen :stepper when="first">
45+
<template #default="step">
46+
<p>First step: {{ step.title }}</p>
47+
</template>
48+
</StepperWhen>
49+
50+
<StepperWhen :stepper when="second">
51+
<template #default="step">
52+
<p>Second step: {{ step.title }}</p>
53+
</template>
54+
</StepperWhen>
55+
56+
<StepperWhen :stepper when="last">
57+
<template #default>
58+
Finished!
59+
</template>
60+
<template #else>
61+
Not finished yet
62+
</template>
63+
</StepperWhen>
64+
65+
</template>
66+
```
67+
</Tab>
68+
<Tab value="jsx">
69+
```tsx
70+
import { defineComponent } from 'vue'
71+
72+
const MyStepperComponent = defineComponent(() => {
73+
const stepper = useStepper()
74+
75+
return () => (
76+
<>
77+
{ stepper.value.when("first", step => <p>First step: {step.title}</p>) }
78+
{ stepper.value.when("second", step => <p>Second step: {step.title}</p>) }
79+
{ stepper.value.when("last", "Finished!", "Not finished yet") }
80+
</>
81+
)
82+
})
83+
```
84+
</Tab>
85+
</Tabs>
86+
87+
You can define more complex conditions that not only depend on the current step's ID
88+
but also on additional boolean values. This allows for multi-condition logic where each
89+
boolean must evaluate to true for the step to match. The boolean values can represent
90+
different state conditions or external factors that affect the step's visibility or behavior.
91+
92+
> The first element of the array is the step ID, the following elements are the boolean values.
93+
94+
<Tabs groupId="components" items={['SFC', 'JSX']} defaultValue="sfc">
95+
<Tab value="sfc">
96+
```vue
97+
<script setup lang="ts">
98+
import { defineStepper, StepperWhen } from '@stepperize/vue'
99+
100+
const stepper = useStepper()
101+
102+
const condition1 = ... // boolean
103+
const condition2 = ... // boolean
104+
105+
</script>
106+
107+
<template>
108+
109+
<StepperWhen :stepper :when="['first', condition1, condition2]">
110+
<template #default="step">
111+
<p>First step: {{ step.title }}</p>
112+
</template>
113+
</StepperWhen>
114+
115+
</template>
116+
```
117+
</Tab>
118+
<Tab value="jsx">
119+
```tsx
120+
import { defineComponent } from 'vue'
121+
122+
const MyStepperComponent = defineComponent(() => {
123+
const stepper = useStepper()
124+
125+
return () => (
126+
<>
127+
{ stepper.when(["first", condition1, condition2], step => <p>First step: {step.title}</p>) }
128+
</>
129+
)
130+
})
131+
```
132+
</Tab>
133+
</Tabs>
134+
135+
### switch
136+
137+
The switch method allows you to render content based on the current step's ID,
138+
similar to a switch-case structure. This method provides a cleaner and more scalable
139+
way to handle different step-specific rendering logic, making it ideal for scenarios
140+
where you need to differentiate the UI depending on the current step without writing
141+
multiple when conditions.
142+
143+
<Tabs groupId="components" items={['SFC', 'JSX']} defaultValue="sfc">
144+
<Tab value="sfc">
145+
```vue
146+
<script setup lang="ts">
147+
import { defineStepper, StepperSwitch } from '@stepperize/vue'
148+
149+
const stepper = useStepper()
150+
151+
</script>
152+
153+
<template>
154+
155+
<StepperSwitch :stepper>
156+
<template #first="step">
157+
<p>First: {{ step.title }}</p>
158+
</template>
159+
<template #second="step">
160+
<p>Second: {{ step.title }}</p>
161+
</template>
162+
<template #last>
163+
Finished!
164+
</template>
165+
</StepperSwitch>
166+
167+
</template>
168+
```
169+
</Tab>
170+
<Tab value="jsx">
171+
```tsx
172+
import { defineComponent } from 'vue'
173+
174+
const MyStepperComponent = defineComponent(() => {
175+
const stepper = useStepper()
176+
177+
return () => (
178+
<>
179+
{ stepper.value.switch({
180+
first: step => <p>First: {step.title}</p>,
181+
second: step => <p>Second: {step.title}</p>,
182+
last: () => <p>Finished!</p>,
183+
}) }
184+
</>
185+
)
186+
})
187+
```
188+
</Tab>
189+
</Tabs>
190+
191+
### match
192+
193+
The match method allows you to render content based on an external state,
194+
such as a value fetched from a server or any dynamic state in your application.
195+
This provides flexibility for rendering content that is tied not only to the
196+
current step in the stepper but also to any other state outside the stepper's
197+
context, such as user actions, data from an API, or global application state.
198+
199+
<Tabs groupId="components" items={['SFC', 'JSX']} defaultValue="sfc">
200+
<Tab value="sfc">
201+
```vue
202+
<script setup lang="ts">
203+
import { defineStepper, StepperMatch } from '@stepperize/vue'
204+
205+
const stepper = useStepper()
206+
207+
const state = "Value from server or client state"
208+
209+
</script>
210+
211+
<template>
212+
213+
<StepperMatch :stepper :state>
214+
<template #first="step">
215+
<p>First: {{ step.title }}</p>
216+
</template>
217+
<template #second="step">
218+
<p>Second: {{ step.title }}</p>
219+
</template>
220+
<template #last>
221+
Finished!
222+
</template>
223+
</StepperMatch>
224+
225+
</template>
226+
```
227+
</Tab>
228+
<Tab value="jsx">
229+
```tsx
230+
import { defineComponent } from 'vue'
231+
232+
const MyStepperComponent = defineComponent(() => {
233+
const stepper = useStepper()
234+
const state = "Value from server or client state"
235+
236+
return () => (
237+
<>
238+
{ stepper.value.match(state, {
239+
first: step => <p>First: {step.title}</p>,
240+
second: step => <p>Second: {step.title}</p>,
241+
last: () => <p>Finished!</p>,
242+
}) }
243+
</>
244+
)
245+
})
246+
```
247+
</Tab>
248+
</Tabs>
249+
250+
<Callout type="info">
251+
`match` allows state-based control from client or server, useful for frameworks like Nuxt with server-side state management.
252+
</Callout>
253+
254+
## API Reference
255+
256+
| Name | Type | Description |
257+
| --- | --- | --- |
258+
| all | `Step[]` | Returns all steps |
259+
| current | `Step` | Returns the current step |
260+
| isLast | `boolean` | Returns true if the current step is the last step |
261+
| isFirst | `boolean` | Returns true if the current step is the first step |
262+
| next | `() => void` | Advances to the next step |
263+
| prev | `() => void` | Returns to the previous step |
264+
| get | `(id: string) => Step` | Returns a step by its ID |
265+
| goTo | `(id: string) => void` | Navigates to a specific step by its ID |
266+
| reset | `() => void` | Resets the stepper to its initial state |
267+
| when | `(id: string, whenFn: (step: Step) => VNodeChild, elseFn?: (step: Step) => VNodeChild) => VNodeChild` | Executes a function based on the current step ID |
268+
| switch | `(steps: { [id: string]: (step: Step) => VNodeChild }) => VNodeChild` | Executes a function based on a switch-case-like structure for steps |
269+
| match | `(state: string, steps: { [id: string]: (step: Step) => VNodeChild }) => VNodeChild` | Matches the current state with a set of possible states and executes the corresponding function |
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
title: Define
3+
description: How to define a stepper using defineStepper
4+
---
5+
6+
`defineStepper` is the core function for creating a customizable stepper. It generates the necessary components and composables for building your stepper UI and managing its state.
7+
8+
## Usage
9+
10+
<Steps>
11+
<Step>
12+
### Import
13+
14+
```tsx
15+
import { defineStepper } from "@stepperize/vue";
16+
```
17+
</Step>
18+
<Step>
19+
### Define steps
20+
21+
Call `defineStepper` with your step configurations:
22+
23+
```tsx
24+
const { Scoped, useStepper, steps } = defineStepper(
25+
{ id: "step-1", title: "Step 1", description: "First step" },
26+
{ id: "step-2", title: "Step 2", description: "Second step" },
27+
{ id: "step-3", title: "Step 3", description: "Third step" }
28+
);
29+
```
30+
31+
- `id` (required): Unique identifier for each step
32+
- Add any custom properties (e.g., `title`, `description`) for use in your UI
33+
</Step>
34+
</Steps>
35+
36+
## Return Value
37+
38+
`defineStepper` returns an object with:
39+
40+
- `Scoped`: A Provider component for scoping stepper state
41+
- `useStepper`: A custom composable for accessing and controlling the stepper
42+
- `steps`: An array of the defined step objects
43+
44+
## Next Steps
45+
46+
Learn how to use the returned components and composables:
47+
48+
- [useStepper Composable](./composable)
49+
- [Scoped Component](./scoped)

0 commit comments

Comments
 (0)