@aviala-design/color 0.1.0 → 0.2.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.zh-CN.md CHANGED
@@ -1,90 +1,192 @@
1
1
  # ArcoDesign Color
2
2
 
3
- ArcoDesign Color Utils.
3
+ ArcoDesign Color Utils - 一个强大的颜色处理工具库。
4
4
 
5
- 根据给定颜色通过算法生成指定包含十个颜色的梯度色板,也可生成暗色模式下包含十个颜色的色板。
5
+ ## 功能概述
6
6
 
7
- ## Usage
7
+ 本库提供两大核心功能:
8
+
9
+ 1. **色盘生成**:根据给定颜色通过算法生成包含十个颜色的梯度色板,支持亮色模式和暗色模式。
10
+ 2. **图片取色**:从图片中提取主色调,可用于生成与图片匹配的调色板或主题色。
11
+
12
+ ## 安装
8
13
 
9
14
  ```bash
10
- npm i @arco-design/color
11
- ```
15
+ npm install @aviala-design/color```
16
+
17
+ ## 基本使用
12
18
 
13
19
  ```js
14
- import { generate, presetColor } from '@arco-design/color';
15
-
16
- console.log(generate('#123456'));
17
-
18
- console.log(presetColor);
19
- // {
20
- // red: {...},
21
- // orangered: {...},
22
- // orange: {...},
23
- // gold: {...},
24
- // yellow: {...},
25
- // lime: {...},
26
- // green: {...},
27
- // cyan: {...},
28
- // blue: {...},
29
- // arcoblue: {...},
30
- // purple: {...},
31
- // pinkpurple: {...},
32
- // magenta: {...},
33
- // gray: {...}
34
- // }
20
+ import { generate, getPresetColors, getRgbStr, extractColorFromImage } from '@arco-design/color';
21
+
22
+ // 生成色盘
23
+ const colorPalette = generate('#3491FA', { list: true });
24
+ console.log(colorPalette); // 返回包含10个颜色的数组
25
+
26
+ // 使用预设颜色
27
+ const { red, blue, arcoblue } = getPresetColors();
28
+ console.log(red.light); // 亮色模式下的红色色盘
29
+ console.log(blue.dark); // 暗色模式下的蓝色色盘
30
+ console.log(arcoblue.primary); // arco蓝的主色
31
+
32
+ // 获取RGB字符串
33
+ const rgbStr = getRgbStr('#F53F3F');
34
+ console.log(rgbStr); // 245,63,63
35
35
  ```
36
36
 
37
- ## API
37
+ ## API 详解
38
+
39
+ ### 色盘生成功能
40
+
41
+ #### generate(color: string, options?: Object)
38
42
 
39
- ### generate(color: string, options: Object);
43
+ 基于基础颜色生成色盘。
40
44
 
41
- #### options.index {number | 1-10}
45
+ **参数:**
46
+ - `color`: string - 基础颜色,支持十六进制格式(如 '#FF5733')
47
+ - `options`: Object - 可选配置项
48
+ - `index`: number - 指定返回色盘中的第几个颜色,范围1-10,默认为6(基础颜色)
49
+ - `dark`: boolean - 是否生成暗色模式的色盘,默认为false
50
+ - `list`: boolean - 是否返回完整色盘列表,默认为false
51
+ - `format`: string - 返回颜色的格式,可选值:'hex'(默认)、'rgb'、'hsl'
42
52
 
43
- 生成 10 个梯度色中的第几个颜色。
53
+ **返回值:**
54
+ - 当 `list` 为 true 时,返回 `string[]` - 包含10个颜色的数组
55
+ - 当 `list` 为 false 时,返回 `string` - 指定索引位置的单个颜色
44
56
 
45
- #### options.list {boolean}
57
+ **示例:**
46
58
 
47
- 生成包含十个颜色的梯度颜色数组。
59
+ ```js
60
+ // 生成单个颜色
61
+ const baseColor = '#3491FA';
62
+ const color = generate(baseColor); // 返回基础颜色本身
48
63
 
49
- #### options.dark
64
+ // 生成亮色模式下的第3个颜色
65
+ const lightColor = generate(baseColor, { index: 3 });
50
66
 
51
- 生成暗色色板的颜色。
67
+ // 生成暗色模式下的色盘
68
+ const darkPalette = generate(baseColor, { dark: true, list: true });
52
69
 
53
- #### options.format {'hex' | 'rgb' | 'hsl'}
70
+ // 以RGB格式返回颜色
71
+ const rgbColor = generate(baseColor, { format: 'rgb' });
72
+ ```
54
73
 
55
- 生成颜色的格式。
74
+ #### getPresetColors()
75
+
76
+ 获取预设的14组颜色,包括一组中性灰。
77
+
78
+ **返回值:**
79
+ 包含以下颜色的对象:
80
+ * `red` - 红色
81
+ * `orangered` - 橙红色
82
+ * `orange` - 橙色
83
+ * `gold` - 金色
84
+ * `yellow` - 黄色
85
+ * `lime` - 青柠色
86
+ * `green` - 绿色
87
+ * `cyan` - 青色
88
+ * `blue` - 蓝色
89
+ * `arcoblue` - arco蓝
90
+ * `purple` - 紫色
91
+ * `pinkpurple` - 粉紫色
92
+ * `magenta` - 品红色
93
+ * `gray` - 灰色
94
+
95
+ 每种颜色包含以下属性:
96
+ - `light`: 亮色模式下的10个颜色数组
97
+ - `dark`: 暗色模式下的10个颜色数组
98
+ - `primary`: 主色(亮色模式下的第6个颜色)
99
+
100
+ **示例:**
56
101
 
57
- ### getPresetColors {Function}
102
+ ```js
103
+ const { red, blue, arcoblue } = getPresetColors();
104
+
105
+ console.log(red.light); // 亮色模式下的红色色盘
106
+ console.log(blue.dark); // 暗色模式下的蓝色色盘
107
+ console.log(arcoblue.primary); // arco蓝的主色
108
+ ```
58
109
 
59
- 包含了预设的 14 组颜色,包括一组中性灰。
110
+ #### getRgbStr(color: string)
60
111
 
61
- * `red`
62
- * `orangered`
63
- * `orange`
64
- * `gold`
65
- * `yellow`
66
- * `lime`
67
- * `green`
68
- * `cyan`
69
- * `blue`
70
- * `arcoblue`
71
- * `purple`
72
- * `pinkpurple`
73
- * `magenta`
74
- * `gray`
112
+ 获取指定颜色的RGB三通道字符串。
113
+
114
+ **参数:**
115
+ - `color`: string - 颜色值,支持十六进制格式
116
+
117
+ **返回值:**
118
+ - `string` - RGB三通道字符串,格式为 "r,g,b"
119
+
120
+ **示例:**
75
121
 
76
122
  ```js
77
- const { red } = getPresetColors();
123
+ const rgbStr = getRgbStr('#F53F3F');
124
+ console.log(rgbStr); // 245,63,63
125
+ ```
78
126
 
79
- console.log(red.light);
80
- console.log(red.dark);
81
- console.log(red.primary);
127
+ ### 图片取色功能
128
+
129
+ #### extractColorFromImage(image: HTMLImageElement)
130
+
131
+ 从已加载的图片元素中提取主色调。
132
+
133
+ **参数:**
134
+ - `image`: HTMLImageElement - 已加载的图片元素
135
+
136
+ **返回值:**
137
+ - `Promise<string>` - 提取的主色调(十六进制格式)
138
+
139
+ **示例:**
140
+
141
+ ```js
142
+ const image = document.getElementById('myImage');
143
+ extractColorFromImage(image).then(color => {
144
+ console.log('提取的主色调:', color);
145
+ // 可以用提取的颜色生成色盘
146
+ const palette = generate(color, { list: true });
147
+ });
82
148
  ```
83
149
 
84
- ### getRgbStr(color: string)
150
+ #### extractColorFromFile(file: File)
151
+
152
+ 从文件对象中读取图片并提取主色调。
153
+
154
+ **参数:**
155
+ - `file`: File - 图片文件对象
85
156
 
86
- 获得指定颜色的三通道 r, g, b 字符串。
157
+ **返回值:**
158
+ - `Promise<string>` - 提取的主色调(十六进制格式)
159
+
160
+ **示例:**
87
161
 
88
162
  ```js
