@velkymx/vibeui 0.8.2 → 1.0.2

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 (200) hide show
  1. package/AGENTS.md +44 -0
  2. package/README.md +245 -58
  3. package/dist/purify.es-1D-VntFD.mjs +679 -0
  4. package/dist/src/App.vue.d.ts +3 -0
  5. package/dist/src/components/HelloWorld.vue.d.ts +6 -0
  6. package/dist/src/components/VibeAccordion.vue.d.ts +89 -0
  7. package/dist/{components → src/components}/VibeAlert.vue.d.ts +24 -30
  8. package/dist/src/components/VibeAutocomplete.vue.d.ts +74 -0
  9. package/dist/{components → src/components}/VibeBadge.vue.d.ts +10 -18
  10. package/dist/src/components/VibeBreadcrumb.vue.d.ts +51 -0
  11. package/dist/{components → src/components}/VibeButton.vue.d.ts +16 -20
  12. package/dist/{components → src/components}/VibeButtonGroup.vue.d.ts +10 -18
  13. package/dist/{components → src/components}/VibeCard.vue.d.ts +51 -24
  14. package/dist/{components → src/components}/VibeCarousel.vue.d.ts +27 -49
  15. package/dist/src/components/VibeChartBar.vue.d.ts +61 -0
  16. package/dist/src/components/VibeChartLine.vue.d.ts +70 -0
  17. package/dist/src/components/VibeChartPie.vue.d.ts +34 -0
  18. package/dist/{components → src/components}/VibeCloseButton.vue.d.ts +9 -7
  19. package/dist/{components → src/components}/VibeCol.vue.d.ts +9 -17
  20. package/dist/src/components/VibeCollapse.vue.d.ts +76 -0
  21. package/dist/src/components/VibeContainer.vue.d.ts +36 -0
  22. package/dist/src/components/VibeDataTable.vue.d.ts +131 -0
  23. package/dist/src/components/VibeDatePicker.vue.d.ts +120 -0
  24. package/dist/src/components/VibeDraggable.vue.d.ts +77 -0
  25. package/dist/{components → src/components}/VibeDropdown.vue.d.ts +46 -43
  26. package/dist/src/components/VibeDroppable.vue.d.ts +70 -0
  27. package/dist/src/components/VibeFileInput.vue.d.ts +127 -0
  28. package/dist/{components → src/components}/VibeFormCheckbox.vue.d.ts +30 -22
  29. package/dist/{components → src/components}/VibeFormDatepicker.vue.d.ts +27 -30
  30. package/dist/{components → src/components}/VibeFormGroup.vue.d.ts +11 -14
  31. package/dist/{components → src/components}/VibeFormInput.vue.d.ts +22 -23
  32. package/dist/{components → src/components}/VibeFormRadio.vue.d.ts +23 -24
  33. package/dist/{components → src/components}/VibeFormSelect.vue.d.ts +28 -34
  34. package/dist/{components → src/components}/VibeFormSpinbutton.vue.d.ts +31 -34
  35. package/dist/{components → src/components}/VibeFormSwitch.vue.d.ts +22 -23
  36. package/dist/{components → src/components}/VibeFormTextarea.vue.d.ts +24 -25
  37. package/dist/{components → src/components}/VibeFormWysiwyg.vue.d.ts +24 -23
  38. package/dist/src/components/VibeHero.vue.d.ts +108 -0
  39. package/dist/{components → src/components}/VibeIcon.vue.d.ts +27 -7
  40. package/dist/{components → src/components}/VibeInputGroup.vue.d.ts +11 -13
  41. package/dist/{components → src/components}/VibeLink.vue.d.ts +14 -18
  42. package/dist/{components → src/components}/VibeListGroup.vue.d.ts +26 -22
  43. package/dist/{components → src/components}/VibeModal.vue.d.ts +29 -45
  44. package/dist/{components → src/components}/VibeNav.vue.d.ts +40 -20
  45. package/dist/{components → src/components}/VibeNavbar.vue.d.ts +12 -19
  46. package/dist/src/components/VibeNavbarBrand.vue.d.ts +34 -0
  47. package/dist/src/components/VibeNavbarNav.vue.d.ts +80 -0
  48. package/dist/{components → src/components}/VibeNavbarToggle.vue.d.ts +7 -5
  49. package/dist/{components → src/components}/VibeOffcanvas.vue.d.ts +28 -43
  50. package/dist/{components → src/components}/VibePagination.vue.d.ts +38 -29
  51. package/dist/{components → src/components}/VibePlaceholder.vue.d.ts +9 -17
  52. package/dist/src/components/VibePopover.vue.d.ts +72 -0
  53. package/dist/src/components/VibeProgress.vue.d.ts +37 -0
  54. package/dist/src/components/VibeResizable.vue.d.ts +140 -0
  55. package/dist/{components → src/components}/VibeRow.vue.d.ts +9 -17
  56. package/dist/src/components/VibeScrollspy.vue.d.ts +89 -0
  57. package/dist/src/components/VibeSkeleton.vue.d.ts +54 -0
  58. package/dist/src/components/VibeSlider.vue.d.ts +77 -0
  59. package/dist/src/components/VibeSortable.vue.d.ts +59 -0
  60. package/dist/{components → src/components}/VibeSpinner.vue.d.ts +4 -7
  61. package/dist/src/components/VibeStepper.vue.d.ts +133 -0
  62. package/dist/src/components/VibeTab.vue.d.ts +41 -0
  63. package/dist/src/components/VibeTabContent.vue.d.ts +56 -0
  64. package/dist/src/components/VibeTabs.vue.d.ts +78 -0
  65. package/dist/{components → src/components}/VibeToast.vue.d.ts +40 -42
  66. package/dist/src/components/VibeToastHost.vue.d.ts +16 -0
  67. package/dist/src/components/VibeTooltip.vue.d.ts +63 -0
  68. package/dist/src/components/chart/chartColors.d.ts +3 -0
  69. package/dist/src/components/chart/chartResize.d.ts +2 -0
  70. package/dist/src/components/chart/chartTooltip.d.ts +2 -0
  71. package/dist/src/components/chart/chartTypes.d.ts +6 -0
  72. package/dist/src/components/chart/drawBar.d.ts +5 -0
  73. package/dist/src/components/chart/drawLine.d.ts +18 -0
  74. package/dist/src/components/chart/drawPie.d.ts +4 -0
  75. package/dist/src/components/dndStore.d.ts +7 -0
  76. package/dist/{components → src/components}/index.d.ts +18 -1
  77. package/dist/{composables → src/composables}/useBreakpoints.d.ts +1 -0
  78. package/dist/{composables → src/composables}/useColorMode.d.ts +1 -1
  79. package/dist/src/composables/useForm.d.ts +22 -0
  80. package/dist/src/composables/useId.d.ts +2 -0
  81. package/dist/src/composables/usePosition.d.ts +20 -0
  82. package/dist/src/composables/useToast.d.ts +52 -0
  83. package/dist/src/directives/vTooltip.d.ts +24 -0
  84. package/dist/{index.d.ts → src/index.d.ts} +6 -0
  85. package/dist/src/injectionKeys.d.ts +28 -0
  86. package/dist/{types.d.ts → src/types.d.ts} +32 -6
  87. package/dist/src/utils/safeCss.d.ts +16 -0
  88. package/dist/src/utils/safeHref.d.ts +7 -0
  89. package/dist/src/utils/sanitizeHtml.d.ts +13 -0
  90. package/dist/vibeui.css +2 -1
  91. package/dist/vibeui.es.js +8351 -3508
  92. package/dist/vibeui.umd.js +3 -1
  93. package/docs/README.md +85 -13
  94. package/docs/components/advanced/popover.md +27 -52
  95. package/docs/components/advanced/scrollspy.md +57 -15
  96. package/docs/components/advanced/tooltip.md +26 -47
  97. package/docs/components/card/card.md +9 -1
  98. package/docs/components/charts/chart-bar.md +129 -0
  99. package/docs/components/charts/chart-line.md +136 -0
  100. package/docs/components/charts/chart-pie.md +102 -0
  101. package/docs/components/core/alert.md +27 -5
  102. package/docs/components/core/badge.md +0 -6
  103. package/docs/components/core/button-group.md +0 -6
  104. package/docs/components/core/button.md +1 -1
  105. package/docs/components/core/close-button.md +5 -5
  106. package/docs/components/core/link.md +60 -17
  107. package/docs/components/core/placeholder.md +0 -6
  108. package/docs/components/core/skeleton.md +40 -0
  109. package/docs/components/core/spinner.md +0 -6
  110. package/docs/components/data/datatable.md +29 -10
  111. package/docs/components/hero/hero.md +64 -0
  112. package/docs/components/interactive/accordion.md +29 -0
  113. package/docs/components/interactive/carousel.md +19 -4
  114. package/docs/components/interactive/collapse.md +3 -2
  115. package/docs/components/interactive/date-picker.md +78 -0
  116. package/docs/components/interactive/draggable.md +91 -0
  117. package/docs/components/interactive/dropdown.md +54 -18
  118. package/docs/components/interactive/modal.md +15 -20
  119. package/docs/components/interactive/offcanvas.md +4 -1
  120. package/docs/components/interactive/resizable.md +73 -0
  121. package/docs/components/interactive/slider.md +57 -0
  122. package/docs/components/interactive/sortable.md +52 -0
  123. package/docs/components/interactive/stepper.md +83 -0
  124. package/docs/components/interactive/tabs.md +66 -0
  125. package/docs/components/interactive/toast.md +93 -30
  126. package/docs/components/layout/col.md +0 -6
  127. package/docs/components/layout/container.md +0 -6
  128. package/docs/components/layout/row.md +0 -6
  129. package/docs/components/list/list-group.md +4 -0
  130. package/docs/components/navigation/breadcrumb.md +4 -0
  131. package/docs/components/navigation/nav.md +64 -1
  132. package/docs/components/navigation/navbar.md +2 -0
  133. package/docs/components/navigation/pagination.md +16 -0
  134. package/docs/components/progress/progress.md +7 -1
  135. package/docs/composables/color-mode.md +44 -6
  136. package/docs/composables/use-form.md +78 -0
  137. package/docs/composables/use-position.md +68 -0
  138. package/docs/composables/use-toast.md +91 -0
  139. package/docs/directives/v-tooltip.md +58 -0
  140. package/docs/forms/README.md +60 -61
  141. package/docs/forms/autocomplete.md +96 -0
  142. package/docs/forms/file-input.md +97 -0
  143. package/docs/forms/form-checkbox.md +75 -25
  144. package/docs/forms/form-datepicker.md +58 -28
  145. package/docs/forms/form-group.md +79 -44
  146. package/docs/forms/form-input.md +88 -31
  147. package/docs/forms/form-radio.md +60 -36
  148. package/docs/forms/form-select.md +75 -31
  149. package/docs/forms/form-spinbutton.md +72 -33
  150. package/docs/forms/form-switch.md +53 -25
  151. package/docs/forms/form-textarea.md +60 -29
  152. package/docs/forms/form-wysiwyg.md +73 -38
  153. package/docs/forms/input-group.md +53 -34
  154. package/docs/forms/validation.md +135 -521
  155. package/docs/getting-started/starter-template.md +136 -0
  156. package/docs/superpowers/plans/2026-05-12-vibe-charts.md +1999 -0
  157. package/docs/superpowers/plans/2026-05-29-e2e-browser-testing.md +615 -0
  158. package/docs/superpowers/specs/2026-05-12-charting-design.md +185 -0
  159. package/docs/superpowers/specs/2026-05-29-e2e-browser-testing-design.md +168 -0
  160. package/docs/utilities/position.md +82 -0
  161. package/docs/versioning.md +57 -0
  162. package/examples/README.md +201 -0
  163. package/examples/album.html +262 -0
  164. package/examples/blog.html +166 -0
  165. package/examples/carousel.html +114 -0
  166. package/examples/checkout.html +275 -0
  167. package/examples/cover.html +89 -0
  168. package/examples/dashboard.html +156 -0
  169. package/examples/index.html +129 -0
  170. package/examples/jumbotron.html +56 -0
  171. package/examples/mobile-dashboard.html +138 -0
  172. package/examples/pricing.html +172 -0
  173. package/examples/product.html +145 -0
  174. package/examples/sidebars.html +166 -0
  175. package/examples/sign-in.html +119 -0
  176. package/examples/starter.html +314 -0
  177. package/examples/sticky-footer-navbar.html +70 -0
  178. package/examples/sticky-footer.html +60 -0
  179. package/examples/test-simple.html +91 -0
  180. package/llms.txt +407 -47
  181. package/package.json +42 -13
  182. package/dist/App.vue.d.ts +0 -2
  183. package/dist/components/HelloWorld.vue.d.ts +0 -5
  184. package/dist/components/VibeAccordion.vue.d.ts +0 -90
  185. package/dist/components/VibeBreadcrumb.vue.d.ts +0 -47
  186. package/dist/components/VibeCollapse.vue.d.ts +0 -84
  187. package/dist/components/VibeContainer.vue.d.ts +0 -44
  188. package/dist/components/VibeDataTable.vue.d.ts +0 -76
  189. package/dist/components/VibeNavbarBrand.vue.d.ts +0 -42
  190. package/dist/components/VibeNavbarNav.vue.d.ts +0 -61
  191. package/dist/components/VibePopover.vue.d.ts +0 -95
  192. package/dist/components/VibeProgress.vue.d.ts +0 -45
  193. package/dist/components/VibeScrollspy.vue.d.ts +0 -77
  194. package/dist/components/VibeTabContent.vue.d.ts +0 -74
  195. package/dist/components/VibeTooltip.vue.d.ts +0 -86
  196. package/dist/composables/useId.d.ts +0 -5
  197. package/dist/types/index.d.ts +0 -6
  198. /package/dist/{composables → src/composables}/useBackButton.d.ts +0 -0
  199. /package/dist/{composables → src/composables}/useFormValidation.d.ts +0 -0
  200. /package/dist/{main.d.ts → src/main.d.ts} +0 -0
