@rxdrag/website-lib-core 0.0.119 → 0.0.121
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/package.json +3 -3
- package/src/astro/background.ts +17 -12
- package/src/astro/media.ts +1 -1
- package/src/design-tokens.ts +160 -0
- package/src/entify/Entify.ts +10 -0
- package/src/entify/IEntify.ts +6 -0
- package/src/entify/lib/index.ts +2 -0
- package/src/entify/lib/queryTagCategories.ts +58 -0
- package/src/entify/lib/queryTags.ts +57 -0
- package/src/entify/view-model/models.ts +17 -0
- package/src/index.ts +2 -0
- package/src/react/components/Icon/index.tsx +6 -12
- package/src/react/components/Icon/svgToIconify.ts +0 -59
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rxdrag/website-lib-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.121",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.ts"
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"eslint": "^9.39.2",
|
|
25
25
|
"typescript": "^5",
|
|
26
26
|
"@rxdrag/eslint-config-custom": "0.2.13",
|
|
27
|
-
"@rxdrag/tiptap-preview": "0.0.
|
|
27
|
+
"@rxdrag/tiptap-preview": "0.0.3",
|
|
28
28
|
"@rxdrag/tsconfig": "0.2.1"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"hls.js": "^1.6.13",
|
|
35
35
|
"lodash-es": "^4.17.21",
|
|
36
36
|
"@rxdrag/entify-lib": "0.0.24",
|
|
37
|
-
"@rxdrag/rxcms-models": "0.3.
|
|
37
|
+
"@rxdrag/rxcms-models": "0.3.98"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"astro": "^4.0.0 || ^5.0.0",
|
package/src/astro/background.ts
CHANGED
|
@@ -2,45 +2,50 @@
|
|
|
2
2
|
export type ColorBackgroundConfig = {
|
|
3
3
|
id?: string;
|
|
4
4
|
type: "color";
|
|
5
|
-
|
|
5
|
+
class?: string; // 颜色 ,模糊,图案等,如 "bg-blue-500", "bg-gradient-to-r from-blue-500 to-purple-600"
|
|
6
|
+
className?: string;//兼容旧的
|
|
6
7
|
};
|
|
7
8
|
|
|
8
9
|
export type BlurBackgroundConfig = {
|
|
9
10
|
id?: string;
|
|
10
11
|
type: "blur";
|
|
11
|
-
|
|
12
|
+
class?: string; // 模糊,如 "backdrop-blur"
|
|
13
|
+
className?: string;//兼容旧的
|
|
12
14
|
};
|
|
13
15
|
|
|
14
16
|
export type ImageBackgroundConfig = {
|
|
15
17
|
id?: string;
|
|
16
18
|
type: "image";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
class?: string; // 图片,如 "bg-cover bg-center bg-no-repeat"
|
|
20
|
+
className?: string;//兼容旧的
|
|
21
|
+
//实际组件中还会传入ImageMetadata
|
|
19
22
|
src?: string; // 图片源
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
export type SvgBackgroundConfig = {
|
|
23
26
|
id?: string;
|
|
24
27
|
type: "svg";
|
|
25
|
-
|
|
28
|
+
class?: string; // 图案,如 "bg-dots-sm bg-gray-100"
|
|
29
|
+
className?: string;//兼容旧的
|
|
26
30
|
code?: string; // SVG代码
|
|
27
31
|
};
|
|
28
32
|
|
|
29
33
|
export type VideoBackgroundConfig = {
|
|
30
34
|
id?: string;
|
|
31
35
|
type: "video";
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
class?: string; // 视频,如 "bg-cover bg-center bg-no-repeat"
|
|
37
|
+
className?: string;//兼容旧的
|
|
38
|
+
mediaRef?: string; // 视频源
|
|
39
|
+
//实际组件中还会传入ImageMetadata
|
|
40
|
+
poster?: string; // 视频封面图源
|
|
37
41
|
};
|
|
38
42
|
|
|
39
43
|
export type SplineBackgroundConfig = {
|
|
40
44
|
id?: string;
|
|
41
45
|
type: "spline";
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
class?: string; // Spline,如 "bg-cover bg-center bg-no-repeat"
|
|
47
|
+
className?: string;//兼容旧的
|
|
48
|
+
spline?: string; // Spline ID
|
|
44
49
|
url?: string; // Spline 场景 URL
|
|
45
50
|
};
|
|
46
51
|
|
package/src/astro/media.ts
CHANGED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 站点排版(Typography)相关的 className 枚举。
|
|
3
|
+
*
|
|
4
|
+
* - 这些值对应 Tailwind/CSS 中的 class 名称(例如 `.text-h1`)。
|
|
5
|
+
* - 用 enum 的好处是:业务侧使用时避免手写字符串、避免拼写错误。
|
|
6
|
+
*/
|
|
7
|
+
export enum TypographyClassName {
|
|
8
|
+
/**
|
|
9
|
+
* 一级标题(H1)
|
|
10
|
+
* - 使用场景:首页 Banner 主标题、内页页面标题
|
|
11
|
+
* - 样式:`@apply text-4xl sm:text-5xl lg:text-6xl xl:text-7xl font-semibold leading-tight;`
|
|
12
|
+
* - 文字颜色:品牌主色
|
|
13
|
+
* - 例:工业蓝 `#2E5AAC` / RGB(46, 90, 172)
|
|
14
|
+
* - Tailwind:`text-[#2E5AAC]`
|
|
15
|
+
*/
|
|
16
|
+
textH1 = "text-h1",
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 二级标题(H2)
|
|
20
|
+
* - 使用场景:板块标题(如“关于我们 / 产品分类 / 数字实力”)
|
|
21
|
+
* - 样式:`@apply text-3xl sm:text-4xl lg:text-5xl font-semibold leading-snug;`
|
|
22
|
+
* - 文字颜色:深灰色
|
|
23
|
+
* - 例:`#333333` / RGB(51, 51, 51)
|
|
24
|
+
* - Tailwind:`text-[#333333]`
|
|
25
|
+
*/
|
|
26
|
+
textH2 = "text-h2",
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 三级标题(H3)
|
|
30
|
+
* - 使用场景:子板块标题(如产品子类、优势小点)
|
|
31
|
+
* - 样式:`@apply text-2xl sm:text-3xl lg:text-4xl font-semibold leading-snug;`
|
|
32
|
+
* - 文字颜色:中深灰色
|
|
33
|
+
* - 例:`#444444` / RGB(68, 68, 68)
|
|
34
|
+
* - Tailwind:`text-[#444444]`
|
|
35
|
+
*/
|
|
36
|
+
textH3 = "text-h3",
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 四级标题(H4)
|
|
40
|
+
* - 使用场景:详情页小标题(如参数分类、案例亮点)
|
|
41
|
+
* - 样式:`@apply text-xl sm:text-2xl lg:text-3xl font-semibold leading-snug;`
|
|
42
|
+
* - 文字颜色:中灰色
|
|
43
|
+
* - 例:`#555555` / RGB(85, 85, 85)
|
|
44
|
+
* - Tailwind:`text-[#555555]`
|
|
45
|
+
*/
|
|
46
|
+
textH4 = "text-h4",
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* H5
|
|
50
|
+
* - 使用场景:H5 标题
|
|
51
|
+
* - 样式:`@apply text-lg md:text-xl leading-snug;`
|
|
52
|
+
*/
|
|
53
|
+
textH5 = "text-h5",
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* H6
|
|
57
|
+
* - 使用场景:H6 标题
|
|
58
|
+
* - 样式:`@apply text-base md:text-lg leading-relaxed;`
|
|
59
|
+
*/
|
|
60
|
+
textH6 = "text-h6",
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
// 正文(Body)
|
|
64
|
+
// - 更符合网站惯例:用全局基准字体(body 或内容容器)统一控制正文样式,段落直接继承
|
|
65
|
+
// - 文字颜色:中灰色
|
|
66
|
+
// - 例:`#666666` / RGB(102, 102, 102)
|
|
67
|
+
// - Tailwind:`text-[#666666]`
|
|
68
|
+
// textBody = "text-body",
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 辅助说明(Caption)
|
|
72
|
+
* - 使用场景:图片标注、参数备注、表单提示
|
|
73
|
+
* - 样式:`@apply text-xs md:text-sm leading-snug;` + `color: var(--foreground-secondary);`
|
|
74
|
+
* - 文字颜色:浅灰色
|
|
75
|
+
* - 例:`#888888` / RGB(136, 136, 136)
|
|
76
|
+
* - Tailwind:`text-[#888888]`
|
|
77
|
+
*/
|
|
78
|
+
textCaption = "text-caption",
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 强调文本(Strong)
|
|
82
|
+
* - 使用场景:核心数据、优势关键词(适配“数字实力”板块)
|
|
83
|
+
* - 样式:`@apply text-lg md:text-xl font-semibold leading-snug;`
|
|
84
|
+
* - 文字颜色:建议使用深灰色或继承当前容器标题色(以保证强调对比)
|
|
85
|
+
* - 深灰示例:`#333333` / RGB(51, 51, 51)
|
|
86
|
+
* - Tailwind:`text-[#333333]`
|
|
87
|
+
*/
|
|
88
|
+
textStrong = "text-strong",
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 链接文本(Link)
|
|
92
|
+
* - 使用场景:导航栏、按钮文字、详情跳转
|
|
93
|
+
* - 样式:`@apply text-sm md:text-base font-medium leading-snug;`
|
|
94
|
+
* - 文字颜色:品牌主色(同 H1)或深灰色 `#333333`
|
|
95
|
+
* - 常规:品牌主色 `#2E5AAC` / RGB(46, 90, 172)
|
|
96
|
+
* - Hover:主色加深 `#1E4A9C`
|
|
97
|
+
* - Tailwind:`text-[#2E5AAC] hover:text-[#1E4A9C]`
|
|
98
|
+
*/
|
|
99
|
+
textLink = "text-link",
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 颜色规范补充(非 Typography class):
|
|
104
|
+
* - 表单必填提示 / 订单须知:低饱和警示色
|
|
105
|
+
* - 例:`#E67E22` / RGB(230, 126, 34)
|
|
106
|
+
* - Tailwind:`text-[#E67E22]`
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 下拉/单选等 UI 控件的可选项顺序。
|
|
111
|
+
*
|
|
112
|
+
* 说明:不要依赖 `Object.values(TypographyClassName)` 做 UI 列表
|
|
113
|
+
* - 顺序不一定符合展示需求
|
|
114
|
+
* - 后续插入/调整可能导致 UI 顺序变化
|
|
115
|
+
*/
|
|
116
|
+
export const typographyClassNameList: TypographyClassName[] = [
|
|
117
|
+
TypographyClassName.textCaption,
|
|
118
|
+
TypographyClassName.textStrong,
|
|
119
|
+
TypographyClassName.textLink,
|
|
120
|
+
TypographyClassName.textH1,
|
|
121
|
+
TypographyClassName.textH2,
|
|
122
|
+
TypographyClassName.textH3,
|
|
123
|
+
TypographyClassName.textH4,
|
|
124
|
+
TypographyClassName.textH5,
|
|
125
|
+
TypographyClassName.textH6,
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 面向 UI 展示的短 label(用于下拉选项文案)。
|
|
130
|
+
*
|
|
131
|
+
* 约束:尽量短,避免下拉太宽。
|
|
132
|
+
*/
|
|
133
|
+
export const typographyClassNameLabels: Record<TypographyClassName, string> = {
|
|
134
|
+
[TypographyClassName.textH1]: "一级标题",
|
|
135
|
+
[TypographyClassName.textH2]: "二级标题",
|
|
136
|
+
[TypographyClassName.textH3]: "三级标题",
|
|
137
|
+
[TypographyClassName.textH4]: "四级标题",
|
|
138
|
+
[TypographyClassName.textH5]: "五级标题",
|
|
139
|
+
[TypographyClassName.textH6]: "六级标题",
|
|
140
|
+
[TypographyClassName.textCaption]: "说明",
|
|
141
|
+
[TypographyClassName.textStrong]: "强调",
|
|
142
|
+
[TypographyClassName.textLink]: "链接",
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Heading 组件 level(1-6) 与 Typography class 的映射。
|
|
147
|
+
*
|
|
148
|
+
* 说明:只定义 1-4(H1~H4)的排版规范;H5/H6 暂时回退到较小正文规格。
|
|
149
|
+
*/
|
|
150
|
+
export const headingLevelToTypographyClassName: Record<
|
|
151
|
+
1 | 2 | 3 | 4 | 5 | 6,
|
|
152
|
+
TypographyClassName
|
|
153
|
+
> = {
|
|
154
|
+
1: TypographyClassName.textH1,
|
|
155
|
+
2: TypographyClassName.textH2,
|
|
156
|
+
3: TypographyClassName.textH3,
|
|
157
|
+
4: TypographyClassName.textH4,
|
|
158
|
+
5: TypographyClassName.textH5,
|
|
159
|
+
6: TypographyClassName.textH6,
|
|
160
|
+
};
|
package/src/entify/Entify.ts
CHANGED
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
queryPosts,
|
|
16
16
|
queryProductCategories,
|
|
17
17
|
queryProducts,
|
|
18
|
+
queryTagCategories,
|
|
19
|
+
queryTags,
|
|
18
20
|
queryUserPosts,
|
|
19
21
|
fulltextSearch,
|
|
20
22
|
queryOneEntity,
|
|
@@ -268,6 +270,14 @@ export class Entify implements IEntify {
|
|
|
268
270
|
return await queryOnePostCategoryBySlug(slug, this.envVariables);
|
|
269
271
|
}
|
|
270
272
|
|
|
273
|
+
public async getTagCategories() {
|
|
274
|
+
return await queryTagCategories(this.envVariables);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public async getTags(categoryId?: string) {
|
|
278
|
+
return await queryTags(this.envVariables, categoryId);
|
|
279
|
+
}
|
|
280
|
+
|
|
271
281
|
public async getProducts(
|
|
272
282
|
conditions: ListConditions,
|
|
273
283
|
imageSize: ImageSize | undefined,
|
package/src/entify/IEntify.ts
CHANGED
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
TPostCategory,
|
|
6
6
|
TProduct,
|
|
7
7
|
TProductCategory,
|
|
8
|
+
TTag,
|
|
9
|
+
TTagCategory,
|
|
8
10
|
TUser,
|
|
9
11
|
} from "./view-model";
|
|
10
12
|
import {
|
|
@@ -123,6 +125,10 @@ export interface IEntify {
|
|
|
123
125
|
|
|
124
126
|
getPostCategoryBySlug(slug: string): Promise<TPostCategory | undefined>;
|
|
125
127
|
|
|
128
|
+
getTagCategories(): Promise<TTagCategory[] | undefined>;
|
|
129
|
+
|
|
130
|
+
getTags(categoryId?: string): Promise<TTag[] | undefined>;
|
|
131
|
+
|
|
126
132
|
getProducts(
|
|
127
133
|
conditions: ListConditions,
|
|
128
134
|
imageSize: ImageSize | undefined,
|
package/src/entify/lib/index.ts
CHANGED
|
@@ -19,6 +19,8 @@ export * from "./queryOneProductCategoryBySlug";
|
|
|
19
19
|
export * from "./queryOneUser";
|
|
20
20
|
export * from "./queryPostCategories";
|
|
21
21
|
export * from "./queryPosts";
|
|
22
|
+
export * from "./queryTagCategories";
|
|
23
|
+
export * from "./queryTags";
|
|
22
24
|
export * from "./queryProductCategories";
|
|
23
25
|
export * from "./queryProducts";
|
|
24
26
|
export * from "./queryProductsInMenu";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TagCategory,
|
|
3
|
+
TagCategoryBoolExp,
|
|
4
|
+
TagCategoryOrderBy,
|
|
5
|
+
TagCategoryDistinctExp,
|
|
6
|
+
TagCategoryFields,
|
|
7
|
+
TagCategoryQueryOptions,
|
|
8
|
+
TagQueryOptions,
|
|
9
|
+
TagFields,
|
|
10
|
+
} from "@rxdrag/rxcms-models";
|
|
11
|
+
import { queryEntityList } from "./queryEntityList";
|
|
12
|
+
import { ListResult } from "@rxdrag/entify-lib";
|
|
13
|
+
import { EnvVariables } from "../types";
|
|
14
|
+
import { TTagCategory } from "../view-model";
|
|
15
|
+
import { listToTree } from "./listToTree";
|
|
16
|
+
|
|
17
|
+
export async function queryTagCategories(envVariables: EnvVariables) {
|
|
18
|
+
const result = await queryEntityList<
|
|
19
|
+
TagCategory,
|
|
20
|
+
TagCategoryBoolExp,
|
|
21
|
+
TagCategoryOrderBy,
|
|
22
|
+
TagCategoryDistinctExp
|
|
23
|
+
>(
|
|
24
|
+
new TagCategoryQueryOptions(
|
|
25
|
+
[
|
|
26
|
+
TagCategoryFields.id,
|
|
27
|
+
TagCategoryFields.name,
|
|
28
|
+
],
|
|
29
|
+
{
|
|
30
|
+
where: {
|
|
31
|
+
lang: {
|
|
32
|
+
abbr: {
|
|
33
|
+
_eq: envVariables.language,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
orderBy: [{ [TagCategoryFields.name]: "asc" }],
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
.parent()
|
|
41
|
+
.tags(
|
|
42
|
+
new TagQueryOptions(
|
|
43
|
+
[TagFields.id, TagFields.name, TagFields.color],
|
|
44
|
+
{
|
|
45
|
+
orderBy: [{ [TagFields.createdAt]: "desc" }],
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
),
|
|
49
|
+
envVariables
|
|
50
|
+
);
|
|
51
|
+
const typedResult = result as ListResult<TTagCategory> | undefined;
|
|
52
|
+
|
|
53
|
+
if (!typedResult) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return listToTree(typedResult.items || []);
|
|
58
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Tag,
|
|
3
|
+
TagBoolExp,
|
|
4
|
+
TagOrderBy,
|
|
5
|
+
TagDistinctExp,
|
|
6
|
+
TagFields,
|
|
7
|
+
TagQueryOptions,
|
|
8
|
+
TagAssciations,
|
|
9
|
+
} from "@rxdrag/rxcms-models";
|
|
10
|
+
import { queryEntityList } from "./queryEntityList";
|
|
11
|
+
import { ListResult } from "@rxdrag/entify-lib";
|
|
12
|
+
import { EnvVariables } from "../types";
|
|
13
|
+
import { TTag } from "../view-model";
|
|
14
|
+
|
|
15
|
+
export async function queryTags(envVariables: EnvVariables, categoryId?: string) {
|
|
16
|
+
const whereCondition: TagBoolExp = {
|
|
17
|
+
lang: {
|
|
18
|
+
abbr: {
|
|
19
|
+
_eq: envVariables.language,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if (categoryId) {
|
|
25
|
+
whereCondition[TagAssciations.category] = {
|
|
26
|
+
id: { _eq: categoryId },
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const result = await queryEntityList<
|
|
31
|
+
Tag,
|
|
32
|
+
TagBoolExp,
|
|
33
|
+
TagOrderBy,
|
|
34
|
+
TagDistinctExp
|
|
35
|
+
>(
|
|
36
|
+
new TagQueryOptions(
|
|
37
|
+
[
|
|
38
|
+
TagFields.id,
|
|
39
|
+
TagFields.name,
|
|
40
|
+
TagFields.color,
|
|
41
|
+
],
|
|
42
|
+
{
|
|
43
|
+
where: whereCondition,
|
|
44
|
+
orderBy: [{ [TagFields.name]: "asc" }],
|
|
45
|
+
}
|
|
46
|
+
).category(),
|
|
47
|
+
envVariables
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const typedResult = result as ListResult<TTag> | undefined;
|
|
51
|
+
|
|
52
|
+
if (!typedResult) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return typedResult.items;
|
|
57
|
+
}
|
|
@@ -50,6 +50,21 @@ export type TPostCategory = {
|
|
|
50
50
|
posts?: TPost[];
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
+
export type TTagCategory = {
|
|
54
|
+
id?: string | null;
|
|
55
|
+
name?: string;
|
|
56
|
+
children?: TTagCategory[];
|
|
57
|
+
parent?: TTagCategory;
|
|
58
|
+
tags?: TTag[];
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export type TTag = {
|
|
62
|
+
id?: string | null;
|
|
63
|
+
name?: string;
|
|
64
|
+
color?: string;
|
|
65
|
+
category?: TTagCategory;
|
|
66
|
+
};
|
|
67
|
+
|
|
53
68
|
export type TUser = {
|
|
54
69
|
id?: string | null;
|
|
55
70
|
name?: string;
|
|
@@ -113,6 +128,8 @@ export const entityMaps: Record<string, string> = {
|
|
|
113
128
|
Product: "TProduct",
|
|
114
129
|
Post: "TPost",
|
|
115
130
|
PostCategory: "TPostCategory",
|
|
131
|
+
TagCategory: "TTagCategory",
|
|
132
|
+
Tag: "TTag",
|
|
116
133
|
User: "TUser",
|
|
117
134
|
WebsiteSettings: "TWebsiteSettings",
|
|
118
135
|
};
|
package/src/index.ts
CHANGED
|
@@ -2,25 +2,19 @@ import {
|
|
|
2
2
|
Icon as IconifyIcon,
|
|
3
3
|
IconProps as IconifyIconProps,
|
|
4
4
|
} from "@iconify/react";
|
|
5
|
+
import type { IconifyIcon as IconifyIconData } from "@iconify/react";
|
|
5
6
|
import { forwardRef } from "react";
|
|
6
|
-
import { svgToIconify } from "./svgToIconify";
|
|
7
|
-
|
|
8
|
-
export { svgToIconify };
|
|
9
7
|
|
|
10
8
|
export type IconProps = Omit<IconifyIconProps, "icon"> & {
|
|
11
|
-
icon?: string;
|
|
12
|
-
svg?: string;
|
|
9
|
+
icon?: string | IconifyIconData;
|
|
13
10
|
};
|
|
14
11
|
|
|
15
12
|
export const Icon = forwardRef<SVGSVGElement, IconProps>((props, ref) => {
|
|
16
|
-
const { icon,
|
|
17
|
-
|
|
18
|
-
const iconObj = svg ? svgToIconify(svg) : undefined;
|
|
19
|
-
const finalIcon = icon || iconObj;
|
|
13
|
+
const { icon, ...rest } = props;
|
|
20
14
|
|
|
21
|
-
if (!
|
|
15
|
+
if (!icon) {
|
|
22
16
|
return null;
|
|
23
17
|
}
|
|
24
18
|
|
|
25
|
-
return <IconifyIcon ref={ref} {...rest} icon={
|
|
26
|
-
});
|
|
19
|
+
return <IconifyIcon ref={ref} {...rest} icon={icon} />;
|
|
20
|
+
});
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { IconifyIcon } from "@iconify/react";
|
|
2
|
-
|
|
3
|
-
export function svgToIconify(svgString: string): IconifyIcon | null {
|
|
4
|
-
if (typeof window === 'undefined') return null;
|
|
5
|
-
|
|
6
|
-
try {
|
|
7
|
-
const parser = new DOMParser();
|
|
8
|
-
const doc = parser.parseFromString(svgString, "image/svg+xml");
|
|
9
|
-
const svg = doc.querySelector("svg");
|
|
10
|
-
|
|
11
|
-
if (!svg) {
|
|
12
|
-
console.error("Invalid SVG string");
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const viewBox = svg.getAttribute("viewBox");
|
|
17
|
-
let width = svg.getAttribute("width");
|
|
18
|
-
let height = svg.getAttribute("height");
|
|
19
|
-
|
|
20
|
-
// 如果没有显式宽高,尝试从 viewBox 解析
|
|
21
|
-
if (viewBox && (!width || !height)) {
|
|
22
|
-
const parts = viewBox.split(/\s+/).map(parseFloat);
|
|
23
|
-
if (parts.length === 4) {
|
|
24
|
-
if (!width) width = parts[2].toString();
|
|
25
|
-
if (!height) height = parts[3].toString();
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// 提取关键属性并包裹在 <g> 中,以保留 SVG 根节点的样式
|
|
30
|
-
const attributesToPreserve = [
|
|
31
|
-
"fill",
|
|
32
|
-
"stroke",
|
|
33
|
-
"stroke-width",
|
|
34
|
-
"stroke-linecap",
|
|
35
|
-
"stroke-linejoin"
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
const gAttributes = attributesToPreserve
|
|
39
|
-
.map(attr => {
|
|
40
|
-
const value = svg.getAttribute(attr);
|
|
41
|
-
return value ? `${attr}="${value}"` : "";
|
|
42
|
-
})
|
|
43
|
-
.filter(Boolean)
|
|
44
|
-
.join(" ");
|
|
45
|
-
|
|
46
|
-
const body = gAttributes
|
|
47
|
-
? `<g ${gAttributes}>${svg.innerHTML}</g>`
|
|
48
|
-
: svg.innerHTML;
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
body,
|
|
52
|
-
width: width ? parseFloat(width) : undefined,
|
|
53
|
-
height: height ? parseFloat(height) : undefined,
|
|
54
|
-
};
|
|
55
|
-
} catch (e) {
|
|
56
|
-
console.error("Error parsing SVG:", e);
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
}
|