89
- getRgbStr('#F53F3F') // 245,63,63
163
+ // 在文件输入事件中使用
164
+ document.getElementById('fileInput').addEventListener('change', (event) => {
165
+ const file = event.target.files[0];
166
+ if (file) {
167
+ extractColorFromFile(file).then(color => {
168
+ console.log('提取的主色调:', color);
169
+ });
170
+ }
171
+ });
90
172
  ```
173
+
174
+ ## 实现原理
175
+
176
+ ### 色盘生成算法
177
+
178
+ 色盘生成功能基于HSV颜色空间,通过动态调整色相(H)、饱和度(S)和明度(V)生成和谐的色盘:
179
+
180
+ 1. **动态梯度算法**:根据基础颜色的HSV值,动态计算色盘中其他颜色的参数
181
+ 2. **色相调整**:根据色相区域动态调整色相变化方向和步长
182
+ 3. **饱和度和明度调整**:使用非线性函数确保过渡平滑
183
+ 4. **暗色模式特殊处理**:基于亮色模式的算法,但进行了特殊调整以适应深色背景
184
+
185
+ ### 图片取色算法
186
+
187
+ 图片取色功能通过以下步骤提取主色调:
188
+
189
+ 1. **图片处理**:将图片缩小并绘制到Canvas上
190
+ 2. **像素量化**:将RGB颜色空间从256^3种可能的颜色减少到16^3种
191
+ 3. **颜色频率统计**:统计每种颜色的出现频率
192
+ 4. **主色调提取**:过滤掉灰色和接近白色/黑色的颜色,选择出现频率最高的颜色
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { default as generate } from './generate.js';
2
2
  import { getRgbStr } from './utils.js';
3
3
  import { extractColorFromImage, extractColorFromFile } from './image-color.js';
4
+ import { generateLinear, generateGrayLinear, generateMonochromeLinear, generateLinearHSL } from './linear.js';
5
+ import { rgbToHct, hctToRgb, blendInHct, harmonizeColor, generateThemeVariants, blendSemanticColors, blendUIColors, generateThemePalette, generateControlColors, generateSemanticColors, generateThemeColors, generateInterfaceColorSystem } from './theme-blend.js';
4
6
  export namespace colorList {
5
7
  let red: string;
6
8
  let orangered: string;
@@ -23,4 +25,4 @@ export function getPresetColors(): {
23
25
  primary: string;
24
26
  };
25
27
  };
26
- export { generate, getRgbStr, extractColorFromImage, extractColorFromFile };
28
+ export { generate, getRgbStr, extractColorFromImage, extractColorFromFile, generateLinear, generateGrayLinear, generateMonochromeLinear, generateLinearHSL, rgbToHct, hctToRgb, blendInHct, harmonizeColor, generateThemeVariants, blendSemanticColors, blendUIColors, generateThemePalette, generateControlColors, generateSemanticColors, generateThemeColors, generateInterfaceColorSystem };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- (function(h,f){typeof exports=="object"&&typeof module<"u"?f(exports,require("color")):typeof define=="function"&&define.amd?define(["exports","color"],f):(h=typeof globalThis<"u"?globalThis:h||self,f(h.AvialaColor={},h.Color))})(this,function(h,f){"use strict";function P(t){return f(t).rgb().round().color.join(",")}const E=["hex","rgb","hsl"];function A(t){return!t||E.indexOf(t)<0?"hex":t}function D(t,e){const o=A(e);return o==="hex"?t[o]():t[o]().round().string()}function x(t,e,o){const a=f(t),r=a.hue(),n=a.saturationv(),s=a.value(),c=(l=>l>=60&&l<=240?2.5:l>=0&&l<60||l>300&&l<=360?1.5:2)(r),w=100,p=9,m=100,u=30;function b(l,d){let g;return r>=60&&r<=240?g=l?r-c*d:r+c*d:g=l?r+c*d:r-c*d,g<0?g+=360:g>=360&&(g-=360),Math.round(g)}function z(l,d){let g;if(l)g=n<=p?n:n-(n-p)/5.5*Math.pow(d,1.05);else{const O=Math.min(w,n+30);g=n+(O-n)/4.2*Math.pow(d,.95)}return Math.max(0,Math.min(100,g))}function H(l,d){return l?Math.min(m,s+(m-s)/5.2*Math.pow(d,.9)):s<=u?s:Math.max(u,s-(s-u)/4.2*Math.pow(d,1.05))}const M=e<6,S=M?6-e:e-6,L=e===6?a:f({h:b(M,S),s:z(M,S),v:H(M,S)});return D(L,o)}function v(t,e,o){const a=f(x(t,10-e+1)),r=f(t),n=r.hue(),s=r.saturationv(),c=f({h:r.hue(),s:m(6),v:r.value()}).saturationv(),w=Math.ceil((c-9)/4),p=Math.ceil((100-c)/5);function m(b){if(b<6)return c+(6-b)*p;if(b===6){if(n>=0&&n<50)return s-15;if(n>=50&&n<191)return s-20;if(n>=191&&n<=360)return s-15}return c-w*(b-6)}const u=f({h:a.hue(),s:m(e),v:a.value()});return D(u,o)}function y(t,e={}){const{dark:o,list:a,index:r=6,format:n="hex"}=e;if(a){const s=[],i=o?v:x;for(let c=1;c<=10;c++)s.push(i(t,c,n));return s}return o?v(t,r,n):x(t,r,n)}async function C(t){try{const e=await B(t),o=I(e);return q(o)}catch(e){throw console.error("提取图片颜色失败:",e),e}}async function B(t){return new Promise((e,o)=>{try{const a=document.createElement("canvas"),r=a.getContext("2d"),n=Math.min(t.width,100),s=Math.min(t.height,100),i=Math.min(n/t.width,s/t.height);a.width=t.width*i,a.height=t.height*i,r.drawImage(t,0,0,a.width,a.height);const c=r.getImageData(0,0,a.width,a.height);e(c)}catch(a){o(a)}})}function I(t){const e=t.data,o=new Map;for(let r=0;r<e.length;r+=4){const n=e[r],s=e[r+1],i=e[r+2];if(e[r+3]<128)continue;const w=Math.round(n/16)*16,p=Math.round(s/16)*16,m=Math.round(i/16)*16,u=`${w},${p},${m}`;o.has(u)?o.set(u,o.get(u)+1):o.set(u,1)}const a=[];return o.forEach((r,n)=>{const[s,i,c]=n.split(",").map(Number);a.push({r:s,g:i,b:c,count:r})}),a}function q(t){t.sort((r,n)=>n.count-r.count);const e=t.filter(r=>{const{r:n,g:s,b:i}=r,c=Math.max(n,s,i),w=Math.min(n,s,i),p=c-w,m=c===0?0:p/c,u=c/255;return m>.15&&u>.2&&u<.8}),o=e.length>0?e[0]:t[0];return f({r:o.r,g:o.g,b:o.b}).hex()}function N(t){return new Promise((e,o)=>{if(!t.type.startsWith("image/")){o(new Error("请选择图片文件"));return}const a=new FileReader;a.onload=async r=>{try{const n=new Image;n.onload=async()=>{try{const s=await C(n);e(s)}catch(s){o(s)}},n.onerror=()=>o(new Error("图片加载失败")),n.src=r.target.result}catch(n){o(n)}},a.onerror=()=>o(new Error("文件读取失败")),a.readAsDataURL(t)})}const F={red:"#F53F3F",orangered:"#F77234",orange:"#FF7D00",gold:"#F7BA1E",yellow:"#FADC19",lime:"#9FDB1D",green:"#00B42A",cyan:"#14C9C9",blue:"#3491FA",arcoblue:"#165DFF",purple:"#722ED1",pinkpurple:"#D91AD9",magenta:"#F5319D"};function R(){const t={};return Object.keys(F).forEach(e=>{t[e]={},t[e].light=y(F[e],{list:!0}),t[e].dark=y(F[e],{list:!0,dark:!0}),t[e].primary=F[e]}),t.gray={},t.gray.light=["#f7f8fa","#f2f3f5","#e5e6eb","#c9cdd4","#a9aeb8","#86909c","#6b7785","#4e5969","#272e3b","#1d2129"],t.gray.dark=["#17171a","#2e2e30","#484849","#5f5f60","#78787a","#929293","#ababac","#c5c5c5","#dfdfdf","#f6f6f6"],t.gray.primary=t.gray.light[6],t}h.colorList=F,h.extractColorFromFile=N,h.extractColorFromImage=C,h.generate=y,h.getPresetColors=R,h.getRgbStr=P,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})});
1
+ (function(f,g){typeof exports=="object"&&typeof module<"u"?g(exports,require("color")):typeof define=="function"&&define.amd?define(["exports","color"],g):(f=typeof globalThis<"u"?globalThis:f||self,g(f.AvialaColor={},f.Color))})(this,function(f,g){"use strict";function O(t){return g(t).rgb().round().color.join(",")}const q=["hex","rgb","hsl"];function N(t){return!t||q.indexOf(t)<0?"hex":t}function E(t,r){const s=N(r);return s==="hex"?t[s]().toLowerCase():t[s]().round().string()}function R(t,r,s){const n=g(t),e=n.hue(),o=n.saturationv(),a=n.value(),c=(M=>M>=60&&M<=240?2.5:M>=0&&M<60||M>300&&M<=360?1.5:2)(e),l=100,d=9,h=100,u=30;function m(M,w){let S;return e>=60&&e<=240?S=M?e-c*w:e+c*w:S=M?e+c*w:e-c*w,S<0?S+=360:S>=360&&(S-=360),Math.round(S)}function b(M,w){let S;if(M)S=o<=d?o:o-(o-d)/5.5*Math.pow(w,1.05);else{const tt=Math.min(l,o+30);S=o+(tt-o)/4.2*Math.pow(w,.95)}return Math.max(0,Math.min(100,S))}function p(M,w){return M?Math.min(h,a+(h-a)/5.2*Math.pow(w,.9)):a<=u?a:Math.max(u,a-(a-u)/4.2*Math.pow(w,1.05))}const y=r<6,x=y?6-r:r-6,D=r===6?n:g({h:m(y,x),s:b(y,x),v:p(y,x)});return E(D,s)}function T(t,r,s){const n=g(R(t,10-r+1)),e=g(t),o=e.hue(),a=e.saturationv(),c=g({h:e.hue(),s:h(6),v:e.value()}).saturationv(),l=Math.ceil((c-9)/4),d=Math.ceil((100-c)/5);function h(m){if(m<6)return c+(6-m)*d;if(m===6){if(o>=0&&o<50)return a-15;if(o>=50&&o<191)return a-20;if(o>=191&&o<=360)return a-15}return c-l*(m-6)}const u=g({h:n.hue(),s:h(r),v:n.value()});return E(u,s)}function v(t,r={}){const{dark:s,list:n,index:e=6,format:o="hex"}=r;if(n){const a=[],i=s?T:R;for(let c=1;c<=10;c++)a.push(i(t,c,o));return a}return s?T(t,e,o):R(t,e,o)}async function P(t){try{const r=await j(t),s=U(r);return K(s)}catch(r){throw console.error("提取图片颜色失败:",r),r}}async function j(t){return new Promise((r,s)=>{try{const n=document.createElement("canvas"),e=n.getContext("2d"),o=Math.min(t.width,100),a=Math.min(t.height,100),i=Math.min(o/t.width,a/t.height);n.width=t.width*i,n.height=t.height*i,e.drawImage(t,0,0,n.width,n.height);const c=e.getImageData(0,0,n.width,n.height);r(c)}catch(n){s(n)}})}function U(t){const r=t.data,s=new Map;for(let e=0;e<r.length;e+=4){const o=r[e],a=r[e+1],i=r[e+2];if(r[e+3]<128)continue;const l=Math.round(o/16)*16,d=Math.round(a/16)*16,h=Math.round(i/16)*16,u=`${l},${d},${h}`;s.has(u)?s.set(u,s.get(u)+1):s.set(u,1)}const n=[];return s.forEach((e,o)=>{const[a,i,c]=o.split(",").map(Number);n.push({r:a,g:i,b:c,count:e})}),n}function K(t){t.sort((e,o)=>o.count-e.count);const r=t.filter(e=>{const{r:o,g:a,b:i}=e,c=Math.max(o,a,i),l=Math.min(o,a,i),d=c-l,h=c===0?0:d/c,u=c/255;return h>.15&&u>.2&&u<.8}),s=r.length>0?r[0]:t[0];return g({r:s.r,g:s.g,b:s.b}).hex()}function W(t){return new Promise((r,s)=>{if(!t.type.startsWith("image/")){s(new Error("请选择图片文件"));return}const n=new FileReader;n.onload=async e=>{try{const o=new Image;o.onload=async()=>{try{const a=await P(o);r(a)}catch(a){s(a)}},o.onerror=()=>s(new Error("图片加载失败")),o.src=e.target.result}catch(o){s(o)}},n.onerror=()=>s(new Error("文件读取失败")),n.readAsDataURL(t)})}function I(t,r,s={}){const{steps:n=10,format:e="hex",includeEnds:o=!0}=s;if(n<2)throw new Error("步数必须至少为2");const a=g(t),i=g(r),c=[],l=o?n:n+2,d=1/(l-1);for(let h=0;h<l;h++){const u=h*d,m=Math.round(a.red()+(i.red()-a.red())*u),b=Math.round(a.green()+(i.green()-a.green())*u),p=Math.round(a.blue()+(i.blue()-a.blue())*u),y=g({r:m,g:b,b:p});!o&&(h===0||h===l-1)||c.push(E(y,e))}return c}function J(t={}){const{startGray:r="#ffffff",endGray:s="#000000",steps:n=10,format:e="hex"}=t;return I(r,s,{steps:n,format:e,includeEnds:!0})}function Q(t,r={}){const{steps:s=10,format:n="hex",lightnessRange:e=80}=r,a=g(t).hsl(),i=a.lightness(),c=Math.min(95,i+e/2),l=Math.max(5,i-e/2),d=g({h:a.hue(),s:a.saturationl(),l:c}),h=g({h:a.hue(),s:a.saturationl(),l});return I(d.hex(),h.hex(),{steps:s,format:n,includeEnds:!0})}function X(t,r,s={}){const{steps:n=10,format:e="hex",includeEnds:o=!0}=s;if(n<2)throw new Error("步数必须至少为2");const a=g(t).hsl(),i=g(r).hsl(),c=[],l=o?n:n+2,d=1/(l-1);let h=a.hue()||0,u=i.hue()||0;const m=u-h;Math.abs(m)>180&&(m>0?h+=360:u+=360);for(let b=0;b<l;b++){const p=b*d;let y=h+(u-h)*p;const x=a.saturationl()+(i.saturationl()-a.saturationl())*p,D=a.lightness()+(i.lightness()-a.lightness())*p;y=y%360,y<0&&(y+=360);const M=g({h:y,s:x,l:D});!o&&(b===0||b===l-1)||c.push(E(M,e))}return c}function C(t){const r=t.replace("#",""),s=parseInt(r.substr(0,2),16)/255,n=parseInt(r.substr(2,2),16)/255,e=parseInt(r.substr(4,2),16)/255,o=Math.max(s,n,e),a=Math.min(s,n,e),i=o-a;let c=0;i!==0&&(o===s?c=(n-e)/i%6:o===n?c=(e-s)/i+2:c=(s-n)/i+4),c=Math.round(c*60),c<0&&(c+=360);const l=Math.round((.299*s+.587*n+.114*e)*100),d=(o+a)/2,h=i===0?0:i/(1-Math.abs(2*d-1)),u=Math.round(h*Math.min(l,100-l));return{h:c,c:u,t:l}}function H(t){const{h:r,c:s,t:n}=t,e=(r%360+360)%360,o=Math.max(0,Math.min(150,s)),a=Math.max(0,Math.min(100,n)),i=a/100,c=a===0||a===100?0:o/Math.min(a,100-a),l=(1-Math.abs(2*i-1))*Math.min(1,c),d=l*(1-Math.abs(e/60%2-1)),h=i-l/2;let u,m,b;e>=0&&e<60?[u,m,b]=[l,d,0]:e>=60&&e<120?[u,m,b]=[d,l,0]:e>=120&&e<180?[u,m,b]=[0,l,d]:e>=180&&e<240?[u,m,b]=[0,d,l]:e>=240&&e<300?[u,m,b]=[d,0,l]:[u,m,b]=[l,0,d];const p=y=>{const x=Math.max(0,Math.min(1,y+h)),D=Math.round(x*255).toString(16);return D.length===1?"0"+D:D};return`#${p(u)}${p(m)}${p(b)}`}function L(t,r,s=.5){const n=C(t),e=C(r);let o=n.h,a=e.h,i=a-o;Math.abs(i)>180&&(i>0?o+=360:a+=360);const c=(o+(a-o)*s)%360,l=n.c+(e.c-n.c)*s,d=n.t+(e.t-n.t)*s;return H({h:c<0?c+360:c,c:Math.max(0,Math.round(l)),t:Math.max(0,Math.min(100,Math.round(d)))})}function A(t,r,s=.15){const n=C(t),e=C(r);let o=e.h,a=n.h,i=a-o;Math.abs(i)>180&&(i>0?o+=360:a+=360,i=a-o);const c=(o+i*s)%360;return H({h:c<0?c+360:c,c:e.c,t:e.t})}function k(t,r=[10,20,30,40,50,60,70,80,90]){const s=C(t);let n;return Array.isArray(r)?n=r:r&&r.tones&&Array.isArray(r.tones)?n=r.tones:n=[10,20,30,40,50,60,70,80,90],n.map(e=>H({h:s.h,c:s.c,t:e}))}function z(t,r,s=.15){const n={};for(const[e,o]of Object.entries(r))n[e]=A(t,o,s);return n}function $(t,r,s=.2){const n={};for(const[e,o]of Object.entries(r))n[e]=L(t,o,s);return n}function B(t,r={}){const{baseGray:s="#666666"}=r,{blendRatio:n=.08,isDark:e=!1}=r,o=C(s),a={};return(e?[95,90,85,80,70,60,50,40,30,20,15,10]:[10,15,20,30,40,50,60,70,80,85,90,95]).forEach((c,l)=>{const d={h:o.h,c:o.c,t:c},h=L(H(d),t,n);a[`gray-${l+1}`]=h}),a}function V(t,r={}){const{semanticColors:s={success:"#52c41a",warning:"#faad14",error:"#ff4d4f",info:"#1890ff"},blendRatio:n=.12,isDark:e=!1}=r,o={};return Object.entries(s).forEach(([a,i])=>{const c={},l=C(i);(e?[90,80,70,60,50,40,30,25,20,15]:[15,25,35,45,55,65,75,85,90,95]).forEach((h,u)=>{const m={h:l.h,c:l.c,t:h},b=L(H(m),t,n);c[`${a}-${u+1}`]=b}),Object.assign(o,c)}),o}function G(t,r={}){const{isDark:s=!1}=r,n=C(t),e={};return(s?[90,80,70,60,50,40,30,25,20,15]:[15,25,35,45,55,65,75,85,90,95]).forEach((a,i)=>{const c={h:n.h,c:n.c,t:a};e[`theme-${i+1}`]=H(c)}),e}function Y(t,r={}){const{baseGray:s="#666666",isDark:n=!1,semanticColors:e,controlBlendRatio:o=.08,semanticBlendRatio:a=.12}=r;return{controls:B(t,{baseGray:s,blendRatio:o,isDark:n}),semantic:V(t,{semanticColors:e,blendRatio:a,isDark:n}),theme:G(t,{isDark:n})}}function Z(t,r={}){const{semanticColors:s={success:"#4caf50",warning:"#ff9800",error:"#f44336",info:"#2196f3"},uiColors:n={primary:t,"primary-light":"#ffffff","primary-lighter":"#f8f9ff","primary-dark":"#000000","primary-darker":"#0a0a0a",accent:"#722ed1","neutral-1":"#f7f8fa","neutral-2":"#f2f3f5","neutral-3":"#e5e6eb","neutral-4":"#c9cdd4","neutral-5":"#a9aeb8","neutral-6":"#86909c",background:"#ffffff",surface:"#f8f9fa",border:"#e5e6eb",disabled:"#c9cdd4"},harmonizeRatio:e=.15,blendRatio:o=.12,generateVariants:a=!0}=r,i={theme:t,semantic:z(t,s,e),ui:$(t,n,o)};return a&&(i.variants=k(t)),i}const F={red:"#F53F3F",orangered:"#F77234",orange:"#FF7D00",gold:"#F7BA1E",yellow:"#FADC19",lime:"#9FDB1D",green:"#00B42A",cyan:"#14C9C9",blue:"#3491FA",arcoblue:"#165DFF",purple:"#722ED1",pinkpurple:"#D91AD9",magenta:"#F5319D"};function _(){const t={};return Object.keys(F).forEach(r=>{t[r]={},t[r].light=v(F[r],{list:!0}),t[r].dark=v(F[r],{list:!0,dark:!0}),t[r].primary=F[r]}),t.gray={},t.gray.light=["#f7f8fa","#f2f3f5","#e5e6eb","#c9cdd4","#a9aeb8","#86909c","#6b7785","#4e5969","#272e3b","#1d2129"],t.gray.dark=["#17171a","#2e2e30","#484849","#5f5f60","#78787a","#929293","#ababac","#c5c5c5","#dfdfdf","#f6f6f6"],t.gray.primary=t.gray.light[6],t}f.blendInHct=L,f.blendSemanticColors=z,f.blendUIColors=$,f.colorList=F,f.extractColorFromFile=W,f.extractColorFromImage=P,f.generate=v,f.generateControlColors=B,f.generateGrayLinear=J,f.generateInterfaceColorSystem=Y,f.generateLinear=I,f.generateLinearHSL=X,f.generateMonochromeLinear=Q,f.generateSemanticColors=V,f.generateThemeColors=G,f.generateThemePalette=Z,f.generateThemeVariants=k,f.getPresetColors=_,f.getRgbStr=O,f.harmonizeColor=A,f.hctToRgb=H,f.rgbToHct=C,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});
package/dist/index.mjs CHANGED
@@ -1,144 +1,350 @@
1
1
  import m from "color";
