@fastkit/vui 0.19.56 → 0.20.1
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/README.md +932 -1
- package/dist/vui.d.ts +45 -0
- package/package.json +18 -18
package/README.md
CHANGED
|
@@ -1,4 +1,935 @@
|
|
|
1
|
+
|
|
1
2
|
# @fastkit/vui
|
|
2
3
|
|
|
4
|
+
🌐 English | [日本語](https://github.com/dadajam4/fastkit/blob/main/packages/vui/README-ja.md)
|
|
5
|
+
|
|
6
|
+
A simple and extensible UI component library for Vue.js 3 applications. Focused on full TypeScript support, color theme system, accessibility, and tight integration with @fastkit/vue-form-control.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **45+ UI Components**: Comprehensive component set including buttons, forms, navigation, data display
|
|
11
|
+
- **Integrated Ecosystem**: 20+ @fastkit packages with unified API
|
|
12
|
+
- **Full TypeScript Support**: Type-safe props, events, and slot definitions
|
|
13
|
+
- **Composition API Design**: Full adoption of Vue 3 modern patterns
|
|
14
|
+
- **Color Theme System**: Flexible theming with CSS Variables foundation
|
|
15
|
+
- **Form Integration**: Seamless integration with @fastkit/vue-form-control
|
|
16
|
+
- **Accessibility**: WAI-ARIA compliant, keyboard navigation support
|
|
17
|
+
- **Responsive Design**: Mobile-first grid system
|
|
18
|
+
- **Internationalization**: Multi-language font settings, RTL language support
|
|
19
|
+
- **Programmatic UI**: Imperative operations for dialogs, notifications, etc.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @fastkit/vui
|
|
25
|
+
# or
|
|
26
|
+
pnpm add @fastkit/vui
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Basic Usage
|
|
30
|
+
|
|
31
|
+
### Plugin Setup
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { createApp } from 'vue';
|
|
35
|
+
import { VuiPlugin } from '@fastkit/vui';
|
|
36
|
+
import { createRouter } from 'vue-router';
|
|
37
|
+
|
|
38
|
+
const app = createApp(App);
|
|
39
|
+
const router = createRouter(/* routes */);
|
|
40
|
+
|
|
41
|
+
// Install VUI plugin
|
|
42
|
+
app.use(VuiPlugin, {
|
|
43
|
+
router,
|
|
44
|
+
colorScheme: {
|
|
45
|
+
// Color theme settings
|
|
46
|
+
primary: '#1976d2',
|
|
47
|
+
secondary: '#424242'
|
|
48
|
+
},
|
|
49
|
+
uiSettings: {
|
|
50
|
+
primaryScope: 'primary',
|
|
51
|
+
buttonDefault: {
|
|
52
|
+
color: 'primary',
|
|
53
|
+
variant: 'contained'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Application Setup
|
|
60
|
+
|
|
61
|
+
```vue
|
|
62
|
+
<template>
|
|
63
|
+
<VApp>
|
|
64
|
+
<!-- Application content -->
|
|
65
|
+
<router-view />
|
|
66
|
+
</VApp>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<script setup lang="ts">
|
|
70
|
+
import { VApp } from '@fastkit/vui';
|
|
71
|
+
</script>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Component List
|
|
75
|
+
|
|
76
|
+
### Layout & Structure
|
|
77
|
+
|
|
78
|
+
- **VApp** - Application root container
|
|
79
|
+
- **VGrid** (`VGridContainer`, `VGridItem`) - Responsive grid system
|
|
80
|
+
- **VPaper** - Material Design-style paper container
|
|
81
|
+
- **VCard** (`VCardContent`, `VCardActions`) - Card layout
|
|
82
|
+
- **VToolbar** (`VToolbarTitle`, `VToolbarMenu`, `VToolbarEdge`) - Toolbar
|
|
83
|
+
|
|
84
|
+
### Navigation
|
|
85
|
+
|
|
86
|
+
- **VNavigation**, **VNavigationItem** - Side navigation
|
|
87
|
+
- **VBreadcrumbs** - Breadcrumb navigation
|
|
88
|
+
- **VTabs**, **VTab** - Tab interface
|
|
89
|
+
- **VPagination** - Pagination
|
|
90
|
+
|
|
91
|
+
### Form Controls
|
|
92
|
+
|
|
93
|
+
- **VButton**, **VButtonGroup** - Button and button group
|
|
94
|
+
- **VTextField** - Text input field
|
|
95
|
+
- **VTextarea** - Multi-line text input
|
|
96
|
+
- **VNumberField** - Number input field
|
|
97
|
+
- **VSelect** - Select dropdown
|
|
98
|
+
- **VCheckbox**, **VCheckboxGroup** - Checkbox
|
|
99
|
+
- **VRadio**, **VRadioGroup** - Radio button
|
|
100
|
+
- **VSwitch**, **VSwitchGroup** - Switch toggle
|
|
101
|
+
- **VOption**, **VOptionGroup** - Option element
|
|
102
|
+
|
|
103
|
+
### Data Display
|
|
104
|
+
|
|
105
|
+
- **VDataTable** - Data table
|
|
106
|
+
- **VListTile** - List item
|
|
107
|
+
- **VAvatar** - User avatar
|
|
108
|
+
- **VChip** - Chip/tag element
|
|
109
|
+
- **VIcon** - Icon display
|
|
110
|
+
|
|
111
|
+
### Feedback & Interaction
|
|
112
|
+
|
|
113
|
+
- **VDialog** - Modal dialog
|
|
114
|
+
- **VSnackbar** - Notification snackbar
|
|
115
|
+
- **VTooltip** - Tooltip
|
|
116
|
+
- **VMenu** - Context menu
|
|
117
|
+
- **VSheetModal** - Sheet modal
|
|
118
|
+
|
|
119
|
+
### Others
|
|
120
|
+
|
|
121
|
+
- **VSkeltonLoader** - Skeleton loading
|
|
122
|
+
- **VBusyImage** - Lazy loading image
|
|
123
|
+
- **VHero** - Hero section
|
|
124
|
+
- **VContentSwitcher** - Content switcher
|
|
125
|
+
|
|
126
|
+
## Usage Examples
|
|
127
|
+
|
|
128
|
+
### Button Components
|
|
129
|
+
|
|
130
|
+
```vue
|
|
131
|
+
<template>
|
|
132
|
+
<div>
|
|
133
|
+
<!-- Basic button -->
|
|
134
|
+
<VButton @click="handleClick">Click</VButton>
|
|
135
|
+
|
|
136
|
+
<!-- Primary button -->
|
|
137
|
+
<VButton color="primary" variant="contained">
|
|
138
|
+
Save
|
|
139
|
+
</VButton>
|
|
140
|
+
|
|
141
|
+
<!-- Button with icon -->
|
|
142
|
+
<VButton
|
|
143
|
+
startIcon="mdi-search"
|
|
144
|
+
color="primary"
|
|
145
|
+
variant="outlined"
|
|
146
|
+
:loading="searching"
|
|
147
|
+
@click="handleSearch"
|
|
148
|
+
>
|
|
149
|
+
Search
|
|
150
|
+
</VButton>
|
|
151
|
+
|
|
152
|
+
<!-- Button group -->
|
|
153
|
+
<VButtonGroup>
|
|
154
|
+
<VButton>Left</VButton>
|
|
155
|
+
<VButton>Center</VButton>
|
|
156
|
+
<VButton>Right</VButton>
|
|
157
|
+
</VButtonGroup>
|
|
158
|
+
</div>
|
|
159
|
+
</template>
|
|
160
|
+
|
|
161
|
+
<script setup lang="ts">
|
|
162
|
+
import { ref } from 'vue';
|
|
163
|
+
import { VButton, VButtonGroup } from '@fastkit/vui';
|
|
164
|
+
|
|
165
|
+
const searching = ref(false);
|
|
166
|
+
|
|
167
|
+
const handleClick = () => {
|
|
168
|
+
console.log('Button clicked');
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const handleSearch = async () => {
|
|
172
|
+
searching.value = true;
|
|
173
|
+
try {
|
|
174
|
+
// Search processing
|
|
175
|
+
await performSearch();
|
|
176
|
+
} finally {
|
|
177
|
+
searching.value = false;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
</script>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Form Components
|
|
184
|
+
|
|
185
|
+
```vue
|
|
186
|
+
<template>
|
|
187
|
+
<VCard>
|
|
188
|
+
<VCardContent>
|
|
189
|
+
<h2>User Registration</h2>
|
|
190
|
+
|
|
191
|
+
<!-- Text input -->
|
|
192
|
+
<VTextField
|
|
193
|
+
v-model="form.name.value"
|
|
194
|
+
label="Name"
|
|
195
|
+
required
|
|
196
|
+
:rules="[required(), minLength(2)]"
|
|
197
|
+
:invalid="form.name.invalid"
|
|
198
|
+
:error-message="form.name.errorMessage"
|
|
199
|
+
/>
|
|
200
|
+
|
|
201
|
+
<!-- Email input -->
|
|
202
|
+
<VTextField
|
|
203
|
+
v-model="form.email.value"
|
|
204
|
+
label="Email Address"
|
|
205
|
+
type="email"
|
|
206
|
+
required
|
|
207
|
+
:rules="[required(), email()]"
|
|
208
|
+
:invalid="form.email.invalid"
|
|
209
|
+
:error-message="form.email.errorMessage"
|
|
210
|
+
/>
|
|
211
|
+
|
|
212
|
+
<!-- Select -->
|
|
213
|
+
<VSelect
|
|
214
|
+
v-model="form.category.value"
|
|
215
|
+
label="Category"
|
|
216
|
+
:items="categories"
|
|
217
|
+
placeholder="Select category"
|
|
218
|
+
required
|
|
219
|
+
/>
|
|
220
|
+
|
|
221
|
+
<!-- Checkbox -->
|
|
222
|
+
<VCheckbox
|
|
223
|
+
v-model="form.agreement.value"
|
|
224
|
+
:rules="[required()]"
|
|
225
|
+
>
|
|
226
|
+
I agree to the terms of use
|
|
227
|
+
</VCheckbox>
|
|
228
|
+
</VCardContent>
|
|
229
|
+
|
|
230
|
+
<VCardActions>
|
|
231
|
+
<VButton
|
|
232
|
+
color="primary"
|
|
233
|
+
variant="contained"
|
|
234
|
+
:disabled="form.invalid"
|
|
235
|
+
@click="handleSubmit"
|
|
236
|
+
>
|
|
237
|
+
Register
|
|
238
|
+
</VButton>
|
|
239
|
+
<VButton variant="text" @click="handleCancel">
|
|
240
|
+
Cancel
|
|
241
|
+
</VButton>
|
|
242
|
+
</VCardActions>
|
|
243
|
+
</VCard>
|
|
244
|
+
</template>
|
|
245
|
+
|
|
246
|
+
<script setup lang="ts">
|
|
247
|
+
import {
|
|
248
|
+
VCard, VCardContent, VCardActions,
|
|
249
|
+
VTextField, VSelect, VCheckbox, VButton
|
|
250
|
+
} from '@fastkit/vui';
|
|
251
|
+
import { useForm } from '@fastkit/vue-form-control';
|
|
252
|
+
import { required, email, minLength } from '@fastkit/rules';
|
|
253
|
+
|
|
254
|
+
const categories = [
|
|
255
|
+
{ value: 'personal', label: 'Personal' },
|
|
256
|
+
{ value: 'business', label: 'Business' },
|
|
257
|
+
{ value: 'education', label: 'Education' }
|
|
258
|
+
];
|
|
259
|
+
|
|
260
|
+
const form = useForm({
|
|
261
|
+
name: {
|
|
262
|
+
value: '',
|
|
263
|
+
rules: [required(), minLength(2)]
|
|
264
|
+
},
|
|
265
|
+
email: {
|
|
266
|
+
value: '',
|
|
267
|
+
rules: [required(), email()]
|
|
268
|
+
},
|
|
269
|
+
category: {
|
|
270
|
+
value: '',
|
|
271
|
+
rules: [required()]
|
|
272
|
+
},
|
|
273
|
+
agreement: {
|
|
274
|
+
value: false,
|
|
275
|
+
rules: [required()]
|
|
276
|
+
}
|
|
277
|
+
}, {
|
|
278
|
+
onSubmit: async (values) => {
|
|
279
|
+
console.log('Form submitted:', values);
|
|
280
|
+
await api.register(values);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const handleSubmit = () => {
|
|
285
|
+
form.submit();
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const handleCancel = () => {
|
|
289
|
+
form.reset();
|
|
290
|
+
};
|
|
291
|
+
</script>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Data Table
|
|
295
|
+
|
|
296
|
+
```vue
|
|
297
|
+
<template>
|
|
298
|
+
<VDataTable
|
|
299
|
+
:items="users"
|
|
300
|
+
:headers="headers"
|
|
301
|
+
:loading="loading"
|
|
302
|
+
item-key="id"
|
|
303
|
+
selectable
|
|
304
|
+
@select="handleSelect"
|
|
305
|
+
>
|
|
306
|
+
<!-- Custom column -->
|
|
307
|
+
<template #item.status="{ item }">
|
|
308
|
+
<VChip
|
|
309
|
+
:color="item.status === 'active' ? 'success' : 'warning'"
|
|
310
|
+
size="sm"
|
|
311
|
+
>
|
|
312
|
+
{{ item.status === 'active' ? 'Active' : 'Inactive' }}
|
|
313
|
+
</VChip>
|
|
314
|
+
</template>
|
|
315
|
+
|
|
316
|
+
<template #item.actions="{ item }">
|
|
317
|
+
<VButton size="sm" variant="text" @click="editUser(item)">
|
|
318
|
+
Edit
|
|
319
|
+
</VButton>
|
|
320
|
+
<VButton
|
|
321
|
+
size="sm"
|
|
322
|
+
variant="text"
|
|
323
|
+
color="error"
|
|
324
|
+
@click="deleteUser(item)"
|
|
325
|
+
>
|
|
326
|
+
Delete
|
|
327
|
+
</VButton>
|
|
328
|
+
</template>
|
|
329
|
+
</VDataTable>
|
|
330
|
+
</template>
|
|
331
|
+
|
|
332
|
+
<script setup lang="ts">
|
|
333
|
+
import { ref } from 'vue';
|
|
334
|
+
import { VDataTable, VChip, VButton } from '@fastkit/vui';
|
|
335
|
+
|
|
336
|
+
const loading = ref(false);
|
|
337
|
+
const users = ref([
|
|
338
|
+
{ id: 1, name: 'John Tanaka', email: 'tanaka@example.com', status: 'active' },
|
|
339
|
+
{ id: 2, name: 'Hanako Sato', email: 'sato@example.com', status: 'inactive' }
|
|
340
|
+
]);
|
|
341
|
+
|
|
342
|
+
const headers = [
|
|
343
|
+
{ key: 'name', title: 'Name', sortable: true },
|
|
344
|
+
{ key: 'email', title: 'Email', sortable: true },
|
|
345
|
+
{ key: 'status', title: 'Status' },
|
|
346
|
+
{ key: 'actions', title: 'Actions', width: 120 }
|
|
347
|
+
];
|
|
348
|
+
|
|
349
|
+
const handleSelect = (selectedItems: any[]) => {
|
|
350
|
+
console.log('Selected items:', selectedItems);
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
const editUser = (user: any) => {
|
|
354
|
+
console.log('Edit:', user);
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
const deleteUser = (user: any) => {
|
|
358
|
+
console.log('Delete:', user);
|
|
359
|
+
};
|
|
360
|
+
</script>
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Layout System
|
|
364
|
+
|
|
365
|
+
```vue
|
|
366
|
+
<template>
|
|
367
|
+
<VApp>
|
|
368
|
+
<!-- Toolbar -->
|
|
369
|
+
<VToolbar color="primary" variant="flat">
|
|
370
|
+
<VToolbarTitle>My App</VToolbarTitle>
|
|
371
|
+
<VToolbarMenu>
|
|
372
|
+
<VButton variant="text" color="on-primary">
|
|
373
|
+
Menu
|
|
374
|
+
</VButton>
|
|
375
|
+
</VToolbarMenu>
|
|
376
|
+
</VToolbar>
|
|
377
|
+
|
|
378
|
+
<!-- Main content -->
|
|
379
|
+
<VGridContainer>
|
|
380
|
+
<VGridItem cols="12" md="3">
|
|
381
|
+
<!-- Side navigation -->
|
|
382
|
+
<VNavigation>
|
|
383
|
+
<VNavigationItem to="/dashboard" icon="mdi-dashboard">
|
|
384
|
+
Dashboard
|
|
385
|
+
</VNavigationItem>
|
|
386
|
+
<VNavigationItem to="/users" icon="mdi-account-group">
|
|
387
|
+
Users
|
|
388
|
+
</VNavigationItem>
|
|
389
|
+
<VNavigationItem to="/settings" icon="mdi-cog">
|
|
390
|
+
Settings
|
|
391
|
+
</VNavigationItem>
|
|
392
|
+
</VNavigation>
|
|
393
|
+
</VGridItem>
|
|
394
|
+
|
|
395
|
+
<VGridItem cols="12" md="9">
|
|
396
|
+
<!-- Page content -->
|
|
397
|
+
<VPaper class="pa-4">
|
|
398
|
+
<router-view />
|
|
399
|
+
</VPaper>
|
|
400
|
+
</VGridItem>
|
|
401
|
+
</VGridContainer>
|
|
402
|
+
</VApp>
|
|
403
|
+
</template>
|
|
404
|
+
|
|
405
|
+
<script setup lang="ts">
|
|
406
|
+
import {
|
|
407
|
+
VApp, VToolbar, VToolbarTitle, VToolbarMenu,
|
|
408
|
+
VGridContainer, VGridItem, VNavigation, VNavigationItem,
|
|
409
|
+
VPaper, VButton
|
|
410
|
+
} from '@fastkit/vui';
|
|
411
|
+
</script>
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## Programmatic UI Operations
|
|
415
|
+
|
|
416
|
+
You can control UI elements from JavaScript using VUI services.
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
import { useVui } from '@fastkit/vui';
|
|
420
|
+
|
|
421
|
+
const vui = useVui();
|
|
422
|
+
|
|
423
|
+
// Alert dialog
|
|
424
|
+
await vui.alert('Processing completed');
|
|
425
|
+
|
|
426
|
+
// Confirmation dialog
|
|
427
|
+
const confirmed = await vui.confirm({
|
|
428
|
+
title: 'Confirmation',
|
|
429
|
+
message: 'Do you want to execute this operation?',
|
|
430
|
+
okText: 'Execute',
|
|
431
|
+
cancelText: 'Cancel'
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
if (confirmed) {
|
|
435
|
+
// Process when confirmed
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Prompt dialog
|
|
439
|
+
const result = await vui.prompt({
|
|
440
|
+
title: 'Enter name',
|
|
441
|
+
message: 'Please enter a new name',
|
|
442
|
+
defaultValue: 'Default value'
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
// Form prompt
|
|
446
|
+
const formResult = await vui.formPrompt(
|
|
447
|
+
{
|
|
448
|
+
state: { name: '', description: '' },
|
|
449
|
+
title: 'Create New'
|
|
450
|
+
},
|
|
451
|
+
(state) => (
|
|
452
|
+
<>
|
|
453
|
+
<VTextField
|
|
454
|
+
label="Name"
|
|
455
|
+
v-model={state.name}
|
|
456
|
+
required
|
|
457
|
+
/>
|
|
458
|
+
<VTextarea
|
|
459
|
+
label="Description"
|
|
460
|
+
v-model={state.description}
|
|
461
|
+
rows={3}
|
|
462
|
+
/>
|
|
463
|
+
</>
|
|
464
|
+
)
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
// Snackbar notification
|
|
468
|
+
vui.snackbar.show({
|
|
469
|
+
message: 'Saved',
|
|
470
|
+
color: 'success',
|
|
471
|
+
timeout: 3000
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
// Custom dialog
|
|
475
|
+
const dialog = await vui.dialog.show({
|
|
476
|
+
component: MyCustomDialog,
|
|
477
|
+
props: {
|
|
478
|
+
data: someData
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
## Theme Customization
|
|
484
|
+
|
|
485
|
+
### CSS Variables
|
|
486
|
+
|
|
487
|
+
```css
|
|
488
|
+
:root {
|
|
489
|
+
/* Color palette */
|
|
490
|
+
--color-primary: #1976d2;
|
|
491
|
+
--color-secondary: #424242;
|
|
492
|
+
--color-success: #4caf50;
|
|
493
|
+
--color-warning: #ff9800;
|
|
494
|
+
--color-error: #f44336;
|
|
495
|
+
|
|
496
|
+
/* Size settings */
|
|
497
|
+
--control-field-rem-sm: 0.875rem;
|
|
498
|
+
--control-field-rem-md: 1rem;
|
|
499
|
+
--control-field-rem-lg: 1.125rem;
|
|
500
|
+
|
|
501
|
+
/* Spacing */
|
|
502
|
+
--root-spacing: 8px;
|
|
503
|
+
|
|
504
|
+
/* Font */
|
|
505
|
+
--typo-base-font: Roboto, 'Noto Sans JP', sans-serif;
|
|
506
|
+
|
|
507
|
+
/* Shadow */
|
|
508
|
+
--shadow-1: 0px 2px 1px -1px rgba(0, 0, 0, 0.2);
|
|
509
|
+
--shadow-4: 0px 2px 4px -1px rgba(0, 0, 0, 0.2);
|
|
510
|
+
|
|
511
|
+
/* Transition */
|
|
512
|
+
--transition-primary: cubic-bezier(0.25, 0.8, 0.5, 1);
|
|
513
|
+
}
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Custom Color Scheme
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
// Define custom colors
|
|
520
|
+
app.use(VuiPlugin, {
|
|
521
|
+
colorScheme: {
|
|
522
|
+
primary: {
|
|
523
|
+
main: '#1976d2',
|
|
524
|
+
light: '#42a5f5',
|
|
525
|
+
dark: '#1565c0',
|
|
526
|
+
contrast: '#ffffff'
|
|
527
|
+
},
|
|
528
|
+
secondary: {
|
|
529
|
+
main: '#dc004e',
|
|
530
|
+
light: '#ff5983',
|
|
531
|
+
dark: '#9a0036',
|
|
532
|
+
contrast: '#ffffff'
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### Dark Theme Support
|
|
539
|
+
|
|
540
|
+
```vue
|
|
541
|
+
<template>
|
|
542
|
+
<VApp :theme="currentTheme">
|
|
543
|
+
<VButton @click="toggleTheme">
|
|
544
|
+
{{ currentTheme === 'dark' ? 'Light' : 'Dark' }} Theme
|
|
545
|
+
</VButton>
|
|
546
|
+
<!-- App content -->
|
|
547
|
+
</VApp>
|
|
548
|
+
</template>
|
|
549
|
+
|
|
550
|
+
<script setup lang="ts">
|
|
551
|
+
import { ref } from 'vue';
|
|
552
|
+
import { useColorScheme } from '@fastkit/vui';
|
|
553
|
+
|
|
554
|
+
const { theme: currentTheme, toggle: toggleTheme } = useColorScheme();
|
|
555
|
+
</script>
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
## Advanced Usage Examples
|
|
559
|
+
|
|
560
|
+
### Custom Component Creation
|
|
561
|
+
|
|
562
|
+
```vue
|
|
563
|
+
<template>
|
|
564
|
+
<VCard class="user-profile">
|
|
565
|
+
<VCardContent>
|
|
566
|
+
<div class="user-profile__header">
|
|
567
|
+
<VAvatar :src="user.avatar" size="lg" />
|
|
568
|
+
<div class="user-profile__info">
|
|
569
|
+
<h3>{{ user.name }}</h3>
|
|
570
|
+
<p>{{ user.role }}</p>
|
|
571
|
+
</div>
|
|
572
|
+
</div>
|
|
573
|
+
|
|
574
|
+
<VTabs v-model="activeTab">
|
|
575
|
+
<VTab value="profile">Profile</VTab>
|
|
576
|
+
<VTab value="settings">Settings</VTab>
|
|
577
|
+
<VTab value="activity">Activity</VTab>
|
|
578
|
+
</VTabs>
|
|
579
|
+
|
|
580
|
+
<VContentSwitcher :value="activeTab">
|
|
581
|
+
<template #profile>
|
|
582
|
+
<UserProfileTab :user="user" />
|
|
583
|
+
</template>
|
|
584
|
+
<template #settings>
|
|
585
|
+
<UserSettingsTab :user="user" />
|
|
586
|
+
</template>
|
|
587
|
+
<template #activity>
|
|
588
|
+
<UserActivityTab :user="user" />
|
|
589
|
+
</template>
|
|
590
|
+
</VContentSwitcher>
|
|
591
|
+
</VCardContent>
|
|
592
|
+
</VCard>
|
|
593
|
+
</template>
|
|
594
|
+
|
|
595
|
+
<script setup lang="ts">
|
|
596
|
+
import { ref } from 'vue';
|
|
597
|
+
import {
|
|
598
|
+
VCard, VCardContent, VAvatar, VTabs, VTab, VContentSwitcher
|
|
599
|
+
} from '@fastkit/vui';
|
|
600
|
+
|
|
601
|
+
interface User {
|
|
602
|
+
name: string;
|
|
603
|
+
role: string;
|
|
604
|
+
avatar: string;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const props = defineProps<{
|
|
608
|
+
user: User;
|
|
609
|
+
}>();
|
|
610
|
+
|
|
611
|
+
const activeTab = ref('profile');
|
|
612
|
+
</script>
|
|
613
|
+
|
|
614
|
+
<style scoped>
|
|
615
|
+
.user-profile__header {
|
|
616
|
+
display: flex;
|
|
617
|
+
align-items: center;
|
|
618
|
+
gap: 1rem;
|
|
619
|
+
margin-bottom: 1.5rem;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.user-profile__info h3 {
|
|
623
|
+
margin: 0;
|
|
624
|
+
font-size: 1.25rem;
|
|
625
|
+
font-weight: 500;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
.user-profile__info p {
|
|
629
|
+
margin: 0.25rem 0 0;
|
|
630
|
+
color: var(--color-text-secondary);
|
|
631
|
+
}
|
|
632
|
+
</style>
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### Complex Form Wizard
|
|
636
|
+
|
|
637
|
+
```vue
|
|
638
|
+
<template>
|
|
639
|
+
<VCard class="form-wizard">
|
|
640
|
+
<VCardContent>
|
|
641
|
+
<VToolbar variant="flat" class="mb-4">
|
|
642
|
+
<VToolbarTitle>Registration Wizard</VToolbarTitle>
|
|
643
|
+
<VToolbarEdge>
|
|
644
|
+
Step {{ currentStep + 1 }} / {{ steps.length }}
|
|
645
|
+
</VToolbarEdge>
|
|
646
|
+
</VToolbar>
|
|
647
|
+
|
|
648
|
+
<!-- Step indicator -->
|
|
649
|
+
<div class="step-indicator">
|
|
650
|
+
<div
|
|
651
|
+
v-for="(step, index) in steps"
|
|
652
|
+
:key="step.name"
|
|
653
|
+
class="step-indicator__item"
|
|
654
|
+
:class="{
|
|
655
|
+
'step-indicator__item--active': index === currentStep,
|
|
656
|
+
'step-indicator__item--completed': index < currentStep
|
|
657
|
+
}"
|
|
658
|
+
>
|
|
659
|
+
<VIcon
|
|
660
|
+
:name="index < currentStep ? 'mdi-check' : step.icon"
|
|
661
|
+
size="sm"
|
|
662
|
+
/>
|
|
663
|
+
<span>{{ step.title }}</span>
|
|
664
|
+
</div>
|
|
665
|
+
</div>
|
|
666
|
+
|
|
667
|
+
<!-- Step content -->
|
|
668
|
+
<VContentSwitcher :value="currentStep">
|
|
669
|
+
<template #0>
|
|
670
|
+
<PersonalInfoStep v-model="formData.personal" />
|
|
671
|
+
</template>
|
|
672
|
+
<template #1>
|
|
673
|
+
<ContactInfoStep v-model="formData.contact" />
|
|
674
|
+
</template>
|
|
675
|
+
<template #2>
|
|
676
|
+
<PreferencesStep v-model="formData.preferences" />
|
|
677
|
+
</template>
|
|
678
|
+
<template #3>
|
|
679
|
+
<ConfirmationStep :data="formData" />
|
|
680
|
+
</template>
|
|
681
|
+
</VContentSwitcher>
|
|
682
|
+
</VCardContent>
|
|
683
|
+
|
|
684
|
+
<VCardActions>
|
|
685
|
+
<VButton
|
|
686
|
+
variant="text"
|
|
687
|
+
:disabled="currentStep === 0"
|
|
688
|
+
@click="previousStep"
|
|
689
|
+
>
|
|
690
|
+
Back
|
|
691
|
+
</VButton>
|
|
692
|
+
|
|
693
|
+
<div class="flex-grow" />
|
|
694
|
+
|
|
695
|
+
<VButton
|
|
696
|
+
v-if="currentStep < steps.length - 1"
|
|
697
|
+
color="primary"
|
|
698
|
+
variant="contained"
|
|
699
|
+
:disabled="!canProceed"
|
|
700
|
+
@click="nextStep"
|
|
701
|
+
>
|
|
702
|
+
Next
|
|
703
|
+
</VButton>
|
|
704
|
+
|
|
705
|
+
<VButton
|
|
706
|
+
v-else
|
|
707
|
+
color="primary"
|
|
708
|
+
variant="contained"
|
|
709
|
+
:loading="submitting"
|
|
710
|
+
@click="submitForm"
|
|
711
|
+
>
|
|
712
|
+
Complete
|
|
713
|
+
</VButton>
|
|
714
|
+
</VCardActions>
|
|
715
|
+
</VCard>
|
|
716
|
+
</template>
|
|
717
|
+
|
|
718
|
+
<script setup lang="ts">
|
|
719
|
+
import { ref, computed } from 'vue';
|
|
720
|
+
import {
|
|
721
|
+
VCard, VCardContent, VCardActions,
|
|
722
|
+
VToolbar, VToolbarTitle, VToolbarEdge,
|
|
723
|
+
VContentSwitcher, VButton, VIcon
|
|
724
|
+
} from '@fastkit/vui';
|
|
725
|
+
|
|
726
|
+
const currentStep = ref(0);
|
|
727
|
+
const submitting = ref(false);
|
|
728
|
+
|
|
729
|
+
const steps = [
|
|
730
|
+
{ name: 'personal', title: 'Personal Info', icon: 'mdi-account' },
|
|
731
|
+
{ name: 'contact', title: 'Contact Info', icon: 'mdi-email' },
|
|
732
|
+
{ name: 'preferences', title: 'Preferences', icon: 'mdi-cog' },
|
|
733
|
+
{ name: 'confirm', title: 'Confirmation', icon: 'mdi-check-circle' }
|
|
734
|
+
];
|
|
735
|
+
|
|
736
|
+
const formData = ref({
|
|
737
|
+
personal: { name: '', birthday: '' },
|
|
738
|
+
contact: { email: '', phone: '' },
|
|
739
|
+
preferences: { newsletter: false, theme: 'light' }
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
const canProceed = computed(() => {
|
|
743
|
+
// Validation for each step
|
|
744
|
+
switch (currentStep.value) {
|
|
745
|
+
case 0:
|
|
746
|
+
return formData.value.personal.name && formData.value.personal.birthday;
|
|
747
|
+
case 1:
|
|
748
|
+
return formData.value.contact.email;
|
|
749
|
+
case 2:
|
|
750
|
+
return true;
|
|
751
|
+
default:
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
const nextStep = () => {
|
|
757
|
+
if (currentStep.value < steps.length - 1) {
|
|
758
|
+
currentStep.value++;
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
const previousStep = () => {
|
|
763
|
+
if (currentStep.value > 0) {
|
|
764
|
+
currentStep.value--;
|
|
765
|
+
}
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
const submitForm = async () => {
|
|
769
|
+
submitting.value = true;
|
|
770
|
+
try {
|
|
771
|
+
await api.submitRegistration(formData.value);
|
|
772
|
+
// Success processing
|
|
773
|
+
} finally {
|
|
774
|
+
submitting.value = false;
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
</script>
|
|
778
|
+
|
|
779
|
+
<style scoped>
|
|
780
|
+
.step-indicator {
|
|
781
|
+
display: flex;
|
|
782
|
+
justify-content: space-between;
|
|
783
|
+
margin-bottom: 2rem;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
.step-indicator__item {
|
|
787
|
+
display: flex;
|
|
788
|
+
flex-direction: column;
|
|
789
|
+
align-items: center;
|
|
790
|
+
gap: 0.5rem;
|
|
791
|
+
opacity: 0.6;
|
|
792
|
+
transition: opacity 0.2s;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
.step-indicator__item--active,
|
|
796
|
+
.step-indicator__item--completed {
|
|
797
|
+
opacity: 1;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
.flex-grow {
|
|
801
|
+
flex-grow: 1;
|
|
802
|
+
}
|
|
803
|
+
</style>
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
## API
|
|
807
|
+
|
|
808
|
+
### Composables
|
|
809
|
+
|
|
810
|
+
#### useVui()
|
|
811
|
+
|
|
812
|
+
Access VUI service instance.
|
|
813
|
+
|
|
814
|
+
```typescript
|
|
815
|
+
const vui = useVui();
|
|
816
|
+
|
|
817
|
+
// Dialog operations
|
|
818
|
+
vui.alert(message)
|
|
819
|
+
vui.confirm(options)
|
|
820
|
+
vui.prompt(options)
|
|
821
|
+
vui.formPrompt(state, renderer)
|
|
822
|
+
|
|
823
|
+
// Notifications
|
|
824
|
+
vui.snackbar.show(options)
|
|
825
|
+
vui.snackbar.hide()
|
|
826
|
+
|
|
827
|
+
// Navigation
|
|
828
|
+
vui.router.push(location)
|
|
829
|
+
vui.location.assign(url)
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
#### useControl()
|
|
833
|
+
|
|
834
|
+
Provides common functionality for control elements.
|
|
835
|
+
|
|
836
|
+
```typescript
|
|
837
|
+
const control = useControl(props, options);
|
|
838
|
+
|
|
839
|
+
// Properties
|
|
840
|
+
control.size // 'sm' | 'md' | 'lg'
|
|
841
|
+
control.classes // Computed CSS classes
|
|
842
|
+
control.isDisabled // Disabled state
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
#### useColorScheme()
|
|
846
|
+
|
|
847
|
+
Provides color theme control.
|
|
848
|
+
|
|
849
|
+
```typescript
|
|
850
|
+
const { theme, toggle, setTheme } = useColorScheme();
|
|
851
|
+
|
|
852
|
+
theme.value // Current theme
|
|
853
|
+
toggle() // Toggle theme
|
|
854
|
+
setTheme('dark') // Set specific theme
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
### Plugin Options
|
|
858
|
+
|
|
859
|
+
```typescript
|
|
860
|
+
interface VuiPluginOptions {
|
|
861
|
+
router: Router;
|
|
862
|
+
colorScheme?: VueColorSchemePluginSettings;
|
|
863
|
+
uiSettings?: {
|
|
864
|
+
primaryScope: ScopeName;
|
|
865
|
+
buttonDefault: {
|
|
866
|
+
color: ScopeName;
|
|
867
|
+
variant: ColorVariant;
|
|
868
|
+
};
|
|
869
|
+
dialogOk?: {
|
|
870
|
+
color?: ScopeName;
|
|
871
|
+
variant?: ColorVariant;
|
|
872
|
+
};
|
|
873
|
+
};
|
|
874
|
+
icons?: {
|
|
875
|
+
menuDown: IconName;
|
|
876
|
+
navigationExpand: RawIconProp;
|
|
877
|
+
// Other icon settings
|
|
878
|
+
};
|
|
879
|
+
stack?: VueStackPluginOptions;
|
|
880
|
+
form?: VueFormServiceOptions;
|
|
881
|
+
}
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
## Accessibility
|
|
885
|
+
|
|
886
|
+
### Keyboard Navigation
|
|
887
|
+
|
|
888
|
+
- **Tab/Shift+Tab**: Focus movement
|
|
889
|
+
- **Enter/Space**: Button/checkbox operation
|
|
890
|
+
- **Arrow Keys**: Radio button/tab/menu navigation
|
|
891
|
+
- **Escape**: Close dialog/menu
|
|
892
|
+
- **Home/End**: Move to beginning/end of list/table
|
|
893
|
+
|
|
894
|
+
### ARIA Support
|
|
895
|
+
|
|
896
|
+
```html
|
|
897
|
+
<!-- Automatically applied ARIA attributes -->
|
|
898
|
+
<button aria-disabled="true" aria-label="Save button">
|
|
899
|
+
<input aria-invalid="true" aria-describedby="error-message">
|
|
900
|
+
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
### Screen Reader Support
|
|
904
|
+
|
|
905
|
+
- Voice reading of form errors
|
|
906
|
+
- State change notifications
|
|
907
|
+
- Proper placement of landmark elements
|
|
908
|
+
|
|
909
|
+
## Dependencies
|
|
910
|
+
|
|
911
|
+
```json
|
|
912
|
+
{
|
|
913
|
+
"dependencies": {
|
|
914
|
+
"@fastkit/vue-form-control": "Form functionality",
|
|
915
|
+
"@fastkit/vue-color-scheme": "Color theme",
|
|
916
|
+
"@fastkit/vue-stack": "Stack management",
|
|
917
|
+
"@fastkit/vue-action": "Action functionality",
|
|
918
|
+
"@fastkit/vue-app-layout": "Layout",
|
|
919
|
+
"@fastkit/rules": "Validation",
|
|
920
|
+
"@fastkit/helpers": "Utilities"
|
|
921
|
+
},
|
|
922
|
+
"peerDependencies": {
|
|
923
|
+
"vue": "^3.4.0",
|
|
924
|
+
"vue-router": "^4.0.0"
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
```
|
|
928
|
+
|
|
3
929
|
## Documentation
|
|
4
|
-
|
|
930
|
+
|
|
931
|
+
For detailed documentation, please visit [here](https://dadajam4.github.io/fastkit/vui/).
|
|
932
|
+
|
|
933
|
+
## License
|
|
934
|
+
|
|
935
|
+
MIT
|
package/dist/vui.d.ts
CHANGED
|
@@ -141,6 +141,10 @@ declare function defineFormSelectorComponent(opts: DefineFormSelectorComponentOp
|
|
|
141
141
|
type: PropType<_fastkit_vue_form_control.RawFormSelectorItems>;
|
|
142
142
|
default: () => never[];
|
|
143
143
|
};
|
|
144
|
+
preserveOrder: {
|
|
145
|
+
type: BooleanConstructor;
|
|
146
|
+
default: boolean;
|
|
147
|
+
};
|
|
144
148
|
onClickItem: PropType<_fastkit_vue_form_control.FormSelectorGuard>;
|
|
145
149
|
name: StringConstructor;
|
|
146
150
|
tag: StringConstructor;
|
|
@@ -218,6 +222,10 @@ declare function defineFormSelectorComponent(opts: DefineFormSelectorComponentOp
|
|
|
218
222
|
type: PropType<_fastkit_vue_form_control.RawFormSelectorItems>;
|
|
219
223
|
default: () => never[];
|
|
220
224
|
};
|
|
225
|
+
preserveOrder: {
|
|
226
|
+
type: BooleanConstructor;
|
|
227
|
+
default: boolean;
|
|
228
|
+
};
|
|
221
229
|
onClickItem: PropType<_fastkit_vue_form_control.FormSelectorGuard>;
|
|
222
230
|
name: StringConstructor;
|
|
223
231
|
tag: StringConstructor;
|
|
@@ -274,6 +282,7 @@ declare function defineFormSelectorComponent(opts: DefineFormSelectorComponentOp
|
|
|
274
282
|
multiple: boolean;
|
|
275
283
|
stacked: boolean;
|
|
276
284
|
items: _fastkit_vue_form_control.RawFormSelectorItems;
|
|
285
|
+
preserveOrder: boolean;
|
|
277
286
|
}, _fastkit_vue_utils.DefinedSlots<{
|
|
278
287
|
[x: `error:${string}`]: (error: _fastkit_vue_form_control.FormNodeError) => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
279
288
|
[key: string]: any;
|
|
@@ -4627,6 +4636,10 @@ declare const VCheckboxGroup: vue.DefineComponent<{
|
|
|
4627
4636
|
type: vue.PropType<_fastkit_vue_form_control.RawFormSelectorItems>;
|
|
4628
4637
|
default: () => never[];
|
|
4629
4638
|
};
|
|
4639
|
+
preserveOrder: {
|
|
4640
|
+
type: BooleanConstructor;
|
|
4641
|
+
default: boolean;
|
|
4642
|
+
};
|
|
4630
4643
|
onClickItem: vue.PropType<_fastkit_vue_form_control.FormSelectorGuard>;
|
|
4631
4644
|
name: StringConstructor;
|
|
4632
4645
|
tag: StringConstructor;
|
|
@@ -4704,6 +4717,10 @@ declare const VCheckboxGroup: vue.DefineComponent<{
|
|
|
4704
4717
|
type: vue.PropType<_fastkit_vue_form_control.RawFormSelectorItems>;
|
|
4705
4718
|
default: () => never[];
|
|
4706
4719
|
};
|
|
4720
|
+
preserveOrder: {
|
|
4721
|
+
type: BooleanConstructor;
|
|
4722
|
+
default: boolean;
|
|
4723
|
+
};
|
|
4707
4724
|
onClickItem: vue.PropType<_fastkit_vue_form_control.FormSelectorGuard>;
|
|
4708
4725
|
name: StringConstructor;
|
|
4709
4726
|
tag: StringConstructor;
|
|
@@ -4760,6 +4777,7 @@ declare const VCheckboxGroup: vue.DefineComponent<{
|
|
|
4760
4777
|
multiple: boolean;
|
|
4761
4778
|
stacked: boolean;
|
|
4762
4779
|
items: _fastkit_vue_form_control.RawFormSelectorItems;
|
|
4780
|
+
preserveOrder: boolean;
|
|
4763
4781
|
}, _fastkit_vue_utils.DefinedSlots<{
|
|
4764
4782
|
[x: `error:${string}`]: (error: _fastkit_vue_form_control.FormNodeError) => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
4765
4783
|
[key: string]: any;
|
|
@@ -4926,6 +4944,10 @@ declare const VRadioGroup: vue.DefineComponent<{
|
|
|
4926
4944
|
type: vue.PropType<_fastkit_vue_form_control.RawFormSelectorItems>;
|
|
4927
4945
|
default: () => never[];
|
|
4928
4946
|
};
|
|
4947
|
+
preserveOrder: {
|
|
4948
|
+
type: BooleanConstructor;
|
|
4949
|
+
default: boolean;
|
|
4950
|
+
};
|
|
4929
4951
|
onClickItem: vue.PropType<_fastkit_vue_form_control.FormSelectorGuard>;
|
|
4930
4952
|
name: StringConstructor;
|
|
4931
4953
|
tag: StringConstructor;
|
|
@@ -5003,6 +5025,10 @@ declare const VRadioGroup: vue.DefineComponent<{
|
|
|
5003
5025
|
type: vue.PropType<_fastkit_vue_form_control.RawFormSelectorItems>;
|
|
5004
5026
|
default: () => never[];
|
|
5005
5027
|
};
|
|
5028
|
+
preserveOrder: {
|
|
5029
|
+
type: BooleanConstructor;
|
|
5030
|
+
default: boolean;
|
|
5031
|
+
};
|
|
5006
5032
|
onClickItem: vue.PropType<_fastkit_vue_form_control.FormSelectorGuard>;
|
|
5007
5033
|
name: StringConstructor;
|
|
5008
5034
|
tag: StringConstructor;
|
|
@@ -5059,6 +5085,7 @@ declare const VRadioGroup: vue.DefineComponent<{
|
|
|
5059
5085
|
multiple: boolean;
|
|
5060
5086
|
stacked: boolean;
|
|
5061
5087
|
items: _fastkit_vue_form_control.RawFormSelectorItems;
|
|
5088
|
+
preserveOrder: boolean;
|
|
5062
5089
|
}, _fastkit_vue_utils.DefinedSlots<{
|
|
5063
5090
|
[x: `error:${string}`]: (error: _fastkit_vue_form_control.FormNodeError) => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
5064
5091
|
[key: string]: any;
|
|
@@ -5225,6 +5252,10 @@ declare const VSwitchGroup: vue.DefineComponent<{
|
|
|
5225
5252
|
type: vue.PropType<_fastkit_vue_form_control.RawFormSelectorItems>;
|
|
5226
5253
|
default: () => never[];
|
|
5227
5254
|
};
|
|
5255
|
+
preserveOrder: {
|
|
5256
|
+
type: BooleanConstructor;
|
|
5257
|
+
default: boolean;
|
|
5258
|
+
};
|
|
5228
5259
|
onClickItem: vue.PropType<_fastkit_vue_form_control.FormSelectorGuard>;
|
|
5229
5260
|
name: StringConstructor;
|
|
5230
5261
|
tag: StringConstructor;
|
|
@@ -5302,6 +5333,10 @@ declare const VSwitchGroup: vue.DefineComponent<{
|
|
|
5302
5333
|
type: vue.PropType<_fastkit_vue_form_control.RawFormSelectorItems>;
|
|
5303
5334
|
default: () => never[];
|
|
5304
5335
|
};
|
|
5336
|
+
preserveOrder: {
|
|
5337
|
+
type: BooleanConstructor;
|
|
5338
|
+
default: boolean;
|
|
5339
|
+
};
|
|
5305
5340
|
onClickItem: vue.PropType<_fastkit_vue_form_control.FormSelectorGuard>;
|
|
5306
5341
|
name: StringConstructor;
|
|
5307
5342
|
tag: StringConstructor;
|
|
@@ -5358,6 +5393,7 @@ declare const VSwitchGroup: vue.DefineComponent<{
|
|
|
5358
5393
|
multiple: boolean;
|
|
5359
5394
|
stacked: boolean;
|
|
5360
5395
|
items: _fastkit_vue_form_control.RawFormSelectorItems;
|
|
5396
|
+
preserveOrder: boolean;
|
|
5361
5397
|
}, _fastkit_vue_utils.DefinedSlots<{
|
|
5362
5398
|
[x: `error:${string}`]: (error: _fastkit_vue_form_control.FormNodeError) => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
5363
5399
|
[key: string]: any;
|
|
@@ -5570,6 +5606,10 @@ declare const VSelect: vue.DefineComponent<{
|
|
|
5570
5606
|
type: PropType<_fastkit_vue_form_control.RawFormSelectorItems>;
|
|
5571
5607
|
default: () => never[];
|
|
5572
5608
|
};
|
|
5609
|
+
preserveOrder: {
|
|
5610
|
+
type: BooleanConstructor;
|
|
5611
|
+
default: boolean;
|
|
5612
|
+
};
|
|
5573
5613
|
onClickItem: PropType<_fastkit_vue_form_control.FormSelectorGuard>;
|
|
5574
5614
|
name: StringConstructor;
|
|
5575
5615
|
tag: StringConstructor;
|
|
@@ -5657,6 +5697,10 @@ declare const VSelect: vue.DefineComponent<{
|
|
|
5657
5697
|
type: PropType<_fastkit_vue_form_control.RawFormSelectorItems>;
|
|
5658
5698
|
default: () => never[];
|
|
5659
5699
|
};
|
|
5700
|
+
preserveOrder: {
|
|
5701
|
+
type: BooleanConstructor;
|
|
5702
|
+
default: boolean;
|
|
5703
|
+
};
|
|
5660
5704
|
onClickItem: PropType<_fastkit_vue_form_control.FormSelectorGuard>;
|
|
5661
5705
|
name: StringConstructor;
|
|
5662
5706
|
tag: StringConstructor;
|
|
@@ -5709,6 +5753,7 @@ declare const VSelect: vue.DefineComponent<{
|
|
|
5709
5753
|
hiddenInfo: boolean;
|
|
5710
5754
|
multiple: boolean;
|
|
5711
5755
|
items: _fastkit_vue_form_control.RawFormSelectorItems;
|
|
5756
|
+
preserveOrder: boolean;
|
|
5712
5757
|
}, _fastkit_vue_utils.DefinedSlots<{
|
|
5713
5758
|
[x: `error:${string}`]: (error: _fastkit_vue_form_control.FormNodeError) => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
5714
5759
|
[key: string]: any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fastkit/vui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"description": "A simple, extensible UI kit for Vue applications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fastkit",
|
|
@@ -44,31 +44,31 @@
|
|
|
44
44
|
"src"
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@fastkit/color-scheme": "^2.0.10",
|
|
48
47
|
"@fastkit/dom": "^0.2.6",
|
|
48
|
+
"@fastkit/color-scheme-gen": "^0.14.13",
|
|
49
|
+
"@fastkit/color-scheme": "^2.0.10",
|
|
50
|
+
"@fastkit/icon-font": "^2.0.7",
|
|
49
51
|
"@fastkit/helpers": "^0.14.5",
|
|
52
|
+
"@fastkit/tiny-logger": "^0.14.5",
|
|
53
|
+
"@fastkit/media-match": "^2.0.7",
|
|
54
|
+
"@fastkit/media-match-gen": "^0.14.13",
|
|
50
55
|
"@fastkit/rules": "^0.14.7",
|
|
51
|
-
"@fastkit/vue-action": "^0.3.19",
|
|
52
|
-
"@fastkit/vue-app-layout": "^0.16.2",
|
|
53
|
-
"@fastkit/vue-body-scroll-lock": "^0.2.13",
|
|
54
56
|
"@fastkit/vue-click-outside": "^0.2.12",
|
|
55
|
-
"@fastkit/
|
|
56
|
-
"@fastkit/vue-
|
|
57
|
-
"@fastkit/vue-
|
|
57
|
+
"@fastkit/stylebase": "^0.13.1",
|
|
58
|
+
"@fastkit/vue-form-control": "^0.21.0",
|
|
59
|
+
"@fastkit/vue-loading": "^0.15.15",
|
|
58
60
|
"@fastkit/vue-location": "^0.4.2",
|
|
61
|
+
"@fastkit/vue-keyboard": "^0.2.5",
|
|
62
|
+
"@fastkit/vue-resize": "^0.2.12",
|
|
63
|
+
"@fastkit/vue-action": "^0.3.19",
|
|
64
|
+
"@fastkit/vue-stack": "^0.16.20",
|
|
65
|
+
"@fastkit/vue-body-scroll-lock": "^0.2.13",
|
|
59
66
|
"@fastkit/vue-media-match": "^0.14.10",
|
|
60
67
|
"@fastkit/vue-scroller": "^0.15.12",
|
|
61
|
-
"@fastkit/vue-
|
|
62
|
-
"@fastkit/vue-
|
|
63
|
-
"@fastkit/vue-transitions": "^0.2.13",
|
|
64
|
-
"@fastkit/tiny-logger": "^0.14.5",
|
|
68
|
+
"@fastkit/vue-color-scheme": "^0.15.15",
|
|
69
|
+
"@fastkit/vue-app-layout": "^0.16.2",
|
|
65
70
|
"@fastkit/vue-utils": "^0.15.12",
|
|
66
|
-
"@fastkit/
|
|
67
|
-
"@fastkit/stylebase": "^0.13.1",
|
|
68
|
-
"@fastkit/media-match": "^2.0.7",
|
|
69
|
-
"@fastkit/vue-loading": "^0.15.15",
|
|
70
|
-
"@fastkit/color-scheme-gen": "^0.14.13",
|
|
71
|
-
"@fastkit/media-match-gen": "^0.14.13"
|
|
71
|
+
"@fastkit/vue-transitions": "^0.2.13"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
74
|
"vue": "^3.4.0",
|