@@ -0,0 +1,96 @@
1
+ # VibeAutocomplete
2
+
3
+ Search-as-you-type input backed by an array or async source, with keyboard navigation. Generic over the item type `T`.
4
+
5
+ ## Props
6
+
7
+ | Prop | Type | Default | Description |
8
+ |------|------|---------|-------------|
9
+ | `modelValue` | `string` | `''` | The text value of the input (v-model). |
10
+ | `source` | `T[] \| (query: string) => T[] \| Promise<T[]>` | — (required) | Array to filter, or a function returning matches (sync or async). |
11
+ | `itemText` | `(item: T) => string` | `undefined` | Maps an item to its display/filter text. Defaults to the string form of the item. |
12
+ | `minChars` | `number` | `1` | Minimum characters before searching. |
13
+ | `debounce` | `number` | `200` | Debounce in ms before running a query (`0` disables debouncing). |
14
+ | `maxResults` | `number` | `10` | Maximum number of results shown. |
15
+ | `placeholder` | `string` | `''` | Placeholder text. |
16
+ | `label` | `string` | `undefined` | Label text. |
17
+ | `id` | `string` | auto-generated | Element id. |
18
+ | `disabled` | `boolean` | `false` | Disable the input. |
19
+
20
+ ## Events
21
+
22
+ | Event | Payload | Description |
23
+ |-------|---------|-------------|
24
+ | `update:modelValue` | `string` | Emitted as the user types and when an item is selected. |
25
+ | `select` | `T` | Emitted with the chosen item when a result is selected. |
26
+
27
+ ## Slots
28
+
29
+ | Slot | Scope | Description |
30
+ |------|-------|-------------|
31
+ | `item` | `{ item: T, index: number, label: string }` | Custom rendering for each result row. |
32
+ | `empty` | — | Content shown when there are no results. Defaults to "No results". |
33
+
34
+ ## Usage
35
+
36
+ ### Array source
37
+
38
+ ```vue
39
+ <script setup lang="ts">
40
+ import { ref } from 'vue'
41
+ const query = ref('')
42
+ const fruits = ['Apple', 'Apricot', 'Banana', 'Cherry', 'Mango']
43
+ </script>
44
+
45
+ <template>
46
+ <VibeAutocomplete v-model="query" :source="fruits" label="Fruit" />
47
+ </template>
48
+ ```
49
+
50
+ ### Async source with typed items
51
+
52
+ ```vue
53
+ <script setup lang="ts">
54
+ import { ref } from 'vue'
55
+
56
+ interface User { id: number; name: string }
57
+ const value = ref('')
58
+
59
+ const search = async (q: string): Promise<User[]> => {
60
+ const res = await fetch(`/api/users?q=${encodeURIComponent(q)}`)
61
+ return res.json()
62
+ }
63
+
64
+ const onSelect = (user: User) => console.log('picked', user.id)
65
+ </script>
66
+
67
+ <template>
68
+ <VibeAutocomplete
69
+ v-model="value"
70
+ :source="search"
71
+ :item-text="(u) => u.name"
72
+ :min-chars="2"
73
+ label="Assignee"
74
+ @select="onSelect"
75
+ >
76
+ <template #item="{ item }">
77
+ <strong>{{ item.name }}</strong> <small class="text-muted">#{{ item.id }}</small>
78
+ </template>
79
+ <template #empty>No users found</template>
80
+ </VibeAutocomplete>
81
+ </template>
82
+ ```
83
+
84
+ ## Important Notes
85
+
86
+ - **Async race-safety:** in-flight async queries are token-guarded, so only the latest query's results are applied.
87
+ - **Keyboard support:** Arrow Up/Down move the highlight, Enter selects, Escape closes the menu. The combobox exposes `aria-expanded`, `aria-controls`, and `aria-activedescendant`.
88
+ - **Selection text:** selecting an item sets the input to the item's `itemText` (or string) value and emits both `update:modelValue` and `select`.
89
+ - **Outside click:** clicking outside the component closes the menu.
90
+
91
+ ## Bootstrap CSS Classes
92
+
93
+ - `.form-control`
94
+ - `.form-label`
95
+
96
+ The dropdown menu, items, and empty state use VibeUI's own `.vibe-autocomplete*` classes (styled with Bootstrap CSS variables).
@@ -0,0 +1,97 @@
1
+ # VibeFileInput
2
+
3
+ File attachment input with optional drag-and-drop zone. `v-model` exposes the selected files as `File[]`.
4
+
5
+ ## Props
6
+
7
+ | Prop | Type | Default | Description |
8
+ |------|------|---------|-------------|
9
+ | `modelValue` | `File[]` | `[]` | The accepted files (v-model). |
10
+ | `id` | `string` | auto-generated | Element id. |
11
+ | `label` | `string` | `undefined` | Label text. |
12
+ | `multiple` | `boolean` | `false` | Allow selecting multiple files. |
13
+ | `accept` | `string` | `undefined` | Comma-separated MIME types and/or extensions (e.g. `image/*,.pdf`). Used both as the native filter and for rejection. |
14
+ | `maxSize` | `number` | `undefined` | Maximum file size in bytes; larger files are rejected. |
15
+ | `dragDrop` | `boolean` | `false` | Render a drag-and-drop zone instead of the native control. |
16
+ | `disabled` | `boolean` | `false` | Disable the input. |
17
+ | `size` | `'sm' \| 'lg'` | `undefined` | Control size (native control only). |
18
+ | `helpText` | `string` | `undefined` | Help text below the input. |
19
+ | `dropzoneText` | `string` | `'Drag files here or click to browse'` | Text shown inside the drop zone. |
20
+
21
+ ## Events
22
+
23
+ | Event | Payload | Description |
24
+ |-------|---------|-------------|
25
+ | `update:modelValue` | `File[]` | Emitted with the accepted files. |
26
+ | `change` | `File[]` | Emitted with the accepted files (mirrors `update:modelValue`). |
27
+ | `invalid` | `File[]` | Emitted with files rejected by `accept` or `maxSize`. |
28
+
29
+ ## Slots
30
+
31
+ | Slot | Description |
32
+ |------|-------------|
33
+ | `dropzone` | Custom content for the drop zone (only when `dragDrop` is set). |
34
+
35
+ ## Exposed methods
36
+
37
+ | Method | Description |
38
+ |--------|-------------|
39
+ | `clearFiles()` | Clears the native input and emits an empty selection. |
40
+
41
+ ## Usage
42
+
43
+ ### Native input
44
+
45
+ ```vue
46
+ <script setup lang="ts">
47
+ import { ref } from 'vue'
48
+ const files = ref<File[]>([])
49
+ </script>
50
+
51
+ <template>
52
+ <VibeFileInput
53
+ v-model="files"
54
+ label="Attachment"
55
+ accept="image/*,.pdf"
56
+ :max-size="5 * 1024 * 1024"
57
+ help-text="Images or PDF, up to 5 MB."
58
+ />
59
+ </template>
60
+ ```
61
+
62
+ ### Drag-and-drop with rejection handling
63
+
64
+ ```vue
65
+ <script setup lang="ts">
66
+ import { ref } from 'vue'
67
+ const files = ref<File[]>([])
68
+
69
+ const onInvalid = (rejected: File[]) => {
70
+ console.warn('Rejected:', rejected.map((f) => f.name))
71
+ }
72
+ </script>
73
+
74
+ <template>
75
+ <VibeFileInput
76
+ v-model="files"
77
+ multiple
78
+ drag-drop
79
+ accept="image/*"
80
+ :max-size="2 * 1024 * 1024"
81
+ @invalid="onInvalid"
82
+ />
83
+ </template>
84
+ ```
85
+
86
+ ## Important Notes
87
+
88
+ - **Same-file reselection:** the native input is reset after each change so picking the same file again still fires `change`.
89
+ - **Rejection:** files failing `accept` or exceeding `maxSize` are excluded from the model and reported via the `invalid` event.
90
+ - **Drag safety:** a document-level fallback resets the dragging state if a drag ends or drops outside the zone.
91
+
92
+ ## Bootstrap CSS Classes
93
+
94
+ - `.form-control`, `.form-control-{sm|lg}`
95
+ - `.form-label`, `.form-text`
96
+
97
+ The drop zone uses VibeUI's own `.vibe-file-input-dropzone*` classes.
@@ -1,8 +1,44 @@
1
1
  # VibeFormCheckbox
