@techui/colors 1.0.1 → 1.0.3
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 +467 -83
- package/UPDATE.md +55 -0
- package/index.js +227 -180
- package/package.json +1 -4
- package/preview.html +641 -0
- package/README.cn.md +0 -283
package/UPDATE.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @techui/colors Update Log | 更新日志
|
|
2
|
+
|
|
3
|
+
[English](#english) | [中文](#中文)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## English
|
|
8
|
+
|
|
9
|
+
### v1.0.3 (2026-04-16)
|
|
10
|
+
|
|
11
|
+
- Added `$c.resolve` — resolves preset color names, `@`-prefixed names, and raw Hex/RGB values
|
|
12
|
+
- Added `$c.valid` — validates whether a color name or value is recognized
|
|
13
|
+
- Added `$c.expr` — expression syntax with pipe-based color transforms (e.g. `@bll5|.3`, `@bll5|lighten(2)`)
|
|
14
|
+
- Added `$c.genColors` — generates a semantic color scale from a base color or array
|
|
15
|
+
- Added `$c.genColorObj` — converts a color scale array into a semantic object (`weak/base/strong`) with optional opacity variants
|
|
16
|
+
|
|
17
|
+
### v1.0.2 (2025-11-09)
|
|
18
|
+
|
|
19
|
+
- Added preview.html, which allows filtering, querying, and matching operations on the current color table.
|
|
20
|
+
|
|
21
|
+
### v1.0.1 (2025-11-08)
|
|
22
|
+
|
|
23
|
+
- Internal file update, expand.less renamed to extended.less
|
|
24
|
+
- Minor iteration of index.js
|
|
25
|
+
|
|
26
|
+
### v1.0.0 (2025-10-15 Removed)
|
|
27
|
+
|
|
28
|
+
- First release
|
|
29
|
+
- Renamed from ayin-color to @techui/colors
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 中文
|
|
34
|
+
|
|
35
|
+
### v1.0.3 (2026-04-16)
|
|
36
|
+
|
|
37
|
+
- 新增 `$c.resolve` — 解析预定义颜色名、`@` 前缀写法及原始 Hex/RGB 值
|
|
38
|
+
- 新增 `$c.valid` — 校验颜色名或颜色值是否有效
|
|
39
|
+
- 新增 `$c.expr` — 表达式语法,支持管道式颜色变换(如 `@bll5|.3`、`@bll5|lighten(2)`)
|
|
40
|
+
- 新增 `$c.genColors` — 根据基础色或颜色数组生成语义色阶
|
|
41
|
+
- 新增 `$c.genColorObj` — 将色阶数组转换为 `weak/base/strong` 语义对象,支持附加透明度变体
|
|
42
|
+
|
|
43
|
+
### v1.0.2 (2025-11-9)
|
|
44
|
+
|
|
45
|
+
- 新增preview.html可以对当前颜色表进行筛选查询以及匹配操作
|
|
46
|
+
|
|
47
|
+
### v1.0.1 (2025-11-8)
|
|
48
|
+
|
|
49
|
+
- 内部文件更新,expand.less更名为extended.less
|
|
50
|
+
- index.js进行轻微迭代
|
|
51
|
+
|
|
52
|
+
### v1.0.0 (2025-10-15 已移除)
|
|
53
|
+
|
|
54
|
+
- 首次发布
|
|
55
|
+
- 从ayin-color更名为@techui/colors
|
package/index.js
CHANGED
|
@@ -1,181 +1,228 @@
|
|
|
1
|
-
import chroma from "@techui/libs/chroma";
|
|
2
|
-
import json from "./all.json";
|
|
3
|
-
/*
|
|
4
|
-
code by ayin86cn@gmail.com
|
|
5
|
-
chsname:["红","红橙","橙","橙黄","黄","黄草","草绿","草绿-绿","绿","绿-水绿","水绿","水绿-青","青","青蓝","蓝","蓝靛","靛","靛紫","紫","紫粉","粉","粉-洋红","洋红","洋红-红","灰"],
|
|
6
|
-
engname:["red","red-orange","orange","orange-yellow","yellow","yellow-chartreuse","chartreuse","chartreuse-green","green","green-aquamarine","aquamarine","aquamarine-cyan","cyan","cyan-blue","blue","blue-indigo","indigo","indigo-purple","purple","purple-pink","pink","pink-violetred","violetred","violetred-red","gray"],
|
|
7
|
-
colors:["re","ro","or","oy","ye","yc","ch","cg","gr","ga","aq","ac","cy","cb","bl","bi","in","ip","pu","pp","pi","pv","vi","vr","gy"],
|
|
8
|
-
*/
|
|
9
|
-
//chroma.hsl(hue, saturation, lightness)
|
|
10
|
-
//chroma.hsv(hue, saturation, value)
|
|
11
|
-
//chroma.lab(Lightness, a, b)
|
|
12
|
-
//chroma.lch(Lightness, chroma, hue)
|
|
13
|
-
//chroma.hcl(hue, chroma, lightness)
|
|
14
|
-
//chroma.cmyk(cy, magenta, ye, black)
|
|
15
|
-
//chroma.gl(re, gr, bl, [alpha])
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
){
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
1
|
+
import chroma from "@techui/libs/chroma";
|
|
2
|
+
import json from "./all.json";
|
|
3
|
+
/*
|
|
4
|
+
code by ayin86cn@gmail.com
|
|
5
|
+
chsname:["红","红橙","橙","橙黄","黄","黄草","草绿","草绿-绿","绿","绿-水绿","水绿","水绿-青","青","青蓝","蓝","蓝靛","靛","靛紫","紫","紫粉","粉","粉-洋红","洋红","洋红-红","灰"],
|
|
6
|
+
engname:["red","red-orange","orange","orange-yellow","yellow","yellow-chartreuse","chartreuse","chartreuse-green","green","green-aquamarine","aquamarine","aquamarine-cyan","cyan","cyan-blue","blue","blue-indigo","indigo","indigo-purple","purple","purple-pink","pink","pink-violetred","violetred","violetred-red","gray"],
|
|
7
|
+
colors:["re","ro","or","oy","ye","yc","ch","cg","gr","ga","aq","ac","cy","cb","bl","bi","in","ip","pu","pp","pi","pv","vi","vr","gy"],
|
|
8
|
+
*/
|
|
9
|
+
// chroma.hsl(hue, saturation, lightness)
|
|
10
|
+
// chroma.hsv(hue, saturation, value)
|
|
11
|
+
// chroma.lab(Lightness, a, b)
|
|
12
|
+
// chroma.lch(Lightness, chroma, hue)
|
|
13
|
+
// chroma.hcl(hue, chroma, lightness)
|
|
14
|
+
// chroma.cmyk(cy, magenta, ye, black)
|
|
15
|
+
// chroma.gl(re, gr, bl, [alpha])
|
|
16
|
+
const illegal = "Illegal color !";
|
|
17
|
+
const transformFns = ["fade", "lighten", "darken", "hslh", "hsls", "hsll"];
|
|
18
|
+
|
|
19
|
+
const stripColorPrefix = (color) => {
|
|
20
|
+
if (typeof color !== "string") return color;
|
|
21
|
+
const trimmed = color.trim();
|
|
22
|
+
return trimmed.startsWith("@") ? trimmed.slice(1) : trimmed;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const resolveColor = (color) => {
|
|
26
|
+
if (typeof color !== "string") return color;
|
|
27
|
+
const name = stripColorPrefix(color);
|
|
28
|
+
return json[name] || name;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const isValidColor = (color) => chroma.valid(resolveColor(color));
|
|
32
|
+
|
|
33
|
+
const warnInvalidColor = (...args) => {
|
|
34
|
+
console.warn(illegal, ...args);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const normalizeNumber = (value) => {
|
|
38
|
+
const num = Number(String(value).trim());
|
|
39
|
+
return Number.isFinite(num) ? num : null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const parseTransform = (rawTransform) => {
|
|
43
|
+
if (!rawTransform) return null;
|
|
44
|
+
|
|
45
|
+
const text = rawTransform.trim();
|
|
46
|
+
const defaultValue = normalizeNumber(text);
|
|
47
|
+
if (defaultValue !== null) {
|
|
48
|
+
return { name: "fade", value: defaultValue };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const matched = text.match(/^([a-zA-Z]\w*)\((.*)\)$/);
|
|
52
|
+
if (!matched) return null;
|
|
53
|
+
|
|
54
|
+
const name = matched[1];
|
|
55
|
+
const value = normalizeNumber(matched[2]);
|
|
56
|
+
if (!transformFns.includes(name) || value === null) return null;
|
|
57
|
+
|
|
58
|
+
return { name, value };
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const splitExpression = (expression) => {
|
|
62
|
+
const pipeIndex = expression.indexOf("|");
|
|
63
|
+
if (pipeIndex < 0) {
|
|
64
|
+
return [expression.trim(), ""];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return [expression.slice(0, pipeIndex).trim(), expression.slice(pipeIndex + 1).trim()];
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const coFuncs = {
|
|
71
|
+
resolve: resolveColor,
|
|
72
|
+
valid: isValidColor,
|
|
73
|
+
expr: (expression) => {
|
|
74
|
+
if (typeof expression !== "string") return expression;
|
|
75
|
+
|
|
76
|
+
const [rawColor, rawTransform] = splitExpression(expression);
|
|
77
|
+
const color = resolveColor(rawColor);
|
|
78
|
+
const transform = parseTransform(rawTransform);
|
|
79
|
+
|
|
80
|
+
if (!transform) return color;
|
|
81
|
+
return coFuncs[transform.name](color, transform.value);
|
|
82
|
+
},
|
|
83
|
+
fade: (color, num) => {
|
|
84
|
+
const resolved = resolveColor(color);
|
|
85
|
+
if (chroma.valid(resolved)) {
|
|
86
|
+
return chroma(resolved).alpha(num).hex();
|
|
87
|
+
}
|
|
88
|
+
warnInvalidColor(color, num);
|
|
89
|
+
},
|
|
90
|
+
// hue色相,saturation饱和度,lightness明暗
|
|
91
|
+
hslh: (color, num) => {
|
|
92
|
+
const resolved = resolveColor(color);
|
|
93
|
+
if (chroma.valid(resolved)) {
|
|
94
|
+
return chroma(resolved).set("hsl.h", num).hex();
|
|
95
|
+
}
|
|
96
|
+
warnInvalidColor(color, num);
|
|
97
|
+
},
|
|
98
|
+
hsls: (color, num) => {
|
|
99
|
+
const resolved = resolveColor(color);
|
|
100
|
+
if (chroma.valid(resolved)) {
|
|
101
|
+
return chroma(resolved).set("hsl.s", num).hex();
|
|
102
|
+
}
|
|
103
|
+
warnInvalidColor(color, num);
|
|
104
|
+
},
|
|
105
|
+
hsll: (color, num) => {
|
|
106
|
+
const resolved = resolveColor(color);
|
|
107
|
+
if (chroma.valid(resolved)) {
|
|
108
|
+
return chroma(resolved).set("hsl.l", num).hex();
|
|
109
|
+
}
|
|
110
|
+
warnInvalidColor(color, num);
|
|
111
|
+
},
|
|
112
|
+
darken: (color, num) => {
|
|
113
|
+
const resolved = resolveColor(color);
|
|
114
|
+
if (chroma.valid(resolved)) {
|
|
115
|
+
return chroma(resolved).darken(num).hex();
|
|
116
|
+
}
|
|
117
|
+
warnInvalidColor(color, num);
|
|
118
|
+
},
|
|
119
|
+
lighten: (color, num) => {
|
|
120
|
+
const resolved = resolveColor(color);
|
|
121
|
+
if (chroma.valid(resolved)) {
|
|
122
|
+
return chroma(resolved).brighten(num).hex();
|
|
123
|
+
}
|
|
124
|
+
warnInvalidColor(color, num);
|
|
125
|
+
},
|
|
126
|
+
scale: (arry, num = 7, mode = "lch") => {
|
|
127
|
+
const newArray = [];
|
|
128
|
+
arry.forEach((item, index) => {
|
|
129
|
+
const color = resolveColor(item);
|
|
130
|
+
if (chroma.valid(color)) {
|
|
131
|
+
newArray.push(color);
|
|
132
|
+
} else {
|
|
133
|
+
console.warn("The color set contains illegal color ", arry, index);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
if (newArray.length > 0) {
|
|
137
|
+
return chroma.scale(newArray).mode(mode).colors(num);
|
|
138
|
+
}
|
|
139
|
+
console.error("The color set initialization failed ", arry);
|
|
140
|
+
},
|
|
141
|
+
genColors(coIpt, count = 7, diff = 50, satReduce = true) {
|
|
142
|
+
if (!coIpt) throw new Error("The color parameter cannot be empty !");
|
|
143
|
+
count = Math.max(2, count);
|
|
144
|
+
|
|
145
|
+
if (typeof coIpt === "string") {
|
|
146
|
+
const resolvedColor = resolveColor(coIpt);
|
|
147
|
+
if (!chroma.valid(resolvedColor)) throw new Error(`Invalid Color: ${coIpt}`);
|
|
148
|
+
const color = chroma(resolvedColor);
|
|
149
|
+
const labL = color.get("lab.l");
|
|
150
|
+
const lchColor = chroma(color).lch();
|
|
151
|
+
const lchC = lchColor[1];
|
|
152
|
+
let colorL = color.set("lab.l", Math.min(100, labL + diff));
|
|
153
|
+
let colorD = color.set("lab.l", Math.max(0, labL - diff));
|
|
154
|
+
|
|
155
|
+
if (satReduce) {
|
|
156
|
+
colorL = colorL.set("lch.c", lchC * 0.2);
|
|
157
|
+
colorD = colorD.set("lch.c", lchC * 0.1);
|
|
158
|
+
}
|
|
159
|
+
return coFuncs.scale([colorL, color, colorD], count);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (Array.isArray(coIpt)) {
|
|
163
|
+
const validColors = coIpt.map(resolveColor).filter((color) => chroma.valid(color));
|
|
164
|
+
if (validColors.length === 0) throw new Error("No valid color value");
|
|
165
|
+
return coFuncs.scale(coIpt, count);
|
|
166
|
+
}
|
|
167
|
+
throw new Error("Color parameter must be a string or array");
|
|
168
|
+
},
|
|
169
|
+
genColorObj(
|
|
170
|
+
colors,
|
|
171
|
+
opacities,
|
|
172
|
+
names = ["weakest", "weaker", "weak", "base", "strong", "stronger", "strongest"]
|
|
173
|
+
) {
|
|
174
|
+
if (!colors || !Array.isArray(colors) || colors.length < names.length) {
|
|
175
|
+
throw new Error(`The colors array must contain at least${names.length}`);
|
|
176
|
+
}
|
|
177
|
+
const result = {};
|
|
178
|
+
names.forEach((name, index) => {
|
|
179
|
+
result[name] = colors[index];
|
|
180
|
+
});
|
|
181
|
+
if (opacities) {
|
|
182
|
+
names.forEach((name, colorIndex) => {
|
|
183
|
+
opacities.forEach((opacity) => {
|
|
184
|
+
const opacitySuffix = `op${Math.floor(opacity * 10)}`;
|
|
185
|
+
const propertyName = `${name}_${opacitySuffix}`;
|
|
186
|
+
result[propertyName] = coFuncs.fade(colors[colorIndex], opacity);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
return result;
|
|
191
|
+
},
|
|
192
|
+
sort(colors) {
|
|
193
|
+
return [...colors].sort((a, b) => chroma(resolveColor(b)).luminance() - chroma(resolveColor(a)).luminance());
|
|
194
|
+
},
|
|
195
|
+
viewColor(arr) {
|
|
196
|
+
console.info("viewColor", arr);
|
|
197
|
+
arr.forEach((co) => {
|
|
198
|
+
console.info("%c ■■■■■■■■", "color:" + co);
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
analysis(co) {
|
|
202
|
+
const color = chroma(resolveColor(co));
|
|
203
|
+
const luminance = color.luminance();
|
|
204
|
+
const isDark = luminance < 0.5;
|
|
205
|
+
const colorDepth = isDark ? (0.5 - luminance) * 2 : (luminance - 0.5) * 2;
|
|
206
|
+
let middleColor;
|
|
207
|
+
if (isDark) {
|
|
208
|
+
middleColor = color.luminance(0.5 - colorDepth / 4);
|
|
209
|
+
} else {
|
|
210
|
+
middleColor = color.luminance(0.5 + colorDepth / 4);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
originalColor: color.hex(),
|
|
215
|
+
isDark,
|
|
216
|
+
luminance,
|
|
217
|
+
colorDepth,
|
|
218
|
+
middleColor: middleColor.hex(),
|
|
219
|
+
};
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
const $c = Object.assign(coFuncs, json);
|
|
223
|
+
|
|
224
|
+
export default (Vue) => {
|
|
225
|
+
window.$c = $c;
|
|
226
|
+
window.$chroma = chroma;
|
|
227
|
+
};
|
|
180
228
|
export { $c, chroma as $chroma };
|
|
181
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techui/colors",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Color tables for js and less versions developed by ayin.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "aYin <ayin86cn@gmail.com> <wechat:jay1986cn>",
|
|
@@ -25,9 +25,6 @@
|
|
|
25
25
|
"chroma",
|
|
26
26
|
"chroma.js"
|
|
27
27
|
],
|
|
28
|
-
"dependencies": {
|
|
29
|
-
"@techui/lessmixins": "^1.0.0"
|
|
30
|
-
},
|
|
31
28
|
"devDependencies":{
|
|
32
29
|
"less": "*",
|
|
33
30
|
"less-loader": "*"
|