@coffic/cosy-ui 0.6.18 → 0.6.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/app.css +1 -1
  2. package/dist/assets/iconData.ts +5 -0
  3. package/dist/env.d.ts +12 -0
  4. package/dist/icons/AstroIcon.astro +1 -1
  5. package/dist/icons/InboxArchive.astro +23 -0
  6. package/dist/index_icons.ts +1 -0
  7. package/dist/index_vue.ts +10 -4
  8. package/dist/vue/BlogList/Basic.vue +30 -0
  9. package/dist/vue/BlogList/BlogList.vue +100 -0
  10. package/dist/vue/BlogList/Empty.vue +8 -0
  11. package/dist/vue/BlogList/EmptyEnglish.vue +8 -0
  12. package/dist/vue/BlogList/English.vue +24 -0
  13. package/dist/vue/BlogList/index.ts +50 -0
  14. package/dist/vue/Buttons/FeatureBasic.vue +8 -0
  15. package/dist/vue/{FeatureButton.vue → Buttons/FeatureButton.vue} +7 -10
  16. package/dist/vue/Buttons/FeatureWithTips.vue +8 -0
  17. package/dist/vue/Buttons/LinkBasic.vue +8 -0
  18. package/dist/vue/Buttons/LinkButton.vue +65 -0
  19. package/dist/vue/Buttons/Multiple.vue +11 -0
  20. package/dist/vue/Buttons/index.ts +59 -0
  21. package/dist/vue/ConfirmDialog/Basic.vue +57 -0
  22. package/dist/vue/ConfirmDialog/ConfirmDialog.vue +134 -0
  23. package/dist/vue/ConfirmDialog/CustomButtons.vue +69 -0
  24. package/dist/vue/ConfirmDialog/index.ts +58 -0
  25. package/dist/vue/Icons/InboxArchiveIcon.vue +30 -0
  26. package/dist/vue/SmartHero/Basic.vue +14 -0
  27. package/dist/vue/SmartHero/SmartHero.vue +132 -0
  28. package/dist/vue/SmartHero/WithCustomContent.vue +36 -0
  29. package/dist/vue/SmartHero/WithImage.vue +19 -0
  30. package/dist/vue/SmartHero/index.ts +46 -0
  31. package/dist/vue/SmartLink.vue +7 -11
  32. package/package.json +1 -1
  33. package/dist/vue/ConfirmDialog.vue +0 -76
  34. package/dist/vue/SmartHero.vue +0 -88
