@coffic/cosy-ui 0.6.40 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/alert/{AlertBasicContainer.astro → EAlertBasicContainer.astro} +2 -2
  2. package/dist/alert/{AlertCustomStyleContainer.astro → EAlertCustomStyleContainer.astro} +2 -2
  3. package/dist/alert/{AlertTypesContainer.astro → EAlertTypesContainer.astro} +8 -8
  4. package/dist/alert/{AlertWithTitleContainer.astro → EAlertWithTitleContainer.astro} +2 -2
  5. package/dist/alert/index.ts +12 -12
  6. package/dist/app.css +1 -1
  7. package/dist/button/ButtonBasicContainer.astro +1 -7
  8. package/dist/button/ButtonLinkContainer.astro +1 -7
  9. package/dist/button/ButtonSizesContainer.astro +1 -7
  10. package/dist/button/ButtonVariantsContainer.astro +1 -8
  11. package/dist/button/ButtonWithIconsContainer.astro +2 -13
  12. package/dist/button/index_astro.ts +1 -3
  13. package/dist/code-container/CodeContainer.astro +2 -2
  14. package/dist/code-container/index.ts +7 -7
  15. package/dist/container/EContainerBasic.astro +13 -0
  16. package/dist/container/EContainerBasicContainer.astro +11 -0
  17. package/dist/container/EContainerFlexBetween.astro +16 -0
  18. package/dist/container/EContainerFlexCenter.astro +23 -0
  19. package/dist/container/EContainerFlexColumn.astro +16 -0
  20. package/dist/container/EContainerFlexContainer.astro +34 -0
  21. package/dist/container/EContainerFlexRow.astro +16 -0
  22. package/dist/container/EContainerPadding.astro +32 -0
  23. package/dist/container/EContainerPaddingContainer.astro +11 -0
  24. package/dist/container/EContainerSizes.astro +36 -0
  25. package/dist/container/EContainerSizesContainer.astro +11 -0
  26. package/dist/container/index.ts +16 -1
  27. package/dist/footer/{FooterBasic.astro → EFooterBasic.astro} +7 -1
  28. package/dist/footer/EFooterBasicContainer.astro +11 -0
  29. package/dist/footer/EFooterComplete.astro +45 -0
  30. package/dist/footer/EFooterCompleteContainer.astro +11 -0
  31. package/dist/footer/EFooterFeaturesContainer.astro +40 -0
  32. package/dist/footer/EFooterWithLogo.astro +23 -0
  33. package/dist/footer/EFooterWithLogoContainer.astro +11 -0
  34. package/dist/footer/EFooterWithNavigation.astro +24 -0
  35. package/dist/footer/EFooterWithNavigationContainer.astro +11 -0
  36. package/dist/footer/EFooterWithProducts.astro +24 -0
  37. package/dist/footer/EFooterWithProductsContainer.astro +11 -0
  38. package/dist/footer/EFooterWithSocial.astro +24 -0
  39. package/dist/footer/EFooterWithSocialContainer.astro +11 -0
  40. package/dist/footer/FooterSection.astro +4 -2
  41. package/dist/footer/index.ts +24 -4
  42. package/dist/icons/index.ts +3 -0
  43. package/dist/index_astro.ts +1 -0
  44. package/dist/layout-app/AppLayout.astro +1 -0
  45. package/dist/layout-basic/BaseLayout.astro +3 -3
  46. package/dist/types/meta.ts +5 -0
  47. package/package.json +2 -9
  48. package/dist/button/Button.vue +0 -105
  49. package/dist/button/ButtonBasic.vue +0 -11
  50. package/dist/button/ButtonFeature.vue +0 -91
  51. package/dist/button/ButtonFeatureBasic.vue +0 -8
  52. package/dist/button/ButtonFeatureContainer.astro +0 -18
  53. package/dist/button/ButtonFeatureWithTips.vue +0 -7
  54. package/dist/button/ButtonLink.vue +0 -13
  55. package/dist/button/ButtonSizes.vue +0 -12
  56. package/dist/button/ButtonWithIcons.vue +0 -21
  57. package/dist/button/index_vue.ts +0 -4
  58. package/dist/vue/AlertDialog/AlertDialog.vue +0 -120
  59. package/dist/vue/AlertDialog/Basic.vue +0 -38
  60. package/dist/vue/AlertDialog/Multilang.vue +0 -48
  61. package/dist/vue/AlertDialog/index.ts +0 -20
  62. package/dist/vue/BannerBox/BannerBox.vue +0 -296
  63. package/dist/vue/BannerBox/DownloadButton.vue +0 -202
  64. package/dist/vue/BannerBox/ExampleBasic.vue +0 -32
  65. package/dist/vue/BannerBox/ExampleCustomBg.vue +0 -32
  66. package/dist/vue/BannerBox/ExampleDisplayModeAlways.vue +0 -34
  67. package/dist/vue/BannerBox/ExampleDisplayModeHover.vue +0 -34
  68. package/dist/vue/BannerBox/ExampleDisplayModeNever.vue +0 -34
  69. package/dist/vue/BannerBox/ExampleImageExport.vue +0 -37
  70. package/dist/vue/BannerBox/ExampleSizePreset.vue +0 -35
  71. package/dist/vue/BannerBox/FeatureCard.vue +0 -190
  72. package/dist/vue/BannerBox/SmartBanner.vue +0 -44
  73. package/dist/vue/BannerBox/bgStyles.ts +0 -55
  74. package/dist/vue/BannerBox/index.ts +0 -48
  75. package/dist/vue/BannerBox/sizePresets.ts +0 -23
  76. package/dist/vue/BlogList/Basic.vue +0 -30
  77. package/dist/vue/BlogList/BlogList.vue +0 -100
  78. package/dist/vue/BlogList/Empty.vue +0 -8
  79. package/dist/vue/BlogList/EmptyEnglish.vue +0 -8
  80. package/dist/vue/BlogList/English.vue +0 -24
  81. package/dist/vue/BlogList/index.ts +0 -29
  82. package/dist/vue/ConfirmDialog/Basic.vue +0 -57
  83. package/dist/vue/ConfirmDialog/ConfirmDialog.vue +0 -134
  84. package/dist/vue/ConfirmDialog/CustomButtons.vue +0 -69
  85. package/dist/vue/ConfirmDialog/index.ts +0 -20
  86. package/dist/vue/Icons/AlertTriangleIcon.vue +0 -30
  87. package/dist/vue/Icons/CalendarIcon.vue +0 -30
  88. package/dist/vue/Icons/CheckCircleIcon.vue +0 -30
  89. package/dist/vue/Icons/CheckIcon.vue +0 -30
  90. package/dist/vue/Icons/ChevronDownIcon.vue +0 -30
  91. package/dist/vue/Icons/ClipboardIcon.vue +0 -30
  92. package/dist/vue/Icons/CloseIcon.vue +0 -30
  93. package/dist/vue/Icons/InboxArchiveIcon.vue +0 -30
  94. package/dist/vue/Icons/InfoCircleIcon.vue +0 -30
  95. package/dist/vue/Icons/InfoIcon.vue +0 -30
  96. package/dist/vue/Icons/LinkIcon.vue +0 -30
  97. package/dist/vue/Icons/MenuIcon.vue +0 -30
  98. package/dist/vue/Icons/SearchIcon.vue +0 -30
  99. package/dist/vue/Icons/SettingsIcon.vue +0 -30
  100. package/dist/vue/Icons/UserIcon.vue +0 -30
  101. package/dist/vue/Icons/VueIcon.vue +0 -76
  102. package/dist/vue/Icons/XCircleIcon.vue +0 -30
  103. package/dist/vue/ListItem.vue +0 -5
  104. package/dist/vue/MacWindow/Basic.vue +0 -11
  105. package/dist/vue/MacWindow/CustomHeight.vue +0 -13
  106. package/dist/vue/MacWindow/MacWindow.vue +0 -262
  107. package/dist/vue/MacWindow/WithEvents.vue +0 -34
  108. package/dist/vue/MacWindow/WithSidebar.vue +0 -21
  109. package/dist/vue/MacWindow/WithTabs.vue +0 -21
  110. package/dist/vue/MacWindow/WithToolbar.vue +0 -43
  111. package/dist/vue/MacWindow/index.ts +0 -36
  112. package/dist/vue/SmartLink.vue +0 -17
  113. package/dist/vue/TagList.vue +0 -23
  114. package/dist/vue/VueCounter.vue +0 -29
  115. package/dist/vue/iPhone/Basic.vue +0 -33
  116. package/dist/vue/iPhone/CustomBackground.vue +0 -33
  117. package/dist/vue/iPhone/NoFrame.vue +0 -33
  118. package/dist/vue/iPhone/WeatherApp.vue +0 -97
  119. package/dist/vue/iPhone/assets/iPhone 14 Pro - Deep Purple - Landscape.png +0 -0
  120. package/dist/vue/iPhone/assets/iPhone 14 Pro - Deep Purple - Portrait.png +0 -0
  121. package/dist/vue/iPhone/assets/iPhone 14 Pro - Gold - Landscape.png +0 -0
  122. package/dist/vue/iPhone/assets/iPhone 14 Pro - Gold - Portrait.png +0 -0
  123. package/dist/vue/iPhone/assets/iPhone 14 Pro - Silver - Landscape.png +0 -0
  124. package/dist/vue/iPhone/assets/iPhone 14 Pro - Silver - Portrait.png +0 -0
  125. package/dist/vue/iPhone/assets/iPhone 14 Pro - Space Black - Landscape.png +0 -0
  126. package/dist/vue/iPhone/assets/iPhone 14 Pro - Space Black - Portrait.png +0 -0
  127. package/dist/vue/iPhone/iPhoneWindow.vue +0 -193
  128. package/dist/vue/iPhone/index.ts +0 -28
  129. /package/dist/alert/{AlertBasic.astro → EAlertBasic.astro} +0 -0
  130. /package/dist/alert/{AlertCustomStyle.astro → EAlertCustomStyle.astro} +0 -0
  131. /package/dist/alert/{AlertError.astro → EAlertError.astro} +0 -0
  132. /package/dist/alert/{AlertInfo.astro → EAlertInfo.astro} +0 -0
  133. /package/dist/alert/{AlertSuccess.astro → EAlertSuccess.astro} +0 -0
  134. /package/dist/alert/{AlertWarning.astro → EAlertWarning.astro} +0 -0
  135. /package/dist/alert/{AlertWithTitle.astro → EAlertWithTitle.astro} +0 -0
  136. /package/dist/code-container/{CodeContainerBasic.astro → ECodeContainerBasic.astro} +0 -0
  137. /package/dist/code-container/{CodeContainerMultiple.astro → ECodeContainerMultiple.astro} +0 -0
