@openconsole/shadcn 0.2.1 → 0.2.4
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/icon.tsx +55 -21
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/icon.tsx
CHANGED
|
@@ -1,21 +1,55 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { icons as lucideIcons, type LucideProps } from "lucide-react";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { icons as lucideIcons, type LucideProps } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "./lib/utils";
|
|
6
|
+
|
|
7
|
+
interface IconProps extends LucideProps {
|
|
8
|
+
/**
|
|
9
|
+
* 图标来源,按形态自动判别(三选一):
|
|
10
|
+
* - lucide-react 图标名,PascalCase(例如 `"LayoutDashboard"`);
|
|
11
|
+
* - 内联 SVG 源码(以 `<svg` 开头);
|
|
12
|
+
* - 图片地址:http(s) URL、绝对/相对路径、`data:image/` 或以图片
|
|
13
|
+
* 后缀(png/jpg/svg/webp…)结尾的字符串。
|
|
14
|
+
*/
|
|
15
|
+
name?: string;
|
|
16
|
+
/** `name` 为图片时的 `alt`;其余形态忽略。默认空串(按装饰性处理)。 */
|
|
17
|
+
alt?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** 起始前缀或图片后缀任一命中即视为图片地址。 */
|
|
21
|
+
const IMAGE_SOURCE =
|
|
22
|
+
/^(https?:\/\/|\/|\.\.?\/|data:image\/)|\.(png|jpe?g|gif|webp|avif|svg|ico|bmp)(\?.*)?$/i;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 渲染一个图标。`name` 可以是 lucide 图标名、内联 SVG 源码或图片地址,
|
|
26
|
+
* 组件按形态自动选择渲染方式,三者共享同一个 `className`(尺寸/颜色)。
|
|
27
|
+
*
|
|
28
|
+
* Sidebar 等数据把图标存成可序列化的纯字符串,以跨 RSC / Client 边界传递,
|
|
29
|
+
* 真正的查表 / 渲染发生在这里(客户端)。
|
|
30
|
+
*
|
|
31
|
+
* 注意:内联 SVG 经 `dangerouslySetInnerHTML` 注入,仅供可信来源(应用
|
|
32
|
+
* 自身配置)使用,切勿把用户输入直接传入。
|
|
33
|
+
*/
|
|
34
|
+
export function Icon({ name, alt = "", className, ...props }: IconProps) {
|
|
35
|
+
if (!name) return null;
|
|
36
|
+
|
|
37
|
+
if (name.trimStart().startsWith("<svg")) {
|
|
38
|
+
return (
|
|
39
|
+
<span
|
|
40
|
+
className={cn("inline-flex [&>svg]:size-full", className)}
|
|
41
|
+
dangerouslySetInnerHTML={{ __html: name }}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (IMAGE_SOURCE.test(name)) {
|
|
47
|
+
// 基础原语,刻意用原生 <img> 而非 next/image,避免 shadcn 层耦合框架。
|
|
48
|
+
return (
|
|
49
|
+
<img src={name} alt={alt} className={cn("object-contain", className)} />
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const LucideIcon = lucideIcons[name as keyof typeof lucideIcons];
|
|
54
|
+
return LucideIcon ? <LucideIcon className={className} {...props} /> : null;
|
|
55
|
+
}
|