@@ -0,0 +1,134 @@
1
+ <!--
2
+ @component ConfirmDialog
3
+
4
+ @description
5
+ ConfirmDialog 组件用于显示确认对话框,带有标题、消息内容和两个按钮(确认和取消),支持自定义按钮文本,并带有淡入淡出动画效果。
6
+
7
+ @usage
8
+ 基本用法:
9
+ ```vue
10
+ <ConfirmDialog v-model="showDialog" title="确认操作" message="您确定要执行此操作吗?" @confirm="handleConfirm" />
11
+ ```
12
+
13
+ 自定义按钮文本:
14
+ ```vue
15
+ <ConfirmDialog
16
+ v-model="showDialog"
17
+ title="删除确认"
18
+ message="您确定要删除此项目吗?此操作无法撤销。"
19
+ cancel-text="取消"
20
+ confirm-text="删除"
21
+ @confirm="handleDelete"
22
+ />
23
+ ```
24
+
25
+ 组合使用:
26
+ ```vue
27
+ <template>
28
+ <button @click="showDialog = true">删除项目</button>
29
+ <ConfirmDialog v-model="showDialog" title="删除确认" message="此操作无法撤销" @confirm="handleDelete" />
30
+ </template>
31
+
32
+ <script setup lang="ts">
33
+ import { ref } from 'vue';
34
+ import { ConfirmDialog } from 'cosy-ui';
35
+
36
+ const showDialog = ref(false);
37
+ const handleDelete = () => {
38
+ // 处理确认删除逻辑
39
+ };
40
+ </script>
41
+ ```
42
+
43
+ @props
44
+ @prop {boolean} modelValue - 控制对话框显示状态,支持v-model双向绑定
45
+ @prop {string} [title='Confirm'] - 对话框标题
46
+ @prop {string} [message='Are you sure you want to confirm this action?'] - 对话框显示的消息内容
47
+ @prop {string} [cancel-text='取消'] - 取消按钮的文本
48
+ @prop {string} [confirm-text='确认'] - 确认按钮的文本
49
+
50
+ @emits
51
+ @emit {update:modelValue} - 当对话框关闭时触发,用于更新v-model绑定值
52
+ @emit {confirm} - 当用户点击确认按钮时触发
53
+ -->
54
+
55
+ <template>
56
+ <Transition name="fade" class="cosy:transition-opacity cosy:duration-200 cosy:ease-in-out">
57
+ <div v-if="modelValue"
58
+ class="cosy:fixed cosy:inset-0 cosy:z-50 cosy:flex cosy:items-center cosy:justify-center">
59
+ <!-- 背景遮罩 -->
60
+ <div class="cosy:absolute cosy:inset-0 cosy:bg-base-200/80 cosy:backdrop-blur-sm"
61
+ @click="$emit('update:modelValue', false)" />
62
+
63
+ <!-- 对话框 -->
64
+ <div
65
+ class="cosy:relative cosy:bg-base-100 cosy:rounded-xl cosy:shadow-xl cosy:w-[400px] cosy:transform cosy:transition-all">
66
+ <!-- 内容区域 -->
67
+ <div class="cosy:p-6">
68
+ <h3 class="cosy:text-lg cosy:font-medium cosy:text-base-content cosy:mb-2">
69
+ {{ title }}
70
+ </h3>
71
+ <p class="cosy:text-base-content/80">
72
+ {{ message }}
73
+ </p>
74
+ </div>
75
+
76
+ <!-- 按钮区域 -->
77
+ <div class="cosy:flex cosy:border-t cosy:border-base-300">
78
+ <button class="cosy:flex-1 cosy:btn cosy:btn-ghost cosy:rounded-none cosy:rounded-bl-xl"
79
+ @click="$emit('update:modelValue', false)">
80
+ {{ cancelText }}
81
+ </button>
82
+ <button
83
+ class="cosy:flex-1 cosy:btn cosy:btn-ghost cosy:text-primary cosy:rounded-none cosy:rounded-br-xl cosy:border-l cosy:border-base-300"
84
+ @click="handleConfirm">
85
+ {{ confirmText }}
86
+ </button>
87
+ </div>
88
+ </div>
89
+ </div>
90
+ </Transition>
91
+ </template>
92
+
93
+ <script setup lang="ts">
94
+ import '../../style'
95
+
96
+ defineProps({
97
+ modelValue: Boolean,
98
+ title: {
99
+ type: String,
100
+ default: 'Confirm'
101
+ },
102
+ message: {
103
+ type: String,
104
+ default: 'Are you sure you want to confirm this action?'
105
+ },
106
+ cancelText: {
107
+ type: String,
108
+ default: '取消'
109
+ },
110
+ confirmText: {
111
+ type: String,
112
+ default: '确认'
113
+ }
114
+ })
115
+
116
+ const emit = defineEmits(['update:modelValue', 'confirm'])
117
+
118
+ const handleConfirm = () => {
119
+ emit('update:modelValue', false)
120
+ emit('confirm')
121
+ }
122
+ </script>
123
+
124
+ <style scoped>
125
+ .fade-enter-active,
126
+ .fade-leave-active {
127
+ transition: opacity 0.2s ease;
128
+ }
129
+
130
+ .fade-enter-from,
131
+ .fade-leave-to {
132
+ opacity: 0;
133
+ }
134
+ </style>
@@ -0,0 +1,69 @@
1
+ <!--
2
+ @component ConfirmDialog.CustomButtons
3
+
4
+ @description
5
+ 展示如何自定义 ConfirmDialog 组件的按钮文本。
6
+
7
+ @usage
8
+ ```vue
9
+ <ConfirmDialogExamples.CustomButtons />
10
+ ```
11
+ -->
12
+
13
+ <script lang="ts">
14
+ import '../../app.css'
15
+ import { ref, defineComponent } from 'vue'
16
+ import ConfirmDialog from './ConfirmDialog.vue'
17
+
18
+ export default defineComponent({
19
+ name: 'ConfirmDialogCustomButtonsExample',
20
+ components: {
21
+ ConfirmDialog
22
+ },
23
+ setup() {
24
+ const isShowDelete = ref(false)
25
+ const isShowSave = ref(false)
26
+ const result = ref('')
27
+
28
+ const handleConfirm = (action: string) => {
29
+ result.value = `用户已${action}`
30
+
31
+ // 3秒后清除结果
32
+ setTimeout(() => {
33
+ result.value = ''
34
+ }, 3000)
35
+ }
36
+
37
+ return {
38
+ isShowDelete,
39
+ isShowSave,
40
+ result,
41
+ handleConfirm
42
+ }
43
+ }
44
+ })
45
+ </script>
46
+
47
+ <template>
48
+ <div class="cosy:flex cosy:flex-col cosy:gap-4">
49
+ <div class="cosy:flex cosy:gap-4">
50
+ <button @click="isShowDelete = true" class="cosy:btn cosy:btn-error">
51
+ 删除文件
52
+ </button>
53
+
54
+ <button @click="isShowSave = true" class="cosy:btn cosy:btn-success">
55
+ 保存更改
56
+ </button>
57
+ </div>
58
+
59
+ <div v-if="result" class="cosy:alert cosy:alert-info cosy:shadow-lg">
60
+ <span>{{ result }}</span>
61
+ </div>
62
+ </div>
63
+
64
+ <ConfirmDialog v-model="isShowDelete" title="警告" message="您确定要删除这个文件吗?此操作无法撤销。" cancel-text="取消" confirm-text="删除"
65
+ @confirm="handleConfirm('删除了文件')" />
66
+
67
+ <ConfirmDialog v-model="isShowSave" title="保存更改" message="您的更改尚未保存,确定要保存吗?" cancel-text="稍后再说" confirm-text="保存"
68
+ @confirm="handleConfirm('保存了更改')" />
69
+ </template>
@@ -0,0 +1,58 @@
1
+ import Basic from './Basic.vue';
2
+ import CustomButtons from './CustomButtons.vue';
3
+ import BasicSource from './Basic.vue?raw';
4
+ import CustomButtonsSource from './CustomButtons.vue?raw';
5
+
6
+ // 提取简单示例源代码函数
7
+ function extractSimpleExample(source: string): string {
8
+ // 提取模板部分
9
+ const templateMatch = source.match(/<template>([\s\S]*)<\/template>/m);
10
+ const scriptMatch = source.match(/<script[\s\S]*?>([\s\S]*)<\/script>/m);
11
+
12
+ if (!templateMatch) {
13
+ return source;
14
+ }
15
+
16
+ let importSection = `<script setup lang="ts">
17
+ import { ref } from 'vue'
18
+ import { ConfirmDialog } from '@cosy/index_vue'
19
+ `;
20
+
21
+ // 从源码中提取导入语句(除了组件的导入和app.css)
22
+ if (scriptMatch && scriptMatch[1]) {
23
+ const importLines = scriptMatch[1]
24
+ .split('\n')
25
+ .filter(
26
+ (line) =>
27
+ line.includes('import') &&
28
+ !line.includes('../../app.css') &&
29
+ !line.includes('ConfirmDialog')
30
+ );
31
+
32
+ if (importLines.length > 0) {
33
+ importSection += importLines.join('\n') + '\n';
34
+ }
35
+ }
36
+
37
+ importSection += '</script>\n\n';
38
+
39
+ // 提取模板内容,并替换组件路径
40
+ const templateContent = templateMatch[1].replace('../ConfirmDialog.vue', 'ConfirmDialog');
41
+
42
+ return importSection + '<template>' + templateContent + '</template>';
43
+ }
44
+
45
+ // 导出主组件
46
+ export { default as ConfirmDialog } from './ConfirmDialog.vue';
47
+
48
+ // 导出示例组件
49
+ export const ConfirmDialogExamples = {
50
+ Basic,
51
+ CustomButtons,
52
+ };
53
+
54
+ // 导出示例源代码
55
+ export const ConfirmDialogExampleCodes = {
56
+ Basic: extractSimpleExample(BasicSource),
57
+ CustomButtons: extractSimpleExample(CustomButtonsSource),
58
+ };
@@ -0,0 +1,30 @@
1
+ <script setup lang="ts">
2
+ import Icon from './VueIcon.vue';
3
+
4
+ interface Props {
5
+ /**
6
+ * 图标的大小
7
+ * @default "24px"
8
+ */
9
+ size?: string;
10
+ /**
11
+ * 图标的颜色
12
+ * @default "currentColor"
13
+ */
14
+ color?: string;
15
+ /**
16
+ * 自定义类名
17
+ */
18
+ class?: string;
19
+ }
20
+
21
+ const props = withDefaults(defineProps<Props>(), {
22
+ size: '24px',
23
+ color: 'currentColor',
24
+ class: ''
25
+ });
26
+ </script>
27
+
28
+ <template>
29
+ <Icon name="inboxArchive" :size="size" :color="color" :class="props.class" />
30
+ </template>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <SmartHero title="智能英雄组件" description="一个现代化的页面英雄区域组件,适合用作页面顶部的展示区域" :links="links" />
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ import '../../style';
7
+ import { ref } from 'vue';
8
+ import SmartHero from './SmartHero.vue';
9
+
10
+ const links = ref([
11
+ { text: '了解更多', href: '#' },
12
+ { text: '查看文档', href: '#docs' }
13
+ ]);
14
+ </script>
@@ -0,0 +1,132 @@
1
+ <!--
2
+ @component SmartHero
3
+
4
+ @description
5
+ SmartHero 组件是一个响应式的英雄区域组件,用于展示标题、描述、图片和操作链接。
6
+ 支持自定义内容插槽,适合用作页面顶部的展示区域。
7
+
8
+ @usage
9
+ 基本用法:
10
+ ```vue
11
+ <SmartHero
12
+ title="智能英雄组件"
13
+ description="一个现代化的页面英雄区域组件"
14
+ :links="[{text: '了解更多', href: '#'}]"
15
+ />
16
+ ```
17
+
18
+ 带图片:
19
+ ```vue
20
+ <SmartHero
21
+ title="智能英雄组件"
22
+ description="一个现代化的页面英雄区域组件"
23
+ :image="{src: '/images/hero.png', alt: '英雄图片'}"
24
+ :links="[{text: '了解更多', href: '#'}, {text: '查看文档', href: '#docs'}]"
25
+ />
26
+ ```
27
+
28
+ 使用插槽:
29
+ ```vue
30
+ <SmartHero
31
+ title="智能英雄组件"
32
+ description="一个现代化的页面英雄区域组件"
33
+ :links="[{text: '了解更多', href: '#'}]"
34
+ >
35
+ <template #app>
36
+ <div class="demo-app">自定义内容</div>
37
+ </template>
38
+ </SmartHero>
39
+ ```
40
+
41
+ @props
42
+ @prop {string} title - 标题文本
43
+ @prop {string} description - 描述文本
44
+ @prop {object} [image] - 图片配置对象,包含src和alt属性
45
+ @prop {array} links - 链接数组,每个链接包含text和href属性
46
+
47
+ @slots
48
+ @slot app - 用于插入自定义应用或组件展示
49
+ -->
50
+
51
+ <script setup lang="ts">
52
+ import '../../style';
53
+ import type { PropType } from 'vue';
54
+ import LinkButton from '../Buttons/LinkButton.vue';
55
+
56
+ interface Link {
57
+ text: string;
58
+ href: string;
59
+ }
60
+
61
+ interface ImageProps {
62
+ src: string;
63
+ alt: string;
64
+ }
65
+
66
+ defineProps({
67
+ title: {
68
+ type: String,
69
+ required: true
70
+ },
71
+ description: {
72
+ type: String,
73
+ required: true
74
+ },
75
+ image: {
76
+ type: Object as PropType<ImageProps>,
77
+ required: false,
78
+ default: () => ({
79
+ src: '',
80
+ alt: ''
81
+ })
82
+ },
83
+ links: {
84
+ type: Array as PropType<Link[]>,
85
+ required: true,
86
+ default: () => []
87
+ }
88
+ });
89
+ </script>
90
+
91
+ <template>
92
+ <div class="cosy:py-16 cosy:px-8 cosy:text-center cosy:w-full cosy:min-h-screen cosy:relative cosy:overflow-hidden">
93
+ <div class="cosy:relative cosy:z-10 cosy:rounded-lg cosy:w-full cosy:h-full">
94
+ <template v-if="image.src">
95
+ <img :src="image.src" :alt="image.alt" class="cosy:h-1/2 cosy:mx-auto cosy:mb-8 cosy:drop-shadow-xl">
96
+ </template>
97
+
98
+ <h2 class="cosy:text-4xl cosy:mb-4 cosy:animate-fade-up">
99
+ {{ title }}
100
+ </h2>
101
+ <p class="cosy:text-lg cosy:mb-12 cosy:text-center cosy:max-w-2xl cosy:mx-auto">
102
+ {{ description }}
103
+ </p>
104
+
105
+ <div class="cosy:my-12 cosy:w-full">
106
+ <slot name="app" />
107
+ </div>
108
+
109
+ <div class="cosy:flex cosy:flex-row cosy:justify-center cosy:gap-8 cosy:mx-auto cosy:w-full">
110
+ <LinkButton v-for="link in links" :key="link.text" :text="link.text" :href="link.href" />
111
+ </div>
112
+ </div>
113
+ </div>
114
+ </template>
115
+
116
+ <style scoped>
117
+ @keyframes fade-up {
118
+ from {
119
+ opacity: 0;
120
+ transform: translateY(-20px);
121
+ }
122
+
123
+ to {
124
+ opacity: 1;
125
+ transform: translateY(0);
126
+ }
127
+ }
128
+
129
+ .cosy\:animate-fade-up {
130
+ animation: fade-up 0.8s ease-out forwards;
131
+ }
132
+ </style>
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <SmartHero title="支持自定义内容" description="这个示例展示了如何使用插槽添加自定义内容" :links="links">
3
+ <template #app>
4
+ <div class="cosy:p-6 cosy:bg-base-200 cosy:rounded-xl cosy:max-w-lg cosy:mx-auto cosy:shadow-lg">
5
+ <div class="cosy:bg-base-100 cosy:p-4 cosy:rounded-lg cosy:text-left">
6
+ <div class="cosy:font-mono cosy:text-sm cosy:mb-2 cosy:text-success">// 示例代码</div>
7
+ <div class="cosy:font-mono cosy:text-sm">
8
+ <div><span class="cosy:text-primary">&lt;SmartHero</span></div>
9
+ <div class="cosy:pl-4"><span class="cosy:text-info">title</span>=<span
10
+ class="cosy:text-warning">"支持自定义内容"</span></div>
11
+ <div class="cosy:pl-4"><span class="cosy:text-info">description</span>=<span
12
+ class="cosy:text-warning">"自定义内容示例"</span></div>
13
+ <div class="cosy:pl-4">...</div>
14
+ <div><span class="cosy:text-primary">&gt;</span></div>
15
+ <div class="cosy:pl-2"><span class="cosy:text-primary">&lt;template</span> <span
16
+ class="cosy:text-info">#app</span><span class="cosy:text-primary">&gt;</span></div>
17
+ <div class="cosy:pl-4">// 您的自定义内容</div>
18
+ <div class="cosy:pl-2"><span class="cosy:text-primary">&lt;/template&gt;</span></div>
19
+ <div><span class="cosy:text-primary">&lt;/SmartHero&gt;</span></div>
20
+ </div>
21
+ </div>
22
+ </div>
23
+ </template>
24
+ </SmartHero>
25
+ </template>
26
+
27
+ <script setup lang="ts">
28
+ import '../../style';
29
+ import { ref } from 'vue';
30
+ import SmartHero from './SmartHero.vue';
31
+
32
+ const links = ref([
33
+ { text: '了解插槽', href: '#slots' },
34
+ { text: '查看文档', href: '#docs' }
35
+ ]);
36
+ </script>
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <SmartHero title="带图片的英雄组件" description="这是一个包含图片的英雄组件示例,展示了如何在顶部添加图片" :image="image" :links="links" />
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ import '../../style';
7
+ import { ref } from 'vue';
8
+ import SmartHero from './SmartHero.vue';
9
+
10
+ const image = ref({
11
+ src: 'https://via.placeholder.com/600x300/4F46E5/FFFFFF?text=Smart+Hero',
12
+ alt: '英雄图片示例'
13
+ });
14
+
15
+ const links = ref([
16
+ { text: '了解更多', href: '#' },
17
+ { text: '立即开始', href: '#get-started' }
18
+ ]);
19
+ </script>
@@ -0,0 +1,46 @@
1
+ import Basic from './Basic.vue';
2
+ import WithImage from './WithImage.vue';
3
+ import WithCustomContent from './WithCustomContent.vue';
4
+ import BasicSource from './Basic.vue?raw';
5
+ import WithImageSource from './WithImage.vue?raw';
6
+ import WithCustomContentSource from './WithCustomContent.vue?raw';
7
+
8
+ // 转换Vue SFC组件为简化的示例代码(只保留template和setup script)
9
+ function extractSimpleExample(source: string): string {
10
+ // 提取模板部分
11
+ const templateMatch = source.match(/<template>([\s\S]*?)<\/template>/);
12
+ const template = templateMatch ? templateMatch[1].trim() : '';
13
+
14
+ // 提取script setup部分(去除import部分)
15
+ const scriptMatch = source.match(/<script setup lang="ts">([\s\S]*?)<\/script>/);
16
+ let script = '';
17
+ if (scriptMatch) {
18
+ // 只保留相关变量定义,去除导入语句
19
+ script = scriptMatch[1]
20
+ .replace(/import [^;]+;/g, '')
21
+ .replace(/import SmartHero from '[^']+';/g, "import { SmartHero } from 'cosy-ui';")
22
+ .trim();
23
+ }
24
+
25
+ // 创建简化版本的代码
26
+ return `<template>${template}</template>
27
+
28
+ <script setup lang="ts">${script}</script>`;
29
+ }
30
+
31
+ // 导出主组件
32
+ export { default as SmartHero } from './SmartHero.vue';
33
+
34
+ // 将示例组件整合为一个对象导出
35
+ export const SmartHeroExamples = {
36
+ Basic,
37
+ WithImage,
38
+ WithCustomContent,
39
+ };
40
+
41
+ // 导出示例组件的源代码(简化版本)
42
+ export const SmartHeroExampleCodes = {
43
+ Basic: extractSimpleExample(BasicSource),
44
+ WithImage: extractSimpleExample(WithImageSource),
45
+ WithCustomContent: extractSimpleExample(WithCustomContentSource),
46
+ };
@@ -7,15 +7,11 @@ defineProps<{
7
7
  </script>
8
8
 
9
9
  <template>
10
- <a
11
- :href="href"
12
- :target="external ? '_blank' : undefined"
13
- :rel="external ? 'noopener noreferrer' : undefined"
14
- :class="{
15
- 'no-underline rounded-md p-1 transition-all duration-300 hover:text-primary/80': true,
16
- [externalClass]: external
17
- }"
18
- >
19
- <slot />
20
- </a>
10
+ <a :href="href" :target="external ? '_blank' : undefined" :rel="external ? 'noopener noreferrer' : undefined"
11
+ :class="{
12
+ 'cosy:no-underline cosy:rounded-md cosy:p-1 cosy:transition-all cosy:duration-300 cosy:hover:text-primary/80': true,
13
+ [externalClass]: external
14
+ }">
15
+ <slot />
16
+ </a>
21
17
  </template>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffic/cosy-ui",
