@baklavue/mcp 1.0.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 (93) hide show
  1. package/README.md +72 -0
  2. package/dist/data/component-categories.d.ts +7 -0
  3. package/dist/data/component-categories.js +48 -0
  4. package/dist/data/loaders.d.ts +22 -0
  5. package/dist/data/loaders.js +346 -0
  6. package/dist/docs/components/accordion.md +601 -0
  7. package/dist/docs/components/alert.md +233 -0
  8. package/dist/docs/components/badge.md +100 -0
  9. package/dist/docs/components/banner.md +231 -0
  10. package/dist/docs/components/button.md +324 -0
  11. package/dist/docs/components/checkbox.md +343 -0
  12. package/dist/docs/components/chip.md +199 -0
  13. package/dist/docs/components/datepicker.md +243 -0
  14. package/dist/docs/components/dialog.md +224 -0
  15. package/dist/docs/components/drawer.md +188 -0
  16. package/dist/docs/components/dropdown.md +291 -0
  17. package/dist/docs/components/file-upload.md +248 -0
  18. package/dist/docs/components/icon.md +142 -0
  19. package/dist/docs/components/image.md +161 -0
  20. package/dist/docs/components/index.md +151 -0
  21. package/dist/docs/components/input.md +407 -0
  22. package/dist/docs/components/link.md +249 -0
  23. package/dist/docs/components/notification.md +179 -0
  24. package/dist/docs/components/pagination.md +168 -0
  25. package/dist/docs/components/radio.md +221 -0
  26. package/dist/docs/components/scroll-to-top.md +90 -0
  27. package/dist/docs/components/select.md +239 -0
  28. package/dist/docs/components/skeleton.md +79 -0
  29. package/dist/docs/components/spinner.md +93 -0
  30. package/dist/docs/components/split-button.md +165 -0
  31. package/dist/docs/components/stepper.md +337 -0
  32. package/dist/docs/components/switch.md +144 -0
  33. package/dist/docs/components/tab.md +140 -0
  34. package/dist/docs/components/table.md +362 -0
  35. package/dist/docs/components/tag.md +243 -0
  36. package/dist/docs/components/textarea.md +190 -0
  37. package/dist/docs/components/tooltip.md +155 -0
  38. package/dist/docs/composables/alert.md +87 -0
  39. package/dist/docs/composables/asyncState.md +74 -0
  40. package/dist/docs/composables/base64.md +72 -0
  41. package/dist/docs/composables/breakpoints.md +129 -0
  42. package/dist/docs/composables/clipboard.md +108 -0
  43. package/dist/docs/composables/colorScheme.md +110 -0
  44. package/dist/docs/composables/confirmDialog.md +105 -0
  45. package/dist/docs/composables/containerScroll.md +89 -0
  46. package/dist/docs/composables/cookie.md +137 -0
  47. package/dist/docs/composables/debounce.md +69 -0
  48. package/dist/docs/composables/disclosure.md +69 -0
  49. package/dist/docs/composables/elementSize.md +84 -0
  50. package/dist/docs/composables/fetch.md +257 -0
  51. package/dist/docs/composables/fieldArray.md +104 -0
  52. package/dist/docs/composables/file.md +343 -0
  53. package/dist/docs/composables/focusTrap.md +87 -0
  54. package/dist/docs/composables/formPersistence.md +69 -0
  55. package/dist/docs/composables/formState.md +71 -0
  56. package/dist/docs/composables/formValidation.md +355 -0
  57. package/dist/docs/composables/format.md +107 -0
  58. package/dist/docs/composables/id.md +54 -0
  59. package/dist/docs/composables/index.md +112 -0
  60. package/dist/docs/composables/infiniteQuery.md +104 -0
  61. package/dist/docs/composables/intersectionObserver.md +64 -0
  62. package/dist/docs/composables/lazyQuery.md +68 -0
  63. package/dist/docs/composables/loading.md +91 -0
  64. package/dist/docs/composables/mutation.md +83 -0
  65. package/dist/docs/composables/notification.md +169 -0
  66. package/dist/docs/composables/pagination.md +109 -0
  67. package/dist/docs/composables/polling.md +76 -0
  68. package/dist/docs/composables/previous.md +58 -0
  69. package/dist/docs/composables/query.md +248 -0
  70. package/dist/docs/composables/raf.md +78 -0
  71. package/dist/docs/composables/scrollLock.md +46 -0
  72. package/dist/docs/composables/scrollToError.md +291 -0
  73. package/dist/docs/composables/scrollVisibility.md +60 -0
  74. package/dist/docs/composables/share.md +78 -0
  75. package/dist/docs/composables/slug.md +58 -0
  76. package/dist/docs/composables/stepper.md +117 -0
  77. package/dist/docs/composables/stepperForm.md +74 -0
  78. package/dist/docs/composables/sticky.md +91 -0
  79. package/dist/docs/composables/storage.md +193 -0
  80. package/dist/docs/composables/theme.md +252 -0
  81. package/dist/docs/composables/themePreset.md +62 -0
  82. package/dist/docs/composables/throttle.md +76 -0
  83. package/dist/docs/composables/timer.md +78 -0
  84. package/dist/docs/composables/toggle.md +55 -0
  85. package/dist/docs/guide/contributing.md +364 -0
  86. package/dist/docs/guide/design-tokens.md +29 -0
  87. package/dist/docs/guide/getting-started.md +181 -0
  88. package/dist/docs/guide/installation.md +287 -0
  89. package/dist/docs/guide/localization.md +132 -0
  90. package/dist/docs/guide/mcp.md +141 -0
  91. package/dist/index.d.ts +2 -0
  92. package/dist/index.js +177 -0
  93. package/package.json +48 -0