2
2
 
3
- Checkbox component for single boolean values or multiple selections.
3
+ Checkbox for a single boolean value or as part of a grouped multi-select (array model).
4
4
 
5
- ## Basic Usage
5
+ ## Props
6
+
7
+ | Prop | Type | Default | Description |
8
+ |------|------|---------|-------------|
9
+ | `modelValue` | `boolean \| string \| number \| (string \| number \| boolean)[]` | `false` | v-model. A boolean (or `value`/`uncheckedValue`) for single checkboxes; an array for grouped checkboxes. |
10
+ | `value` | `string \| number \| boolean` | `true` | Value emitted/added to the array when checked. |
11
+ | `uncheckedValue` | `string \| number \| boolean` | `false` | Value emitted when unchecked (non-array model only). |
12
+ | `id` | `string` | auto-generated | Element id. Auto-generated, or inherited from a parent `VibeFormGroup`. |
13
+ | `label` | `string` | `undefined` | Checkbox label text. |
14
+ | `disabled` | `boolean` | `false` | Disable the checkbox. |
15
+ | `required` | `boolean` | `false` | Mark as required. |
16
+ | `inline` | `boolean` | `false` | Render inline (`.form-check-inline`). |
17
+ | `indeterminate` | `boolean` | `false` | Show the indeterminate (mixed) state. |
18
+ | `reverse` | `boolean` | `false` | Place the label before the checkbox (`.form-check-reverse`). |
19
+ | `validationState` | `'valid' \| 'invalid' \| null` | `null` | Visual validation state. |
20
+ | `validationMessage` | `string` | `undefined` | Feedback message for the current state. |
21
+ | `validationRules` | `ValidationRule[] \| ValidatorFunction` | `undefined` | Rules carried for use with a validation composable. |
22
+ | `validateOn` | `'change' \| 'blur'` | `'change'` | When the `validate` event fires. |
23
+ | `helpText` | `string` | `undefined` | Help text below the checkbox. |
24
+
25
+ ## Events
26
+
27
+ | Event | Payload | Description |
28
+ |-------|---------|-------------|
29
+ | `update:modelValue` | `boolean \| string \| number \| (string \| number \| boolean)[]` | Emitted on toggle. Array result when the model is an array. |
30
+ | `change` | `Event` | Native change event. |
31
+ | `blur` | `FocusEvent` | Emitted on blur. |
32
+ | `focus` | `FocusEvent` | Emitted on focus. |
33
+ | `validate` | — | Emitted when the `validateOn` trigger occurs. |
34
+
35
+ ## Slots
36
+
37
+ None.
38
+
39
+ ## Usage
40
+
41
+ ### Single checkbox
6
42
 