2
- function R(t) {
2
+ function W(t) {
3
3
  return m(t).rgb().round().color.join(",");
4
4
  }
5
- const B = ["hex", "rgb", "hsl"];
6
- function A(t) {
7
- return !t || B.indexOf(t) < 0 ? "hex" : t;
5
+ const A = ["hex", "rgb", "hsl"];
6
+ function P(t) {
7
+ return !t || A.indexOf(t) < 0 ? "hex" : t;
8
8
  }
9
- function S(t, n) {
10
- const o = A(n);
11
- return o === "hex" ? t[o]() : t[o]().round().string();
9
+ function F(t, r) {
10
+ const a = P(r);
11
+ return a === "hex" ? t[a]().toLowerCase() : t[a]().round().string();
12
12
  }
13
- function F(t, n, o) {
14
- const a = m(t), e = a.hue(), r = a.saturationv(), s = a.value(), c = ((l) => l >= 60 && l <= 240 ? 2.5 : l >= 0 && l < 60 || l > 300 && l <= 360 ? 1.5 : 2)(e), p = 100, d = 9, f = 100, u = 30;
15
- function w(l, g) {
16
- let h;
17
- return e >= 60 && e <= 240 ? h = l ? e - c * g : e + c * g : h = l ? e + c * g : e - c * g, h < 0 ? h += 360 : h >= 360 && (h -= 360), Math.round(h);
13
+ function E(t, r, a) {
14
+ const e = m(t), n = e.hue(), o = e.saturationv(), s = e.value(), c = ((b) => b >= 60 && b <= 240 ? 2.5 : b >= 0 && b < 60 || b > 300 && b <= 360 ? 1.5 : 2)(n), l = 100, f = 9, h = 100, u = 30;
15
+ function d(b, w) {
16
+ let x;
17
+ return n >= 60 && n <= 240 ? x = b ? n - c * w : n + c * w : x = b ? n + c * w : n - c * w, x < 0 ? x += 360 : x >= 360 && (x -= 360), Math.round(x);
18
18
  }
19
- function y(l, g) {
20
- let h;
21
- if (l)
22
- h = r <= d ? r : r - (r - d) / 5.5 * Math.pow(g, 1.05);
19
+ function g(b, w) {
20
+ let x;
21
+ if (b)
22
+ x = o <= f ? o : o - (o - f) / 5.5 * Math.pow(w, 1.05);
23
23
  else {
24
- const E = Math.min(p, r + 30);
25
- h = r + (E - r) / 4.2 * Math.pow(g, 0.95);
24
+ const k = Math.min(l, o + 30);
25
+ x = o + (k - o) / 4.2 * Math.pow(w, 0.95);
26
26
  }
27
- return Math.max(0, Math.min(100, h));
27
+ return Math.max(0, Math.min(100, x));
28
28
  }
29
- function v(l, g) {
30
- return l ? Math.min(f, s + (f - s) / 5.2 * Math.pow(g, 0.9)) : s <= u ? s : Math.max(u, s - (s - u) / 4.2 * Math.pow(g, 1.05));
29
+ function M(b, w) {
30
+ return b ? Math.min(h, s + (h - s) / 5.2 * Math.pow(w, 0.9)) : s <= u ? s : Math.max(u, s - (s - u) / 4.2 * Math.pow(w, 1.05));
31
31
  }
32
- const x = n < 6, b = x ? 6 - n : n - 6, P = n === 6 ? a : m({
33
- h: w(x, b),
34
- s: y(x, b),
35
- v: v(x, b)
32
+ const p = r < 6, C = p ? 6 - r : r - 6, S = r === 6 ? e : m({
33
+ h: d(p, C),
34
+ s: g(p, C),
35
+ v: M(p, C)
36
36
  });
37
- return S(P, o);
37
+ return F(S, a);
38
38
  }
39
- function C(t, n, o) {
40
- const a = m(F(t, 10 - n + 1)), e = m(t), r = e.hue(), s = e.saturationv(), c = m({
41
- h: e.hue(),
42
- s: f(6),
43
- v: e.value()
44
- }).saturationv(), p = Math.ceil((c - 9) / 4), d = Math.ceil((100 - c) / 5);
45
- function f(w) {
46
- if (w < 6)
47
- return c + (6 - w) * d;
48
- if (w === 6) {
49
- if (r >= 0 && r < 50)
39
+ function v(t, r, a) {
40
+ const e = m(E(t, 10 - r + 1)), n = m(t), o = n.hue(), s = n.saturationv(), c = m({
41
+ h: n.hue(),
42
+ s: h(6),
43
+ v: n.value()
44
+ }).saturationv(), l = Math.ceil((c - 9) / 4), f = Math.ceil((100 - c) / 5);
45
+ function h(d) {
46
+ if (d < 6)
47
+ return c + (6 - d) * f;
48
+ if (d === 6) {
49
+ if (o >= 0 && o < 50)
50
50
  return s - 15;
51
- if (r >= 50 && r < 191)
51
+ if (o >= 50 && o < 191)
52
52
  return s - 20;
53
- if (r >= 191 && r <= 360)
53
+ if (o >= 191 && o <= 360)
54
54
  return s - 15;
55
55
  }
56
- return c - p * (w - 6);
56
+ return c - l * (d - 6);
57
57
  }
58
58
  const u = m({
59
- h: a.hue(),
60
- s: f(n),
61
- v: a.value()
59
+ h: e.hue(),
60
+ s: h(r),
61
+ v: e.value()
62
62
  });
63
- return S(u, o);
63
+ return F(u, a);
64
64
  }
65
- function D(t, n = {}) {
66
- const { dark: o, list: a, index: e = 6, format: r = "hex" } = n;
67
- if (a) {
68
- const s = [], i = o ? C : F;
65
+ function I(t, r = {}) {
66
+ const { dark: a, list: e, index: n = 6, format: o = "hex" } = r;
67
+ if (e) {
68
+ const s = [], i = a ? v : E;
69
69
  for (let c = 1; c <= 10; c++)
70
- s.push(i(t, c, r));
70
+ s.push(i(t, c, o));
71
71
  return s;
72
72
  }
73
- return o ? C(t, e, r) : F(t, e, r);
73
+ return a ? v(t, n, o) : E(t, n, o);
74
74
  }
75
- async function I(t) {
75
+ async function $(t) {
76
76
  try {
77
- const n = await N(t), o = q(n);
78
- return z(o);
79
- } catch (n) {
80
- throw console.error("提取图片颜色失败:", n), n;
77
+ const r = await z(t), a = B(r);
78
+ return V(a);
79
+ } catch (r) {
80
+ throw console.error("提取图片颜色失败:", r), r;
81
81
  }
82
82
  }
83
- async function N(t) {
84
- return new Promise((n, o) => {
83
+ async function z(t) {
84
+ return new Promise((r, a) => {
85
85
  try {
86
- const a = document.createElement("canvas"), e = a.getContext("2d"), r = Math.min(t.width, 100), s = Math.min(t.height, 100), i = Math.min(r / t.width, s / t.height);
87
- a.width = t.width * i, a.height = t.height * i, e.drawImage(t, 0, 0, a.width, a.height);
88
- const c = e.getImageData(0, 0, a.width, a.height);
89
- n(c);
90
- } catch (a) {
91
- o(a);
86
+ const e = document.createElement("canvas"), n = e.getContext("2d"), o = Math.min(t.width, 100), s = Math.min(t.height, 100), i = Math.min(o / t.width, s / t.height);
87
+ e.width = t.width * i, e.height = t.height * i, n.drawImage(t, 0, 0, e.width, e.height);
88
+ const c = n.getImageData(0, 0, e.width, e.height);
89
+ r(c);
90
+ } catch (e) {
91
+ a(e);
92
92
  }
93
93
  });
94
94
  }
95
- function q(t) {
96
- const n = t.data, o = /* @__PURE__ */ new Map();
97
- for (let e = 0; e < n.length; e += 4) {
98
- const r = n[e], s = n[e + 1], i = n[e + 2];
99
- if (n[e + 3] < 128) continue;
100
- const p = Math.round(r / 16) * 16, d = Math.round(s / 16) * 16, f = Math.round(i / 16) * 16, u = `${p},${d},${f}`;
101
- o.has(u) ? o.set(u, o.get(u) + 1) : o.set(u, 1);
95
+ function B(t) {
96
+ const r = t.data, a = /* @__PURE__ */ new Map();
97
+ for (let n = 0; n < r.length; n += 4) {
98
+ const o = r[n], s = r[n + 1], i = r[n + 2];
99
+ if (r[n + 3] < 128) continue;
100
+ const l = Math.round(o / 16) * 16, f = Math.round(s / 16) * 16, h = Math.round(i / 16) * 16, u = `${l},${f},${h}`;
101
+ a.has(u) ? a.set(u, a.get(u) + 1) : a.set(u, 1);
102
102
  }
103
- const a = [];
104
- return o.forEach((e, r) => {
105
- const [s, i, c] = r.split(",").map(Number);
106
- a.push({ r: s, g: i, b: c, count: e });
107
- }), a;
108
- }
109
- function z(t) {
110
- t.sort((e, r) => r.count - e.count);
111
- const n = t.filter((e) => {
112
- const { r, g: s, b: i } = e, c = Math.max(r, s, i), p = Math.min(r, s, i), d = c - p, f = c === 0 ? 0 : d / c, u = c / 255;
113
- return f > 0.15 && u > 0.2 && u < 0.8;
114
- }), o = n.length > 0 ? n[0] : t[0];
115
- return m({ r: o.r, g: o.g, b: o.b }).hex();
103
+ const e = [];
104
+ return a.forEach((n, o) => {
105
+ const [s, i, c] = o.split(",").map(Number);
106
+ e.push({ r: s, g: i, b: c, count: n });
107
+ }), e;
116
108
  }
117
109
  function V(t) {
118
- return new Promise((n, o) => {
110
+ t.sort((n, o) => o.count - n.count);
111
+ const r = t.filter((n) => {
112
+ const { r: o, g: s, b: i } = n, c = Math.max(o, s, i), l = Math.min(o, s, i), f = c - l, h = c === 0 ? 0 : f / c, u = c / 255;
113
+ return h > 0.15 && u > 0.2 && u < 0.8;
114
+ }), a = r.length > 0 ? r[0] : t[0];
115
+ return m({ r: a.r, g: a.g, b: a.b }).hex();
116
+ }
117
+ function J(t) {
118
+ return new Promise((r, a) => {
119
119
  if (!t.type.startsWith("image/")) {
120
- o(new Error("请选择图片文件"));
120
+ a(new Error("请选择图片文件"));
121
121
  return;
122
122
  }
123
- const a = new FileReader();
124
- a.onload = async (e) => {
123
+ const e = new FileReader();
124
+ e.onload = async (n) => {
125
125
  try {
126
- const r = new Image();
127
- r.onload = async () => {
126
+ const o = new Image();
127
+ o.onload = async () => {
128
128
  try {
129
- const s = await I(r);
130
- n(s);
129
+ const s = await $(o);
130
+ r(s);
131
131
  } catch (s) {
132
- o(s);
132
+ a(s);
133
133
  }
134
- }, r.onerror = () => o(new Error("图片加载失败")), r.src = e.target.result;
135
- } catch (r) {
136
- o(r);
134
+ }, o.onerror = () => a(new Error("图片加载失败")), o.src = n.target.result;
135
+ } catch (o) {
136
+ a(o);
137
137
  }
138
- }, a.onerror = () => o(new Error("文件读取失败")), a.readAsDataURL(t);
138
+ }, e.onerror = () => a(new Error("文件读取失败")), e.readAsDataURL(t);
139
+ });
140
+ }
141
+ function L(t, r, a = {}) {
142
+ const { steps: e = 10, format: n = "hex", includeEnds: o = !0 } = a;
143
+ if (e < 2)
144
+ throw new Error("步数必须至少为2");
145
+ const s = m(t), i = m(r), c = [], l = o ? e : e + 2, f = 1 / (l - 1);
146
+ for (let h = 0; h < l; h++) {
147
+ const u = h * f, d = Math.round(s.red() + (i.red() - s.red()) * u), g = Math.round(s.green() + (i.green() - s.green()) * u), M = Math.round(s.blue() + (i.blue() - s.blue()) * u), p = m({ r: d, g, b: M });
148
+ !o && (h === 0 || h === l - 1) || c.push(F(p, n));
149
+ }
150
+ return c;
151
+ }
152
+ function Q(t = {}) {
153
+ const {
154
+ startGray: r = "#ffffff",
155
+ endGray: a = "#000000",
156
+ steps: e = 10,
157
+ format: n = "hex"
158
+ } = t;
159
+ return L(r, a, { steps: e, format: n, includeEnds: !0 });
160
+ }
161
+ function X(t, r = {}) {
162
+ const { steps: a = 10, format: e = "hex", lightnessRange: n = 80 } = r, s = m(t).hsl(), i = s.lightness(), c = Math.min(95, i + n / 2), l = Math.max(5, i - n / 2), f = m({
163
+ h: s.hue(),
164
+ s: s.saturationl(),
165
+ l: c
166
+ }), h = m({
167
+ h: s.hue(),
168
+ s: s.saturationl(),
169
+ l
170
+ });
171
+ return L(f.hex(), h.hex(), { steps: a, format: e, includeEnds: !0 });
172
+ }
173
+ function Y(t, r, a = {}) {
174
+ const { steps: e = 10, format: n = "hex", includeEnds: o = !0 } = a;
175
+ if (e < 2)
176
+ throw new Error("步数必须至少为2");
177
+ const s = m(t).hsl(), i = m(r).hsl(), c = [], l = o ? e : e + 2, f = 1 / (l - 1);
178
+ let h = s.hue() || 0, u = i.hue() || 0;
179
+ const d = u - h;
180
+ Math.abs(d) > 180 && (d > 0 ? h += 360 : u += 360);
181
+ for (let g = 0; g < l; g++) {
182
+ const M = g * f;
183
+ let p = h + (u - h) * M;
184
+ const C = s.saturationl() + (i.saturationl() - s.saturationl()) * M, S = s.lightness() + (i.lightness() - s.lightness()) * M;
185
+ p = p % 360, p < 0 && (p += 360);
186
+ const b = m({ h: p, s: C, l: S });
187
+ !o && (g === 0 || g === l - 1) || c.push(F(b, n));
188
+ }
189
+ return c;
190
+ }
191
+ function y(t) {
192
+ const r = t.replace("#", ""), a = parseInt(r.substr(0, 2), 16) / 255, e = parseInt(r.substr(2, 2), 16) / 255, n = parseInt(r.substr(4, 2), 16) / 255, o = Math.max(a, e, n), s = Math.min(a, e, n), i = o - s;
193
+ let c = 0;
194
+ i !== 0 && (o === a ? c = (e - n) / i % 6 : o === e ? c = (n - a) / i + 2 : c = (a - e) / i + 4), c = Math.round(c * 60), c < 0 && (c += 360);
195
+ const l = Math.round((0.299 * a + 0.587 * e + 0.114 * n) * 100), f = (o + s) / 2, h = i === 0 ? 0 : i / (1 - Math.abs(2 * f - 1)), u = Math.round(h * Math.min(l, 100 - l));
196
+ return { h: c, c: u, t: l };
197
+ }
198
+ function D(t) {
199
+ const { h: r, c: a, t: e } = t, n = (r % 360 + 360) % 360, o = Math.max(0, Math.min(150, a)), s = Math.max(0, Math.min(100, e)), i = s / 100, c = s === 0 || s === 100 ? 0 : o / Math.min(s, 100 - s), l = (1 - Math.abs(2 * i - 1)) * Math.min(1, c), f = l * (1 - Math.abs(n / 60 % 2 - 1)), h = i - l / 2;
200
+ let u, d, g;
201
+ n >= 0 && n < 60 ? [u, d, g] = [l, f, 0] : n >= 60 && n < 120 ? [u, d, g] = [f, l, 0] : n >= 120 && n < 180 ? [u, d, g] = [0, l, f] : n >= 180 && n < 240 ? [u, d, g] = [0, f, l] : n >= 240 && n < 300 ? [u, d, g] = [f, 0, l] : [u, d, g] = [l, 0, f];
202
+ const M = (p) => {
203
+ const C = Math.max(0, Math.min(1, p + h)), S = Math.round(C * 255).toString(16);
204
+ return S.length === 1 ? "0" + S : S;
205
+ };
206
+ return `#${M(u)}${M(d)}${M(g)}`;
207
+ }
208
+ function R(t, r, a = 0.5) {
209
+ const e = y(t), n = y(r);
210
+ let o = e.h, s = n.h, i = s - o;
211
+ Math.abs(i) > 180 && (i > 0 ? o += 360 : s += 360);
212
+ const c = (o + (s - o) * a) % 360, l = e.c + (n.c - e.c) * a, f = e.t + (n.t - e.t) * a;
213
+ return D({
214
+ h: c < 0 ? c + 360 : c,
215
+ c: Math.max(0, Math.round(l)),
216
+ t: Math.max(0, Math.min(100, Math.round(f)))
139
217
  });
140
218
  }
141
- const M = {
219
+ function G(t, r, a = 0.15) {
220
+ const e = y(t), n = y(r);
221
+ let o = n.h, s = e.h, i = s - o;
222
+ Math.abs(i) > 180 && (i > 0 ? o += 360 : s += 360, i = s - o);
223
+ const c = (o + i * a) % 360;
224
+ return D({
225
+ h: c < 0 ? c + 360 : c,
226
+ c: n.c,
227
+ // 保持原有色度
228
+ t: n.t
229
+ // 保持原有色调
230
+ });
231
+ }
232
+ function O(t, r = [10, 20, 30, 40, 50, 60, 70, 80, 90]) {
233
+ const a = y(t);
234
+ let e;
235
+ return Array.isArray(r) ? e = r : r && r.tones && Array.isArray(r.tones) ? e = r.tones : e = [10, 20, 30, 40, 50, 60, 70, 80, 90], e.map((n) => D({
236
+ h: a.h,
237
+ c: a.c,
238
+ t: n
239
+ }));
240
+ }
241
+ function T(t, r, a = 0.15) {
242
+ const e = {};
243
+ for (const [n, o] of Object.entries(r))
244
+ e[n] = G(t, o, a);
245
+ return e;
246
+ }
247
+ function N(t, r, a = 0.2) {
248
+ const e = {};
249
+ for (const [n, o] of Object.entries(r))
250
+ e[n] = R(t, o, a);
251
+ return e;
252
+ }
253
+ function q(t, r = {}) {
254
+ const { baseGray: a = "#666666" } = r, { blendRatio: e = 0.08, isDark: n = !1 } = r, o = y(a), s = {};
255
+ return (n ? [95, 90, 85, 80, 70, 60, 50, 40, 30, 20, 15, 10] : [10, 15, 20, 30, 40, 50, 60, 70, 80, 85, 90, 95]).forEach((c, l) => {
256
+ const f = { h: o.h, c: o.c, t: c }, h = R(D(f), t, e);
257
+ s[`gray-${l + 1}`] = h;
258
+ }), s;
259
+ }
260
+ function j(t, r = {}) {
261
+ const {
262
+ semanticColors: a = {
263
+ success: "#52c41a",
264
+ warning: "#faad14",
265
+ error: "#ff4d4f",
266
+ info: "#1890ff"
267
+ },
268
+ blendRatio: e = 0.12,
269
+ isDark: n = !1
270
+ } = r, o = {};
271
+ return Object.entries(a).forEach(([s, i]) => {
272
+ const c = {}, l = y(i);
273
+ (n ? [90, 80, 70, 60, 50, 40, 30, 25, 20, 15] : [15, 25, 35, 45, 55, 65, 75, 85, 90, 95]).forEach((h, u) => {
274
+ const d = { h: l.h, c: l.c, t: h }, g = R(D(d), t, e);
275
+ c[`${s}-${u + 1}`] = g;
276
+ }), Object.assign(o, c);
277
+ }), o;
278
+ }
279
+ function U(t, r = {}) {
280
+ const { isDark: a = !1 } = r, e = y(t), n = {};
281
+ return (a ? [90, 80, 70, 60, 50, 40, 30, 25, 20, 15] : [15, 25, 35, 45, 55, 65, 75, 85, 90, 95]).forEach((s, i) => {
282
+ const c = { h: e.h, c: e.c, t: s };
283
+ n[`theme-${i + 1}`] = D(c);
284
+ }), n;
285
+ }
286
+ function Z(t, r = {}) {
287
+ const {
288
+ baseGray: a = "#666666",
289
+ isDark: e = !1,
290
+ semanticColors: n,
291
+ controlBlendRatio: o = 0.08,
292
+ semanticBlendRatio: s = 0.12
293
+ } = r;
294
+ return {
295
+ // 1. 基础控件颜色(灰色系1-12)
296
+ controls: q(t, {
297
+ baseGray: a,
298
+ blendRatio: o,
299
+ isDark: e
300
+ }),
301
+ // 2. 表意色(1-10)
302
+ semantic: j(t, {
303
+ semanticColors: n,
304
+ blendRatio: s,
305
+ isDark: e
306
+ }),
307
+ // 3. 主题色(1-10)
308
+ theme: U(t, { isDark: e })
309
+ };
310
+ }
311
+ function _(t, r = {}) {
312
+ const {
313
+ semanticColors: a = {
314
+ success: "#4caf50",
315
+ warning: "#ff9800",
316
+ error: "#f44336",
317
+ info: "#2196f3"
318
+ },
319
+ uiColors: e = {
320
+ primary: t,
321
+ "primary-light": "#ffffff",
322
+ "primary-lighter": "#f8f9ff",
323
+ "primary-dark": "#000000",
324
+ "primary-darker": "#0a0a0a",
325
+ accent: "#722ed1",
326
+ "neutral-1": "#f7f8fa",
327
+ "neutral-2": "#f2f3f5",
328
+ "neutral-3": "#e5e6eb",
329
+ "neutral-4": "#c9cdd4",
330
+ "neutral-5": "#a9aeb8",
331
+ "neutral-6": "#86909c",
332
+ background: "#ffffff",
333
+ surface: "#f8f9fa",
334
+ border: "#e5e6eb",
335
+ disabled: "#c9cdd4"
336
+ },
337
+ harmonizeRatio: n = 0.15,
338
+ blendRatio: o = 0.12,
339
+ generateVariants: s = !0
340
+ } = r, i = {
341
+ theme: t,
342
+ semantic: T(t, a, n),
343
+ ui: N(t, e, o)
344
+ };
345
+ return s && (i.variants = O(t)), i;
346
+ }
347
+ const H = {
142
348
  red: "#F53F3F",
143
349
  orangered: "#F77234",
144
350
  orange: "#FF7D00",
@@ -153,10 +359,10 @@ const M = {
153
359
  pinkpurple: "#D91AD9",
154
360
  magenta: "#F5319D"
155
361
  };
156
- function $() {
362
+ function tt() {
157
363
  const t = {};
158
- return Object.keys(M).forEach((n) => {
159
- t[n] = {}, t[n].light = D(M[n], { list: !0 }), t[n].dark = D(M[n], { list: !0, dark: !0 }), t[n].primary = M[n];
364
+ return Object.keys(H).forEach((r) => {
365
+ t[r] = {}, t[r].light = I(H[r], { list: !0 }), t[r].dark = I(H[r], { list: !0, dark: !0 }), t[r].primary = H[r];
160
366
  }), t.gray = {}, t.gray.light = [
161
367
  "#f7f8fa",
162
368
  "#f2f3f5",
@@ -182,10 +388,26 @@ function $() {
182
388
  ], t.gray.primary = t.gray.light[6], t;
183
389
  }
184
390
  export {
185
- M as colorList,
186
- V as extractColorFromFile,
187
- I as extractColorFromImage,
188
- D as generate,
189
- $ as getPresetColors,
190
- R as getRgbStr
391
+ R as blendInHct,
392
+ T as blendSemanticColors,
393
+ N as blendUIColors,
394
+ H as colorList,
395
+ J as extractColorFromFile,
396
+ $ as extractColorFromImage,
397
+ I as generate,
398
+ q as generateControlColors,
399
+ Q as generateGrayLinear,
400
+ Z as generateInterfaceColorSystem,
401
+ L as generateLinear,
402
+ Y as generateLinearHSL,
403
+ X as generateMonochromeLinear,
404
+ j as generateSemanticColors,
405
+ U as generateThemeColors,
406
+ _ as generateThemePalette,
407
+ O as generateThemeVariants,
408
+ tt as getPresetColors,
409
+ W as getRgbStr,
410
+ G as harmonizeColor,
411
+ D as hctToRgb,
412
+ y as rgbToHct
191
413
  };
@@ -0,0 +1,68 @@
1
+ /**
2
+ * 线性颜色生成器
3
+ * 在两个颜色之间进行线性插值,生成指定数量的颜色
4
+ * 特别适用于灰色系和单色调渐变
5
+ *
6
+ * @param {string} startColor - 起始颜色
7
+ * @param {string} endColor - 结束颜色
8
+ * @param {Object} options - 配置选项
9
+ * @param {number} options.steps - 生成的颜色数量 (默认: 10)
10
+ * @param {string} options.format - 颜色格式 'hex' | 'rgb' | 'hsl' (默认: 'hex')
11
+ * @param {boolean} options.includeEnds - 是否包含起始和结束颜色 (默认: true)
12
+ * @returns {string[]} 颜色数组
13
+ */
14
+ export function generateLinear(startColor: string, endColor: string, options?: {
15
+ steps: number;
16
+ format: string;
17
+ includeEnds: boolean;
18
+ }): string[];
19
+ /**
20
+ * 生成灰色系线性渐变
21
+ * 从白色到黑色或指定的灰色范围
22
+ *
23
+ * @param {Object} options - 配置选项
24
+ * @param {string} options.startGray - 起始灰色 (默认: '#ffffff')
25
+ * @param {string} options.endGray - 结束灰色 (默认: '#000000')
26
+ * @param {number} options.steps - 生成的颜色数量 (默认: 10)
27
+ * @param {string} options.format - 颜色格式 (默认: 'hex')
28
+ * @returns {string[]} 灰色系颜色数组
29
+ */
30
+ export function generateGrayLinear(options?: {
31
+ startGray: string;
32
+ endGray: string;
33
+ steps: number;
34
+ format: string;
35
+ }): string[];
36
+ /**
37
+ * 生成单色调线性渐变
38
+ * 基于一个基础颜色,生成从浅到深的渐变
39
+ *
40
+ * @param {string} baseColor - 基础颜色
41
+ * @param {Object} options - 配置选项
42
+ * @param {number} options.steps - 生成的颜色数量 (默认: 10)
43
+ * @param {string} options.format - 颜色格式 (默认: 'hex')
44
+ * @param {number} options.lightnessRange - 亮度范围 0-100 (默认: 80)
45
+ * @returns {string[]} 单色调颜色数组
46
+ */
47
+ export function generateMonochromeLinear(baseColor: string, options?: {
48
+ steps: number;
49
+ format: string;
50
+ lightnessRange: number;
51
+ }): string[];
52
+ /**
53
+ * 在HSL空间进行线性插值
54
+ * 适用于需要更自然色彩过渡的场景
55
+ *
56
+ * @param {string} startColor - 起始颜色
57
+ * @param {string} endColor - 结束颜色
58
+ * @param {Object} options - 配置选项
59
+ * @param {number} options.steps - 生成的颜色数量 (默认: 10)
60
+ * @param {string} options.format - 颜色格式 (默认: 'hex')
61
+ * @param {boolean} options.includeEnds - 是否包含起始和结束颜色 (默认: true)
62
+ * @returns {string[]} 颜色数组
63
+ */
64
+ export function generateLinearHSL(startColor: string, endColor: string, options?: {
65
+ steps: number;
66
+ format: string;
67
+ includeEnds: boolean;
68
+ }): string[];
@@ -0,0 +1,96 @@
1
+ /**
2
+ * 生成基础控件颜色(灰色系1-12)
3
+ * @param {string} themeColor - 主题颜色
4
+ * @param {Object} options - 配置选项
5
+ * @returns {Object} 基础控件颜色对象
6
+ */
7
+ export function generateControlColors(themeColor: string, options?: Object): Object;
8
+ /**
9
+ * 生成表意色(1-10)
10
+ * @param {string} themeColor - 主题颜色
11
+ * @param {Object} options - 配置选项
12
+ * @returns {Object} 表意色对象
13
+ */
14
+ export function generateSemanticColors(themeColor: string, options?: Object): Object;
15
+ /**
16
+ * 生成主题色(1-10)
17
+ * @param {string} themeColor - 主题颜色
18
+ * @param {Object} options - 配置选项
19
+ * @returns {Object} 主题色对象
20
+ */
21
+ export function generateThemeColors(themeColor: string, options?: Object): Object;
22
+ /**
23
+ * 生成完整的界面色彩系统
24
+ * @param {string} themeColor - 主题颜色
25
+ * @param {Object} options - 配置选项
26
+ * @returns {Object} 包含三个部分的完整色彩系统
27
+ */
28
+ export function generateInterfaceColorSystem(themeColor: string, options?: Object): Object;
29
+ /**
30
+ * 主题色混合模块
31
+ * 基于 Material Design 3 的 HCT 颜色空间实现颜色混合和调和
32
+ *
33
+ * HCT (Hue, Chroma, Tone) 颜色空间结合了 CAM16 和 CIE-Lab 的优势:
34
+ * - H (Hue): 色相,0-360度
35
+ * - C (Chroma): 色度,颜色的饱和度
36
+ * - T (Tone): 色调,亮度从黑色(0)到白色(100)
37
+ */
38
+ /**
39
+ * 将 RGB 颜色转换为 HCT 颜色空间
40
+ * 这是一个简化的实现,实际的 HCT 转换需要复杂的 CAM16 计算
41
+ * @param {string} rgb - RGB 颜色值,格式如 "#ff0000"
42
+ * @returns {Object} HCT 颜色对象 {h, c, t}
43
+ */
44
+ export function rgbToHct(rgb: string): Object;
45
+ /**
46
+ * 将 HCT 颜色转换为 RGB
47
+ * @param {Object} hct - HCT 颜色对象 {h, c, t}
48
+ * @returns {string} RGB 颜色值,格式如 "#ff0000"
49
+ */
50
+ export function hctToRgb(hct: Object): string;
51
+ /**
52
+ * 在 HCT 颜色空间中混合两种颜色
53
+ * @param {string} color1 - 第一种颜色 (RGB)
54
+ * @param {string} color2 - 第二种颜色 (RGB)
55
+ * @param {number} ratio - 混合比例,0-1,0表示完全是color1,1表示完全是color2
56
+ * @returns {string} 混合后的颜色 (RGB)
57
+ */
58
+ export function blendInHct(color1: string, color2: string, ratio?: number): string;
59
+ /**
60
+ * 颜色调和 - 让目标颜色向主题色的色相靠拢
61
+ * @param {string} themeColor - 主题色 (RGB)
62
+ * @param {string} targetColor - 目标颜色 (RGB)
63
+ * @param {number} harmonizeRatio - 调和强度,0-1,0表示不调和,1表示完全采用主题色的色相
64
+ * @returns {string} 调和后的颜色 (RGB)
65
+ */
66
+ export function harmonizeColor(themeColor: string, targetColor: string, harmonizeRatio?: number): string;
67
+ /**
68
+ * 生成主题色变体 - 基于主题色生成不同明度的颜色变体
69
+ * @param {string} themeColor - 主题色 (RGB)
70
+ * @param {Object|Array} options - 配置选项,可以是对象 {tones: [...]} 或直接传入数组
71
+ * @returns {Array} 主题色变体数组
72
+ */
73
+ export function generateThemeVariants(themeColor: string, options?: Object | any[]): any[];
74
+ /**
75
+ * 表意色混合 - 为成功、警告、错误等状态色添加主题色调
76
+ * @param {string} themeColor - 主题色
77
+ * @param {Object} semanticColors - 表意色对象,如 {success: '#4caf50', warning: '#ff9800', error: '#f44336'}
78
+ * @param {number} blendRatio - 混合强度
79
+ * @returns {Object} 混合后的表意色对象
80
+ */
81
+ export function blendSemanticColors(themeColor: string, semanticColors: Object, blendRatio?: number): Object;
82
+ /**
83
+ * UI 元素颜色混合 - 为按钮、卡片等 UI 元素生成主题化颜色
84
+ * @param {string} themeColor - 主题色
85
+ * @param {Object} uiColors - UI 颜色对象
86
+ * @param {number} blendRatio - 混合强度
87
+ * @returns {Object} 混合后的 UI 颜色对象
88
+ */
89
+ export function blendUIColors(themeColor: string, uiColors: Object, blendRatio?: number): Object;
90
+ /**
91
+ * 生成完整的主题色板
92
+ * @param {string} themeColor - 主题色
93
+ * @param {Object} options - 配置选项
94
+ * @returns {Object} 完整的主题色板
95
+ */
96
+ export function generateThemePalette(themeColor: string, options?: Object): Object;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aviala-design/color",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Aviala Design color utils",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",