@coffic/cosy-ui 0.8.22 → 0.8.24

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.
@@ -0,0 +1,174 @@
1
+ ---
2
+ /**
3
+ * @component InstallTabs
4
+ *
5
+ * @description
6
+ * 展示多个包管理器(npm、pnpm、yarn等)的安装命令,支持标签切换和一键复制。
7
+ * 只需传入包名即可自动生成各包管理器的安装命令。
8
+ *
9
+ * @props
10
+ * @param packageName 要安装的包名
11
+ * @param managers 支持的包管理器,默认['npm','pnpm','yarn']
12
+ * @param dev 是否为开发依赖,影响命令参数(如-D/--save-dev)
13
+ *
14
+ * @usage
15
+ * ```astro
16
+ * <InstallTabs packageName="react" />
17
+ * <InstallTabs packageName="vite" dev />
18
+ * <InstallTabs packageName="eslint" managers={["npm","yarn"]} />
19
+ * ```
20
+ */
21
+ import '../../style.ts';
22
+ import ButtonCopyInstall from './ButtonCopyInstall.astro';
23
+ import { CodePanel } from '../code-panel';
24
+
25
+ interface Props {
26
+ /** 要安装的包名 */
27
+ packageName: string;
28
+ /** 支持的包管理器,默认['npm','pnpm','yarn'] */
29
+ managers?: string[];
30
+ /** 是否为开发依赖 */
31
+ dev?: boolean;
32
+ }
33
+
34
+ const {
35
+ packageName,
36
+ managers = ['npm', 'pnpm', 'yarn'],
37
+ dev = false,
38
+ } = Astro.props;
39
+
40
+ const managerLabels: Record<string, string> = {
41
+ npm: 'npm',
42
+ pnpm: 'pnpm',
43
+ yarn: 'yarn',
44
+ };
45
+
46
+ function getCommand(manager: string, pkg: string, dev: boolean) {
47
+ switch (manager) {
48
+ case 'npm':
49
+ return `npm install${dev ? ' -D' : ''} ${pkg}`;
50
+ case 'pnpm':
51
+ return `pnpm add${dev ? ' -D' : ''} ${pkg}`;
52
+ case 'yarn':
53
+ return `yarn add${dev ? ' -D' : ''} ${pkg}`;
54
+ default:
55
+ return '';
56
+ }
57
+ }
58
+
59
+ const commands = managers.map((m) => getCommand(m, packageName, dev));
60
+ ---
61
+
62
+ <div
63
+ class="cosy:mb-8 cosy:card cosy:p-0 cosy:overflow-hidden"
64
+ data-role="install-tabs">
65
+ <div
66
+ class="cosy:flex cosy:justify-between cosy:items-center cosy:bg-base-200 cosy:px-4 cosy:rounded-t">
67
+ <div class="cosy:flex cosy:items-center cosy:gap-4">
68
+ <div role="tablist" class="cosy:tabs cosy:tabs-box">
69
+ {
70
+ managers.map((manager, idx) => (
71
+ <button
72
+ role="tab"
73
+ class={`cosy:tab${idx === 0 ? ' cosy:tab-active' : ''}`}
74
+ data-tab={`tab-${idx + 1}`}
75
+ aria-selected={idx === 0 ? 'true' : 'false'}>
76
+ {managerLabels[manager] ?? manager}
77
+ </button>
78
+ ))
79
+ }
80
+ </div>
81
+ </div>
82
+ <div class="cosy:flex cosy:items-center cosy:gap-2">
83
+ {
84
+ commands.map((cmd, idx) => (
85
+ <div
86
+ class={`cosy:install-copy-container ${idx === 0 ? 'cosy:block' : 'cosy:hidden'}`}
87
+ data-copy-container={`tab-${idx + 1}`}>
88
+ <ButtonCopyInstall code={cmd} />
89
+ </div>
90
+ ))
91
+ }
92
+ </div>
93
+ </div>
94
+ {
95
+ commands.map((cmd, idx) => (
96
+ <div
97
+ class={`cosy:install-panel ${idx === 0 ? 'cosy:block' : 'cosy:hidden'}`}
98
+ data-panel={`tab-${idx + 1}`}>
99
+ <CodePanel code={cmd} language="bash" theme="dark-plus" />
100
+ </div>
101
+ ))
102
+ }
103
+ </div>
104
+
105
+ <script>
106
+ function initializeInstallTabs() {
107
+ console.log('InstallTabs: 初始化安装标签组件');
108
+
109
+ // 为所有InstallTabs容器添加事件委托
110
+ document
111
+ .querySelectorAll('[data-role="install-tabs"]')
112
+ .forEach((container) => {
113
+ // 防止重复绑定
114
+ if (container.hasAttribute('data-initialized')) return;
115
+ container.setAttribute('data-initialized', 'true');
116
+
117
+ // 使用事件委托处理标签点击
118
+ container.addEventListener('click', (event) => {
119
+ const target = event.target as HTMLElement;
120
+ const tab = target.closest('[role="tab"][data-tab^="tab-"]');
121
+
122
+ if (!tab) return;
123
+
124
+ console.log('InstallTabs: 切换标签', tab.getAttribute('data-tab'));
125
+
126
+ const targetTab = tab.getAttribute('data-tab');
127
+ if (!targetTab) return;
128
+
129
+ // 更新标签状态
130
+ container
131
+ .querySelectorAll('[role="tab"][data-tab^="tab-"]')
132
+ .forEach((t) => {
133
+ t.classList.remove('cosy:tab-active');
134
+ t.setAttribute('aria-selected', 'false');
135
+ });
136
+ tab.classList.add('cosy:tab-active');
137
+ tab.setAttribute('aria-selected', 'true');
138
+
139
+ // 切换面板显示
140
+ container
141
+ .querySelectorAll('.cosy\\:install-panel')
142
+ .forEach((panel) => {
143
+ if (panel.getAttribute('data-panel') === targetTab) {
144
+ panel.classList.remove('cosy:hidden');
145
+ panel.classList.add('cosy:block');
146
+ } else {
147
+ panel.classList.add('cosy:hidden');
148
+ panel.classList.remove('cosy:block');
149
+ }
150
+ });
151
+
152
+ // 切换复制按钮显示
153
+ container
154
+ .querySelectorAll('.cosy\\:install-copy-container')
155
+ .forEach((copyContainer) => {
156
+ if (
157
+ copyContainer.getAttribute('data-copy-container') === targetTab
158
+ ) {
159
+ copyContainer.classList.remove('cosy:hidden');
160
+ copyContainer.classList.add('cosy:block');
161
+ } else {
162
+ copyContainer.classList.add('cosy:hidden');
163
+ copyContainer.classList.remove('cosy:block');
164
+ }
165
+ });
166
+ });
167
+ });
168
+ }
169
+
170
+ document.addEventListener('astro:page-load', () => {
171
+ console.log('InstallTabs: 页面加载完成,初始化安装标签组件');
172
+ initializeInstallTabs();
173
+ });
174
+ </script>
@@ -0,0 +1,2 @@
1
+ export { default as InstallTabs } from './InstallTabs.astro';
2
+ export type { InstallTabsProps } from './types';
@@ -0,0 +1,8 @@
1
+ export interface InstallTabsProps {
2
+ /** 要安装的包名 */
3
+ packageName: string;
4
+ /** 支持的包管理器,默认['npm','pnpm','yarn'] */
5
+ managers?: string[];
6
+ /** 是否为开发依赖 */
7
+ dev?: boolean;
8
+ }
@@ -195,16 +195,7 @@ const {
195
195
  }: Props = Astro.props;