7
43
  ```vue
8
44
  <script setup lang="ts">
@@ -10,41 +46,55 @@ import { ref } from 'vue'
10
46
  const agreed = ref(false)
11
47
  </script>
12
48
 
49
+ <template>
50
+ <VibeFormCheckbox v-model="agreed" label="I accept the terms" />
51
+ </template>
52
+ ```
53
+
54
+ ### Custom checked / unchecked values
55
+
56
+ ```vue
57
+ <script setup lang="ts">
58
+ import { ref } from 'vue'
59
+ const status = ref('off')
60
+ </script>
61
+
13
62
  <template>
14
63
  <VibeFormCheckbox
15
- v-model="agreed"
16
- label="I agree to the terms"
64
+ v-model="status"
65
+ value="on"
66
+ unchecked-value="off"
67
+ label="Enable feature"
17
68
  />
18
69
  </template>
19
70
  ```
20
71
 
21
- ## Props
72
+ ### Grouped checkboxes (array model)
22
73
 
23
- | Prop | Type | Default | Description |
24
- |------|------|---------|-------------|
25
- | `modelValue` | `any` | `false` | The checked state (v-model) |
26
- | `value` | `any` | `true` | Value when checked |
27
- | `id` | `String` | `Auto-generated` | Unique identifier |
28
- | `label` | `String` | `undefined` | Label text |
29
- | `disabled` | `Boolean` | `false` | Disable the checkbox |
30
- | `required` | `Boolean` | `false` | Mark as required |
31
- | `inline` | `Boolean` | `false` | Display inline |
32
- | `indeterminate` | `Boolean` | `false` | Set indeterminate state |
33
- | `validationState` | `'valid' \| 'invalid' \| null` | `null` | Validation state |
34
- | `validationMessage` | `String` | `undefined` | Validation message |
35
- | `validateOn` | `'change' \| 'blur'` | `'change'` | When to validate |
36
- | `helpText` | `String` | `undefined` | Help text |
37
- | `reverse` | `Boolean` | `false` | Reverse label and input |
74
+ ```vue
75
+ <script setup lang="ts">
76
+ import { ref } from 'vue'
77
+ const selected = ref<string[]>([])
78
+ </script>
38
79
 
39
- ## Important Notes
80
+ <template>
81
+ <VibeFormGroup label="Interests">
82
+ <VibeFormCheckbox v-model="selected" value="vue" label="Vue" />
83
+ <VibeFormCheckbox v-model="selected" value="ts" label="TypeScript" />
84
+ <VibeFormCheckbox v-model="selected" value="css" label="CSS" />
85
+ </VibeFormGroup>
86
+ </template>
87
+ ```
40
88
 
