@vc-shell/create-vc-app 1.1.99-alpha.2 → 1.1.99-alpha.4
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 +41 -5
- package/dist/cli/argv.d.ts.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/types.d.ts +5 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/commands/generate-blade.d.ts +5 -0
- package/dist/commands/generate-blade.d.ts.map +1 -1
- package/dist/index.js +940 -789
- package/dist/templates/base/_package.json +5 -5
- package/dist/templates/blades/grid/blade.vue +4 -15
- package/dist/utils/naming.d.ts +1 -0
- package/dist/utils/naming.d.ts.map +1 -1
- package/dist/utils/register-module.d.ts +4 -0
- package/dist/utils/register-module.d.ts.map +1 -1
- package/dist/utils/templates.d.ts +10 -0
- package/dist/utils/templates.d.ts.map +1 -0
- package/dist/workflows/create-app.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/templates/base/ai-guides/.cursorrules-vc-shell +0 -529
- package/dist/templates/base/ai-guides/README.md +0 -360
- package/dist/templates/base/ai-guides/guides/AI_GUIDE.md +0 -195
- package/dist/templates/base/ai-guides/guides/blade-patterns.md +0 -384
- package/dist/templates/base/ai-guides/guides/complete-workflow.md +0 -781
- package/dist/templates/base/ai-guides/guides/composables-reference.md +0 -338
- package/dist/templates/base/ai-guides/guides/troubleshooting.md +0 -529
- package/dist/templates/base/ai-guides/guides/ui-components-reference.md +0 -903
- package/dist/templates/base/ai-guides/prompts/adapt-existing-module.md +0 -1026
- package/dist/templates/base/ai-guides/prompts/advanced-scenarios.md +0 -852
- package/dist/templates/base/ai-guides/prompts/api-client-generation.md +0 -877
- package/dist/templates/base/ai-guides/prompts/cli-usage.md +0 -640
- package/dist/templates/base/ai-guides/prompts/quick-start-scenarios.md +0 -773
- package/dist/templates/base/ai-guides/prompts/simple-modifications.md +0 -987
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
# Blade Patterns
|
|
2
|
-
|
|
3
|
-
Complete reference for List and Details blade patterns in VC-Shell.
|
|
4
|
-
|
|
5
|
-
## List Blade Pattern
|
|
6
|
-
|
|
7
|
-
### Structure
|
|
8
|
-
List blades display data in a table format using `VcTable` component.
|
|
9
|
-
|
|
10
|
-
### Required Props
|
|
11
|
-
Always include these 4 props:
|
|
12
|
-
```typescript
|
|
13
|
-
interface BladeProps {
|
|
14
|
-
expanded?: boolean; // Expansion state
|
|
15
|
-
closable?: boolean; // Can be closed
|
|
16
|
-
param?: string; // Entity ID (usually undefined for list)
|
|
17
|
-
options?: unknown; // Additional data
|
|
18
|
-
}
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
### Basic Template
|
|
22
|
-
```vue
|
|
23
|
-
<template>
|
|
24
|
-
<VcBlade
|
|
25
|
-
:expanded="true"
|
|
26
|
-
:closable="true"
|
|
27
|
-
:param="undefined"
|
|
28
|
-
:options="undefined"
|
|
29
|
-
:title="$t('module.list.title')"
|
|
30
|
-
>
|
|
31
|
-
<VcTable
|
|
32
|
-
:items="items"
|
|
33
|
-
:columns="columns"
|
|
34
|
-
:loading="loading"
|
|
35
|
-
:total-count="totalCount"
|
|
36
|
-
:pages="pages"
|
|
37
|
-
:current-page="currentPage"
|
|
38
|
-
@item-click="handleItemClick"
|
|
39
|
-
@page-changed="handlePageChange"
|
|
40
|
-
/>
|
|
41
|
-
</VcBlade>
|
|
42
|
-
</template>
|
|
43
|
-
|
|
44
|
-
<script lang="ts" setup>
|
|
45
|
-
import { useAsync } from '@vc-shell/framework';
|
|
46
|
-
import { useBladeNavigation } from '@vc-shell/framework';
|
|
47
|
-
import { useListComposable } from '../composables';
|
|
48
|
-
|
|
49
|
-
const props = defineProps<{
|
|
50
|
-
expanded?: boolean;
|
|
51
|
-
closable?: boolean;
|
|
52
|
-
param?: string;
|
|
53
|
-
options?: unknown;
|
|
54
|
-
}>();
|
|
55
|
-
|
|
56
|
-
const { openBlade } = useBladeNavigation();
|
|
57
|
-
const { items, columns, loading, totalCount, pages, currentPage, loadItems } = useListComposable();
|
|
58
|
-
|
|
59
|
-
const { action: loadData } = useAsync(async () => {
|
|
60
|
-
await loadItems();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
loadData();
|
|
64
|
-
|
|
65
|
-
function handleItemClick(item: any) {
|
|
66
|
-
openBlade({
|
|
67
|
-
blade: DetailsComponent,
|
|
68
|
-
param: item.id
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function handlePageChange(page: number) {
|
|
73
|
-
loadItems({ page });
|
|
74
|
-
}
|
|
75
|
-
</script>
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Key Components
|
|
79
|
-
- **VcBlade**: Container with toolbar and actions
|
|
80
|
-
- **VcTable**: Data table with sorting, pagination, selection
|
|
81
|
-
|
|
82
|
-
### Toolbar Configuration
|
|
83
|
-
```typescript
|
|
84
|
-
const toolbarItems: IBladeToolbar[] = [
|
|
85
|
-
{
|
|
86
|
-
id: 'add',
|
|
87
|
-
title: 'Add New',
|
|
88
|
-
icon: 'add',
|
|
89
|
-
onClick: () => openBlade({ blade: DetailsComponent })
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
id: 'refresh',
|
|
93
|
-
title: 'Refresh',
|
|
94
|
-
icon: 'refresh',
|
|
95
|
-
onClick: () => loadData()
|
|
96
|
-
}
|
|
97
|
-
];
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### Table Columns
|
|
101
|
-
```typescript
|
|
102
|
-
const columns: ITableColumn[] = [
|
|
103
|
-
{
|
|
104
|
-
id: 'name',
|
|
105
|
-
title: 'Name',
|
|
106
|
-
field: 'name',
|
|
107
|
-
sortable: true,
|
|
108
|
-
width: 200
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
id: 'status',
|
|
112
|
-
title: 'Status',
|
|
113
|
-
field: 'status',
|
|
114
|
-
type: 'badge',
|
|
115
|
-
sortable: true
|
|
116
|
-
}
|
|
117
|
-
];
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Details Blade Pattern
|
|
121
|
-
|
|
122
|
-
### Structure
|
|
123
|
-
Details blades display forms using `VcForm` and `VeeValidate` for validation.
|
|
124
|
-
|
|
125
|
-
### Required Props
|
|
126
|
-
Always include these 4 props:
|
|
127
|
-
```typescript
|
|
128
|
-
interface BladeProps {
|
|
129
|
-
expanded?: boolean; // Expansion state
|
|
130
|
-
closable?: boolean; // Can be closed
|
|
131
|
-
param?: string; // Entity ID (required for details)
|
|
132
|
-
options?: unknown; // Additional data
|
|
133
|
-
}
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Basic Template
|
|
137
|
-
```vue
|
|
138
|
-
<template>
|
|
139
|
-
<VcBlade
|
|
140
|
-
:expanded="true"
|
|
141
|
-
:closable="true"
|
|
142
|
-
:param="param"
|
|
143
|
-
:options="options"
|
|
144
|
-
:title="$t('module.details.title')"
|
|
145
|
-
:modified="isModified"
|
|
146
|
-
:toolbar-items="toolbarItems"
|
|
147
|
-
>
|
|
148
|
-
<VcForm @submit="handleSubmit">
|
|
149
|
-
<Field
|
|
150
|
-
name="name"
|
|
151
|
-
v-slot="{ errors, errorMessage, handleChange }"
|
|
152
|
-
:rules="{ required: true }"
|
|
153
|
-
>
|
|
154
|
-
<VcInput
|
|
155
|
-
:model-value="data.name"
|
|
156
|
-
:error-message="errorMessage"
|
|
157
|
-
:error="!!errors.length"
|
|
158
|
-
@update:model-value="(v) => { data.name = v; handleChange(v); }"
|
|
159
|
-
/>
|
|
160
|
-
</Field>
|
|
161
|
-
|
|
162
|
-
<Field
|
|
163
|
-
name="email"
|
|
164
|
-
v-slot="{ errors, errorMessage, handleChange }"
|
|
165
|
-
:rules="{ required: true, email: true }"
|
|
166
|
-
>
|
|
167
|
-
<VcInput
|
|
168
|
-
:model-value="data.email"
|
|
169
|
-
type="email"
|
|
170
|
-
:error-message="errorMessage"
|
|
171
|
-
:error="!!errors.length"
|
|
172
|
-
@update:model-value="(v) => { data.email = v; handleChange(v); }"
|
|
173
|
-
/>
|
|
174
|
-
</Field>
|
|
175
|
-
</VcForm>
|
|
176
|
-
</VcBlade>
|
|
177
|
-
</template>
|
|
178
|
-
|
|
179
|
-
<script lang="ts" setup>
|
|
180
|
-
import { ref, watch } from 'vue';
|
|
181
|
-
import { Field, useForm } from 'vee-validate';
|
|
182
|
-
import { useAsync } from '@vc-shell/framework';
|
|
183
|
-
import { useModificationTracker } from '@vc-shell/framework';
|
|
184
|
-
import { useDetailsComposable } from '../composables';
|
|
185
|
-
|
|
186
|
-
const props = defineProps<{
|
|
187
|
-
expanded?: boolean;
|
|
188
|
-
closable?: boolean;
|
|
189
|
-
param?: string;
|
|
190
|
-
options?: unknown;
|
|
191
|
-
}>();
|
|
192
|
-
|
|
193
|
-
const item = ref({
|
|
194
|
-
name: '',
|
|
195
|
-
email: ''
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
const { isModified, currentValue, resetModificationState } = useModificationTracker(item);
|
|
199
|
-
const { loadItem, saveItem } = useDetailsComposable();
|
|
200
|
-
|
|
201
|
-
const { handleSubmit } = useForm();
|
|
202
|
-
|
|
203
|
-
const { action: loadData } = useAsync(async () => {
|
|
204
|
-
if (props.param) {
|
|
205
|
-
const data = await loadItem(props.param);
|
|
206
|
-
currentValue.value = data; // Assign to currentValue
|
|
207
|
-
resetModificationState();
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
watch(() => props.param, () => {
|
|
212
|
-
if (props.param) {
|
|
213
|
-
loadData();
|
|
214
|
-
}
|
|
215
|
-
}, { immediate: true });
|
|
216
|
-
|
|
217
|
-
const toolbarItems = [
|
|
218
|
-
{
|
|
219
|
-
id: 'save',
|
|
220
|
-
title: 'Save',
|
|
221
|
-
icon: 'save',
|
|
222
|
-
onClick: () => handleSubmit(onSubmit)()
|
|
223
|
-
}
|
|
224
|
-
];
|
|
225
|
-
|
|
226
|
-
async function onSubmit() {
|
|
227
|
-
await saveItem(currentValue.value); // Use currentValue
|
|
228
|
-
resetModificationState();
|
|
229
|
-
}
|
|
230
|
-
</script>
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
### Form Validation Pattern
|
|
234
|
-
Always use VeeValidate `Field` component with:
|
|
235
|
-
- `v-slot="{ errors, errorMessage, handleChange }"`
|
|
236
|
-
- `:rules` prop for validation rules
|
|
237
|
-
- `handleChange` for tracking changes
|
|
238
|
-
- `errorMessage` and `error` props on inputs
|
|
239
|
-
|
|
240
|
-
### Modification Tracking
|
|
241
|
-
```typescript
|
|
242
|
-
const item = ref({ /* form data */ });
|
|
243
|
-
const { isModified, currentValue, resetModificationState } = useModificationTracker(item);
|
|
244
|
-
|
|
245
|
-
// Load data
|
|
246
|
-
currentValue.value = await loadItem(id);
|
|
247
|
-
|
|
248
|
-
// After successful save
|
|
249
|
-
await saveItem(currentValue.value);
|
|
250
|
-
resetModificationState();
|
|
251
|
-
|
|
252
|
-
// Pass to blade for modified indicator
|
|
253
|
-
:modified="isModified"
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
## Navigation Patterns
|
|
257
|
-
|
|
258
|
-
### Opening Blades
|
|
259
|
-
```typescript
|
|
260
|
-
const { openBlade } = useBladeNavigation();
|
|
261
|
-
|
|
262
|
-
// Open details blade
|
|
263
|
-
openBlade({
|
|
264
|
-
blade: DetailsComponent,
|
|
265
|
-
param: itemId
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// Open with options
|
|
269
|
-
openBlade({
|
|
270
|
-
blade: DetailsComponent,
|
|
271
|
-
param: itemId,
|
|
272
|
-
options: { mode: 'edit' }
|
|
273
|
-
});
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Closing Blades
|
|
277
|
-
```typescript
|
|
278
|
-
const emit = defineEmits<{
|
|
279
|
-
'close:blade': [];
|
|
280
|
-
}>();
|
|
281
|
-
|
|
282
|
-
// Close current blade
|
|
283
|
-
emit('close:blade');
|
|
284
|
-
|
|
285
|
-
// Or use composable
|
|
286
|
-
const { closeBlade } = useBladeNavigation();
|
|
287
|
-
closeBlade();
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
### Parent Communication
|
|
291
|
-
```typescript
|
|
292
|
-
const emit = defineEmits<{
|
|
293
|
-
'parent:call': [method: string, ...args: any[]];
|
|
294
|
-
}>();
|
|
295
|
-
|
|
296
|
-
// Call parent method
|
|
297
|
-
emit('parent:call', 'refreshList');
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
## State Management
|
|
301
|
-
|
|
302
|
-
### Loading States
|
|
303
|
-
```typescript
|
|
304
|
-
const { action, loading, error } = useAsync(async () => {
|
|
305
|
-
return await apiCall();
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
// Use loading in template
|
|
309
|
-
:loading="loading"
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### Error Handling
|
|
313
|
-
```typescript
|
|
314
|
-
const { action, loading, error } = useAsync(async () => {
|
|
315
|
-
try {
|
|
316
|
-
return await apiCall();
|
|
317
|
-
} catch (err) {
|
|
318
|
-
notification.error('Failed to load data');
|
|
319
|
-
throw err;
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
### Data Refresh
|
|
325
|
-
```typescript
|
|
326
|
-
// Refresh list after save
|
|
327
|
-
emit('parent:call', 'refresh');
|
|
328
|
-
|
|
329
|
-
// Or reload directly
|
|
330
|
-
loadData();
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
## Best Practices
|
|
334
|
-
|
|
335
|
-
1. **Always use 4 required props** on VcBlade
|
|
336
|
-
2. **Use VeeValidate Field** for all form inputs
|
|
337
|
-
3. **Track modifications** with useModificationTracker
|
|
338
|
-
4. **Handle loading states** with useAsync
|
|
339
|
-
5. **Use proper TypeScript types** for props and data
|
|
340
|
-
6. **Implement error handling** for all API calls
|
|
341
|
-
7. **Use localization** for all user-facing text
|
|
342
|
-
8. **Follow naming conventions** (Vc prefix, use prefix)
|
|
343
|
-
9. **Keep composables focused** on single responsibility
|
|
344
|
-
10. **Test navigation flows** between blades
|
|
345
|
-
|
|
346
|
-
## Common Patterns
|
|
347
|
-
|
|
348
|
-
### Conditional Field Display
|
|
349
|
-
```vue
|
|
350
|
-
<Field
|
|
351
|
-
v-if="data.type === 'physical'"
|
|
352
|
-
name="weight"
|
|
353
|
-
v-slot="{ errors, errorMessage, handleChange }"
|
|
354
|
-
>
|
|
355
|
-
<!-- field content -->
|
|
356
|
-
</Field>
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
### Dynamic Columns
|
|
360
|
-
```typescript
|
|
361
|
-
const columns = computed(() => {
|
|
362
|
-
const baseColumns = [...];
|
|
363
|
-
if (showExtraColumns.value) {
|
|
364
|
-
baseColumns.push(...extraColumns);
|
|
365
|
-
}
|
|
366
|
-
return baseColumns;
|
|
367
|
-
});
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
### Toolbar Actions
|
|
371
|
-
```typescript
|
|
372
|
-
const toolbarItems = computed(() => {
|
|
373
|
-
const items: IBladeToolbar[] = [
|
|
374
|
-
{ id: 'save', title: 'Save', icon: 'save', onClick: handleSave }
|
|
375
|
-
];
|
|
376
|
-
|
|
377
|
-
if (props.param) {
|
|
378
|
-
items.push({ id: 'delete', title: 'Delete', icon: 'delete', onClick: handleDelete });
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
return items;
|
|
382
|
-
});
|
|
383
|
-
```
|
|
384
|
-
|