@velkymx/vibeui 0.8.0 → 0.8.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.
- package/CLAUDE.md +48 -0
- package/dist/vibeui.css +1 -1
- package/dist/vibeui.es.js +149 -148
- package/dist/vibeui.umd.js +1 -1
- package/docs/README.md +153 -0
- package/docs/components/advanced/popover.md +150 -0
- package/docs/components/advanced/scrollspy.md +64 -0
- package/docs/components/advanced/tooltip.md +111 -0
- package/docs/components/card/card.md +215 -0
- package/docs/components/core/alert.md +72 -0
- package/docs/components/core/badge.md +81 -0
- package/docs/components/core/button-group.md +105 -0
- package/docs/components/core/button.md +127 -0
- package/docs/components/core/close-button.md +82 -0
- package/docs/components/core/link.md +36 -0
- package/docs/components/core/placeholder.md +135 -0
- package/docs/components/core/spinner.md +109 -0
- package/docs/components/data/datatable.md +416 -0
- package/docs/components/interactive/accordion.md +92 -0
- package/docs/components/interactive/carousel.md +97 -0
- package/docs/components/interactive/collapse.md +105 -0
- package/docs/components/interactive/dropdown.md +93 -0
- package/docs/components/interactive/modal.md +148 -0
- package/docs/components/interactive/offcanvas.md +89 -0
- package/docs/components/interactive/toast.md +114 -0
- package/docs/components/layout/col.md +123 -0
- package/docs/components/layout/container.md +59 -0
- package/docs/components/layout/row.md +113 -0
- package/docs/components/list/list-group.md +221 -0
- package/docs/components/navigation/breadcrumb.md +116 -0
- package/docs/components/navigation/nav.md +88 -0
- package/docs/components/navigation/navbar.md +106 -0
- package/docs/components/navigation/pagination.md +146 -0
- package/docs/components/progress/progress.md +182 -0
- package/docs/composables/back-button.md +28 -0
- package/docs/composables/breakpoints.md +54 -0
- package/docs/composables/color-mode.md +141 -0
- package/docs/forms/README.md +88 -0
- package/docs/forms/form-checkbox.md +50 -0
- package/docs/forms/form-datepicker.md +50 -0
- package/docs/forms/form-group.md +80 -0
- package/docs/forms/form-input.md +55 -0
- package/docs/forms/form-radio.md +58 -0
- package/docs/forms/form-select.md +54 -0
- package/docs/forms/form-spinbutton.md +55 -0
- package/docs/forms/form-switch.md +47 -0
- package/docs/forms/form-textarea.md +51 -0
- package/docs/forms/form-wysiwyg.md +64 -0
- package/docs/forms/input-group.md +51 -0
- package/docs/forms/validation.md +599 -0
- package/llms.txt +422 -0
- package/package.json +5 -2
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# VibeSpinner
|
|
2
|
+
|
|
3
|
+
Loading spinner with border or grow animation styles.
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
|
|
7
|
+
| Prop | Type | Default | Description |
|
|
8
|
+
|------|------|---------|-------------|
|
|
9
|
+
| `variant` | `Variant` | `undefined` | Text color variant |
|
|
10
|
+
| `type` | `SpinnerType` | `'border'` | Spinner type: `'border'` or `'grow'` |
|
|
11
|
+
| `size` | `Size` | `undefined` | Spinner size: `'sm'` or `'lg'` |
|
|
12
|
+
| `label` | `String` | `'Loading...'` | Screen reader text |
|
|
13
|
+
| `tag` | `String` | `'div'` | HTML tag to render |
|
|
14
|
+
|
|
15
|
+
## Events
|
|
16
|
+
|
|
17
|
+
| Event | Payload | Description |
|
|
18
|
+
|-------|---------|-------------|
|
|
19
|
+
| `component-error` | `Object` | Emitted when an error occurs |
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Basic Spinner
|
|
24
|
+
|
|
25
|
+
```vue
|
|
26
|
+
<template>
|
|
27
|
+
<VibeSpinner />
|
|
28
|
+
</template>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Grow Spinner
|
|
32
|
+
|
|
33
|
+
```vue
|
|
34
|
+
<template>
|
|
35
|
+
<VibeSpinner type="grow" />
|
|
36
|
+
</template>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Colored Spinners
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<template>
|
|
43
|
+
<div>
|
|
44
|
+
<VibeSpinner variant="primary" />
|
|
45
|
+
<VibeSpinner variant="success" />
|
|
46
|
+
<VibeSpinner variant="danger" />
|
|
47
|
+
<VibeSpinner variant="warning" />
|
|
48
|
+
<VibeSpinner variant="info" />
|
|
49
|
+
</div>
|
|
50
|
+
</template>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Small Spinners
|
|
54
|
+
|
|
55
|
+
```vue
|
|
56
|
+
<template>
|
|
57
|
+
<div>
|
|
58
|
+
<VibeSpinner size="sm" />
|
|
59
|
+
<VibeSpinner type="grow" size="sm" />
|
|
60
|
+
</div>
|
|
61
|
+
</template>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### In Button
|
|
65
|
+
|
|
66
|
+
```vue
|
|
67
|
+
<template>
|
|
68
|
+
<VibeButton variant="primary" disabled>
|
|
69
|
+
<VibeSpinner size="sm" tag="span" />
|
|
70
|
+
Loading...
|
|
71
|
+
</VibeButton>
|
|
72
|
+
</template>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Custom Label
|
|
76
|
+
|
|
77
|
+
```vue
|
|
78
|
+
<template>
|
|
79
|
+
<VibeSpinner label="Please wait while we load your data..." />
|
|
80
|
+
</template>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Loading State Example
|
|
84
|
+
|
|
85
|
+
```vue
|
|
86
|
+
<script setup>
|
|
87
|
+
import { ref } from 'vue'
|
|
88
|
+
|
|
89
|
+
const loading = ref(true)
|
|
90
|
+
|
|
91
|
+
setTimeout(() => {
|
|
92
|
+
loading.value = false
|
|
93
|
+
}, 3000)
|
|
94
|
+
</script>
|
|
95
|
+
|
|
96
|
+
<template>
|
|
97
|
+
<div>
|
|
98
|
+
<VibeSpinner v-if="loading" variant="primary" />
|
|
99
|
+
<div v-else>Content loaded!</div>
|
|
100
|
+
</div>
|
|
101
|
+
</template>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Bootstrap CSS Classes
|
|
105
|
+
|
|
106
|
+
- `.spinner-border` or `.spinner-grow`
|
|
107
|
+
- `.text-{variant}`
|
|
108
|
+
- `.spinner-{type}-{size}`
|
|
109
|
+
- `.visually-hidden` (for label)
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
# VibeDataTable
|
|
2
|
+
|
|
3
|
+
Powerful data table component with search, sorting, and pagination - similar to DataTables.net but built for Vue 3 and Bootstrap 5.3.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Search/Filter** - Real-time search across all searchable columns
|
|
8
|
+
- **Column Sorting** - Click column headers to sort (asc/desc)
|
|
9
|
+
- **Pagination** - Built-in pagination with customizable page sizes
|
|
10
|
+
- **Responsive** - Mobile-friendly with responsive table wrapper
|
|
11
|
+
- **Bootstrap Styling** - All Bootstrap table variants (striped, bordered, hover, etc.)
|
|
12
|
+
- **Custom Cell Rendering** - Slots for custom cell content
|
|
13
|
+
- **Formatters** - Custom data formatters per column
|
|
14
|
+
- **TypeScript** - Fully typed with comprehensive interfaces
|
|
15
|
+
|
|
16
|
+
## Props
|
|
17
|
+
|
|
18
|
+
### Data Props
|
|
19
|
+
|
|
20
|
+
| Prop | Type | Default | Description |
|
|
21
|
+
|------|------|---------|-------------|
|
|
22
|
+
| `items` | `Array<any>` | `[]` | Array of data objects to display |
|
|
23
|
+
| `columns` | `DataTableColumn[]` | Required | Column definitions |
|
|
24
|
+
|
|
25
|
+
### Table Styling Props
|
|
26
|
+
|
|
27
|
+
| Prop | Type | Default | Description |
|
|
28
|
+
|------|------|---------|-------------|
|
|
29
|
+
| `striped` | `Boolean` | `false` | Striped table rows |
|
|
30
|
+
| `bordered` | `Boolean` | `false` | Bordered table |
|
|
31
|
+
| `borderless` | `Boolean` | `false` | Remove all borders |
|
|
32
|
+
| `hover` | `Boolean` | `false` | Hover effect on rows |
|
|
33
|
+
| `small` | `Boolean` | `false` | Compact table |
|
|
34
|
+
| `responsive` | `Boolean` | `true` | Responsive table wrapper |
|
|
35
|
+
| `stack` | `Boolean` | `false` | Transforms table into cards on mobile screens |
|
|
36
|
+
| `variant` | `String` | `undefined` | Table color variant |
|
|
37
|
+
|
|
38
|
+
### Feature Props
|
|
39
|
+
|
|
40
|
+
| Prop | Type | Default | Description |
|
|
41
|
+
|------|------|---------|-------------|
|
|
42
|
+
| `searchable` | `Boolean` | `true` | Enable search functionality |
|
|
43
|
+
| `sortable` | `Boolean` | `true` | Enable column sorting |
|
|
44
|
+
| `paginated` | `Boolean` | `true` | Enable pagination |
|
|
45
|
+
|
|
46
|
+
### Search Props
|
|
47
|
+
|
|
48
|
+
| Prop | Type | Default | Description |
|
|
49
|
+
|------|------|---------|-------------|
|
|
50
|
+
| `searchPlaceholder` | `String` | `'Search...'` | Search input placeholder |
|
|
51
|
+
| `searchDebounce` | `Number` | `300` | Search debounce delay (ms) |
|
|
52
|
+
|
|
53
|
+
### Pagination Props
|
|
54
|
+
|
|
55
|
+
| Prop | Type | Default | Description |
|
|
56
|
+
|------|------|---------|-------------|
|
|
57
|
+
| `perPage` | `Number` | `10` | Items per page |
|
|
58
|
+
| `currentPage` | `Number` | `1` | Current page number |
|
|
59
|
+
| `perPageOptions` | `Number[]` | `[5, 10, 25, 50, 100]` | Page size options |
|
|
60
|
+
|
|
61
|
+
### Sorting Props
|
|
62
|
+
|
|
63
|
+
| Prop | Type | Default | Description |
|
|
64
|
+
|------|------|---------|-------------|
|
|
65
|
+
| `sortBy` | `String` | `undefined` | Initial sort column key |
|
|
66
|
+
| `sortDesc` | `Boolean` | `false` | Initial sort direction (true = descending) |
|
|
67
|
+
|
|
68
|
+
### Display Props
|
|
69
|
+
|
|
70
|
+
| Prop | Type | Default | Description |
|
|
71
|
+
|------|------|---------|-------------|
|
|
72
|
+
| `showEmpty` | `Boolean` | `true` | Show message when no data |
|
|
73
|
+
| `emptyText` | `String` | `'No data available'` | Empty state message |
|
|
74
|
+
| `showPerPage` | `Boolean` | `true` | Show per-page selector |
|
|
75
|
+
| `showInfo` | `Boolean` | `true` | Show info text (X to Y of Z entries) |
|
|
76
|
+
| `infoText` | `String` | `'Showing {start} to {end} of {total} entries'` | Info text template |
|
|
77
|
+
| `filteredInfoText` | `String` | `'Showing {start} to {end} of {total} entries (filtered from {totalRows} total entries)'` | Filtered info text template |
|
|
78
|
+
|
|
79
|
+
## Column Definition
|
|
80
|
+
|
|
81
|
+
The `columns` prop accepts an array of `DataTableColumn` objects:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
interface DataTableColumn {
|
|
85
|
+
key: string // Property key in data object
|
|
86
|
+
label: string // Column header label
|
|
87
|
+
sortable?: boolean // Enable/disable sorting (default: true)
|
|
88
|
+
searchable?: boolean // Include in search (default: true)
|
|
89
|
+
formatter?: (value: any, row: any) => string | number // Custom formatter
|
|
90
|
+
class?: string // CSS class for td
|
|
91
|
+
headerClass?: string // CSS class for th
|
|
92
|
+
thStyle?: Record<string, string> // Inline styles for th
|
|
93
|
+
tdStyle?: Record<string, string> // Inline styles for td
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Events
|
|
98
|
+
|
|
99
|
+
| Event | Payload | Description |
|
|
100
|
+
|-------|---------|-------------|
|
|
101
|
+
| `update:currentPage` | `Number` | Emitted when page changes |
|
|
102
|
+
| `update:perPage` | `Number` | Emitted when per-page changes |
|
|
103
|
+
| `update:sortBy` | `String` | Emitted when sort column changes |
|
|
104
|
+
| `update:sortDesc` | `Boolean` | Emitted when sort direction changes |
|
|
105
|
+
| `row-clicked` | `(item, index)` | Emitted when row is clicked |
|
|
106
|
+
|
|
107
|
+
## Slots
|
|
108
|
+
|
|
109
|
+
| Slot | Props | Description |
|
|
110
|
+
|------|-------|-------------|
|
|
111
|
+
| `cell({columnKey})` | `{ item, value, index }` | Custom cell rendering for specific column |
|
|
112
|
+
|
|
113
|
+
## Usage
|
|
114
|
+
|
|
115
|
+
### Basic DataTable
|
|
116
|
+
|
|
117
|
+
```vue
|
|
118
|
+
<script setup>
|
|
119
|
+
import { ref } from 'vue'
|
|
120
|
+
|
|
121
|
+
const columns = [
|
|
122
|
+
{ key: 'id', label: 'ID' },
|
|
123
|
+
{ key: 'name', label: 'Name' },
|
|
124
|
+
{ key: 'email', label: 'Email' },
|
|
125
|
+
{ key: 'status', label: 'Status' }
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
const items = [
|
|
129
|
+
{ id: 1, name: 'John Doe', email: 'john@example.com', status: 'Active' },
|
|
130
|
+
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', status: 'Inactive' },
|
|
131
|
+
{ id: 3, name: 'Bob Johnson', email: 'bob@example.com', status: 'Active' }
|
|
132
|
+
]
|
|
133
|
+
</script>
|
|
134
|
+
|
|
135
|
+
<template>
|
|
136
|
+
<VibeDataTable :columns="columns" :items="items" />
|
|
137
|
+
</template>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### With Bootstrap Styling
|
|
141
|
+
|
|
142
|
+
```vue
|
|
143
|
+
<template>
|
|
144
|
+
<VibeDataTable
|
|
145
|
+
:columns="columns"
|
|
146
|
+
:items="items"
|
|
147
|
+
striped
|
|
148
|
+
hover
|
|
149
|
+
bordered
|
|
150
|
+
/>
|
|
151
|
+
</template>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Custom Column Configuration
|
|
155
|
+
|
|
156
|
+
```vue
|
|
157
|
+
<script setup>
|
|
158
|
+
const columns = [
|
|
159
|
+
{
|
|
160
|
+
key: 'id',
|
|
161
|
+
label: 'ID',
|
|
162
|
+
sortable: true,
|
|
163
|
+
searchable: false,
|
|
164
|
+
headerClass: 'bg-primary text-white'
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
key: 'name',
|
|
168
|
+
label: 'Full Name',
|
|
169
|
+
sortable: true
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
key: 'salary',
|
|
173
|
+
label: 'Salary',
|
|
174
|
+
formatter: (value) => `$${value.toLocaleString()}`,
|
|
175
|
+
tdStyle: { textAlign: 'right' }
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
key: 'status',
|
|
179
|
+
label: 'Status',
|
|
180
|
+
class: 'text-center'
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
</script>
|
|
184
|
+
|
|
185
|
+
<template>
|
|
186
|
+
<VibeDataTable :columns="columns" :items="items" />
|
|
187
|
+
</template>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### With Custom Cell Rendering
|
|
191
|
+
|
|
192
|
+
```vue
|
|
193
|
+
<script setup>
|
|
194
|
+
const columns = [
|
|
195
|
+
{ key: 'name', label: 'Name' },
|
|
196
|
+
{ key: 'email', label: 'Email' },
|
|
197
|
+
{ key: 'status', label: 'Status' },
|
|
198
|
+
{ key: 'actions', label: 'Actions', sortable: false }
|
|
199
|
+
]
|
|
200
|
+
</script>
|
|
201
|
+
|
|
202
|
+
<template>
|
|
203
|
+
<VibeDataTable :columns="columns" :items="items">
|
|
204
|
+
<!-- Custom status column -->
|
|
205
|
+
<template #cell(status)="{ value }">
|
|
206
|
+
<VibeBadge :variant="value === 'Active' ? 'success' : 'danger'">
|
|
207
|
+
{{ value }}
|
|
208
|
+
</VibeBadge>
|
|
209
|
+
</template>
|
|
210
|
+
|
|
211
|
+
<!-- Custom actions column -->
|
|
212
|
+
<template #cell(actions)="{ item }">
|
|
213
|
+
<VibeButton size="sm" variant="primary" @click="editItem(item)">
|
|
214
|
+
Edit
|
|
215
|
+
</VibeButton>
|
|
216
|
+
<VibeButton size="sm" variant="danger" @click="deleteItem(item)">
|
|
217
|
+
Delete
|
|
218
|
+
</VibeButton>
|
|
219
|
+
</template>
|
|
220
|
+
</VibeDataTable>
|
|
221
|
+
</template>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Controlled State (v-model)
|
|
225
|
+
|
|
226
|
+
```vue
|
|
227
|
+
<script setup>
|
|
228
|
+
import { ref } from 'vue'
|
|
229
|
+
|
|
230
|
+
const currentPage = ref(1)
|
|
231
|
+
const perPage = ref(25)
|
|
232
|
+
const sortBy = ref('name')
|
|
233
|
+
const sortDesc = ref(false)
|
|
234
|
+
|
|
235
|
+
const handleRowClick = (item, index) => {
|
|
236
|
+
console.log('Clicked row:', item, index)
|
|
237
|
+
}
|
|
238
|
+
</script>
|
|
239
|
+
|
|
240
|
+
<template>
|
|
241
|
+
<VibeDataTable
|
|
242
|
+
:columns="columns"
|
|
243
|
+
:items="items"
|
|
244
|
+
v-model:current-page="currentPage"
|
|
245
|
+
v-model:per-page="perPage"
|
|
246
|
+
v-model:sort-by="sortBy"
|
|
247
|
+
v-model:sort-desc="sortDesc"
|
|
248
|
+
@row-clicked="handleRowClick"
|
|
249
|
+
/>
|
|
250
|
+
</template>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Disable Features
|
|
254
|
+
|
|
255
|
+
```vue
|
|
256
|
+
<template>
|
|
257
|
+
<!-- No search, no pagination -->
|
|
258
|
+
<VibeDataTable
|
|
259
|
+
:columns="columns"
|
|
260
|
+
:items="items"
|
|
261
|
+
:searchable="false"
|
|
262
|
+
:paginated="false"
|
|
263
|
+
/>
|
|
264
|
+
|
|
265
|
+
<!-- No sorting -->
|
|
266
|
+
<VibeDataTable
|
|
267
|
+
:columns="columns"
|
|
268
|
+
:items="items"
|
|
269
|
+
:sortable="false"
|
|
270
|
+
/>
|
|
271
|
+
</template>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Custom Page Sizes
|
|
275
|
+
|
|
276
|
+
```vue
|
|
277
|
+
<template>
|
|
278
|
+
<VibeDataTable
|
|
279
|
+
:columns="columns"
|
|
280
|
+
:items="items"
|
|
281
|
+
:per-page="20"
|
|
282
|
+
:per-page-options="[10, 20, 50, 100, 500]"
|
|
283
|
+
/>
|
|
284
|
+
</template>
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Large Dataset Example
|
|
288
|
+
|
|
289
|
+
```vue
|
|
290
|
+
<script setup>
|
|
291
|
+
import { ref } from 'vue'
|
|
292
|
+
|
|
293
|
+
// Generate large dataset
|
|
294
|
+
const items = ref(
|
|
295
|
+
Array.from({ length: 1000 }, (_, i) => ({
|
|
296
|
+
id: i + 1,
|
|
297
|
+
name: `User ${i + 1}`,
|
|
298
|
+
email: `user${i + 1}@example.com`,
|
|
299
|
+
department: ['Sales', 'Marketing', 'Engineering', 'HR'][i % 4],
|
|
300
|
+
salary: Math.floor(Math.random() * 100000) + 50000,
|
|
301
|
+
joinDate: new Date(2020 + Math.floor(Math.random() * 5), Math.floor(Math.random() * 12), 1)
|
|
302
|
+
.toISOString()
|
|
303
|
+
.split('T')[0]
|
|
304
|
+
}))
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
const columns = [
|
|
308
|
+
{ key: 'id', label: 'ID', sortable: true },
|
|
309
|
+
{ key: 'name', label: 'Name', sortable: true },
|
|
310
|
+
{ key: 'email', label: 'Email', sortable: true },
|
|
311
|
+
{ key: 'department', label: 'Department', sortable: true },
|
|
312
|
+
{
|
|
313
|
+
key: 'salary',
|
|
314
|
+
label: 'Salary',
|
|
315
|
+
sortable: true,
|
|
316
|
+
formatter: (value) => `$${value.toLocaleString()}`
|
|
317
|
+
},
|
|
318
|
+
{ key: 'joinDate', label: 'Join Date', sortable: true }
|
|
319
|
+
]
|
|
320
|
+
</script>
|
|
321
|
+
|
|
322
|
+
<template>
|
|
323
|
+
<VibeDataTable
|
|
324
|
+
:columns="columns"
|
|
325
|
+
:items="items"
|
|
326
|
+
:per-page="25"
|
|
327
|
+
striped
|
|
328
|
+
hover
|
|
329
|
+
small
|
|
330
|
+
/>
|
|
331
|
+
</template>
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### With Custom Empty State
|
|
335
|
+
|
|
336
|
+
```vue
|
|
337
|
+
<template>
|
|
338
|
+
<VibeDataTable
|
|
339
|
+
:columns="columns"
|
|
340
|
+
:items="[]"
|
|
341
|
+
empty-text="No users found. Try adjusting your search."
|
|
342
|
+
/>
|
|
343
|
+
</template>
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Advanced Features
|
|
347
|
+
|
|
348
|
+
### Formatters
|
|
349
|
+
|
|
350
|
+
Use formatters to transform data before display:
|
|
351
|
+
|
|
352
|
+
```vue
|
|
353
|
+
<script setup>
|
|
354
|
+
const columns = [
|
|
355
|
+
{
|
|
356
|
+
key: 'price',
|
|
357
|
+
label: 'Price',
|
|
358
|
+
formatter: (value) => `$${value.toFixed(2)}`
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
key: 'date',
|
|
362
|
+
label: 'Date',
|
|
363
|
+
formatter: (value) => new Date(value).toLocaleDateString()
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
key: 'percentage',
|
|
367
|
+
label: 'Complete',
|
|
368
|
+
formatter: (value) => `${value}%`
|
|
369
|
+
}
|
|
370
|
+
]
|
|
371
|
+
</script>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Accessing Full Row in Formatter
|
|
375
|
+
|
|
376
|
+
```vue
|
|
377
|
+
<script setup>
|
|
378
|
+
const columns = [
|
|
379
|
+
{
|
|
380
|
+
key: 'fullName',
|
|
381
|
+
label: 'Full Name',
|
|
382
|
+
formatter: (value, row) => `${row.firstName} ${row.lastName}`
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
key: 'discount',
|
|
386
|
+
label: 'Discount',
|
|
387
|
+
formatter: (value, row) => {
|
|
388
|
+
return row.isPremium ? `${value}% (Premium)` : `${value}%`
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
]
|
|
392
|
+
</script>
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Bootstrap CSS Classes
|
|
396
|
+
|
|
397
|
+
- `.table` - Base table
|
|
398
|
+
- `.table-striped` - Striped rows
|
|
399
|
+
- `.table-bordered` - Bordered table
|
|
400
|
+
- `.table-borderless` - Borderless table
|
|
401
|
+
- `.table-hover` - Hover effect
|
|
402
|
+
- `.table-sm` - Compact table
|
|
403
|
+
- `.table-{variant}` - Color variants
|
|
404
|
+
- `.table-responsive` - Responsive wrapper
|
|
405
|
+
- `.vibe-table-stack` - Mobile card view transformation
|
|
406
|
+
- `.pagination` - Pagination controls
|
|
407
|
+
- `.form-control` - Search input
|
|
408
|
+
- `.form-select` - Per-page selector
|
|
409
|
+
|
|
410
|
+
## Tips
|
|
411
|
+
|
|
412
|
+
1. **Large Datasets**: For datasets with 1000+ rows, consider server-side pagination
|
|
413
|
+
2. **Performance**: Use `:key` on items for better Vue reactivity
|
|
414
|
+
3. **Search Debounce**: Adjust `searchDebounce` prop for performance with large datasets
|
|
415
|
+
4. **Custom Styling**: Use column `class`, `headerClass`, `thStyle`, `tdStyle` for styling
|
|
416
|
+
5. **Slots**: Use slots for complex cell rendering (badges, buttons, images, etc.)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# VibeAccordion
|
|
2
|
+
|
|
3
|
+
Collapsible accordion component for organizing content in a data-driven way.
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
|
|
7
|
+
| Prop | Type | Default | Description |
|
|
8
|
+
|------|------|---------|-------------|
|
|
9
|
+
| `id` | `String` | `Auto-generated` | Unique identifier for the accordion |
|
|
10
|
+
| `flush` | `Boolean` | `false` | Remove borders and rounded corners |
|
|
11
|
+
| `items` | `AccordionItem[]` | Required | Array of accordion items |
|
|
12
|
+
| `alwaysOpen` | `Boolean` | `false` | Don't collapse other items when one is opened |
|
|
13
|
+
|
|
14
|
+
### AccordionItem Interface
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
interface AccordionItem {
|
|
18
|
+
id: string
|
|
19
|
+
title: string
|
|
20
|
+
content: string
|
|
21
|
+
show?: boolean
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Events
|
|
26
|
+
|
|
27
|
+
| Event | Payload | Description |
|
|
28
|
+
|-------|---------|-------------|
|
|
29
|
+
| `item-click` | `{ item, index }` | Emitted when an accordion item is clicked |
|
|
30
|
+
| `show` | `id` | Emitted when an item starts showing |
|
|
31
|
+
| `shown` | `id` | Emitted when an item is fully shown |
|
|
32
|
+
| `hide` | `id` | Emitted when an item starts hiding |
|
|
33
|
+
| `hidden` | `id` | Emitted when an item is fully hidden |
|
|
34
|
+
|
|
35
|
+
## Slots
|
|
36
|
+
|
|
37
|
+
| Slot | Scope | Description |
|
|
38
|
+
|------|-------|-------------|
|
|
39
|
+
| `title` | `{ item, index }` | Custom title rendering |
|
|
40
|
+
| `content` | `{ item, index }` | Custom content rendering |
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### Basic Example
|
|
45
|
+
|
|
46
|
+
```vue
|
|
47
|
+
<template>
|
|
48
|
+
<VibeAccordion :items="accordionItems" />
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<script setup>
|
|
52
|
+
const accordionItems = [
|
|
53
|
+
{
|
|
54
|
+
id: 'collapseOne',
|
|
55
|
+
title: 'Accordion Item #1',
|
|
56
|
+
content: 'This is the first item\'s content.',
|
|
57
|
+
show: true
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 'collapseTwo',
|
|
61
|
+
title: 'Accordion Item #2',
|
|
62
|
+
content: 'This is the second item\'s content.'
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
</script>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Always Open
|
|
69
|
+
|
|
70
|
+
Items stay open when another item is opened:
|
|
71
|
+
|
|
72
|
+
```vue
|
|
73
|
+
<template>
|
|
74
|
+
<VibeAccordion always-open :items="accordionItems" />
|
|
75
|
+
</template>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Important Notes
|
|
79
|
+
|
|
80
|
+
**Automatic Initialization:** This component automatically initializes Bootstrap's Collapse functionality for each item when it is mounted, provided that Bootstrap's JavaScript is available in your project.
|
|
81
|
+
|
|
82
|
+
**Reactivity:** The `show` property in the `AccordionItem` objects is watched. Changing it in your parent state will trigger the corresponding Bootstrap transition.
|
|
83
|
+
|
|
84
|
+
## Bootstrap CSS Classes
|
|
85
|
+
|
|
86
|
+
- `.accordion`
|
|
87
|
+
- `.accordion-flush`
|
|
88
|
+
- `.accordion-item`
|
|
89
|
+
- `.accordion-header`
|
|
90
|
+
- `.accordion-button`
|
|
91
|
+
- `.accordion-collapse`
|
|
92
|
+
- `.accordion-body`
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# VibeCarousel
|
|
2
|
+
|
|
3
|
+
Data-driven slideshow component for cycling through images or content.
|
|
4
|
+
|
|
5
|
+
## Props
|
|
6
|
+
|
|
7
|
+
| Prop | Type | Default | Description |
|
|
8
|
+
|------|------|---------|-------------|
|
|
9
|
+
| `id` | `String` | `Auto-generated` | Unique identifier |
|
|
10
|
+
| `modelValue` | `Number` | `0` | Active slide index (v-model) |
|
|
11
|
+
| `controls` | `Boolean` | `true` | Show prev/next controls |
|
|
12
|
+
| `indicators` | `Boolean` | `true` | Show slide indicators |
|
|
13
|
+
| `ride` | `Boolean\|String` | `false` | Auto-play: `false`, `true`, or `'carousel'` |
|
|
14
|
+
| `interval` | `Number\|Boolean` | `5000` | Slide interval in ms (`false` to disable) |
|
|
15
|
+
| `keyboard` | `Boolean` | `true` | Keyboard navigation |
|
|
16
|
+
| `pause` | `String\|Boolean` | `'hover'` | Pause on hover (`'hover'` or `false`) |
|
|
17
|
+
| `wrap` | `Boolean` | `true` | Continuous cycling |
|
|
18
|
+
| `touch` | `Boolean` | `true` | Touch swipe support |
|
|
19
|
+
| `dark` | `Boolean` | `false` | Dark variant indicators/controls |
|
|
20
|
+
| `fade` | `Boolean` | `false` | Fade transition instead of slide |
|
|
21
|
+
| `items` | `CarouselItem[]` | Required | Array of carousel items |
|
|
22
|
+
|
|
23
|
+
### CarouselItem Interface
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
interface CarouselItem {
|
|
27
|
+
src: string
|
|
28
|
+
alt?: string
|
|
29
|
+
caption?: string
|
|
30
|
+
captionText?: string
|
|
31
|
+
active?: boolean
|
|
32
|
+
interval?: number
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Events
|
|
37
|
+
|
|
38
|
+
| Event | Payload | Description |
|
|
39
|
+
|-------|---------|-------------|
|
|
40
|
+
| `update:modelValue` | `Number` | Emitted when the active slide changes |
|
|
41
|
+
| `slide` | - | Emitted when slide transition starts |
|
|
42
|
+
| `slid` | - | Emitted when slide transition completes |
|
|
43
|
+
|
|
44
|
+
## Slots
|
|
45
|
+
|
|
46
|
+
| Slot | Scope | Description |
|
|
47
|
+
|------|-------|-------------|
|
|
48
|
+
| `caption` | `{ item, index }` | Custom caption rendering |
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
### Reactive Usage (v-model)
|
|
53
|
+
|
|
54
|
+
```vue
|
|
55
|
+
<template>
|
|
56
|
+
<div>
|
|
57
|
+
<VibeCarousel v-model="currentSlide" :items="carouselItems" />
|
|
58
|
+
|
|
59
|
+
<div class="mt-3">
|
|
60
|
+
<VibeButton @click="currentSlide = 0">Go to Slide 1</VibeButton>
|
|
61
|
+
<VibeButton @click="currentSlide = 1">Go to Slide 2</VibeButton>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</template>
|
|
65
|
+
|
|
66
|
+
<script setup>
|
|
67
|
+
import { ref } from 'vue'
|
|
68
|
+
const currentSlide = ref(0)
|
|
69
|
+
const carouselItems = [...]
|
|
70
|
+
</script>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Basic Carousel
|
|
74
|
+
|
|
75
|
+
```vue
|
|
76
|
+
<template>
|
|
77
|
+
<VibeCarousel :items="carouselItems" />
|
|
78
|
+
</template>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Important Notes
|
|
82
|
+
|
|
83
|
+
**Automatic Initialization:** This component automatically initializes Bootstrap's Carousel functionality when it is mounted, provided that Bootstrap's JavaScript is available in your project.
|
|
84
|
+
|
|
85
|
+
**Instance Exposure:** You can access the underlying Bootstrap instance via template ref using the `bsInstance` property.
|
|
86
|
+
|
|
87
|
+
## Bootstrap CSS Classes
|
|
88
|
+
|
|
89
|
+
- `.carousel`
|
|
90
|
+
- `.carousel-inner`
|
|
91
|
+
- `.carousel-item`
|
|
92
|
+
- `.carousel-control-prev`
|
|
93
|
+
- `.carousel-control-next`
|
|
94
|
+
- `.carousel-indicators`
|
|
95
|
+
- `.carousel-caption`
|
|
96
|
+
- `.carousel-dark`
|
|
97
|
+
- `.carousel-fade`
|