41
- **Automatic ID Generation:** This component automatically generates a unique ID if one is not provided.
89
+ ## Important Notes
42
90
 
43
- **Automatic ID Injection:** When used inside a `VibeFormGroup`, this component will automatically inherit the group's ID to ensure proper label association and accessibility.
91
+ - **Array vs. single model:** if `modelValue` is an array, checking adds `value` and unchecking removes it. Otherwise the model toggles between `value` and `uncheckedValue`.
92
+ - **Indeterminate:** purely visual; it does not change the checked value and is reset once the user toggles.
93
+ - **Group linking:** in a grouped layout, the first checkbox consumes the `VibeFormGroup` id; subsequent checkboxes generate their own ids.
44
94
 
45
95
  ## Bootstrap CSS Classes
46
96
 
47
97
  - `.form-check`
48
- - `.form-check-input`
49
- - `.form-check-label`
98
+ - `.form-check-input`, `.form-check-label`
99
+ - `.form-check-inline`, `.form-check-reverse`
50
100
  - `.is-valid`, `.is-invalid`
@@ -1,50 +1,80 @@
1
1
  # VibeFormDatepicker
2
2
 
3
- Date and time input component using native browser pickers.
3
+ Date, time, and datetime input using the native browser pickers, with built-in validation and accessibility.
4
4
 
