@zl-ui-kit/theme 0.5.1 → 0.6.0

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 CHANGED
@@ -8,7 +8,7 @@ ZL UI 主题引擎(决策 D7):内置 5 套主题(light/dark/red-light/re
8
8
  ## 快速上手
9
9
 
10
10
  ```ts
11
- import '@zl-ui-kit/theme/themes.css' // 或按需 '@zl-ui-kit/theme/light'
11
+ import '@zl-ui-kit/theme/themes.css' // 或按需 '@zl-ui-kit/theme/light'
12
12
  import { setTheme, defineTheme, useTheme } from '@zl-ui-kit/theme'
13
13
 
14
14
  setTheme('dark')
@@ -20,12 +20,12 @@ defineTheme({ name: 'brand', base: 'light', colors: { primary: '#722ED1' }, appl
20
20
 
21
21
  ## 入口
22
22
 
23
- | 入口 | 内容 |
24
- | --- | --- |
25
- | `.` | 运行时 API(defineTheme/setTheme/useTheme/mix/generateElShades)+ 常量 |
26
- | `/light` `/dark` `/red-light` `/red-dark` `/blue` `/themes.css` | 每主题/合集预编译 CSS(变量 + reset + overrides) |
27
- | `/scss`(及 `/scss/*.scss`) | SCSS 工具(colorForEach/colorGradient/theme mixin/mapGet) |
28
- | `/assets/*` | 主题背景图 |
23
+ | 入口 | 内容 |
24
+ | --------------------------------------------------------------- | ---------------------------------------------------------------------- |
25
+ | `.` | 运行时 API(defineTheme/setTheme/useTheme/mix/generateElShades)+ 常量 |
26
+ | `/light` `/dark` `/red-light` `/red-dark` `/blue` `/themes.css` | 每主题/合集预编译 CSS(变量 + reset + overrides) |
27
+ | `/scss`(及 `/scss/*.scss`) | SCSS 工具(colorForEach/colorGradient/theme mixin/mapGet) |
28
+ | `/assets/*` | 主题背景图 |
29
29
 
30
30
  ## 本地调试
31
31
 
package/dist/index.js CHANGED
@@ -1132,7 +1132,11 @@ function parseColor(str) {
1132
1132
  let hex = s.slice(1);
1133
1133
  if (hex.length === 3)
1134
1134
  hex = hex.split("").map((c) => c + c).join("");
1135
- return [Number.parseInt(hex.slice(0, 2), 16), Number.parseInt(hex.slice(2, 4), 16), Number.parseInt(hex.slice(4, 6), 16)];
1135
+ return [
1136
+ Number.parseInt(hex.slice(0, 2), 16),
1137
+ Number.parseInt(hex.slice(2, 4), 16),
1138
+ Number.parseInt(hex.slice(4, 6), 16)
1139
+ ];
1136
1140
  }
1137
1141
  const m = s.match(/rgba?\(([^)]+)\)/);
1138
1142
  if (m) {
@@ -1151,8 +1155,7 @@ function toHex([r, g, b]) {
1151
1155
  function mix(color1, color2, weight) {
1152
1156
  const c1 = parseColor(color1);
1153
1157
  const c2 = parseColor(color2);
1154
- if (!c1 || !c2)
1155
- return color1;
1158
+ if (!c1 || !c2) return color1;
1156
1159
  const w = weight / 100;
1157
1160
  return toHex([c1[0] * (1 - w) + c2[0] * w, c1[1] * (1 - w) + c2[1] * w, c1[2] * (1 - w) + c2[2] * w]);
1158
1161
  }
@@ -1207,13 +1210,28 @@ function buildCssVars(resolved, themeName) {
1207
1210
  decls.push(`--el-color-${name}-${shade}: ${value};`);
1208
1211
  }
1209
1212
  }
1210
- const textMap = { primary: "text-1", regular: "text-2", secondary: "text-3", placeholder: "text-4", disabled: "text-5" };
1211
- for (const [el, token] of Object.entries(textMap))
1212
- decls.push(`--el-text-color-${el}: ${get(token)};`);
1213
- const borderMap = [["extra-light", "border-1"], ["lighter", "border-2"], ["light", "border-3"], ["", "border-4"]];
1213
+ const textMap = {
1214
+ primary: "text-1",
1215
+ regular: "text-2",
1216
+ secondary: "text-3",
1217
+ placeholder: "text-4",
1218
+ disabled: "text-5"
1219
+ };
1220
+ for (const [el, token] of Object.entries(textMap)) decls.push(`--el-text-color-${el}: ${get(token)};`);
1221
+ const borderMap = [
1222
+ ["extra-light", "border-1"],
1223
+ ["lighter", "border-2"],
1224
+ ["light", "border-3"],
1225
+ ["", "border-4"]
1226
+ ];
1214
1227
  for (const [suffix, token] of borderMap)
1215
1228
  decls.push(`--el-border-color${suffix ? `-${suffix}` : ""}: ${get(token)};`);
1216
- const fillMap = [["extra-light", "fill-1"], ["lighter", "fill-2"], ["light", "fill-3"], ["", "fill-4"]];
1229
+ const fillMap = [
1230
+ ["extra-light", "fill-1"],
1231
+ ["lighter", "fill-2"],
1232
+ ["light", "fill-3"],
1233
+ ["", "fill-4"]
1234
+ ];
1217
1235
  for (const [suffix, token] of fillMap)
1218
1236
  decls.push(`--el-fill-color${suffix ? `-${suffix}` : ""}: ${get(token)};`);
1219
1237
  decls.push(`--el-fill-color-blank: ${isDark ? get("bg-2") : "#ffffff"};`);
@@ -1257,8 +1275,7 @@ function defineTheme(options) {
1257
1275
  resolved[`color-${palette}-${level}`] = hex;
1258
1276
  const seedLevel = Number(level);
1259
1277
  for (let i = 1; i <= 10; i++) {
1260
- if (i === seedLevel)
1261
- continue;
1278
+ if (i === seedLevel) continue;
1262
1279
  const weight = Math.abs(i - seedLevel) / 5 * 50;
1263
1280
  resolved[`color-${palette}-${i}`] = i < seedLevel ? mix("#ffffff", hex, 100 - weight) : mix("#000000", hex, 100 - weight);
1264
1281
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zl-ui-kit/theme",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "ZL UI 主题引擎:内置 5 套主题(light/dark/red-light/red-dark/blue),--zl-* 业务变量 + --el-* Element Plus 变量三层体系,支持运行时自定义主题(defineTheme/setTheme)",
6
6
  "license": "MIT",
@@ -41,8 +41,8 @@
41
41
  "cross-env": "^7.0.3",
42
42
  "tsup": "^8.3.5",
43
43
  "typescript": "^5.7.3",
44
- "@jichuang/tsconfig": "1.0.0",
45
- "@jichuang/eslint-config": "1.0.0"
44
+ "@jichuang/eslint-config": "1.0.0",
45
+ "@jichuang/tsconfig": "1.0.0"
46
46
  },
47
47
  "repository": {
48
48
  "type": "git",
@@ -50,8 +50,7 @@ const changeListeners = new Set<(theme: string) => void>()
50
50
  function initThemeFromStorage(): string {
51
51
  try {
52
52
  return localStorage.getItem(THEME_STORAGE_KEY) || 'light'
53
- }
54
- catch {
53
+ } catch {
55
54
  return 'light'
56
55
  }
57
56
  }
@@ -88,15 +87,30 @@ function buildCssVars(resolved: Record<string, string>, themeName: string): stri
88
87
  }
89
88
  }
90
89
 
91
- const textMap: Record<string, string> = { primary: 'text-1', regular: 'text-2', secondary: 'text-3', placeholder: 'text-4', disabled: 'text-5' }
92
- for (const [el, token] of Object.entries(textMap))
93
- decls.push(`--el-text-color-${el}: ${get(token)};`)
90
+ const textMap: Record<string, string> = {
91
+ primary: 'text-1',
92
+ regular: 'text-2',
93
+ secondary: 'text-3',
94
+ placeholder: 'text-4',
95
+ disabled: 'text-5',
96
+ }
97
+ for (const [el, token] of Object.entries(textMap)) decls.push(`--el-text-color-${el}: ${get(token)};`)
94
98
 
95
- const borderMap: Array<[string, string]> = [['extra-light', 'border-1'], ['lighter', 'border-2'], ['light', 'border-3'], ['', 'border-4']]
99
+ const borderMap: Array<[string, string]> = [
100
+ ['extra-light', 'border-1'],
101
+ ['lighter', 'border-2'],
102
+ ['light', 'border-3'],
103
+ ['', 'border-4'],
104
+ ]
96
105
  for (const [suffix, token] of borderMap)
97
106
  decls.push(`--el-border-color${suffix ? `-${suffix}` : ''}: ${get(token)};`)
98
107
 
99
- const fillMap: Array<[string, string]> = [['extra-light', 'fill-1'], ['lighter', 'fill-2'], ['light', 'fill-3'], ['', 'fill-4']]
108
+ const fillMap: Array<[string, string]> = [
109
+ ['extra-light', 'fill-1'],
110
+ ['lighter', 'fill-2'],
111
+ ['light', 'fill-3'],
112
+ ['', 'fill-4'],
113
+ ]
100
114
  for (const [suffix, token] of fillMap)
101
115
  decls.push(`--el-fill-color${suffix ? `-${suffix}` : ''}: ${get(token)};`)
102
116
  decls.push(`--el-fill-color-blank: ${isDark ? get('bg-2') : '#ffffff'};`)
@@ -152,12 +166,10 @@ export function defineTheme(options: DefineThemeOptions): void {
152
166
  // 主色同时派生整组色板(浅→白、深→黑,各 10 级),保证 --zl-{palette}-N 可用
153
167
  const seedLevel = Number(level)
154
168
  for (let i = 1; i <= 10; i++) {
155
- if (i === seedLevel)
156
- continue
169
+ if (i === seedLevel) continue
157
170
  const weight = (Math.abs(i - seedLevel) / 5) * 50
158
- resolved[`color-${palette}-${i}`] = i < seedLevel
159
- ? mix('#ffffff', hex, 100 - weight)
160
- : mix('#000000', hex, 100 - weight)
171
+ resolved[`color-${palette}-${i}`] =
172
+ i < seedLevel ? mix('#ffffff', hex, 100 - weight) : mix('#000000', hex, 100 - weight)
161
173
  }
162
174
  }
163
175
  }
@@ -189,21 +201,19 @@ export function setTheme(name: string, options: SetThemeOptions = {}): void {
189
201
  currentTheme.value = name
190
202
  if (name === 'light') {
191
203
  document.body.removeAttribute('data-theme')
192
- }
193
- else {
204
+ } else {
194
205
  document.body.setAttribute('data-theme', name)
195
206
  }
196
207
 
197
208
  if (persistenceEnabled.value || options.persist) {
198
209
  try {
199
210
  localStorage.setItem(THEME_STORAGE_KEY, name)
200
- }
201
- catch {
211
+ } catch {
202
212
  // storage 不可用时忽略
203
213
  }
204
214
  }
205
215
 
206
- changeListeners.forEach(fn => fn(name))
216
+ changeListeners.forEach((fn) => fn(name))
207
217
  }
208
218
 
209
219
  /** 当前主题名 */
@@ -8,8 +8,15 @@ export function parseColor(str: string): [number, number, number] | null {
8
8
  if (s.startsWith('#')) {
9
9
  let hex = s.slice(1)
10
10
  if (hex.length === 3)
11
- hex = hex.split('').map(c => c + c).join('')
12
- return [Number.parseInt(hex.slice(0, 2), 16), Number.parseInt(hex.slice(2, 4), 16), Number.parseInt(hex.slice(4, 6), 16)]
11
+ hex = hex
12
+ .split('')
13
+ .map((c) => c + c)
14
+ .join('')
15
+ return [
16
+ Number.parseInt(hex.slice(0, 2), 16),
17
+ Number.parseInt(hex.slice(2, 4), 16),
18
+ Number.parseInt(hex.slice(4, 6), 16),
19
+ ]
13
20
  }
14
21
  const m = s.match(/rgba?\(([^)]+)\)/)
15
22
  if (m) {
@@ -31,8 +38,7 @@ export function toHex([r, g, b]: [number, number, number]): string {
31
38
  export function mix(color1: string, color2: string, weight: number): string {
32
39
  const c1 = parseColor(color1)
33
40
  const c2 = parseColor(color2)
34
- if (!c1 || !c2)
35
- return color1
41
+ if (!c1 || !c2) return color1
36
42
  const w = weight / 100
37
43
  return toHex([c1[0] * (1 - w) + c2[0] * w, c1[1] * (1 - w) + c2[1] * w, c1[2] * (1 - w) + c2[2] * w])
38
44
  }