@@ -1,38 +0,0 @@
1
- <!--
2
- @component AlertDialog.Basic
3
-
4
- @description
5
- AlertDialog 组件的基础示例,展示最基本的对话框用法。
6
-
7
- @usage
8
- ```vue
9
- <AlertDialogExamples.Basic />
10
- ```
11
- -->
12
-
13
- <script lang="ts">
14
- import '../../app.css'
15
- import { ref, defineComponent } from 'vue'
16
- import AlertDialog from './AlertDialog.vue'
17
-
18
- export default defineComponent({
19
- name: 'AlertDialogBasicExample',
20
- components: {
21
- AlertDialog
22
- },
23
- setup() {
24
- const isShow = ref(false)
25
-
26
- return {
27
- isShow
28
- }
29
- }
30
- })
31
- </script>
32
-
33
- <template>
34
- <button @click="isShow = true" class="cosy:btn cosy:btn-primary">
35
- 显示对话框
36
- </button>
37
- <AlertDialog v-model="isShow" message="这是一条重要信息" />
38
- </template>
@@ -1,48 +0,0 @@
1
- <!--
2
- @component AlertDialog.Multilang
3
-
4
- @description
5
- AlertDialog 组件的多语言示例,展示如何使用不同语言的对话框。
6
-
7
- @usage
8
- ```vue
9
- <AlertDialogExamples.Multilang />
10
- ```
11
- -->
12
-
13
- <script lang="ts">
14
- import '../../app.css'
15
- import { ref, defineComponent } from 'vue'
16
- import AlertDialog from './AlertDialog.vue'
17
-
18
- export default defineComponent({
19
- name: 'AlertDialogMultilangExample',
20
- components: {
21
- AlertDialog
22
- },
23
- setup() {
24
- const isShowEn = ref(false)
25
- const isShowJa = ref(false)
26
-
27
- return {
28
- isShowEn,
29
- isShowJa
30
- }
31
- }
32
- })
33
- </script>
34
-
35
- <template>
36
- <div class="flex gap-2">
37
- <button @click="isShowEn = true" class="cosy:btn cosy:btn-primary">
38
- English
39
- </button>
40
- <button @click="isShowJa = true" class="cosy:btn cosy:btn-primary">
41
- 日本語
42
- </button>
43
- </div>
44
-
45
- <AlertDialog v-model="isShowEn" message="Important information" ok-text="OK" cancel-text="Cancel" />
46
-
47
- <AlertDialog v-model="isShowJa" message="重要なお知らせ" ok-text="確認" cancel-text="キャンセル" />
48
- </template>
@@ -1,20 +0,0 @@
1
- import Basic from './Basic.vue';
2
- import Multilang from './Multilang.vue';
3
- import BasicSource from './Basic.vue?raw';
4
- import MultilangSource from './Multilang.vue?raw';
5
- import { extractSimpleExample } from '../../utils/component';
6
-
7
- // 导出主组件
8
- export { default as AlertDialog } from './AlertDialog.vue';
9
-
10
- // 导出示例组件
11
- export const AlertDialogExamples = {
12
- Basic,
13
- Multilang,
14
- };
15
-
16
- // 导出示例源代码
17
- export const AlertDialogExampleCodes = {
18
- Basic: extractSimpleExample(BasicSource, 'Basic'),
19
- Multilang: extractSimpleExample(MultilangSource, 'Multilang'),
20
- };
@@ -1,296 +0,0 @@
1
- <!--
2
- @component BannerBox
3
-
4
- @description
5
- BannerBox 组件是一个可定制的横幅容器,支持自定义背景、尺寸调整和导出为图片功能。
6
- 可以直接用作容器,也可以通过传入标题、描述和特性列表来显示内容。
7
- 适用于创建营销横幅、特性展示、社交媒体卡片等内容。
8
-
9
- @usage
10
- 基本用法:
11
- ```vue
12
- <BannerBox>
13
- <div>横幅内容</div>
14
- </BannerBox>
15
- ```
16
-
17
- 使用标题和描述:
18
- ```vue
19
- <BannerBox
20
- title="我的横幅标题"
21
- description="这是一段描述文字"
22
- :features="[
23
- { emoji: '🚀', title: '高性能' },
24
- { emoji: '⚡', title: '快速响应' },
25
- { emoji: '🔒', title: '安全可靠' }
26
- ]"
27
- />
28
- ```
29
-
30
- 自定义背景:
31
- ```vue
32
- <BannerBox :backgroundClassIndex="5">
33
- <div>自定义背景的横幅</div>
34
- </BannerBox>
35
- ```
36
-
37
- 设置下载按钮显示模式:
38
- ```vue
39
- <BannerBox displayMode="always">
40
- <div>总是显示下载按钮</div>
41
- </BannerBox>
42
- ```
43
-
44
- @props
45
- @prop {String} [displayMode='hover'] - 下载按钮显示模式:'always'(总是显示),'hover'(悬停显示),'never'(不显示)
46
- @prop {Number} [backgroundClassIndex=0] - 背景样式索引,对应内置的背景样式列表
47
- @prop {String} [title=''] - 横幅标题
48
- @prop {String} [description=''] - 横幅描述
49
- @prop {Array} [features=[]] - 特性列表,每项包含{emoji, title, link}
50
-
51
- @slots
52
- @slot default - 横幅内容
53
- -->
54
-
55
- <script lang="ts">
56
- import { ref, onMounted, watch, onUnmounted, computed, defineComponent } from 'vue';
57
- import { RiDownloadLine } from '@remixicon/vue';
58
- import { toPng } from 'html-to-image';
59
- import FeatureCard from './FeatureCard.vue';
60
- import DownloadButton from './DownloadButton.vue';
61
- import { bgClasses } from './bgStyles';
62
- import { sizePresets } from './sizePresets';
63
- import '../../style'
64
-
65
- export interface IFeature {
66
- emoji: string;
67
- title: string;
68
- link?: string;
69
- }
70
-
71
- export default defineComponent({
72
- name: 'BannerBox',
73
- components: {
74
- RiDownloadLine,
75
- FeatureCard,
76
- DownloadButton
77
- },
78
- props: {
79
- displayMode: {
80
- type: String,
81
- default: 'hover',
82
- validator: (value: string) => ['always', 'hover', 'never'].includes(value)
83
- },
84
- backgroundClassIndex: {
85
- type: Number,
86
- default: 0
87
- },
88
- title: {
89
- type: String,
90
- default: ''
91
- },
92
- description: {
93
- type: String,
94
- default: ''
95
- },
96
- features: {
97
- type: Array as () => IFeature[],
98
- default: () => []
99
- },
100
- },
101
- setup(props) {
102
- const componentRef = ref<HTMLElement | null>(null);
103
- const isDropdownOpen = ref(false);
104
- const isLoadedFromStorage = ref(false);
105
- const selectedBgIndex = ref(props.backgroundClassIndex);
106
-
107
- const selectedSize = ref(sizePresets[0]);
108
-
109
- const toggleDropdown = () => {
110
- console.log("Toggle Dropdown")
111
- isDropdownOpen.value = !isDropdownOpen.value;
112
- };
113
-
114
- // 监听尺寸变化并保存到 localStorage
115
- watch(selectedSize, (newSize) => {
116
- localStorage.setItem('bannerBoxSize', JSON.stringify(newSize));
117
- // 当尺寸改变时,发出事件通知其他组件
118
- window.dispatchEvent(new CustomEvent('bannerBoxSizeChange', {
119
- detail: newSize
120
- }));
121
- // 设置为已加载状态,显示尺寸标签
122
- isLoadedFromStorage.value = true;
123
- });
124
-
125
- // 创建自定义事件处理函数
126
- const handleSizeClear = () => {
127
- selectedSize.value = sizePresets[0];
128
- isLoadedFromStorage.value = false;
129
- };
130
-
131
- // 处理尺寸变化的事件
132
- const handleSizeChange = (event: Event) => {
133
- const customEvent = event as CustomEvent;
134
- selectedSize.value = customEvent.detail;
135
- isLoadedFromStorage.value = true;
136
- };
137
-
138
- onMounted(() => {
139
- const savedSize = localStorage.getItem('bannerBoxSize');
140
- if (savedSize) {
141
- const parsed = JSON.parse(savedSize);
142
- const found = sizePresets.find(preset => preset.name === parsed.name);
143
- if (found) {
144
- selectedSize.value = found;
145
- isLoadedFromStorage.value = true;
146
- }
147
- }
148
-
149
- // 添加事件监听
150
- window.addEventListener('bannerBoxClear', handleSizeClear);
151
- window.addEventListener('bannerBoxSizeChange', handleSizeChange);
152
-
153
- // 恢复到简单的点击监听方式,但使用正确的选择器
154
- document.addEventListener('click', (event) => {
155
- if (!isDropdownOpen.value) return; // 如果下拉菜单已经关闭,就不需要处理
156
-
157
- const target = event.target as HTMLElement;
158
- // 检查点击的元素是否是下拉菜单中的元素
159
- const isClickedOnDropdown = !!target.closest('[data-dropdown]');
160
-
161
- if (!isClickedOnDropdown) {
162
- isDropdownOpen.value = false;
163
- }
164
- });
165
- });
166
-
167
- // Update downloadAsImage function to accept scale parameter
168
- const downloadAsImage = async () => {
169
- try {
170
- const element = componentRef.value;
171
- if (!element) {
172
- console.error('Component reference is null');
173
- return;
174
- }
175
-
176
- const dataUrl = await toPng(element, {
177
- backgroundColor: undefined,
178
- style: {
179
- transform: 'scale(1)',
180
- transformOrigin: 'top left'
181
- }
182
- });
183
-
184
- const link = document.createElement('a');
185
- const fileName = `feature-${element.offsetWidth}x${element.offsetHeight}.png`;
186
- link.download = fileName;
187
- link.href = dataUrl;
188
- link.click();
189
- isDropdownOpen.value = false;
190
- } catch (error) {
191
- console.error('Failed to download image:', error);
192
- }
193
- };
194
-
195
- const getBackgroundClass = (): string => {
196
- return bgClasses[selectedBgIndex.value % bgClasses.length];
197
- }
198
-
199
- const clearStoredSize = () => {
200
- localStorage.removeItem('bannerBoxSize');
201
- // 触发自定义事件
202
- window.dispatchEvent(new CustomEvent('bannerBoxClear'));
203
- isDropdownOpen.value = false;
204
- };
205
-
206
- // 确保在组件卸载时清理事件监听器
207
- onUnmounted(() => {
208
- window.removeEventListener('bannerBoxClear', handleSizeClear);
209
- window.removeEventListener('bannerBoxSizeChange', handleSizeChange);
210
- });
211
-
212
- // 计算下载按钮是否显示及其样式类
213
- const downloadButtonStyles = computed(() => {
214
- switch (props.displayMode) {
215
- case 'always':
216
- return {
217
- show: true,
218
- classes: 'cosy:opacity-100'
219
- };
220
- case 'hover':
221
- return {
222
- show: true,
223
- classes: 'cosy:opacity-0 cosy:hover:opacity-100 cosy:transition-opacity'
224
- };
225
- case 'never':
226
- return {
227
- show: false,
228
- classes: ''
229
- };
230
- default:
231
- return {
232
- show: true,
233
- classes: 'cosy:opacity-0 cosy:hover:opacity-100 cosy:transition-opacity'
234
- };
235
- }
236
- });
237
-
238
- return {
239
- componentRef,
240
- isDropdownOpen,
241
- isLoadedFromStorage,
242
- selectedSize,
243
- sizePresets,
244
- selectedBgIndex,
245
- toggleDropdown,
246
- downloadAsImage,
247
- getBackgroundClass,
248
- clearStoredSize,
249
- downloadButtonStyles,
250
- bgClasses
251
- };
252
- }
253
- });
254
- </script>
255
-
256
- <template>
257
- <div class="cosy:relative cosy:w-full cosy:rounded-2xl cosy:max-w-7xl cosy:mx-auto">
258
- <!-- Size indicator -->
259
- <div v-if="isLoadedFromStorage"
260
- class="cosy:absolute cosy:top-4 cosy:right-4 cosy:bg-yellow-500/30 cosy:backdrop-blur-sm cosy:px-3 cosy:py-1 cosy:rounded-lg cosy:text-sm cosy:text-white">
261
- {{ selectedSize.name }}
262
- </div>
263
-
264
- <!-- Download button with dropdown menu -->
265
- <DownloadButton :displayMode="displayMode" :isLoadedFromStorage="isLoadedFromStorage"
266
- :selectedSize="selectedSize" :selectedBgIndex="selectedBgIndex" @update:selectedSize="selectedSize = $event"
267
- @update:selectedBgIndex="selectedBgIndex = $event" @clear-stored-size="clearStoredSize"
268
- @download-image="downloadAsImage" />
269
-
270
- <div ref="componentRef" class="cosy:flex cosy:p-8 cosy:rounded-2xl cosy:shadow" :class="[
271
- getBackgroundClass(),
272
- selectedSize.width,
273
- selectedSize.height
274
- ]">
275
- <div class="cosy:py-16 cosy:px-8 cosy:text-center cosy:w-full cosy:rounded-2xl" data-type="smart-banner">
276
- <h2 v-if="title.length > 0" class="cosy:text-4xl cosy:mb-4">
277
- {{ title }}
278
- </h2>
279
-
280
- <p v-if="description.length > 0" class="cosy:text-lg cosy:text-center cosy:max-w-2xl cosy:mx-auto">
281
- {{ description }}
282
- </p>
283
-
284
- <div v-if="features.length > 0"
285
- class="cosy:flex cosy:flex-row cosy:justify-center cosy:gap-8 cosy:mx-auto cosy:w-full cosy:mt-24">
286
- <FeatureCard v-for="feature in features" :key="feature.title" :emoji="feature.emoji"
287
- :title="feature.title" :link="feature.link" />
288
- </div>
289
-
290
- <div :class="{ 'cosy:mt-12': title.length > 0 || description.length > 0 || features.length > 0 }">
291
- <slot />
292
- </div>
293
- </div>
294
- </div>
295
- </div>
296
- </template>
@@ -1,202 +0,0 @@
1
- <!--
2
- @component DownloadButton
3
-
4
- @description
5
- DownloadButton 组件提供了一个下载按钮,带有可展开的下拉菜单,用于调整尺寸、背景和下载图片。
6
-
7
- @usage
8
- 基本用法:
9
- ```vue
10
- <DownloadButton
11
- :displayMode="'hover'"
12
- :isLoadedFromStorage="true"
13
- :selectedSize="selectedSize"
14
- :selectedBgIndex="selectedBgIndex"
15
- :sizePresets="sizePresets"
16
- :bgClasses="bgClasses"
17
- @update:selectedSize="selectedSize = $event"
18
- @update:selectedBgIndex="selectedBgIndex = $event"
19
- @clear-stored-size="clearStoredSize"
20
- @download-image="downloadAsImage"
21
- />
22
- ```
23
-
24
- @props
25
- @prop {String} [displayMode='hover'] - 下载按钮显示模式:'always'(总是显示),'hover'(悬停显示),'never'(不显示)
26
- @prop {Boolean} [isLoadedFromStorage=false] - 是否已从存储中加载尺寸
27
- @prop {Object} [selectedSize] - 当前选中的尺寸预设
28
- @prop {Number} [selectedBgIndex=0] - 当前选中的背景样式索引
29
- @prop {Array} [sizePresets] - 尺寸预设列表
30
- @prop {Array} [bgClasses] - 背景样式类列表
31
-
32
- @emits
33
- @emit update:selectedSize - 当选择新的尺寸预设时触发
34
- @emit update:selectedBgIndex - 当选择新的背景样式时触发
35
- @emit clear-stored-size - 当清除存储的尺寸时触发
36
- @emit download-image - 当请求下载图片时触发
37
- -->
38
-
39
- <script lang="ts">
40
- import { ref, computed, defineComponent } from 'vue';
41
- import { RiDownloadLine } from '@remixicon/vue';
42
- import { bgClasses } from './bgStyles';
43
- import { sizePresets, type SizePreset } from './sizePresets';
44
- import '../../style'
45
-
46
- export default defineComponent({
47
- name: 'DownloadButton',
48
- components: {
49
- RiDownloadLine
50
- },
51
- props: {
52
- displayMode: {
53
- type: String,
54
- default: 'hover',
55
- validator: (value: string) => ['always', 'hover', 'never'].includes(value)
56
- },
57
- isLoadedFromStorage: {
58
- type: Boolean,
59
- default: false
60
- },
61
- selectedSize: {
62
- type: Object as () => SizePreset,
63
- required: true
64
- },
65
- selectedBgIndex: {
66
- type: Number,
67
- default: 0
68
- }
69
- },
70
- emits: ['update:selectedSize', 'update:selectedBgIndex', 'clear-stored-size', 'download-image'],
71
- setup(props, { emit }) {
72
- const isDropdownOpen = ref(false);
73
-
74
- const toggleDropdown = () => {
75
- isDropdownOpen.value = !isDropdownOpen.value;
76
- };
77
-
78
- // 计算下载按钮是否显示及其样式类
79
- const downloadButtonStyles = computed(() => {
80
- switch (props.displayMode) {
81
- case 'always':
82
- return {
83
- show: true,
84
- classes: 'cosy:opacity-100'
85
- };
86
- case 'hover':
87
- return {
88
- show: true,
89
- classes: 'cosy:opacity-0 cosy:hover:opacity-100 cosy:transition-opacity'
90
- };
91
- case 'never':
92
- return {
93
- show: false,
94
- classes: ''
95
- };
96
- default:
97
- return {
98
- show: true,
99
- classes: 'cosy:opacity-0 cosy:hover:opacity-100 cosy:transition-opacity'
100
- };
101
- }
102
- });
103
-
104
- const selectSize = (size: SizePreset) => {
105
- emit('update:selectedSize', size);
106
- };
107
-
108
- const selectBackground = (index: number) => {
109
- emit('update:selectedBgIndex', index);
110
- };
111
-
112
- const clearStoredSize = () => {
113
- emit('clear-stored-size');
114
- isDropdownOpen.value = false;
115
- };
116
-
117
- const downloadImage = () => {
118
- emit('download-image');
119
- isDropdownOpen.value = false;
120
- };
121
-
122
- return {
123
- isDropdownOpen,
124
- toggleDropdown,
125
- downloadButtonStyles,
126
- selectSize,
127
- selectBackground,
128
- clearStoredSize,
129
- downloadImage,
130
- bgClasses,
131
- sizePresets
132
- };
133
- }
134
- });
135
- </script>
136
-
137
- <template>
138
- <div v-if="downloadButtonStyles.show" class="cosy:absolute cosy:top-4 cosy:left-4"
139
- :class="downloadButtonStyles.classes">
140
- <div class="cosy:relative" data-dropdown>
141
- <button
142
- class="cosy:bg-yellow-500/30 cosy:backdrop-blur-sm cosy:p-2 cosy:rounded-lg hover:cosy:bg-yellow-500/40"
143
- @click="toggleDropdown">
144
- <RiDownloadLine class="cosy:w-6 cosy:h-6 cosy:text-white" />
145
- </button>
146
- <!-- Size selection dropdown -->
147
- <div v-if="isDropdownOpen"
148
- class="cosy:absolute cosy:left-0 cosy:mt-2 cosy:w-96 cosy:bg-white dark:cosy:bg-gray-800 cosy:rounded-lg cosy:shadow-lg cosy:py-2 cosy:z-50">
149
- <!-- Component size presets -->
150
- <div class="cosy:px-4 cosy:py-2 cosy:border-b cosy:border-gray-200 dark:cosy:border-gray-700">
151
- <div class="cosy:grid cosy:grid-cols-3 cosy:gap-2">
152
- <button v-for="preset in sizePresets" :key="preset.name" :class="[
153
- 'cosy:p-2 cosy:text-left cosy:rounded cosy:text-sm',
154
- selectedSize.name === preset.name
155
- ? 'cosy:bg-yellow-500/30 cosy:text-yellow-900 dark:cosy:text-yellow-100'
156
- : 'hover:cosy:bg-gray-100 dark:hover:cosy:bg-gray-700'
157
- ]" @click="selectSize(preset)">
158
- <div class="cosy:flex cosy:flex-col">
159
- <span class="cosy:font-medium">{{ preset.name }}</span>
160
- <span class="cosy:text-xs cosy:text-gray-500 dark:cosy:text-gray-400">
161
- {{ preset.width.replace('cosy:w-[', '').replace(']', '') }}
162
- </span>
163
- </div>
164
- </button>
165
- <!-- Clear size button -->
166
- <button
167
- class="cosy:p-2 cosy:text-left cosy:rounded cosy:text-sm hover:cosy:bg-gray-100 dark:hover:cosy:bg-gray-700"
168
- @click="clearStoredSize">
169
- <div class="cosy:flex cosy:flex-col">
170
- <span class="cosy:font-medium cosy:text-red-600 dark:cosy:text-red-400">清除记住的尺寸</span>
171
- <span class="cosy:text-xs cosy:text-gray-500 dark:cosy:text-gray-400">重置为默认尺寸</span>
172
- </div>
173
- </button>
174
- </div>
175
- </div>
176
- <!-- Background settings -->
177
- <div class="cosy:px-4 cosy:py-2 cosy:border-b cosy:border-gray-200 dark:cosy:border-gray-700">
178
- <div class="cosy:mt-2">
179
- <div class="cosy:grid cosy:grid-cols-8 cosy:gap-2">
180
- <button v-for="(className, index) in bgClasses" :key="index" :class="[
181
- className,
182
- 'cosy:w-8 cosy:h-8 cosy:rounded-lg cosy:border-2',
183
- selectedBgIndex === index ? 'cosy:border-yellow-500' : 'cosy:border-transparent'
184
- ]" @click="selectBackground(index)" />
185
- </div>
186
- </div>
187
- </div>
188
- <!-- Size options -->
189
- <div class="cosy:p-4">
190
- <button
191
- class="cosy:w-full cosy:p-2 cosy:text-center cosy:rounded hover:cosy:bg-gray-100 dark:hover:cosy:bg-gray-700"
192
- @click="downloadImage">
193
- <div class="cosy:flex cosy:items-center cosy:justify-center cosy:gap-2">
194
- <RiDownloadLine class="cosy:w-4 cosy:h-4" />
195
- <span class="cosy:font-medium">下载图片</span>
196
- </div>
197
- </button>
198
- </div>
199
- </div>
200
- </div>
201
- </div>
202
- </template>
@@ -1,32 +0,0 @@
1
- <!--
2
- @component BannerBox.Basic
3
-
4
- @description
5
- BannerBox 组件的基础示例,展示最基本的横幅容器用法。
6
-
7
- @usage
8
- ```vue
9
- <BannerBoxExamples.Basic />
10
- ```
11
- -->
12
-
13
- <script lang="ts">
14
- import '../../app.css'
15
- import { defineComponent } from 'vue'
16
- import BannerBox from './BannerBox.vue'
17
-
18
- export default defineComponent({
19
- name: 'BannerBoxBasicExample',
20
- components: {
21
- BannerBox
22
- }
23
- })
24
- </script>
25
-
26
- <template>
27
- <BannerBox>
28
- <div class="cosy:flex cosy:items-center cosy:justify-center cosy:min-h-[200px]">
29
- <h2 class="cosy:text-3xl cosy:font-bold">欢迎使用 BannerBox</h2>
30
- </div>
31
- </BannerBox>
32
- </template>
@@ -1,32 +0,0 @@
1
- <!--
2
- @component BannerBox.CustomBg
3
-
4
- @description
5
- BannerBox 组件的自定义背景示例,展示如何通过 backgroundClassIndex 属性设置背景样式。
6
-
7
- @usage
8
- ```vue
9
- <BannerBoxExamples.CustomBg />
10
- ```
11
- -->
12
-
13
- <script lang="ts">
14
- import '../../app.css'
15
- import { defineComponent } from 'vue'
16
- import BannerBox from './BannerBox.vue'
17
-
18
- export default defineComponent({
19
- name: 'BannerBoxCustomBgExample',
20
- components: {
21
- BannerBox
22
- }
23
- })
24
- </script>
25
-
26
- <template>
27
- <BannerBox :backgroundClassIndex="5">
28
- <div class="cosy:flex cosy:items-center cosy:justify-center cosy:min-h-[200px]">
29
- <h2 class="cosy:text-3xl cosy:font-bold">自定义背景颜色</h2>
30
- </div>
31
- </BannerBox>
32
- </template>