@@ -0,0 +1,291 @@
1
+ # useScrollToError
2
+
3
+ A composable for scrolling to an element with validation error. Scrolls into view, optionally applies a highlight effect, focuses the first focusable control, and announces to screen readers.
4
+
5
+ ## Basic Usage
6
+
7
+ ```vue
8
+ <template>
9
+ <form @submit.prevent="handleSubmit">
10
+ <div data-field="tags">
11
+ <input v-model="tags" />
12
+ </div>
13
+ <button type="submit">Submit</button>
14
+ </form>
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ import { useScrollToError } from "@baklavue/composables";
19
+
20
+ const { scrollToError } = useScrollToError();
21
+
22
+ const handleSubmit = () => {
23
+ const err = validationError.value;
24
+ if (err) {
25
+ scrollToError(err);
26
+ }
27
+ };
28
+ </script>
29
+ ```
30
+
31
+ ### Direct Selector
32
+
33
+ ```vue
34
+ <script setup lang="ts">
35
+ import { useScrollToError } from "@baklavue/composables";
36
+
37
+ const { scrollToError } = useScrollToError();
38
+
39
+ // Scroll to element by selector
40
+ scrollToError('[data-field="tags"]');
41
+ </script>
42
+ ```
43
+
44
+ ### With Validation Error Object
45
+
46
+ ```vue
47
+ <script setup lang="ts">
48
+ import { useScrollToError } from "@baklavue/composables";
49
+
50
+ const { scrollToError } = useScrollToError();
51
+
52
+ // Validation error with scrollTarget
53
+ const validationError = {
54
+ field: "tags",
55
+ message: "Please select at least one option",
56
+ scrollTarget: '[data-field="tags"]',
57
+ };
58
+
59
+ scrollToError(validationError);
60
+ </script>
61
+ ```
62
+
63
+ ## Methods
64
+
65
+ ### scrollToError
66
+
67
+ Scrolls to the target element and optionally applies highlight and focus.
68
+
69
+ ```typescript
70
+ scrollToError(target: ScrollToErrorTarget, options?: ScrollToErrorOptions): ScrollToErrorResult
71
+ ```
72
+
73
+ Returns `{ success: boolean }` indicating whether the target was found and scrolled to.
74
+
75
+ ## Target Types
76
+
77
+ Accepted by `scrollToError`:
78
+
79
+ - **CSS selector string** – e.g. `'[data-field="tags"]'`
80
+ - **HTMLElement** – direct element reference
81
+ - **Object with scrollTarget** – e.g. `{ scrollTarget: '[data-field="tags"]' }` for validation errors
82
+
83
+ ## Options
84
+
85
+ ### ScrollToErrorOptions
86
+
87
+ | Option | Type | Default | Description |
88
+ | --- | --- | --- | --- |
89
+ | `scrollBehavior` | `'smooth' \| 'auto' \| 'instant'` | `'smooth'` | Scroll behavior |
90
+ | `block` | `'start' \| 'center' \| 'end' \| 'nearest'` | `'center'` | Vertical scroll position |
91
+ | `shineClass` | `string` | `'error-shine'` | CSS class for highlight effect |
92
+ | `shineDuration` | `number` | `2500` | Duration in ms to keep the shine class. Use `0` to disable |
93
+ | `focus` | `boolean` | `true` | Whether to attempt focusing the first focusable element |
94
+ | `focusDelay` | `number` | `300` | Delay in ms before focus attempt |
95
+ | `scrollContainer` | `string \| HTMLElement \| null` | — | Scroll container for forms inside modals/drawers. When provided, scrolls this container instead of the viewport |
96
+ | `announce` | `boolean \| string` | `true` | Screen reader announcement. `true` = default message, `string` = custom message, `false` = no announcement |
97
+ | `scrollOffset` | `{ top?: number; left?: number }` | — | Offset in pixels for fixed headers (e.g. `{ top: 80 }`) |
98
+
99
+ ### UseScrollToErrorOptions (composable-level)
100
+
101
+ When creating the composable, you can pass default options applied to every call:
102
+
103
+ ```typescript
104
+ useScrollToError({
105
+ defaultOptions: {
106
+ scrollContainer: "[data-dialog-body]",
107
+ shineClass: "my-app-error",
108
+ },
109
+ });
110
+ ```
111
+
112
+ Call-time options override these defaults.
113
+
114
+ ## Examples
115
+
116
+ ### With Custom Options
117
+
118
+ ```vue
119
+ <script setup lang="ts">
120
+ import { useScrollToError } from "@baklavue/composables";
121
+
122
+ const { scrollToError } = useScrollToError();
123
+
124
+ scrollToError('[data-field="tags"]', {
125
+ shineClass: "my-shine",
126
+ shineDuration: 1500,
127
+ focusDelay: 500,
128
+ });
129
+ </script>
130
+ ```
131
+
132
+ ### With Default Options (for modals)
133
+
134
+ ```vue
135
+ <script setup lang="ts">
136
+ import { useScrollToError } from "@baklavue/composables";
137
+
138
+ const { scrollToError } = useScrollToError({
139
+ defaultOptions: {
140
+ scrollContainer: "[data-dialog-body]",
141
+ announce: "Form has errors. Please fix the highlighted field.",
142
+ },
143
+ });
144
+
145
+ scrollToError('[data-field="tags"]');
146
+ </script>
147
+ ```
148
+
149
+ ### Form in Modal with Scroll Container
150
+
151
+ ```vue
152
+ <template>
153
+ <BvDialog v-model:open="isOpen">
154
+ <div data-dialog-body class="dialog-body">
155
+ <form @submit.prevent="handleSubmit">
156
+ <div data-field="email">
157
+ <input v-model="email" />
158
+ </div>
159
+ </form>
160
+ </div>
161
+ </BvDialog>
162
+ </template>
163
+
164
+ <script setup lang="ts">
165
+ import { useScrollToError } from "@baklavue/composables";
166
+
167
+ const { scrollToError } = useScrollToError({
168
+ defaultOptions: { scrollContainer: "[data-dialog-body]" },
169
+ });
170
+
171
+ const handleSubmit = () => {
172
+ if (hasError) {
173
+ scrollToError('[data-field="email"]');
174
+ }
175
+ };
176
+ </script>
177
+ ```
178
+
179
+ ### With Fixed Header Offset
180
+
181
+ ```vue
182
+ <script setup lang="ts">
183
+ import { useScrollToError } from "@baklavue/composables";
184
+
185
+ const { scrollToError } = useScrollToError();
186
+
187
+ scrollToError('[data-field="tags"]', {
188
+ scrollOffset: { top: 80 },
189
+ });
190
+ </script>
191
+ ```
192
+
193
+ ### Without Shine Effect
194
+
195
+ ```vue
196
+ <script setup lang="ts">
197
+ import { useScrollToError } from "@baklavue/composables";
198
+
199
+ const { scrollToError } = useScrollToError();
200
+
201
+ scrollToError('[data-field="tags"]', {
202
+ shineDuration: 0,
203
+ });
204
+ </script>
205
+ ```
206
+
207
+ ### Without Focus
208
+
209
+ ```vue
210
+ <script setup lang="ts">
211
+ import { useScrollToError } from "@baklavue/composables";
212
+
213
+ const { scrollToError } = useScrollToError();
214
+
215
+ scrollToError('[data-field="tags"]', {
216
+ focus: false,
217
+ });
218
+ </script>
219
+ ```
220
+
221
+ ### Without Screen Reader Announcement
222
+
223
+ ```vue
224
+ <script setup lang="ts">
225
+ import { useScrollToError } from "@baklavue/composables";
226
+
227
+ const { scrollToError } = useScrollToError();
228
+
229
+ scrollToError('[data-field="tags"]', {
230
+ announce: false,
231
+ });
232
+ </script>
233
+ ```
234
+
235
+ ### Using Return Value
236
+
237
+ ```vue
238
+ <script setup lang="ts">
239
+ import { useScrollToError } from "@baklavue/composables";
240
+
241
+ const { scrollToError } = useScrollToError();
242
+
243
+ const handleSubmit = () => {
244
+ const result = scrollToError('[data-field="tags"]');
245
+ if (!result.success) {
246
+ console.warn("Could not scroll to error field");
247
+ }
248
+ };
249
+ </script>
250
+ ```
251
+
252
+ ## CSS for Shine Effect
253
+
254
+ The composable uses `error-shine` by default. Define this class in your styles for the highlight effect:
255
+
256
+ ```css
257
+ .error-shine {
258
+ animation: error-shine 2.5s ease-in-out;
259
+ }
260
+
261
+ @keyframes error-shine {
262
+ 0%,
263
+ 100% {
264
+ box-shadow: none;
265
+ }
266
+ 50% {
267
+ box-shadow: 0 0 0 2px var(--bl-color-danger);
268
+ }
269
+ }
270
+ ```
271
+
272
+ ## TypeScript Support
273
+
274
+ ```typescript
275
+ import {
276
+ useScrollToError,
277
+ type ScrollToErrorOptions,
278
+ type ScrollToErrorResult,
279
+ type ScrollToErrorTarget,
280
+ type UseScrollToErrorOptions,
281
+ } from "@baklavue/composables";
282
+
283
+ const { scrollToError } = useScrollToError();
284
+
285
+ // scrollToError accepts string, HTMLElement, or { scrollTarget: string }
286
+ const result = scrollToError('[data-field="tags"]');
287
+ // result.success: boolean
288
+
289
+ scrollToError(document.getElementById("field"));
290
+ scrollToError({ scrollTarget: '[data-field="tags"]' });
291
+ ```
@@ -0,0 +1,60 @@
1
+ # useScrollVisibility
2
+
3
+ A composable for scroll-based visibility. Detects when scroll position exceeds a threshold. RAF-throttled for performance. Use with BvScrollToTop or custom scroll-to-top and sticky UI.
4
+
5
+ ## Basic Usage
6
+
7
+ ```vue
8
+ <template>
9
+ <div>
10
+ <BvButton v-if="isVisible" @click="scrollToTop">Scroll to top</BvButton>
11
+ </div>
12
+ </template>
13
+
14
+ <script setup>
15
+ import { BvButton } from "@baklavue/ui";
16
+ import { useScrollVisibility } from "@baklavue/composables";
17
+
18
+ const { isVisible, scrollY, scrollToTop } = useScrollVisibility({ threshold: 300 });
19
+ </script>
20
+ ```
21
+
22
+ ## Custom Threshold
23
+
24
+ ```vue
25
+ <script setup>
26
+ import { useScrollVisibility } from "@baklavue/composables";
27
+
28
+ const { isVisible } = useScrollVisibility({ threshold: 500 });
29
+ // isVisible is true when user scrolls past 500px
30
+ </script>
31
+ ```
32
+
33
+ ## API
34
+
35
+ ### Return Value
36
+
37
+ | Property | Type | Description |
38
+ | --- | --- | --- |
39
+ | `isVisible` | `Ref<boolean>` | True when scroll exceeds threshold |
40
+ | `scrollY` | `Ref<number>` | Current scroll position |
41
+ | `scrollToTop` | `() => void` | Smooth scroll to top |
42
+
43
+ ### Options
44
+
45
+ ```typescript
46
+ interface UseScrollVisibilityOptions {
47
+ threshold?: number; // pixels (default: 300)
48
+ }
49
+ ```
50
+
51
+ ## TypeScript Support
52
+
53
+ ```typescript
54
+ import {
55
+ useScrollVisibility,
56
+ type UseScrollVisibilityOptions,
57
+ } from "@baklavue/composables";
58
+
59
+ const { isVisible, scrollToTop } = useScrollVisibility({ threshold: 400 });
60
+ ```
@@ -0,0 +1,78 @@
1
+ # useShare
2
+
3
+ A composable for the Web Share API. Share text, URLs, or files via native share sheet (mobile) or fallback. Pairs with `useClipboard` when share is unavailable.
4
+
5
+ ## Basic Usage
6
+
7
+ ```vue
8
+ <template>
9
+ <BvButton v-if="isSupported" @click="handleShare">Share</BvButton>
10
+ </template>
11
+
12
+ <script setup>
13
+ import { BvButton } from "@baklavue/ui";
14
+ import { useShare, useNotification } from "@baklavue/composables";
15
+
16
+ const { share, isSupported } = useShare();
17
+ const { success } = useNotification();
18
+
19
+ const handleShare = async () => {
20
+ const ok = await share({ title: "Report", url: "https://example.com/report" });
21
+ if (ok) success({ description: "Shared!" });
22
+ };
23
+ </script>
24
+ ```
25
+
26
+ ## With Default Data
27
+
28
+ ```vue
29
+ <script setup>
30
+ import { useShare, useNotification } from "@baklavue/composables";
31
+
32
+ const { success } = useNotification();
33
+ const { share, isSupported } = useShare({
34
+ data: { title: "Check this out", url: window.location.href },
35
+ onSuccess: () => success({ description: "Shared!" }),
36
+ });
37
+
38
+ await share(); // uses default data
39
+ </script>
40
+ ```
41
+
42
+ ## API
43
+
44
+ ### Options
45
+
46
+ | Option | Type | Description |
47
+ | --- | --- | --- |
48
+ | `data` | `ShareData` | Default data to share when `share()` is called without arguments |
49
+ | `onSuccess` | `() => void` | Callback when share succeeds |
50
+ | `onError` | `(error?: Error) => void` | Callback when share fails or is aborted |
51
+
52
+ ### ShareData
53
+
54
+ | Property | Type | Description |
55
+ | --- | --- | --- |
56
+ | `title` | `string` | Title of the shared content |
57
+ | `text` | `string` | Text to share |
58
+ | `url` | `string` | URL to share |
59
+ | `files` | `File[]` | Files to share (when supported) |
60
+
61
+ ### Return Value
62
+
63
+ | Property | Type | Description |
64
+ | --- | --- | --- |
65
+ | `share` | `(data?: ShareData) => Promise<boolean>` | Share data. Uses default when called without args. |
66
+ | `isSupported` | `ComputedRef<boolean>` | Whether Web Share API is available |
67
+ | `canShare` | `ComputedRef<boolean>` | Whether the current data can be shared |
68
+ | `shared` | `Ref<boolean>` | True after successful share |
69
+ | `error` | `Ref<Error \| null>` | Last error if share failed |
70
+
71
+ ## TypeScript Support
72
+
73
+ ```typescript
74
+ import { useShare, type ShareData, type UseShareOptions } from "@baklavue/composables";
75
+
76
+ const { share, isSupported } = useShare();
77
+ await share({ title: "Report", url: "https://example.com" });
78
+ ```
@@ -0,0 +1,58 @@
1
+ # useSlug
2
+
3
+ A composable for converting a string to a URL-friendly slug. Useful for SEO-friendly URLs, filenames, and unique keys.
4
+
5
+ ## Basic Usage
6
+
7
+ ```vue
8
+ <script setup>
9
+ import { ref } from "vue";
10
+ import { useSlug } from "@baklavue/composables";
11
+
12
+ const title = ref("Hello World!");
13
+ const slug = useSlug(title);
14
+ // slug: "hello-world"
15
+ </script>
16
+ ```
17
+
18
+ ## With Options
19
+
20
+ ```vue
21
+ <script setup>
22
+ import { useSlug } from "@baklavue/composables";
23
+
24
+ const slug = useSlug("My Project Name", { separator: "_" });
25
+ // slug: "my_project_name"
26
+ </script>
27
+ ```
28
+
29
+ ## API
30
+
31
+ ### Options
32
+
33
+ | Option | Type | Default | Description |
34
+ | --- | --- | --- | --- |
35
+ | `separator` | `string` | `"-"` | Character to replace spaces/special chars |
36
+ | `lowercase` | `boolean` | `true` | Lowercase the result |
37
+
38
+ ### Return Value
39
+
40
+ | Property | Type | Description |
41
+ | --- | --- | --- |
42
+ | (return) | `ComputedRef<string>` | URL-friendly slug |
43
+
44
+ ### Behavior
45
+
46
+ - Trims whitespace
47
+ - Normalizes Unicode (NFD) and removes diacritics
48
+ - Replaces non-word chars with separator
49
+ - Collapses multiple separators
50
+ - Trims leading/trailing separators
51
+
52
+ ## TypeScript Support
53
+
54
+ ```typescript
55
+ import { useSlug, type UseSlugOptions } from "@baklavue/composables";
56
+
57
+ const slug = useSlug(titleRef, { separator: "_", lowercase: false });
58
+ ```
@@ -0,0 +1,117 @@
1
+ # useStepper
2
+
3
+ A composable for multi-step flow state. Use with BvStepper for wizards and form flows.
4
+
5
+ ## Basic Usage
6
+
7
+ ```vue
8
+ <template>
9
+ <div>
10
+ <BvStepper v-model:current-step="currentStep" :steps="steps" />
11
+ <div>
12
+ <BvButton v-if="!isFirst" @click="prev">Previous</BvButton>
13
+ <BvButton v-if="!isLast" @click="next">Next</BvButton>
14
+ </div>
15
+ </div>
16
+ </template>
17
+
18
+ <script setup>
19
+ import { BvButton, BvStepper } from "@baklavue/ui";
20
+ import { useStepper } from "@baklavue/composables";
21
+
22
+ const {
23
+ currentStep,
24
+ steps,
25
+ next,
26
+ prev,
27
+ isFirst,
28
+ isLast,
29
+ } = useStepper({
30
+ steps: [
31
+ { label: "Details" },
32
+ { label: "Review" },
33
+ { label: "Confirm" },
34
+ ],
35
+ });
36
+ </script>
37
+ ```
38
+
39
+ ## With Step Validation
40
+
41
+ ```vue
42
+ <script setup>
43
+ import { useStepper } from "@baklavue/composables";
44
+
45
+ const {
46
+ currentStep,
47
+ steps,
48
+ next,
49
+ setStepError,
50
+ } = useStepper({
51
+ steps: [
52
+ { label: "Details" },
53
+ { label: "Review" },
54
+ ],
55
+ });
56
+
57
+ const validateAndNext = () => {
58
+ const valid = validateCurrentStep();
59
+ if (!valid) {
60
+ setStepError(currentStep.value, true);
61
+ } else {
62
+ setStepError(currentStep.value, false);
63
+ next();
64
+ }
65
+ };
66
+ </script>
67
+ ```
68
+
69
+ ## API
70
+
71
+ ### Return Value
72
+
73
+ | Property | Type | Description |
74
+ | --- | --- | --- |
75
+ | `currentStep` | `Ref<number>` | Current step index (0-based) |
76
+ | `steps` | `Ref<StepperStep[]>` | Step configurations |
77
+ | `next` | `() => void` | Go to next step |
78
+ | `prev` | `() => void` | Go to previous step |
79
+ | `goTo` | `(index: number) => void` | Go to specific step |
80
+ | `setStepError` | `(index: number, hasError: boolean) => void` | Set error state for step |
81
+ | `isFirst` | `ComputedRef<boolean>` | True on first step |
82
+ | `isLast` | `ComputedRef<boolean>` | True on last step |
83
+ | `canGoNext` | `ComputedRef<boolean>` | True if can advance |
84
+ | `canGoPrev` | `ComputedRef<boolean>` | True if can go back |
85
+ | `stepVariant` | `(index: number) => StepVariant` | Get variant for step (default, active, success, error) |
86
+ | `totalSteps` | `ComputedRef<number>` | Total number of steps |
87
+
88
+ ### Options
89
+
90
+ ```typescript
91
+ interface UseStepperOptions {
92
+ steps: StepperStep[];
93
+ initialStep?: number; // default: 0
94
+ }
95
+
96
+ interface StepperStep {
97
+ label: string;
98
+ description?: string;
99
+ completed?: boolean;
100
+ error?: boolean;
101
+ disabled?: boolean;
102
+ }
103
+ ```
104
+
105
+ ## TypeScript Support
106
+
107
+ ```typescript
108
+ import {
109
+ useStepper,
110
+ type UseStepperOptions,
111
+ type StepperStep,
112
+ } from "@baklavue/composables";
113
+
114
+ const { currentStep, next } = useStepper({
115
+ steps: [{ label: "Step 1" }, { label: "Step 2" }],
116
+ });
117
+ ```
@@ -0,0 +1,74 @@
1
+ # useStepperForm
2
+
3
+ A composable for multi-step form flows with per-step validation. Use with [useStepper](/composables/stepper) and [useZodForm](/composables/formValidation) to validate before advancing to the next step.
4
+
5
+ ## Basic Usage
6
+
7
+ ```vue
8
+ <script setup lang="ts">
9
+ import { useStepper, useStepperForm } from "@baklavue/composables";
10
+ import { useZodForm } from "@baklavue/composables";
11
+ import { ref } from "vue";
12
+ import { z } from "zod";
13
+
14
+ const form = ref({ email: "", name: "", address: "" });
15
+ const schema = z.object({
16
+ email: z.string().email(),
17
+ name: z.string().min(1),
18
+ address: z.string().min(1),
19
+ });
20
+
21
+ const stepper = useStepper({
22
+ steps: [{ label: "Contact" }, { label: "Address" }],
23
+ });
24
+
25
+ const formValidation = useZodForm(schema, form);
26
+ const { nextWithValidation, hasStepError } = useStepperForm(stepper, {
27
+ stepFields: (i) => (i === 0 ? ["email", "name"] : ["address"]),
28
+ });
29
+
30
+ const onNext = () => nextWithValidation(formValidation.validate);
31
+ </script>
32
+
33
+ <template>
34
+ <BvStepper v-model:current-step="stepper.currentStep" :steps="stepper.steps" />
35
+ <form @submit.prevent="onNext">
36
+ <!-- Step 0: email, name -->
37
+ <template v-if="stepper.currentStep.value === 0">
38
+ <BvInput v-model="form.email" :invalid-text="formValidation.getError('email')" />
39
+ <BvInput v-model="form.name" :invalid-text="formValidation.getError('name')" />
40
+ </template>
41
+ <!-- Step 1: address -->
42
+ <template v-else>
43
+ <BvInput v-model="form.address" :invalid-text="formValidation.getError('address')" />
44
+ </template>
45
+ <BvButton type="submit">Next</BvButton>
46
+ </form>
47
+ </template>
48
+ ```
49
+
50
+ ## API
51
+
52
+ ### Parameters
53
+
54
+ ```typescript
55
+ useStepperForm(stepper, options?)
56
+ ```
57
+
58
+ | Parameter | Type | Description |
59
+ | --- | --- | --- |
60
+ | `stepper` | `StepperLike` | Return value from useStepper |
61
+ | `options` | `UseStepperFormOptions` | Optional: `{ stepFields?: (stepIndex) => string[] }` |
62
+
63
+ ### Return Value
64
+
65
+ | Property | Type | Description |
66
+ | --- | --- | --- |
67
+ | `hasStepError` | `() => boolean` | Whether the current step has validation errors |
68
+ | `nextWithValidation` | `(validate: () => Promise<FormErrors \| null>) => Promise<boolean>` | Validates, advances if valid, sets step error if invalid. Returns `true` if advanced |
69
+
70
+ ### stepFields
71
+
72
+ When provided, `stepFields(stepIndex)` returns the field paths for that step. Validation errors are filtered to these paths to determine if the current step has errors. If omitted, any validation error marks the current step as having an error.
73
+
74
+ This is useful when you have a single schema for the whole form but want to show step-specific error indicators on the stepper.