5
- ## Basic Usage
5
+ ## Props
6
+
7
+ | Prop | Type | Default | Description |
8
+ |------|------|---------|-------------|
9
+ | `modelValue` | `string` | `''` | The value (v-model) as an ISO-style string matching the chosen `type` (e.g. `2026-05-28`). |
10
+ | `type` | `'date' \| 'time' \| 'datetime-local' \| 'month' \| 'week'` | `'date'` | Native picker type. |
11
+ | `id` | `string` | auto-generated | Element id. Auto-generated, or inherited from a parent `VibeFormGroup`. |
12
+ | `label` | `string` | `undefined` | Standalone label text. |
13
+ | `disabled` | `boolean` | `false` | Disable the input. |
14
+ | `readonly` | `boolean` | `false` | Make the input read-only. |
15
+ | `required` | `boolean` | `false` | Mark as required. |
16
+ | `min` | `string` | `undefined` | Minimum allowed value. |
17
+ | `max` | `string` | `undefined` | Maximum allowed value. |
18
+ | `size` | `'sm' \| 'lg'` | `undefined` | Control size. |
19
+ | `validationState` | `'valid' \| 'invalid' \| null` | `null` | Visual validation state. |
20
+ | `validationMessage` | `string` | `undefined` | Feedback message for the current state. |
21
+ | `validationRules` | `ValidationRule[] \| ValidatorFunction` | `undefined` | Rules carried for use with a validation composable. |
22
+ | `validateOn` | `'input' \| 'blur' \| 'change'` | `'blur'` | When the `validate` event fires. |
23
+ | `helpText` | `string` | `undefined` | Help text below the input. |
24
+
25
+ ## Events
26
+
27
+ | Event | Payload | Description |
28
+ |-------|---------|-------------|
29
+ | `update:modelValue` | `string` | Emitted on input. |
30
+ | `input` | `Event` | Native input event. |
31
+ | `change` | `Event` | Native change event. |
32
+ | `blur` | `FocusEvent` | Emitted on blur. |
33
+ | `focus` | `FocusEvent` | Emitted on focus. |
34
+ | `validate` | — | Emitted when the `validateOn` trigger occurs. |
35
+
36
+ ## Slots
37
+
38
+ None.
39
+
40
+ ## Usage
41
+
42
+ ### Recommended: inside a VibeFormGroup
6
43
 