196
196
  ---
197
197
 
198
- <BaseLayout
199
- title={metaConfig.title}
200
- description={metaConfig.description}
201
- keywords={metaConfig.keywords}
202
- author={metaConfig.author}
203
- robots={metaConfig.robots}
204
- head={metaConfig.head}
205
- favicon={metaConfig.favicon}
206
- debug={debug}
207
- {...rest}>
198
+ <BaseLayout {...metaConfig} debug={debug}>
208
199
  <ClientRouter />
209
200
  {
210
201
  showHeader && (
@@ -52,9 +52,7 @@
52
52
  import '../../style.ts';
53
53
  import { type IMetaProps } from '../../index-astro';
54
54
 
55
- export interface Props extends IMetaProps {
56
- debug?: boolean;
57
- }
55
+ export interface Props extends IMetaProps {}
58
56
 
59
57
  const {
60
58
  title,
@@ -68,10 +66,28 @@ const {
68
66
  class: className,
69
67
  favicon,
70
68
  'class:list': classList,
69
+ background = 'default',
71
70
  } = Astro.props;
72
71
 
72
+ // 处理背景色 class
73
+ const bgClassMap: Record<string, string> = {
74
+ default: 'cosy:bg-base-100',
75
+ white: 'cosy:bg-white',
76
+ gray: 'cosy:bg-gray-100',
77
+ dark: 'cosy:bg-gray-900',
78
+ 'gradient-blue': 'cosy:bg-gradient-to-br cosy:from-blue-400 cosy:to-blue-600',
79
+ 'gradient-pink': 'cosy:bg-gradient-to-br cosy:from-pink-400 cosy:to-pink-600',
80
+ 'gradient-green':
81
+ 'cosy:bg-gradient-to-br cosy:from-green-400 cosy:to-green-600',
82
+ };
83
+
73
84
  // 处理类名
74
- let bodyClasses = debug ? 'cosy:border cosy:border-red-500' : className || '';
85
+ let bodyClasses = [
86
+ debug ? 'cosy:border cosy:border-red-500' : className || '',
87
+ bgClassMap[background] || '',
88
+ ]
89
+ .filter(Boolean)
90
+ .join(' ');
75
91
  ---
76
92
 
77
93
  <!doctype html>
@@ -0,0 +1,45 @@
1
+ ---
2
+ /**
3
+ * @component ListItem
4
+ * @description 支持加载中进度条的列表项组件。点击后可显示从左到右的进度条,适合异步操作场景。
5
+ * @usage
6
+ * <ListItem loading={loading} duration={1500} on:click={...}>内容</ListItem>
7
+ * @props loading?: boolean 是否加载中
8
+ * @props duration?: number 进度条动画时长(毫秒),默认1500
9
+ * @slots default 默认插槽,列表项内容
10
+ */
11
+ import '../../style.ts';
12
+ const { loading = false, duration = 1500 } = Astro.props;
13
+ ---
14
+
15
+ <li
16
+ class="cosy:mb-2 cosy:rounded-md cosy:p-2 cosy:flex cosy:items-center cosy:gap-3 cosy:bg-base-300 cosy:hover:bg-accent/10 cosy:relative cosy:overflow-hidden"
17
+ {...Astro.props}>
18
+ {
19
+ loading && (
20
+ <div
21
+ class="cosy:absolute cosy:left-0 cosy:top-0 cosy:h-full cosy:bg-accent/40 cosy:z-0 loading-bar"
22
+ style={`animation-duration: ${duration}ms;`}
23
+ />
24
+ )
25
+ }
26
+ <div
27
+ class="cosy:relative cosy:z-10 cosy:w-full cosy:flex cosy:items-center cosy:gap-3">
28
+ <slot />
29
+ </div>
30
+ </li>
31
+ <style scoped>
32
+ .loading-bar {
33
+ width: 0%;
34
+ height: 100%;
35
+ animation: loading-bar-anim linear forwards;
36
+ }
37
+ @keyframes loading-bar-anim {
38
+ 0% {
39
+ width: 0%;
40
+ }
41
+ 100% {
42
+ width: 100%;
43
+ }
44
+ }
45
+ </style>
@@ -0,0 +1 @@
1
+ export { default as ListItem } from './ListItem.astro';
@@ -1,55 +1,67 @@
1
1
  export interface IMetaProps {
2
- title: string;
3
- description: string;
4
- keywords: string;
5
- author: string;
6
- robots: string;
7
-
8
- /**
9
- * 图标
10
- */
11
- favicon?: ImageMetadata;
12
-
13
- /**
14
- * 基础路径,用于处理网站部署在二级目录的情况
15
- * @default ""
16
- */
17
- basePath?: string;
18
-
19
- /**
20
- * 站点名称
21
- */
22
- siteName?: string;
23
-
24
- /**
25
- * 页面语言
26
- * @default "zh-CN"
27
- */
28
- lang?: string;
29
-
30
- /**
31
- * 是否包含视口元标签
32
- * @default true
33
- */
34
- viewport?: boolean;
35
-
36
- /**
37
- * 自定义CSS
38
- */
39
- customStyles?: string;
40
-
41
- /**
42
- * 自定义头部内容
43
- */
44
- head?: astroHTML.JSX.Element;
45
-
46
- /**
47
- * 页面类名
48
- */
49
- class?: string;
50
-
51
- /**
52
- * 类名列表
53
- */
54
- 'class:list'?: any;
2
+ title: string;
3
+ description: string;
4
+ keywords: string;
5
+ author: string;
6
+ robots: string;
7
+
8
+ /**
9
+ * 图标
10
+ */
11
+ favicon?: ImageMetadata;
12
+
13
+ /**
14
+ * 基础路径,用于处理网站部署在二级目录的情况
15
+ * @default ""
16
+ */
17
+ basePath?: string;
18
+
19
+ /**
20
+ * 站点名称
21
+ */
22
+ siteName?: string;
23
+
24
+ /**
25
+ * 页面语言
26
+ * @default "zh-CN"
27
+ */
28
+ lang?: string;
29
+
30
+ /**
31
+ * 是否包含视口元标签
32
+ * @default true
33
+ */
34
+ viewport?: boolean;
35
+
36
+ /**
37
+ * 自定义CSS
38
+ */
39
+ customStyles?: string;
40
+
41
+ /**
42
+ * 自定义头部内容
43
+ */
44
+ head?: astroHTML.JSX.Element;
45
+
46
+ /**
47
+ * 页面类名
48
+ */
49
+ class?: string;
50
+
51
+ /**
52
+ * 类名列表
53
+ */
54
+ 'class:list'?: any;
55
+
56
+ /**
57
+ * 调试模式,显示边框
58
+ * @default false
59
+ */
60
+ debug?: boolean;
61
+
62
+ /**
63
+ * 预设背景色,可选值:'default' | 'white' | 'gray' | 'dark' | 'gradient-blue' | 'gradient-pink' | 'gradient-green'
64
+ * @default 'default'
65
+ */
66
+ background?: 'default' | 'white' | 'gray' | 'dark' | 'gradient-blue' | 'gradient-pink' | 'gradient-green';
55
67
  }
@@ -1,5 +1,50 @@
1
1
  <template>
2
- <li class="mb-2 rounded-md p-2 flex items-center gap-3 hover:bg-accent">
3
- <slot />
2
+ <li
3
+ class="cosy:mb-2 cosy:rounded-md cosy:bg-base-300 cosy:p-2 cosy:flex cosy:items-center cosy:gap-3 cosy:hover:bg-accent/10 cosy:relative cosy:overflow-hidden"
4
+ @click="$emit('click')"
5
+ >
6
+ <div
7
+ v-if="loading"
8
+ class="cosy:absolute cosy:left-0 cosy:top-0 cosy:h-full cosy:bg-accent/40 cosy:z-0 loading-bar"
9
+ :style="{ animationDuration: duration + 'ms' }"
10
+ ></div>
11
+ <div
12
+ class="cosy:relative cosy:z-10 cosy:w-full cosy:flex cosy:items-center cosy:gap-3"
13
+ >
14
+ <slot />
15
+ </div>
4
16
  </li>
5
17
  </template>
18
+
19
+ <script setup lang="ts">
20
+ import { defineProps, withDefaults, defineEmits } from 'vue';
21
+
22
+ withDefaults(
23
+ defineProps<{
24
+ loading?: boolean;
25
+ duration?: number; // 进度条动画时长,毫秒
26
+ }>(),
27
+ {
28
+ loading: false,
29
+ duration: 1500,
30
+ }
31
+ );
32
+
33
+ defineEmits(['click']);
34
+ </script>
35
+
36
+ <style scoped>
37
+ .loading-bar {
38
+ width: 0%;
39
+ height: 100%;
40
+ animation: loading-bar-anim linear forwards;
41
+ }
42
+ @keyframes loading-bar-anim {
43
+ 0% {
44
+ width: 0%;
45
+ }
46
+ 100% {
47
+ width: 100%;
48
+ }
49
+ }
50
+ </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffic/cosy-ui",
3
- "version": "0.8.22",
3
+ "version": "0.8.24",
4
4
  "description": "An astro component library",
5
5
  "author": {
6
6
  "name": "nookery",
@@ -63,7 +63,8 @@
63
63
  "@remixicon/vue": "^4.6.0",
64
64
  "astro-integration-kit": "^0.18.0",
65
65
  "fs-extra": "^11.3.0",
66
- "html-to-image": "^1.11.13"
66
+ "html-to-image": "^1.11.13",
67
+ "shiki": "^3.7.0"
67
68
  },
68
69
  "devDependencies": {
69
70
  "@astrojs/check": "^0.9.4",