@open-dy/lucide-taro 0.0.1-beta.1
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/README.md +147 -0
- package/dist/generate-tabbar-png.mjs +36 -0
- package/dist/iconNodes.mjs +8 -0
- package/dist/lucide-taro.d.ts +3444 -0
- package/dist/lucide-taro.mjs +8 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# @open-dy/lucide-taro
|
|
2
|
+
|
|
3
|
+
面向 Taro 小程序的 Lucide 图标组件库,并提供生成小程序 TabBar PNG 图标的命令行工具。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @open-dy/lucide-taro
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
项目需要同时安装兼容版本的 React 与 `@tarojs/components`。
|
|
12
|
+
|
|
13
|
+
## 使用图标组件
|
|
14
|
+
|
|
15
|
+
图标名和常用 API 与 `lucide-react` 保持一致,业务代码必须从 `@open-dy/lucide-taro` 导入:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { House, Search, Settings } from '@open-dy/lucide-taro'
|
|
19
|
+
import { View } from '@tarojs/components'
|
|
20
|
+
|
|
21
|
+
export function Actions() {
|
|
22
|
+
return (
|
|
23
|
+
<View className="flex items-center gap-3">
|
|
24
|
+
<House size={24} color="#1677ff" strokeWidth={2} />
|
|
25
|
+
<Search size="20" color="#111827" />
|
|
26
|
+
<Settings size={20} color="#6b7280" />
|
|
27
|
+
</View>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 图标属性
|
|
33
|
+
|
|
34
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
35
|
+
| --- | --- | --- | --- |
|
|
36
|
+
| `size` | `string \| number` | `24` | 图标宽高 |
|
|
37
|
+
| `color` | `string` | `currentColor` | 描边颜色;小程序中建议始终显式传入 |
|
|
38
|
+
| `strokeWidth` | `string \| number` | `2` | 描边宽度 |
|
|
39
|
+
| `filled` | `boolean` | `false` | 使用 `color` 填充图标 |
|
|
40
|
+
| `absoluteStrokeWidth` | `boolean` | `false` | 缩放尺寸时保持视觉描边宽度 |
|
|
41
|
+
| `className` | `string` | - | 添加到外层 Taro `Image` |
|
|
42
|
+
| `style` | `CSSProperties` | - | 添加到外层 Taro `Image` |
|
|
43
|
+
|
|
44
|
+
原生小程序不能直接渲染内联 SVG。本包会把图标序列化为 SVG data URI,并通过 Taro `Image` 组件显示。因此:
|
|
45
|
+
|
|
46
|
+
- `className` 和 `style` 只影响外层 `Image`,不会把 CSS `color` 传入 SVG。
|
|
47
|
+
- 不要依赖 `currentColor` 或 `text-*` class 改变图标笔画,始终显式传递 `color`。
|
|
48
|
+
- 图标所在的按钮或容器应提供明确宽高和居中布局。
|
|
49
|
+
|
|
50
|
+
## 全局默认属性
|
|
51
|
+
|
|
52
|
+
可以使用 `LucideProvider` 为子树设置默认值:
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import {
|
|
56
|
+
Bell,
|
|
57
|
+
LucideProvider,
|
|
58
|
+
MessageCircle,
|
|
59
|
+
} from '@open-dy/lucide-taro'
|
|
60
|
+
|
|
61
|
+
export function IconGroup() {
|
|
62
|
+
return (
|
|
63
|
+
<LucideProvider size={20} color="#475569" strokeWidth={2}>
|
|
64
|
+
<Bell />
|
|
65
|
+
<MessageCircle color="#1677ff" />
|
|
66
|
+
</LucideProvider>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
组件自身的属性会覆盖 Provider 默认值。`useLucideContext()` 可读取当前默认配置。
|
|
72
|
+
|
|
73
|
+
## 查找可用图标
|
|
74
|
+
|
|
75
|
+
包会导出 Lucide 的 PascalCase 图标名及常见兼容别名。不要猜测图标是否存在,使用前搜索类型声明:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
rg "declare const House" node_modules/@open-dy/lucide-taro/dist/lucide-taro.d.ts
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
常见命名形态包括 `House`、`HouseIcon` 和部分历史别名。准确导出列表以 `dist/lucide-taro.d.ts` 为准。
|
|
82
|
+
|
|
83
|
+
## 生成 TabBar PNG
|
|
84
|
+
|
|
85
|
+
小程序 TabBar 不支持 SVG 或 data URI,需要使用本地 PNG。安装 `sharp` 后,可使用包内命令生成普通态和选中态图标:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pnpm add -D sharp
|
|
89
|
+
|
|
90
|
+
pnpm exec generate-tabbar-png House Search User \
|
|
91
|
+
-o ./src/assets/tabbar \
|
|
92
|
+
-c "#999999" \
|
|
93
|
+
-a "#1677ff"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
生成结果:
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
src/assets/tabbar/
|
|
100
|
+
├── House.png
|
|
101
|
+
├── House-active.png
|
|
102
|
+
├── Search.png
|
|
103
|
+
├── Search-active.png
|
|
104
|
+
├── User.png
|
|
105
|
+
└── User-active.png
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### CLI 参数
|
|
109
|
+
|
|
110
|
+
| 参数 | 说明 |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| `<icon...>` | 一个或多个 PascalCase 图标名 |
|
|
113
|
+
| `-o, --out <dir>` | 输出目录,必填 |
|
|
114
|
+
| `--output <name>` | 单图模式的输出文件名前缀 |
|
|
115
|
+
| `-s, --size <n>` | PNG 尺寸,默认 `81` |
|
|
116
|
+
| `-c, --color <hex>` | 普通态颜色,默认 `#999999` |
|
|
117
|
+
| `-a, --active-color <hex>` | 选中态颜色;传入后额外生成 `-active.png` |
|
|
118
|
+
| `-w, --stroke-width <n>` | 描边宽度,默认 `2` |
|
|
119
|
+
| `-h, --help` | 显示帮助 |
|
|
120
|
+
|
|
121
|
+
单图自定义文件名示例:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
pnpm exec generate-tabbar-png House \
|
|
125
|
+
-o ./src/assets/tabbar \
|
|
126
|
+
--output home \
|
|
127
|
+
-c "#999999" \
|
|
128
|
+
-a "#1677ff"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## 当前能力
|
|
132
|
+
|
|
133
|
+
- 以 Taro `Image` 渲染 Lucide 图标,支持 H5 与小程序构建。
|
|
134
|
+
- 提供完整 TypeScript 图标类型与常见 Lucide 命名别名。
|
|
135
|
+
- 支持单图属性和 `LucideProvider` 全局默认属性。
|
|
136
|
+
- 支持通过 CLI 批量生成 TabBar 普通态与选中态 PNG。
|
|
137
|
+
- 支持尺寸、颜色、描边宽度和单图输出文件名配置。
|
|
138
|
+
|
|
139
|
+
## 开发与验证
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
pnpm build
|
|
143
|
+
pnpm test
|
|
144
|
+
pnpm pack:local
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`dist/` 是该包直接发布的源码产物。修改图标导出或 TabBar 工具后,需要同步验证 `dist/lucide-taro.mjs`、`dist/lucide-taro.d.ts`、`dist/iconNodes.mjs` 与 `dist/generate-tabbar-png.mjs`。
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license lucide-taro v0.0.1 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import{mkdir as h,writeFile as v}from"fs/promises";import{isAbsolute as z,resolve as p,dirname as $}from"path";import{zM as W,zN as x}from"./iconNodes.mjs";const s={xmlns:"http://www.w3.org/2000/svg",size:24,viewBox:"0 0 24 24",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};function H(u){return u.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}function L(u){return u==="viewBox"?u:H(u)}function w(u){return Object.entries(u).map(([t,e])=>`${L(t)}="${P(e)}"`).join(" ")}function P(u){return String(u).replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function C(u,t={}){const e=t.size??s.size,r=t.color??"#000",o=t.strokeWidth??s.strokeWidth,i={xmlns:s.xmlns,width:e,height:e,viewBox:s.viewBox,fill:s.fill,stroke:r,strokeWidth:o,strokeLinecap:s.strokeLinecap,strokeLinejoin:s.strokeLinejoin},n=u.map(([F,a])=>`<${F} ${w(a)} />`).join("");return`<svg ${w(i)}>${n}</svg>`}let E;async function y(){return E||(E=(async()=>{try{const u=await import("sharp"),t=u.default??u;if(typeof t!="function")throw new Error("unexpected sharp export");return t}catch{throw new Error(`[lucide-taro] \u9700\u8981 sharp \u6765\u751F\u6210 PNG\u3002
|
|
9
|
+
\u8BF7\u5728\u5F53\u524D\u9879\u76EE\u5B89\u88C5\uFF1A
|
|
10
|
+
pnpm add -D sharp`)}})()),E}async function g(u,t={}){let e=(await y())(Buffer.from(u));t.size&&(e=e.resize(t.size,t.size));const r=await e.png().toBuffer();return new Uint8Array(r)}function S(u){let t=u;return t.startsWith("Lucide")&&(t=t.slice(6)),t.endsWith("Icon")&&(t=t.slice(0,-4)),x[t]??t}function N(u){const t=S(u),e=W[t];if(!e)throw new Error(`[lucide-taro] \u672A\u627E\u5230\u56FE\u6807 "${u}"\u3002\u8BF7\u4F7F\u7528\u4E0E lucide-taro \u5BFC\u51FA\u7684\u7EC4\u4EF6\u540D\u4E00\u81F4\u7684 PascalCase\uFF0C\u4F8B\u5982 'House' / 'HouseIcon' / 'LucideHouse' / 'Home'\u3002`);return e}async function A(u,t){await h($(u),{recursive:!0}),await v(u,t)}async function j(u){const t=process.cwd(),e=z(u.outDir)?u.outDir:p(t,u.outDir);await h(e,{recursive:!0});const r=[];for(const o of u.icons){const i=o.size??u.defaultSize??81,n=o.strokeWidth??u.defaultStrokeWidth??2,F=o.color??u.defaultColor??"#999999",a=o.activeColor??u.defaultActiveColor,c=o.output??o.name,B=o.activeSuffix??"-active",f=N(o.name),m=C(f,{size:i,color:F,strokeWidth:n}),D=await g(m,{size:i}),l=p(e,`${c}.png`);if(await A(l,D),r.push({icon:o.name,output:c,file:l,active:!1,size:i}),u.onProgress?.(`[lucide-taro] ${o.name} -> ${l}`),a){const b=C(f,{size:i,color:a,strokeWidth:n}),k=await g(b,{size:i}),d=p(e,`${c}${B}.png`);await A(d,k),r.push({icon:o.name,output:c,file:d,active:!0,size:i}),u.onProgress?.(`[lucide-taro] ${o.name} (active) -> ${d}`)}}return{outDir:e,entries:r}}function I(u){const t={icons:[]};for(let e=0;e<u.length;e+=1){const r=u[e],o=()=>u[++e];switch(r){case"-h":case"--help":t.help=!0;break;case"-o":case"--out":case"--out-dir":t.out=o();break;case"--output":t.output=o();break;case"-s":case"--size":t.size=Number(o());break;case"-c":case"--color":t.color=o();break;case"-a":case"--active-color":t.activeColor=o();break;case"-w":case"--stroke-width":t.strokeWidth=Number(o());break;default:if(r.startsWith("-"))throw new Error(`\u672A\u77E5\u53C2\u6570: ${r}`);t.icons.push(r)}}return t}function G(){process.stdout.write(`lucide-taro-tabbar-png
|
|
11
|
+
|
|
12
|
+
\u7528\u6CD5\uFF1A
|
|
13
|
+
lucide-taro-tabbar-png <icon...> [options]
|
|
14
|
+
|
|
15
|
+
\u793A\u4F8B\uFF1A
|
|
16
|
+
lucide-taro-tabbar-png House -o ./tabbar -c '#999999' -a '#1677ff'
|
|
17
|
+
lucide-taro-tabbar-png House Search User Settings -o ./tabbar -c '#999' -a '#1677ff'
|
|
18
|
+
|
|
19
|
+
\u53C2\u6570\uFF1A
|
|
20
|
+
<icon...> \u4E00\u4E2A\u6216\u591A\u4E2A lucide \u56FE\u6807\u540D\uFF0C\u4F7F\u7528 PascalCase\uFF0C
|
|
21
|
+
\u4E0E lucide-taro \u5BFC\u51FA\u7684\u7EC4\u4EF6\u540D\u4FDD\u6301\u4E00\u81F4\uFF08\u5982 House /
|
|
22
|
+
HouseIcon / LucideHouse / Home / LucideHome\uFF09\uFF0C
|
|
23
|
+
\u8F93\u51FA\u6587\u4EF6\u540D\u4F1A\u76F4\u63A5\u4F7F\u7528\u8BE5\u540D\u79F0
|
|
24
|
+
-o, --out <dir> \u8F93\u51FA\u76EE\u5F55\uFF0C\u5FC5\u586B
|
|
25
|
+
--output <name> \u4EC5\u5355\u56FE\u65F6\u751F\u6548\uFF1B\u8F93\u51FA\u6587\u4EF6\u540D\u524D\u7F00\uFF0C\u9ED8\u8BA4\u4E0E\u56FE\u6807\u540D\u76F8\u540C
|
|
26
|
+
-s, --size <n> PNG \u5C3A\u5BF8\uFF0C\u9ED8\u8BA4 81
|
|
27
|
+
-c, --color <hex> \u666E\u901A\u6001\u989C\u8272\uFF0C\u9ED8\u8BA4 '#999999'
|
|
28
|
+
-a, --active-color <hex> \u9009\u4E2D\u6001\u989C\u8272\uFF1B\u7ED9\u51FA\u4F1A\u989D\u5916\u751F\u6210 <name>-active.png
|
|
29
|
+
-w, --stroke-width <n> \u63CF\u8FB9\u5BBD\u5EA6\uFF0C\u9ED8\u8BA4 2
|
|
30
|
+
-h, --help \u663E\u793A\u5E2E\u52A9
|
|
31
|
+
`)}async function U(){const u=I(process.argv.slice(2));if(u.help||process.argv.length<=2){G();return}if(u.icons.length===0)throw new Error("\u81F3\u5C11\u4F20\u5165\u4E00\u4E2A\u56FE\u6807\u540D\uFF0C\u4F8B\u5982: lucide-taro-tabbar-png house -o ./tabbar");if(!u.out)throw new Error("\u7F3A\u5C11 --out/-o \u53C2\u6570\uFF0C\u5FC5\u987B\u6307\u5B9A\u8F93\u51FA\u76EE\u5F55");if(u.output&&u.icons.length>1)throw new Error("--output \u4EC5\u652F\u6301\u5355\u56FE\u6807\uFF1B\u6279\u91CF\u6A21\u5F0F\u4E0B\u6587\u4EF6\u540D\u5C06\u4F7F\u7528\u56FE\u6807\u540D\u672C\u8EAB");const t=u.icons.map(r=>({name:r,output:u.icons.length===1?u.output:void 0,size:u.size,color:u.color,activeColor:u.activeColor,strokeWidth:u.strokeWidth})),e=await j({outDir:u.out,icons:t,onProgress:r=>process.stdout.write(`${r}
|
|
32
|
+
`)});process.stdout.write(`
|
|
33
|
+
[lucide-taro] \u751F\u6210\u5B8C\u6210\uFF0C\u5171 ${e.entries.length} \u5F20 PNG
|
|
34
|
+
`),process.stdout.write(`[lucide-taro] \u8F93\u51FA\u76EE\u5F55: ${e.outDir}
|
|
35
|
+
`)}U().catch(u=>{process.stderr.write(`[lucide-taro] \u751F\u6210\u5931\u8D25: ${u instanceof Error?u.message:String(u)}
|
|
36
|
+
`),process.exit(1)});
|