7
44
  ```vue
8
45
  <script setup lang="ts">
9
46
  import { ref } from 'vue'
10
- const date = ref('')
47
+ const startDate = ref('')
11
48
  </script>
12
49
 
13
50
  <template>
14
- <VibeFormDatepicker
15
- v-model="date"
16
- label="Choose a date"
17
- />
51
+ <VibeFormGroup label="Start Date">
52
+ <VibeFormDatepicker v-model="startDate" type="date" min="2026-01-01" />
53
+ </VibeFormGroup>
18
54
  </template>
19
55
  ```
20
56
 
21
- ## Props
57
+ ### Standalone
22
58
 
23
- | Prop | Type | Default | Description |
24
- |------|------|---------|-------------|
25
- | `modelValue` | `String` | `''` | The date string (v-model) |
26
- | `id` | `String` | `Auto-generated` | Unique identifier |
27
- | `label` | `String` | `undefined` | Label text |
28
- | `disabled` | `Boolean` | `false` | Disable the picker |
29
- | `readonly` | `Boolean` | `false` | Make readonly |
30
- | `required` | `Boolean` | `false` | Mark as required |
31
- | `min` | `String` | `undefined` | Minimum date |
32
- | `max` | `String` | `undefined` | Maximum date |
33
- | `size` | `'sm' \| 'lg'` | `undefined` | Picker size |
34
- | `type` | `String` | `'date'` | Type: `'date'`, `'time'`, `'datetime-local'`, etc. |
35
- | `validationState` | `'valid' \| 'invalid' \| null` | `null` | Validation state |
36
- | `validationMessage` | `String` | `undefined` | Validation message |
37
- | `validateOn` | `'input' \| 'blur' \| 'change'` | `'blur'` | When to validate |
38
- | `helpText` | `String` | `undefined` | Help text |
59
+ ```vue
60
+ <script setup lang="ts">
61
+ import { ref } from 'vue'
62
+ const meetingTime = ref('')
63
+ </script>
39
64
 
40
- ## Important Notes
65
+ <template>
66
+ <VibeFormDatepicker v-model="meetingTime" label="Meeting Time" type="datetime-local" />
67
+ </template>
68
+ ```
41
69
 
42
- **Automatic ID Generation:** This component automatically generates a unique ID if one is not provided.
70
+ ## Important Notes
43
71
 
44
- **Automatic ID Injection:** When used inside a `VibeFormGroup`, this component will automatically inherit the group's ID to ensure proper label association and accessibility.
72
+ - **String model only:** `modelValue` must be a string. When using a validation composable, bind to `.value` (e.g. `v-model="field.value"`), not the field object a dev-mode warning is logged otherwise.
73
+ - **Native pickers:** rendering and locale formatting come from the browser's native input, so the on-screen appearance varies by platform.
74
+ - **Group linking:** wrapped in a `VibeFormGroup`, the input consumes the group id so the label and feedback link automatically.
45
75
 
46
76
  ## Bootstrap CSS Classes
47
77
 
48
78
  - `.form-control`
49
- - `.form-control-{size}`
79
+ - `.form-control-{sm|lg}`
50
80
  - `.is-valid`, `.is-invalid`
@@ -1,10 +1,39 @@
1
1
  # VibeFormGroup
2
2
 
3
- Form group container component for organizing form fields with labels, help text, and validation feedback.
3
+ Wrapper that owns a form control's label, help text, validation feedback, and id. It is the recommended way to make any VibeUI form control accessible.
4
4
 
5
- ## Basic Usage
5
+ ## How it works
6
6
 
7
- VibeFormGroup automatically links its label to the child VibeUI form component using automatic ID injection.
7
+ `VibeFormGroup` generates a single id and provides it (plus its label/help/validation flags) to descendant controls. The **first** child control consumes the group id and renders against it; the group renders the `<label>` (linked via `for`), `help-text`, and validation feedback so the child does not duplicate them. This auto-wires `for`/`id` and `aria-describedby` with no manual ids.
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ |------|------|---------|-------------|
13
+ | `label` | `string` | `undefined` | Label text rendered for the first child control. |
14
+ | `labelFor` | `string` | `undefined` | Explicit id to use instead of the auto-generated one. |
15
+ | `required` | `boolean` | `false` | Append a `*` to the label. |
16
+ | `validationState` | `'valid' \| 'invalid' \| null` | `null` | Render valid/invalid feedback. |
17
+ | `validationMessage` | `string` | `undefined` | Feedback message text. |
18
+ | `helpText` | `string` | `undefined` | Help text rendered below the control. |
19
+ | `floating` | `boolean` | `false` | Use Bootstrap floating-label layout (`.form-floating`). |
20
+ | `row` | `boolean` | `false` | Use a horizontal (grid row) layout. |
21
+ | `labelCols` | `number \| string` | `undefined` | Label column width (`col-sm-{n}`) in row layout. |
22
+ | `labelAlign` | `'start' \| 'center' \| 'end'` | `undefined` | Label text alignment in row layout. |
23
+
24
+ ## Events
25
+
26
+ None.
27
+
28
+ ## Slots
29
+
30
+ | Slot | Description |
31
+ |------|-------------|
32
+ | default | The form control(s) to wrap. |
33
+
34
+ ## Usage
35
+
36
+ ### Basic
8
37
 