3
- "version": "0.6.18",
3
+ "version": "0.6.20",
4
4
  "description": "An astro component library",
5
5
  "author": {
6
6
  "name": "nookery",
@@ -1,76 +0,0 @@
1
- <template>
2
- <Transition name="fade">
3
- <div
4
- v-if="modelValue"
5
- class="fixed inset-0 z-50 flex items-center justify-center"
6
- >
7
- <!-- 背景遮罩 -->
8
- <div
9
- class="absolute inset-0 bg-black/20 dark:bg-black/40 backdrop-blur-sm"
10
- @click="$emit('update:modelValue', false)"
11
- />
12
-
13
- <!-- 对话框 -->
14
- <div class="relative bg-white dark:bg-gray-800 rounded-xl shadow-xl w-[400px] transform transition-all">
15
- <!-- 内容区域 -->
16
- <div class="p-6">
17
- <h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-2">
18
- {{ title }}
19
- </h3>
20
- <p class="text-gray-600 dark:text-gray-300">
21
- {{ message }}
22
- </p>
23
- </div>
24
-
25
- <!-- 按钮区域 -->
26
- <div class="flex border-t border-gray-200 dark:border-gray-700">
27
- <button
28
- class="flex-1 px-4 py-3 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors rounded-bl-xl"
29
- @click="$emit('update:modelValue', false)"
30
- >
31
- 取消
32
- </button>
33
- <button
34
- class="flex-1 px-4 py-3 text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/30 transition-colors border-l border-gray-200 dark:border-gray-700 rounded-br-xl font-medium"
35
- @click="handleConfirm"
36
- >
37
- 确认
38
- </button>
39
- </div>
40
- </div>
41
- </div>
42
- </Transition>
43
- </template>
44
-
45
- <script setup>
46
- defineProps({
47
- modelValue: Boolean,
48
- title: {
49
- type: String,
50
- default: 'Confirm'
51
- },
52
- message: {
53
- type: String,
54
- default: 'Are you sure you want to confirm this action?'
55
- }
56
- })
57
-
58
- const emit = defineEmits(['update:modelValue', 'confirm'])
59
-
60
- const handleConfirm = () => {
61
- emit('update:modelValue', false)
62
- emit('confirm')
63
- }
64
- </script>
65
-
66
- <style scoped>
67
- .fade-enter-active,
68
- .fade-leave-active {
69
- transition: opacity 0.2s ease;
70
- }
71
-
72
- .fade-enter-from,
73
- .fade-leave-to {
74
- opacity: 0;
75
- }
76
- </style>