@htlkg/components 0.0.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/dist/composables/index.js +388 -0
- package/dist/composables/index.js.map +1 -0
- package/package.json +41 -0
- package/src/composables/index.ts +6 -0
- package/src/composables/useForm.test.ts +229 -0
- package/src/composables/useForm.ts +130 -0
- package/src/composables/useFormValidation.test.ts +189 -0
- package/src/composables/useFormValidation.ts +83 -0
- package/src/composables/useModal.property.test.ts +164 -0
- package/src/composables/useModal.ts +43 -0
- package/src/composables/useNotifications.test.ts +166 -0
- package/src/composables/useNotifications.ts +81 -0
- package/src/composables/useTable.property.test.ts +198 -0
- package/src/composables/useTable.ts +134 -0
- package/src/composables/useTabs.property.test.ts +247 -0
- package/src/composables/useTabs.ts +101 -0
- package/src/data/Chart.demo.vue +340 -0
- package/src/data/Chart.md +525 -0
- package/src/data/Chart.vue +133 -0
- package/src/data/DataList.md +80 -0
- package/src/data/DataList.test.ts +69 -0
- package/src/data/DataList.vue +46 -0
- package/src/data/SearchableSelect.md +107 -0
- package/src/data/SearchableSelect.vue +124 -0
- package/src/data/Table.demo.vue +296 -0
- package/src/data/Table.md +588 -0
- package/src/data/Table.property.test.ts +548 -0
- package/src/data/Table.test.ts +562 -0
- package/src/data/Table.unit.test.ts +544 -0
- package/src/data/Table.vue +321 -0
- package/src/data/index.ts +5 -0
- package/src/domain/BrandCard.md +81 -0
- package/src/domain/BrandCard.vue +63 -0
- package/src/domain/BrandSelector.md +84 -0
- package/src/domain/BrandSelector.vue +65 -0
- package/src/domain/ProductBadge.md +60 -0
- package/src/domain/ProductBadge.vue +47 -0
- package/src/domain/UserAvatar.md +84 -0
- package/src/domain/UserAvatar.vue +60 -0
- package/src/domain/domain-components.property.test.ts +449 -0
- package/src/domain/index.ts +4 -0
- package/src/forms/DateRange.demo.vue +273 -0
- package/src/forms/DateRange.md +337 -0
- package/src/forms/DateRange.vue +110 -0
- package/src/forms/JsonSchemaForm.demo.vue +549 -0
- package/src/forms/JsonSchemaForm.md +112 -0
- package/src/forms/JsonSchemaForm.property.test.ts +817 -0
- package/src/forms/JsonSchemaForm.test.ts +601 -0
- package/src/forms/JsonSchemaForm.unit.test.ts +801 -0
- package/src/forms/JsonSchemaForm.vue +615 -0
- package/src/forms/index.ts +3 -0
- package/src/index.ts +17 -0
- package/src/navigation/Breadcrumbs.demo.vue +142 -0
- package/src/navigation/Breadcrumbs.md +102 -0
- package/src/navigation/Breadcrumbs.test.ts +69 -0
- package/src/navigation/Breadcrumbs.vue +58 -0
- package/src/navigation/Stepper.demo.vue +337 -0
- package/src/navigation/Stepper.md +174 -0
- package/src/navigation/Stepper.vue +146 -0
- package/src/navigation/Tabs.demo.vue +293 -0
- package/src/navigation/Tabs.md +163 -0
- package/src/navigation/Tabs.test.ts +176 -0
- package/src/navigation/Tabs.vue +104 -0
- package/src/navigation/index.ts +5 -0
- package/src/overlays/Alert.demo.vue +377 -0
- package/src/overlays/Alert.md +248 -0
- package/src/overlays/Alert.test.ts +166 -0
- package/src/overlays/Alert.vue +70 -0
- package/src/overlays/Drawer.md +140 -0
- package/src/overlays/Drawer.test.ts +92 -0
- package/src/overlays/Drawer.vue +76 -0
- package/src/overlays/Modal.demo.vue +149 -0
- package/src/overlays/Modal.md +385 -0
- package/src/overlays/Modal.test.ts +128 -0
- package/src/overlays/Modal.vue +86 -0
- package/src/overlays/Notification.md +150 -0
- package/src/overlays/Notification.test.ts +96 -0
- package/src/overlays/Notification.vue +58 -0
- package/src/overlays/index.ts +4 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
|
|
4
|
+
export interface Tab {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
count?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
tabs: Tab[];
|
|
12
|
+
modelValue?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
16
|
+
modelValue: ''
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const emit = defineEmits<{
|
|
20
|
+
'update:modelValue': [tabId: string];
|
|
21
|
+
'tab-change': [tabId: string];
|
|
22
|
+
}>();
|
|
23
|
+
|
|
24
|
+
// Internal state synced with v-model
|
|
25
|
+
const currentTab = computed({
|
|
26
|
+
get: () => props.modelValue || (props.tabs.length > 0 ? props.tabs[0].id : ''),
|
|
27
|
+
set: (value: string) => {
|
|
28
|
+
emit('update:modelValue', value);
|
|
29
|
+
emit('tab-change', value);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
// Expose methods for parent components
|
|
36
|
+
defineExpose({
|
|
37
|
+
setActiveTab: (tabId: string) => { currentTab.value = tabId; },
|
|
38
|
+
getActiveTab: () => currentTab.value,
|
|
39
|
+
nextTab: () => {
|
|
40
|
+
const currentIndex = props.tabs.findIndex(t => t.id === currentTab.value);
|
|
41
|
+
if (currentIndex < props.tabs.length - 1) {
|
|
42
|
+
currentTab.value = props.tabs[currentIndex + 1].id;
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
previousTab: () => {
|
|
46
|
+
const currentIndex = props.tabs.findIndex(t => t.id === currentTab.value);
|
|
47
|
+
if (currentIndex > 0) {
|
|
48
|
+
currentTab.value = props.tabs[currentIndex - 1].id;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<template>
|
|
55
|
+
<div class="tabs-wrapper">
|
|
56
|
+
<div class="border-b border-gray-200">
|
|
57
|
+
<nav class="-mb-px flex space-x-8" aria-label="Tabs">
|
|
58
|
+
<button
|
|
59
|
+
v-for="tab in tabs"
|
|
60
|
+
:key="tab.id"
|
|
61
|
+
@click="currentTab = tab.id"
|
|
62
|
+
:class="[
|
|
63
|
+
currentTab === tab.id
|
|
64
|
+
? 'border-blue-500 text-blue-600'
|
|
65
|
+
: 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700',
|
|
66
|
+
'whitespace-nowrap border-b-2 py-4 px-1 text-sm font-medium transition-colors'
|
|
67
|
+
]"
|
|
68
|
+
:aria-current="currentTab === tab.id ? 'page' : undefined"
|
|
69
|
+
>
|
|
70
|
+
{{ tab.label }}
|
|
71
|
+
<span
|
|
72
|
+
v-if="tab.count !== undefined && tab.count > 0"
|
|
73
|
+
:class="[
|
|
74
|
+
currentTab === tab.id
|
|
75
|
+
? 'bg-blue-100 text-blue-600'
|
|
76
|
+
: 'bg-gray-100 text-gray-900',
|
|
77
|
+
'ml-3 hidden rounded-full py-0.5 px-2.5 text-xs font-medium md:inline-block'
|
|
78
|
+
]"
|
|
79
|
+
>
|
|
80
|
+
{{ tab.count }}
|
|
81
|
+
</span>
|
|
82
|
+
</button>
|
|
83
|
+
</nav>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div class="tabs-content mt-4">
|
|
87
|
+
<template v-for="tab in tabs" :key="tab.id">
|
|
88
|
+
<div v-if="currentTab === tab.id">
|
|
89
|
+
<slot :name="tab.id" :active-tab="currentTab" />
|
|
90
|
+
</div>
|
|
91
|
+
</template>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
</template>
|
|
95
|
+
|
|
96
|
+
<style scoped>
|
|
97
|
+
.tabs-wrapper {
|
|
98
|
+
width: 100%;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.tabs-content {
|
|
102
|
+
margin-top: 1rem;
|
|
103
|
+
}
|
|
104
|
+
</style>
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, computed } from 'vue';
|
|
3
|
+
import { Alert } from '@htlkg/components';
|
|
4
|
+
|
|
5
|
+
// State for different alert types
|
|
6
|
+
const showInfo = ref(true);
|
|
7
|
+
const showSuccess = ref(true);
|
|
8
|
+
const showWarning = ref(true);
|
|
9
|
+
const showDanger = ref(true);
|
|
10
|
+
const showWithActions = ref(true);
|
|
11
|
+
const showLoading = ref(true);
|
|
12
|
+
|
|
13
|
+
// Interactive demo state
|
|
14
|
+
const actionLog = ref<string[]>([]);
|
|
15
|
+
const showInteractive = ref(true);
|
|
16
|
+
const interactiveType = ref<'info' | 'success' | 'warning' | 'danger'>('warning');
|
|
17
|
+
const processingAction = ref(false);
|
|
18
|
+
const actionResult = ref<string>('');
|
|
19
|
+
|
|
20
|
+
// Actions for interactive alert
|
|
21
|
+
const actions = [
|
|
22
|
+
{ name: 'Confirm', event: 'confirm' },
|
|
23
|
+
{ name: 'Cancel', event: 'cancel' }
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
// Interactive alert actions - changes based on state
|
|
27
|
+
const interactiveActions = computed(() => {
|
|
28
|
+
if (actionResult.value) {
|
|
29
|
+
return [{ name: 'Close', event: 'close' }];
|
|
30
|
+
}
|
|
31
|
+
return [
|
|
32
|
+
{ name: 'Approve', event: 'approve' },
|
|
33
|
+
{ name: 'Reject', event: 'reject' },
|
|
34
|
+
{ name: 'Ask Later', event: 'later' }
|
|
35
|
+
];
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Handle alert events
|
|
39
|
+
const handleAlertEvent = (event: string) => {
|
|
40
|
+
console.log('Alert event:', event);
|
|
41
|
+
if (event === 'confirm') {
|
|
42
|
+
alert('Confirmed!');
|
|
43
|
+
showWithActions.value = false;
|
|
44
|
+
} else if (event === 'cancel') {
|
|
45
|
+
showWithActions.value = false;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Handle interactive alert events
|
|
50
|
+
const handleInteractiveEvent = async (event: string) => {
|
|
51
|
+
console.log('๐ฅ handleInteractiveEvent called with:', event, typeof event);
|
|
52
|
+
|
|
53
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
54
|
+
actionLog.value.unshift(`[${timestamp}] ๐ฑ๏ธ Action clicked: ${event}`);
|
|
55
|
+
|
|
56
|
+
// Handle close action
|
|
57
|
+
if (event === 'close') {
|
|
58
|
+
actionLog.value.unshift(`[${timestamp}] ๐ช Alert closed`);
|
|
59
|
+
resetInteractive();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
processingAction.value = true;
|
|
64
|
+
actionResult.value = '';
|
|
65
|
+
|
|
66
|
+
// Simulate processing
|
|
67
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
68
|
+
|
|
69
|
+
processingAction.value = false;
|
|
70
|
+
|
|
71
|
+
if (event === 'approve') {
|
|
72
|
+
actionResult.value = 'โ
Request approved successfully!';
|
|
73
|
+
interactiveType.value = 'success';
|
|
74
|
+
actionLog.value.unshift(`[${timestamp}] โ
Request approved`);
|
|
75
|
+
} else if (event === 'reject') {
|
|
76
|
+
actionResult.value = 'โ Request rejected';
|
|
77
|
+
interactiveType.value = 'danger';
|
|
78
|
+
actionLog.value.unshift(`[${timestamp}] โ Request rejected`);
|
|
79
|
+
} else if (event === 'later') {
|
|
80
|
+
actionResult.value = 'โฐ Reminder set for later';
|
|
81
|
+
interactiveType.value = 'info';
|
|
82
|
+
actionLog.value.unshift(`[${timestamp}] โฐ Reminder set`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Keep only last 15 log entries
|
|
86
|
+
if (actionLog.value.length > 15) {
|
|
87
|
+
actionLog.value = actionLog.value.slice(0, 15);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// Reset interactive demo
|
|
92
|
+
const resetInteractive = () => {
|
|
93
|
+
showInteractive.value = true;
|
|
94
|
+
interactiveType.value = 'warning';
|
|
95
|
+
actionResult.value = '';
|
|
96
|
+
actionLog.value = [];
|
|
97
|
+
processingAction.value = false;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// Simulate loading
|
|
101
|
+
setTimeout(() => {
|
|
102
|
+
showLoading.value = false;
|
|
103
|
+
}, 2000);
|
|
104
|
+
</script>
|
|
105
|
+
|
|
106
|
+
<template>
|
|
107
|
+
<div class="space-y-8">
|
|
108
|
+
<!-- Info Alert -->
|
|
109
|
+
<section>
|
|
110
|
+
<h2 class="text-2xl font-semibold mb-4">Info Alert</h2>
|
|
111
|
+
<Alert
|
|
112
|
+
v-model:show="showInfo"
|
|
113
|
+
title="System Update Available"
|
|
114
|
+
type="info"
|
|
115
|
+
>
|
|
116
|
+
We've updated our Design System to version 1.0. Review the changes and update your components.
|
|
117
|
+
</Alert>
|
|
118
|
+
<button
|
|
119
|
+
v-if="!showInfo"
|
|
120
|
+
@click="showInfo = true"
|
|
121
|
+
class="mt-2 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
|
|
122
|
+
>
|
|
123
|
+
Show Info Alert
|
|
124
|
+
</button>
|
|
125
|
+
</section>
|
|
126
|
+
|
|
127
|
+
<!-- Success Alert -->
|
|
128
|
+
<section>
|
|
129
|
+
<h2 class="text-2xl font-semibold mb-4">Success Alert</h2>
|
|
130
|
+
<Alert
|
|
131
|
+
v-model:show="showSuccess"
|
|
132
|
+
title="Operation Completed"
|
|
133
|
+
type="success"
|
|
134
|
+
>
|
|
135
|
+
The reservation has been created successfully and confirmation has been sent to the guest.
|
|
136
|
+
</Alert>
|
|
137
|
+
<button
|
|
138
|
+
v-if="!showSuccess"
|
|
139
|
+
@click="showSuccess = true"
|
|
140
|
+
class="mt-2 px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600"
|
|
141
|
+
>
|
|
142
|
+
Show Success Alert
|
|
143
|
+
</button>
|
|
144
|
+
</section>
|
|
145
|
+
|
|
146
|
+
<!-- Warning Alert -->
|
|
147
|
+
<section>
|
|
148
|
+
<h2 class="text-2xl font-semibold mb-4">Warning Alert</h2>
|
|
149
|
+
<Alert
|
|
150
|
+
v-model:show="showWarning"
|
|
151
|
+
title="Attention Required"
|
|
152
|
+
type="warning"
|
|
153
|
+
>
|
|
154
|
+
The reservation will be permanently cancelled. This action cannot be undone.
|
|
155
|
+
</Alert>
|
|
156
|
+
<button
|
|
157
|
+
v-if="!showWarning"
|
|
158
|
+
@click="showWarning = true"
|
|
159
|
+
class="mt-2 px-4 py-2 bg-yellow-500 text-white rounded hover:bg-yellow-600"
|
|
160
|
+
>
|
|
161
|
+
Show Warning Alert
|
|
162
|
+
</button>
|
|
163
|
+
</section>
|
|
164
|
+
|
|
165
|
+
<!-- Danger Alert -->
|
|
166
|
+
<section>
|
|
167
|
+
<h2 class="text-2xl font-semibold mb-4">Danger Alert</h2>
|
|
168
|
+
<Alert
|
|
169
|
+
v-model:show="showDanger"
|
|
170
|
+
title="Error Processing Request"
|
|
171
|
+
type="danger"
|
|
172
|
+
>
|
|
173
|
+
Could not connect to the server. Please try again later.
|
|
174
|
+
</Alert>
|
|
175
|
+
<button
|
|
176
|
+
v-if="!showDanger"
|
|
177
|
+
@click="showDanger = true"
|
|
178
|
+
class="mt-2 px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600"
|
|
179
|
+
>
|
|
180
|
+
Show Danger Alert
|
|
181
|
+
</button>
|
|
182
|
+
</section>
|
|
183
|
+
|
|
184
|
+
<!-- Alert with Actions -->
|
|
185
|
+
<section>
|
|
186
|
+
<h2 class="text-2xl font-semibold mb-4">Alert with Actions</h2>
|
|
187
|
+
<Alert
|
|
188
|
+
v-model:show="showWithActions"
|
|
189
|
+
title="Confirm Deletion"
|
|
190
|
+
type="warning"
|
|
191
|
+
:actions="actions"
|
|
192
|
+
@alertEvent="handleAlertEvent"
|
|
193
|
+
>
|
|
194
|
+
Are you sure you want to delete this item? This action cannot be undone.
|
|
195
|
+
</Alert>
|
|
196
|
+
<button
|
|
197
|
+
v-if="!showWithActions"
|
|
198
|
+
@click="showWithActions = true"
|
|
199
|
+
class="mt-2 px-4 py-2 bg-yellow-500 text-white rounded hover:bg-yellow-600"
|
|
200
|
+
>
|
|
201
|
+
Show Alert with Actions
|
|
202
|
+
</button>
|
|
203
|
+
</section>
|
|
204
|
+
|
|
205
|
+
<!-- Interactive Actions Demo -->
|
|
206
|
+
<section class="bg-gradient-to-br from-purple-50 to-blue-50">
|
|
207
|
+
<h2 class="text-2xl font-semibold mb-4">๐ฎ Interactive Actions Demo</h2>
|
|
208
|
+
<p class="text-gray-600 mb-4">
|
|
209
|
+
Click the action buttons in the alert to see real-time feedback. The alert type, title, content, and available actions all change dynamically!
|
|
210
|
+
</p>
|
|
211
|
+
|
|
212
|
+
<div class="mb-4 p-3 bg-blue-50 border border-blue-200 rounded text-sm">
|
|
213
|
+
<strong>๐ก Try this:</strong> Click "Approve", "Reject", or "Ask Later" and watch the alert transform with different colors, messages, and actions!
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<div class="grid md:grid-cols-2 gap-6">
|
|
217
|
+
<!-- Alert Section -->
|
|
218
|
+
<div>
|
|
219
|
+
<div class="mb-3 flex gap-2 text-xs">
|
|
220
|
+
<span class="px-2 py-1 bg-gray-100 rounded">
|
|
221
|
+
Type: <strong>{{ interactiveType }}</strong>
|
|
222
|
+
</span>
|
|
223
|
+
<span class="px-2 py-1 bg-gray-100 rounded">
|
|
224
|
+
Actions: <strong>{{ interactiveActions.length }}</strong>
|
|
225
|
+
</span>
|
|
226
|
+
<span class="px-2 py-1 bg-gray-100 rounded">
|
|
227
|
+
Loading: <strong>{{ processingAction ? 'Yes' : 'No' }}</strong>
|
|
228
|
+
</span>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<Alert
|
|
232
|
+
v-model:show="showInteractive"
|
|
233
|
+
:title="processingAction ? 'Processing...' : actionResult || 'Approval Required'"
|
|
234
|
+
:type="interactiveType"
|
|
235
|
+
:actions="interactiveActions"
|
|
236
|
+
:loading="processingAction"
|
|
237
|
+
@alertEvent="handleInteractiveEvent"
|
|
238
|
+
@alert-event="handleInteractiveEvent"
|
|
239
|
+
>
|
|
240
|
+
<div v-if="!actionResult">
|
|
241
|
+
<p class="mb-2">A new request requires your attention:</p>
|
|
242
|
+
<ul class="list-disc list-inside space-y-1 text-sm">
|
|
243
|
+
<li>User: John Doe</li>
|
|
244
|
+
<li>Action: Update pricing</li>
|
|
245
|
+
<li>Priority: High</li>
|
|
246
|
+
</ul>
|
|
247
|
+
</div>
|
|
248
|
+
<div v-else>
|
|
249
|
+
<p class="font-medium">{{ actionResult }}</p>
|
|
250
|
+
<p class="text-sm mt-2 opacity-75">Click "Close" to reset and try again!</p>
|
|
251
|
+
</div>
|
|
252
|
+
</Alert>
|
|
253
|
+
|
|
254
|
+
<div class="mt-4 flex gap-2 flex-wrap">
|
|
255
|
+
<button
|
|
256
|
+
@click="resetInteractive"
|
|
257
|
+
class="px-4 py-2 bg-purple-500 text-white rounded hover:bg-purple-600 transition-colors"
|
|
258
|
+
>
|
|
259
|
+
๐ Reset Demo
|
|
260
|
+
</button>
|
|
261
|
+
<button
|
|
262
|
+
@click="showInteractive = !showInteractive"
|
|
263
|
+
class="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 transition-colors"
|
|
264
|
+
>
|
|
265
|
+
{{ showInteractive ? '๐๏ธ Hide' : '๐๏ธ Show' }} Alert
|
|
266
|
+
</button>
|
|
267
|
+
<button
|
|
268
|
+
@click="handleInteractiveEvent('approve')"
|
|
269
|
+
class="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 transition-colors text-sm"
|
|
270
|
+
>
|
|
271
|
+
๐งช Test Approve
|
|
272
|
+
</button>
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
|
|
276
|
+
<!-- Action Log Section -->
|
|
277
|
+
<div>
|
|
278
|
+
<h3 class="text-lg font-semibold mb-2">๐ Action Log</h3>
|
|
279
|
+
<div class="bg-gray-900 text-green-400 p-4 rounded font-mono text-sm h-64 overflow-y-auto">
|
|
280
|
+
<div v-if="actionLog.length === 0" class="text-gray-500">
|
|
281
|
+
No actions yet. Click a button to see the log...
|
|
282
|
+
</div>
|
|
283
|
+
<div v-for="(log, index) in actionLog" :key="index" class="mb-1">
|
|
284
|
+
{{ log }}
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
<div class="mt-2 text-sm text-gray-600">
|
|
288
|
+
Total actions: {{ actionLog.length }}
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
</section>
|
|
293
|
+
|
|
294
|
+
<!-- Loading Alert -->
|
|
295
|
+
<section>
|
|
296
|
+
<h2 class="text-2xl font-semibold mb-4">Loading Alert</h2>
|
|
297
|
+
<Alert
|
|
298
|
+
v-model:show="showLoading"
|
|
299
|
+
title="Loading Information..."
|
|
300
|
+
type="info"
|
|
301
|
+
:loading="true"
|
|
302
|
+
>
|
|
303
|
+
Preparing system update
|
|
304
|
+
</Alert>
|
|
305
|
+
<p v-if="!showLoading" class="text-gray-600 mt-2">
|
|
306
|
+
Loading complete!
|
|
307
|
+
</p>
|
|
308
|
+
</section>
|
|
309
|
+
|
|
310
|
+
<!-- Rich Content Alert -->
|
|
311
|
+
<section>
|
|
312
|
+
<h2 class="text-2xl font-semibold mb-4">Alert with Rich Content</h2>
|
|
313
|
+
<Alert
|
|
314
|
+
title="New Features Available"
|
|
315
|
+
type="success"
|
|
316
|
+
:actions="[
|
|
317
|
+
{ name: 'Explore', event: 'explore' },
|
|
318
|
+
{ name: 'Later', event: 'later' }
|
|
319
|
+
]"
|
|
320
|
+
@alertEvent="(e) => console.log('Rich content alert:', e)"
|
|
321
|
+
>
|
|
322
|
+
<p class="mb-2">
|
|
323
|
+
<strong>Update 1.0:</strong> We've added new features:
|
|
324
|
+
</p>
|
|
325
|
+
<ul class="list-disc list-inside space-y-1">
|
|
326
|
+
<li>Improved pricing calendar</li>
|
|
327
|
+
<li>New notification system</li>
|
|
328
|
+
<li>Performance optimization</li>
|
|
329
|
+
</ul>
|
|
330
|
+
</Alert>
|
|
331
|
+
</section>
|
|
332
|
+
|
|
333
|
+
<!-- Code Example -->
|
|
334
|
+
<section class="mt-12">
|
|
335
|
+
<h2 class="text-2xl font-semibold mb-4">Usage Example</h2>
|
|
336
|
+
<pre class="bg-gray-100 p-4 rounded overflow-x-auto"><code><script setup>
|
|
337
|
+
import { ref } from 'vue';
|
|
338
|
+
import { Alert } from '@htlkg/components';
|
|
339
|
+
|
|
340
|
+
const showAlert = ref(true);
|
|
341
|
+
const actions = [
|
|
342
|
+
{ name: 'Confirm', event: 'confirm' },
|
|
343
|
+
{ name: 'Cancel', event: 'cancel' }
|
|
344
|
+
];
|
|
345
|
+
|
|
346
|
+
const handleAlertEvent = (event) => {
|
|
347
|
+
console.log('Alert event:', event);
|
|
348
|
+
if (event === 'confirm') {
|
|
349
|
+
// Handle confirmation
|
|
350
|
+
showAlert.value = false;
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
</script>
|
|
354
|
+
|
|
355
|
+
<template>
|
|
356
|
+
<Alert
|
|
357
|
+
v-model:show="showAlert"
|
|
358
|
+
title="Confirm Action"
|
|
359
|
+
type="warning"
|
|
360
|
+
:actions="actions"
|
|
361
|
+
@alertEvent="handleAlertEvent"
|
|
362
|
+
>
|
|
363
|
+
Are you sure you want to proceed?
|
|
364
|
+
</Alert>
|
|
365
|
+
</template></code></pre>
|
|
366
|
+
</section>
|
|
367
|
+
</div>
|
|
368
|
+
</template>
|
|
369
|
+
|
|
370
|
+
<style scoped>
|
|
371
|
+
section {
|
|
372
|
+
padding: 1rem;
|
|
373
|
+
border: 1px solid #e5e7eb;
|
|
374
|
+
border-radius: 0.5rem;
|
|
375
|
+
background: white;
|
|
376
|
+
}
|
|
377
|
+
</style>
|