9
38
  ```vue
10
39
  <script setup lang="ts">
@@ -13,68 +42,74 @@ const email = ref('')
13
42
  </script>
14
43
 
15
44
  <template>
16
- <VibeFormGroup
17
- label="Email Address"
18
- help-text="We'll never share your email with anyone else."
19
- >
20
- <VibeFormInput
21
- v-model="email"
22
- type="email"
23
- placeholder="Enter email"
24
- />
45
+ <VibeFormGroup label="Email" help-text="We'll never share it.">
46
+ <VibeFormInput v-model="email" type="email" />
25
47
  </VibeFormGroup>
26
48
  </template>
27
49
  ```
28
50
 
29
- ## Floating Labels
51
+ ### With validation
30
52
 
31
53
  ```vue
54
+ <script setup lang="ts">
55
+ import { useFormValidation, validators } from '@velkymx/vibeui'
56
+
57
+ const name = useFormValidation('')
58
+ const validateName = () => name.validate([validators.required()])
59
+ </script>
60
+
32
61
  <template>
33
62
  <VibeFormGroup
34
- label="Email Address"
35
- floating
63
+ label="Name"
64
+ required
65
+ :validation-state="name.validationState"
66
+ :validation-message="name.validationMessage"
36
67
  >
37
- <VibeFormInput
38
- v-model="email"
39
- type="email"
40
- placeholder="name@example.com"
41
- />
68
+ <VibeFormInput v-model="name.value" @validate="validateName" />
69
+ </VibeFormGroup>
70
+ </template>
71
+ ```
72
+
73
+ ### Horizontal (row) layout
74
+
75
+ ```vue
76
+ <script setup lang="ts">
77
+ import { ref } from 'vue'
78
+ const username = ref('')
79
+ </script>
80
+
81
+ <template>
82
+ <VibeFormGroup label="Username" row :label-cols="3" label-align="end">
83
+ <VibeFormInput v-model="username" />
42
84
  </VibeFormGroup>
43
85
  </template>
44
86
  ```
45
87
 
46
- ## Horizontal Layout
88
+ ### Floating label
47
89
 
48
90
  ```vue
91
+ <script setup lang="ts">
92
+ import { ref } from 'vue'
93
+ const city = ref('')
94
+ </script>
95
+
49
96
  <template>
50
- <VibeFormGroup
51
- label="Email"
52
- row
53
- :label-cols="3"
54
- label-align="end"
55
- >
56
- <VibeFormInput v-model="email" type="email" />
97
+ <VibeFormGroup label="City" floating>
98
+ <VibeFormInput v-model="city" placeholder="City" />
57
99
  </VibeFormGroup>
58
100
  </template>
59
101
  ```
60
102
 
61
103
  ## Important Notes
62
104
 
63
- **Automatic ID Injection:** VibeFormGroup uses Vue's provide/inject to share a unique ID with its child VibeUI components (like `VibeFormInput`, `VibeFormSelect`, etc.). This ensures that labels and ARIA attributes are correctly linked without requiring manual `id` or `label-for` props.
64
-
65
- **Manual Linking:** If you are using native HTML elements instead of VibeUI components inside the group, you must still provide a `label-for` on the group and a matching `id` on your element.
105
+ - **Single-consumer rule:** only the first child control consumes the group id. With multiple controls (e.g. a checkbox or radio group), subsequent controls generate their own ids the group's label still describes the set.
106
+ - **Don't double up:** when the group provides `label`, `helpText`, or validation, omit those same props on the child control; the child suppresses its own copies to avoid duplicates.
107
+ - **Floating labels** require the label to render after the control, which the group handles automatically; pair it with a `placeholder` on the input.
66
108
 
67
- ## Props
109
+ ## Bootstrap CSS Classes
68
110
 
69
- | Prop | Type | Default | Description |
70
- |------|------|---------|-------------|
71
- | `label` | `String` | `undefined` | Label text |
72
- | `labelFor` | `String` | `Auto-generated` | ID of the form control |
73
- | `required` | `Boolean` | `false` | Show required asterisk |
74
- | `validationState` | `'valid' \| 'invalid' \| null` | `null` | Validation state |
75
- | `validationMessage` | `String` | `undefined` | Validation message |
76
- | `helpText` | `String` | `undefined` | Help text |
77
- | `floating` | `Boolean` | `false` | Use floating label layout |
78
- | `row` | `Boolean` | `false` | Use horizontal row layout |
79
- | `labelCols` | `Number \| String` | `undefined` | Number of columns for label (1-12) |
80
- | `labelAlign` | `'start' \| 'center' \| 'end'` | `undefined` | Label text alignment |
111
+ - `.mb-3`, `.row`
112
+ - `.form-floating`
113
+ - `.form-label`, `.col-form-label`, `.col-sm-{n}`, `.text-{start|center|end}`
114
+ - `.form-text`
115
+ - `.valid-feedback`, `.invalid-feedback`