@aviala-design/color 0.4.0 → 0.4.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 CHANGED
@@ -1,4 +1,4 @@
1
- <!-- 当前版本: 0.4.0 | 最后同步: 2025/11/25 21:21:09 -->
1
+ <!-- 当前版本: 0.4.1 | 最后同步: 2026/3/8 16:36:55 -->
2
2
  # Aviala Design Color
3
3
 
4
4
  ![npm version](https://img.shields.io/npm/v/@aviala-design/color) ![npm downloads](https://img.shields.io/npm/dm/@aviala-design/color) ![license](https://img.shields.io/npm/l/@aviala-design/color)
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { default as generate } from './generate.js';
2
2
  import { getRgbStr } from './utils.js';
3
3
  import { extractColorFromImage, extractColorFromFile } from './image-color.js';
4
4
  import { generateLinear, generateGrayLinear, generateMonochromeLinear, generateLinearHSL } from './linear.js';
5
- import { rgbToHct, hctToRgb, blendInHct, harmonizeColor, generateThemeVariants, blendUIColors, generateThemePalette, generateControlColors, generateSemanticColors, generateThemeColors, generateInterfaceColorSystem, colorDifference, adjustTone, adjustChroma, adjustHue, rotateHue, getComplementary, getTriadic, getSplitComplementary, getAnalogous } from './theme-blend.js';
5
+ import { rgbToHct, hctToRgb, blendInHct, harmonizeColor, generateThemeVariants, blendUIColors, generateThemePalette, generateControlColors, generateNeutralColors, generateSemanticColors, generateThemeColors, generateInterfaceColorSystem, colorDifference, adjustTone, adjustChroma, adjustHue, rotateHue, getComplementary, getTriadic, getSplitComplementary, getAnalogous } from './theme-blend.js';
6
6
  /**
7
7
  * 获取所有预设颜色的色板
8
8
  *
@@ -80,5 +80,5 @@ export const colorList: {
80
80
  pinkpurple: string;
81
81
  magenta: string;
82
82
  };
83
- export { generate, getRgbStr, extractColorFromImage, extractColorFromFile, generateLinear, generateGrayLinear, generateMonochromeLinear, generateLinearHSL, rgbToHct, hctToRgb, blendInHct, harmonizeColor, generateThemeVariants, blendUIColors, generateThemePalette, generateControlColors, generateSemanticColors, generateThemeColors, generateInterfaceColorSystem, colorDifference, adjustTone, adjustChroma, adjustHue, rotateHue, getComplementary, getTriadic, getSplitComplementary, getAnalogous };
83
+ export { generate, getRgbStr, extractColorFromImage, extractColorFromFile, generateLinear, generateGrayLinear, generateMonochromeLinear, generateLinearHSL, rgbToHct, hctToRgb, blendInHct, harmonizeColor, generateThemeVariants, blendUIColors, generateThemePalette, generateControlColors, generateNeutralColors, generateSemanticColors, generateThemeColors, generateInterfaceColorSystem, colorDifference, adjustTone, adjustChroma, adjustHue, rotateHue, getComplementary, getTriadic, getSplitComplementary, getAnalogous };
84
84
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AAwEA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,mCAtBa;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG;QAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC,CA4D/E;AA7GD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAvBU;IACL,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAA;CAChB,CAuBF;qBAtEmB,eAAe;0BACV,YAAY;sCACsB,kBAAkB;qCAAlB,kBAAkB;+BACkB,aAAa;mCAAb,aAAa;yCAAb,aAAa;kCAAb,aAAa;yBAuBtG,kBAAkB;yBAAlB,kBAAkB;2BAAlB,kBAAkB;+BAAlB,kBAAkB;sCAAlB,kBAAkB;8BAAlB,kBAAkB;qCAAlB,kBAAkB;sCAAlB,kBAAkB;uCAAlB,kBAAkB;oCAAlB,kBAAkB;6CAAlB,kBAAkB;gCAAlB,kBAAkB;2BAAlB,kBAAkB;6BAAlB,kBAAkB;0BAAlB,kBAAkB;0BAAlB,kBAAkB;iCAAlB,kBAAkB;2BAAlB,kBAAkB;sCAAlB,kBAAkB;6BAAlB,kBAAkB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AAyEA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,mCAtBa;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG;QAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC,CA4D/E;AA7GD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAvBU;IACL,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAA;CAChB,CAuBF;qBAvEmB,eAAe;0BACV,YAAY;sCACsB,kBAAkB;qCAAlB,kBAAkB;+BACkB,aAAa;mCAAb,aAAa;yCAAb,aAAa;kCAAb,aAAa;yBAwBtG,kBAAkB;yBAAlB,kBAAkB;2BAAlB,kBAAkB;+BAAlB,kBAAkB;sCAAlB,kBAAkB;8BAAlB,kBAAkB;qCAAlB,kBAAkB;sCAAlB,kBAAkB;sCAAlB,kBAAkB;uCAAlB,kBAAkB;oCAAlB,kBAAkB;6CAAlB,kBAAkB;gCAAlB,kBAAkB;2BAAlB,kBAAkB;6BAAlB,kBAAkB;0BAAlB,kBAAkB;0BAAlB,kBAAkB;iCAAlB,kBAAkB;2BAAlB,kBAAkB;sCAAlB,kBAAkB;6BAAlB,kBAAkB"}
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- (function(f,d){typeof exports=="object"&&typeof module<"u"?d(exports,require("color")):typeof define=="function"&&define.amd?define(["exports","color"],d):(f=typeof globalThis<"u"?globalThis:f||self,d(f.AvialaColor={},f.Color))})(this,function(f,d){"use strict";function N(t){return d(t).rgb().round().color.join(",")}const U=["hex","rgb","hsl"];function K(t){return!t||!U.includes(t)?"hex":t}function D(t,n){const r=K(n);return r==="hex"?t[r]().toLowerCase():t[r]().round().string()}function B(t,n,r){const e=d(t),o=e.hue(),a=e.saturationv(),s=e.value(),i=(p=>p>=60&&p<=240?2.5:p>=0&&p<60||p>300&&p<=360?1.5:2)(o),h=100,m=9,u=100,l=30;function g(p,y){let L;return o>=60&&o<=240?L=p?o-i*y:o+i*y:L=p?o+i*y:o-i*y,L<0?L+=360:L>=360&&(L-=360),Math.round(L)}function b(p,y){let L;if(p)L=a<=m?a:a-(a-m)/5.5*Math.pow(y,1.05);else{const v=Math.min(h,a+30);L=a+(v-a)/4.2*Math.pow(y,.95)}return Math.max(0,Math.min(100,L))}function M(p,y){return p?Math.min(u,s+(u-s)/5.2*Math.pow(y,.9)):s<=l?s:Math.max(l,s-(s-l)/4.2*Math.pow(y,1.05))}const w=n<6,S=w?6-n:n-6,x=n===6?e:d({h:g(w,S),s:b(w,S),v:M(w,S)});return D(x,r)}function j(t,n,r){const e=d(B(t,10-n+1,"hex")),o=d(t),a=o.hue(),s=o.saturationv();function c(g){if(g<6)return h+(6-g)*u;if(g===6){if(a>=0&&a<50)return s-15;if(a>=50&&a<191)return s-20;if(a>=191&&a<=360)return s-15}return h-m*(g-6)}const h=d({h:o.hue(),s:c(6),v:o.value()}).saturationv(),m=Math.ceil((h-9)/4),u=Math.ceil((100-h)/5),l=d({h:e.hue(),s:c(n),v:e.value()});return D(l,r)}function $(t,n={}){const{dark:r,list:e,index:o=6,format:a="hex"}=n;if(e){const s=[],c=r?j:B;for(let i=1;i<=10;i++)s.push(c(t,i,a));return s}return r?j(t,o,a):B(t,o,a)}async function k(t){try{const n=await W(t),r=J(n);return Q(r)}catch(n){throw console.error("提取图片颜色失败:",n),n}}async function W(t){return new Promise((n,r)=>{try{if(typeof document>"u"){r(new Error("图像颜色提取功能仅在浏览器环境中可用"));return}const e=document.createElement("canvas"),o=e.getContext("2d");if(!o){r(new Error("无法获取canvas 2d context"));return}const a=Math.min(t.width,100),s=Math.min(t.height,100),c=Math.min(a/t.width,s/t.height);e.width=t.width*c,e.height=t.height*c,o.drawImage(t,0,0,e.width,e.height);const i=o.getImageData(0,0,e.width,e.height);n(i)}catch(e){r(e)}})}function J(t){const n=t.data,r=new Map;for(let o=0;o<n.length;o+=4){const a=n[o],s=n[o+1],c=n[o+2];if(n[o+3]<128)continue;const h=Math.round(a/16)*16,m=Math.round(s/16)*16,u=Math.round(c/16)*16,l=`${h},${m},${u}`;r.has(l)?r.set(l,r.get(l)+1):r.set(l,1)}const e=[];return r.forEach((o,a)=>{const[s,c,i]=a.split(",").map(Number);e.push({r:s,g:c,b:i,count:o})}),e}function Q(t){t.sort((o,a)=>a.count-o.count);const n=t.filter(o=>{const{r:a,g:s,b:c}=o,i=Math.max(a,s,c),h=Math.min(a,s,c),m=i-h,u=i===0?0:m/i,l=i/255;return u>.15&&l>.2&&l<.8}),r=n.length>0?n[0]:t[0];return d({r:r.r,g:r.g,b:r.b}).hex()}function X(t){return new Promise((n,r)=>{if(typeof FileReader>"u"||typeof Image>"u"){r(new Error("文件读取功能仅在浏览器环境中可用"));return}if(!t.type.startsWith("image/")){r(new Error("请选择图片文件"));return}const e=new FileReader;e.onload=async o=>{var a;try{const s=new Image;s.onload=async()=>{try{const i=await k(s);n(i)}catch(i){r(i)}},s.onerror=()=>r(new Error("图片加载失败"));const c=(a=o.target)==null?void 0:a.result;typeof c=="string"?s.src=c:r(new Error("无法读取图片数据"))}catch(s){r(s)}},e.onerror=()=>r(new Error("文件读取失败")),e.readAsDataURL(t)})}function A(t,n,r={}){const{steps:e=10,format:o="hex",includeEnds:a=!0}=r;if(e<2)throw new Error("步数必须至少为2");const s=d(t),c=d(n),i=[],h=a?e:e+2,m=1/(h-1);for(let u=0;u<h;u++){const l=u*m,g=Math.round(s.red()+(c.red()-s.red())*l),b=Math.round(s.green()+(c.green()-s.green())*l),M=Math.round(s.blue()+(c.blue()-s.blue())*l),w=d({r:g,g:b,b:M});!a&&(u===0||u===h-1)||i.push(D(w,o))}return i}function Y(t={}){const{startGray:n="#ffffff",endGray:r="#000000",steps:e=10,format:o="hex"}=t;return A(n,r,{steps:e,format:o,includeEnds:!0})}function C(t,n={}){const{steps:r=10,format:e="hex",lightnessRange:o=80,minLightness:a=null,maxLightness:s=null}=n,c=d(t);let i,h;if(a!==null&&s!==null){if(a>s)throw new Error("minLightness 不能大于 maxLightness");i=Math.max(0,Math.min(100,s)),h=Math.max(0,Math.min(100,a))}else{const l=c.lightness();i=Math.min(95,l+o/2),h=Math.max(5,l-o/2)}const m=d({h:c.hue(),s:c.saturationl(),l:i}),u=d({h:c.hue(),s:c.saturationl(),l:h});return A(m.hex(),u.hex(),{steps:r,format:e,includeEnds:!0})}function Z(t,n,r={}){const{steps:e=10,format:o="hex",includeEnds:a=!0}=r;if(e<2)throw new Error("步数必须至少为2");const s=d(t),c=d(n),i=[],h=a?e:e+2,m=1/(h-1);let u=s.hue()||0,l=c.hue()||0;const g=l-u;Math.abs(g)>180&&(g>0?u+=360:l+=360);const b=s.saturationl(),M=c.saturationl(),w=s.lightness(),S=c.lightness();for(let x=0;x<h;x++){const p=x*m;let y=u+(l-u)*p;const L=b+(M-b)*p,v=w+(S-w)*p;y=y%360,y<0&&(y+=360);const F=d({h:y,s:L,l:v});!a&&(x===0||x===h-1)||i.push(D(F,o))}return i}function R(t){if(!t||typeof t!="string")throw new Error("Invalid RGB color: must be a string");let n;try{n=d(t)}catch{throw new Error("Invalid RGB color format")}const r=n.l(),e=n.a(),o=n.b();let a=Math.atan2(o,e)*(180/Math.PI);a<0&&(a+=360);const s=Math.sqrt(e*e+o*o);return{h:a,c:s,t:r}}function E(t,n={}){if(!t||typeof t!="object"||t.h===void 0||t.c===void 0||t.t===void 0)throw new Error("Invalid HCT color: must be an object with h, c, t properties");const{gamutMapping:r="reduce-chroma"}=n;let{h:e,c:o,t:a}=t;e=(e%360+360)%360,o=Math.max(0,o),a=Math.max(0,Math.min(100,a));const s=e*(Math.PI/180),c=o*Math.cos(s),i=o*Math.sin(s);try{let h=d.lab(a,c,i);if(r==="reduce-chroma"){let b=o,M=h.rgb().array();for(;(M[0]<0||M[0]>255||M[1]<0||M[1]>255||M[2]<0||M[2]>255)&&b>0;){b-=1;const w=b*Math.cos(s),S=b*Math.sin(s);h=d.lab(a,w,S),M=h.rgb().array()}}const m=h.rgb().array(),u=Math.max(0,Math.min(255,Math.round(m[0]))),l=Math.max(0,Math.min(255,Math.round(m[1]))),g=Math.max(0,Math.min(255,Math.round(m[2])));return`#${u.toString(16).padStart(2,"0")}${l.toString(16).padStart(2,"0")}${g.toString(16).padStart(2,"0")}`}catch{return d.lab(a,c,i).hex().toLowerCase()}}function I(t,n,r=.5,e={}){if(!t||!n)throw new Error("Both colors are required for blending");const{mode:o="lab"}=e,a=Math.max(0,Math.min(1,r));return o==="lab"?_(t,n,a):o==="hue-only"?z(t,n,a):tt(t,n,a)}function _(t,n,r){const e=d(t),o=d(n),a=e.l(),s=e.a(),c=e.b(),i=o.l(),h=o.a(),m=o.b(),u=a+(i-a)*r,l=s+(h-s)*r,g=c+(m-c)*r;return d.lab(u,l,g).hex().toLowerCase()}function tt(t,n,r){const e=R(t),o=R(n),a=G(e.h,o.h,r),s=e.c+(o.c-e.c)*r,c=e.t+(o.t-e.t)*r;return E({h:a,c:Math.max(0,s),t:Math.max(0,Math.min(100,c))})}function z(t,n,r){const e=R(t),o=R(n),a=G(e.h,o.h,r);return E({h:a,c:e.c,t:e.t})}function G(t,n,r){let e=n-t;e>180?e-=360:e<-180&&(e+=360);let o=t+e*r;return o<0&&(o+=360),o>=360&&(o-=360),o}function nt(t,n){const r=d(t),e=d(n),o=r.l(),a=r.a(),s=r.b(),c=e.l(),i=e.a(),h=e.b();return Math.sqrt(Math.pow(c-o,2)+Math.pow(i-a,2)+Math.pow(h-s,2))}function et(t,n){const r=R(t);return E({h:r.h,c:r.c,t:Math.max(0,Math.min(100,n))})}function rt(t,n){const r=R(t);return E({h:r.h,c:Math.max(0,n),t:r.t})}function ot(t,n){const r=R(t);return E({h:(n%360+360)%360,c:r.c,t:r.t})}function T(t,n){const r=R(t);let e=r.h+n;return e=(e%360+360)%360,E({h:e,c:r.c,t:r.t})}function at(t){return T(t,180)}function st(t){return[t,T(t,120),T(t,240)]}function it(t,n=30){return[t,T(t,180-n),T(t,180+n)]}function ct(t,n=3,r=30){const e=[],o=-r*Math.floor(n/2);for(let a=0;a<n;a++)e.push(T(t,o+r*a));return e}function lt(t,n,r=.15){if(!t||!n)throw new Error("Both theme color and target color are required");const e=Math.max(0,Math.min(1,r));return z(n,t,e)}function ht(t,n){if(!t)throw new Error("Theme color is required");const r=R(t);let e;if(Array.isArray(n)?e=n:n&&n.tones&&Array.isArray(n.tones)?e=n.tones:e=[10,20,30,40,50,60,70,80,90],!Array.isArray(e)||e.length===0)throw new Error("Tone steps must be a non-empty array");const o=e.filter(a=>typeof a=="number"&&a>=0&&a<=100);if(o.length===0)throw new Error("No valid tone values found (must be numbers between 0-100)");return o.map(a=>E({h:r.h,c:r.c,t:a}))}function V(t,n,r=.2){if(!t)throw new Error("Theme color is required");if(!n||typeof n!="object")throw new Error("UI colors must be an object");const e=Math.max(0,Math.min(1,r)),o={};for(const[a,s]of Object.entries(n))try{o[a]=I(t,s,e)}catch(c){console.warn(`Failed to blend color for key "${a}": ${c.message}`),o[a]=s}return o}function q(t,n={}){if(!t)throw new Error("Theme color is required");const{baseGray:r="#989898",blendRatio:e=.08,isDark:o=!1,steps:a=12,lightnessRange:s=85,minLightness:c=null,maxLightness:i=null}=n,h=Math.max(0,Math.min(1,e)),m=Math.max(2,Math.min(100,Math.round(a))),u=I(r,t,h),l={steps:m,format:"hex"};if(c!==null&&i!==null)l.minLightness=c,l.maxLightness=i;else{const w=Math.max(20,Math.min(95,s));l.lightnessRange=w}const g=C(u,l),b=o?g.reverse():g,M={};return b.forEach((w,S)=>{M[`gray-${S+1}`]=w}),M}function P(t,n={}){if(!t)throw new Error("Theme color is required");const{semanticColors:r={success:"#52c41a",warning:"#faad14",error:"#ff4d4f",info:"#1890ff"},blendRatio:e=0,isDark:o=!1,steps:a=10,lightnessRange:s=80,minLightness:c=null,maxLightness:i=null}=n;if(!r||typeof r!="object")throw new Error("Semantic colors must be an object");const h=Math.max(0,Math.min(1,e)),m=Math.max(2,Math.min(100,Math.round(a))),u={};return Object.entries(r).forEach(([l,g])=>{if(!g||typeof g!="string"){console.warn(`Invalid color for semantic color "${l}": ${g}`);return}try{const b=I(g,t,h),M={steps:m,format:"hex"};if(c!==null&&i!==null)M.minLightness=c,M.maxLightness=i;else{const x=Math.max(20,Math.min(95,s));M.lightnessRange=x}const w=C(b,M);(o?w.reverse():w).forEach((x,p)=>{u[`${l}-${p+1}`]=x})}catch(b){console.warn(`Failed to generate variants for semantic color "${l}": ${b.message}`)}}),u}function O(t,n={}){if(!t)throw new Error("Theme color is required");const{isDark:r=!1,steps:e=10,lightnessRange:o=80,minLightness:a=null,maxLightness:s=null}=n,i={steps:Math.max(2,Math.min(100,Math.round(e))),format:"hex"};if(a!==null&&s!==null)i.minLightness=a,i.maxLightness=s;else{const l=Math.max(20,Math.min(95,o));i.lightnessRange=l}const h=C(t,i),m=r?h.reverse():h,u={};return m.forEach((l,g)=>{u[`theme-${g+1}`]=l}),u}function ut(t,n={}){if(!t)throw new Error("Theme color is required");const{baseGray:r="#666666",isDark:e=!1,semanticColors:o,controlBlendRatio:a=.08,semanticBlendRatio:s=.12,controlSteps:c=12,controlLightnessRange:i=85,controlMinLightness:h=null,controlMaxLightness:m=null,semanticSteps:u=10,semanticLightnessRange:l=80,semanticMinLightness:g=null,semanticMaxLightness:b=null,themeSteps:M=10,themeLightnessRange:w=80,themeMinLightness:S=null,themeMaxLightness:x=null}=n,p=Math.max(0,Math.min(1,a)),y=Math.max(0,Math.min(1,s)),L={baseGray:r,blendRatio:p,isDark:e,steps:c};h!==null&&m!==null?(L.minLightness=h,L.maxLightness=m):L.lightnessRange=i;const v={semanticColors:o,blendRatio:y,isDark:e,steps:u};g!==null&&b!==null?(v.minLightness=g,v.maxLightness=b):v.lightnessRange=l;const F={isDark:e,steps:M};return S!==null&&x!==null?(F.minLightness=S,F.maxLightness=x):F.lightnessRange=w,{controls:q(t,L),semantic:P(t,v),theme:O(t,F)}}function ft(t,n={}){if(!t)throw new Error("Theme color is required");const{semanticColors:r={success:"#52c41a",warning:"#faad14",error:"#ff4d4f",info:"#1890ff"},uiColors:e={background:"#ffffff",surface:"#fafafa",border:"#d9d9d9",disabled:"#f5f5f5"},harmonizeRatio:o=.15,blendRatio:a=.12,isDark:s=!1}=n,c=Math.max(0,Math.min(1,o)),i=Math.max(0,Math.min(1,a)),h=O(t,{isDark:s}),m=q(t,{blendRatio:i*.5,isDark:s}),u=P(t,{semanticColors:r,blendRatio:c,isDark:s}),l={};return Object.entries(r).forEach(([b])=>{l[b]={};for(let M=1;M<=10;M++){const w=`${b}-${M}`;u[w]&&(l[b][M]=u[w])}}),{theme:h,controls:m,semantic:l,ui:V(t,e,i)}}const H={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 mt(){const t={};return Object.keys(H).forEach(n=>{t[n]={},t[n].light=$(H[n],{list:!0}),t[n].dark=$(H[n],{list:!0,dark:!0}),t[n].primary=H[n]}),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.adjustChroma=rt,f.adjustHue=ot,f.adjustTone=et,f.blendInHct=I,f.blendUIColors=V,f.colorDifference=nt,f.colorList=H,f.extractColorFromFile=X,f.extractColorFromImage=k,f.generate=$,f.generateControlColors=q,f.generateGrayLinear=Y,f.generateInterfaceColorSystem=ut,f.generateLinear=A,f.generateLinearHSL=Z,f.generateMonochromeLinear=C,f.generateSemanticColors=P,f.generateThemeColors=O,f.generateThemePalette=ft,f.generateThemeVariants=ht,f.getAnalogous=ct,f.getComplementary=at,f.getPresetColors=mt,f.getRgbStr=N,f.getSplitComplementary=it,f.getTriadic=st,f.harmonizeColor=lt,f.hctToRgb=E,f.rgbToHct=R,f.rotateHue=T,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})});
1
+ (function(d,b){typeof exports=="object"&&typeof module<"u"?b(exports,require("color")):typeof define=="function"&&define.amd?define(["exports","color"],b):(d=typeof globalThis<"u"?globalThis:d||self,b(d.AvialaColor={},d.Color))})(this,function(d,b){"use strict";function J(t){return b(t).rgb().round().color.join(",")}const Q=["hex","rgb","hsl"];function X(t){return!t||!Q.includes(t)?"hex":t}function C(t,e){const r=X(e);return r==="hex"?t[r]().toLowerCase():t[r]().round().string()}function $(t,e,r){const n=b(t),a=n.hue(),o=n.saturationv(),s=n.value(),i=(p=>p>=60&&p<=240?2.5:p>=0&&p<60||p>300&&p<=360?1.5:2)(a),h=100,f=9,u=100,l=30;function m(p,y){let S;return a>=60&&a<=240?S=p?a-i*y:a+i*y:S=p?a+i*y:a-i*y,S<0?S+=360:S>=360&&(S-=360),Math.round(S)}function g(p,y){let S;if(p)S=o<=f?o:o-(o-f)/5.5*Math.pow(y,1.05);else{const H=Math.min(h,o+30);S=o+(H-o)/4.2*Math.pow(y,.95)}return Math.max(0,Math.min(100,S))}function w(p,y){return p?Math.min(u,s+(u-s)/5.2*Math.pow(y,.9)):s<=l?s:Math.max(l,s-(s-l)/4.2*Math.pow(y,1.05))}const M=e<6,L=M?6-e:e-6,x=e===6?n:b({h:m(M,L),s:g(M,L),v:w(M,L)});return C(x,r)}function G(t,e,r){const n=b($(t,10-e+1,"hex")),a=b(t),o=a.hue(),s=a.saturationv();function c(m){if(m<6)return h+(6-m)*u;if(m===6){if(o>=0&&o<50)return s-15;if(o>=50&&o<191)return s-20;if(o>=191&&o<=360)return s-15}return h-f*(m-6)}const h=b({h:a.hue(),s:c(6),v:a.value()}).saturationv(),f=Math.ceil((h-9)/4),u=Math.ceil((100-h)/5),l=b({h:n.hue(),s:c(e),v:n.value()});return C(l,r)}function q(t,e={}){const{dark:r,list:n,index:a=6,format:o="hex"}=e;if(n){const s=[],c=r?G:$;for(let i=1;i<=10;i++)s.push(c(t,i,o));return s}return r?G(t,a,o):$(t,a,o)}async function N(t){try{const e=await Y(t),r=Z(e);return _(r)}catch(e){throw console.error("提取图片颜色失败:",e),e}}async function Y(t){return new Promise((e,r)=>{try{if(typeof document>"u"){r(new Error("图像颜色提取功能仅在浏览器环境中可用"));return}const n=document.createElement("canvas"),a=n.getContext("2d");if(!a){r(new Error("无法获取canvas 2d context"));return}const o=Math.min(t.width,100),s=Math.min(t.height,100),c=Math.min(o/t.width,s/t.height);n.width=t.width*c,n.height=t.height*c,a.drawImage(t,0,0,n.width,n.height);const i=a.getImageData(0,0,n.width,n.height);e(i)}catch(n){r(n)}})}function Z(t){const e=t.data,r=new Map;for(let a=0;a<e.length;a+=4){const o=e[a],s=e[a+1],c=e[a+2];if(e[a+3]<128)continue;const h=Math.round(o/16)*16,f=Math.round(s/16)*16,u=Math.round(c/16)*16,l=`${h},${f},${u}`;r.has(l)?r.set(l,r.get(l)+1):r.set(l,1)}const n=[];return r.forEach((a,o)=>{const[s,c,i]=o.split(",").map(Number);n.push({r:s,g:c,b:i,count:a})}),n}function _(t){t.sort((a,o)=>o.count-a.count);const e=t.filter(a=>{const{r:o,g:s,b:c}=a,i=Math.max(o,s,c),h=Math.min(o,s,c),f=i-h,u=i===0?0:f/i,l=i/255;return u>.15&&l>.2&&l<.8}),r=e.length>0?e[0]:t[0];return b({r:r.r,g:r.g,b:r.b}).hex()}function tt(t){return new Promise((e,r)=>{if(typeof FileReader>"u"||typeof Image>"u"){r(new Error("文件读取功能仅在浏览器环境中可用"));return}if(!t.type.startsWith("image/")){r(new Error("请选择图片文件"));return}const n=new FileReader;n.onload=async a=>{var o;try{const s=new Image;s.onload=async()=>{try{const i=await N(s);e(i)}catch(i){r(i)}},s.onerror=()=>r(new Error("图片加载失败"));const c=(o=a.target)==null?void 0:o.result;typeof c=="string"?s.src=c:r(new Error("无法读取图片数据"))}catch(s){r(s)}},n.onerror=()=>r(new Error("文件读取失败")),n.readAsDataURL(t)})}function P(t,e,r={}){const{steps:n=10,format:a="hex",includeEnds:o=!0}=r;if(n<2)throw new Error("步数必须至少为2");const s=b(t),c=b(e),i=[],h=o?n:n+2,f=1/(h-1);for(let u=0;u<h;u++){const l=u*f,m=Math.round(s.red()+(c.red()-s.red())*l),g=Math.round(s.green()+(c.green()-s.green())*l),w=Math.round(s.blue()+(c.blue()-s.blue())*l),M=b({r:m,g,b:w});!o&&(u===0||u===h-1)||i.push(C(M,a))}return i}function et(t={}){const{startGray:e="#ffffff",endGray:r="#000000",steps:n=10,format:a="hex"}=t;return P(e,r,{steps:n,format:a,includeEnds:!0})}function T(t,e={}){const{steps:r=10,format:n="hex",lightnessRange:a=80,minLightness:o=null,maxLightness:s=null,preserveChroma:c=!1}=e,i=b(t);let h,f;if(o!==null&&s!==null){if(o>s)throw new Error("minLightness 不能大于 maxLightness");h=Math.max(0,Math.min(100,s)),f=Math.max(0,Math.min(100,o))}else{const m=i.lightness();h=Math.min(95,m+a/2),f=Math.max(5,m-a/2)}if(c)return nt(i,h,f,r,n);const u=b({h:i.hue(),s:i.saturationl(),l:h}),l=b({h:i.hue(),s:i.saturationl(),l:f});return P(u.hex(),l.hex(),{steps:r,format:n,includeEnds:!0})}function nt(t,e,r,n,a){const o=t.a(),s=t.b(),c=Math.sqrt(o*o+s*s),i=Math.atan2(s,o),h=[],f=(e-r)/(n-1);for(let u=0;u<n;u++){const l=e-f*u;let m=c;if(l>85){const p=Math.max(0,(100-l)/15);m=c*p}else if(l<15){const p=Math.max(0,l/15);m=c*p}const g=m*Math.cos(i),w=m*Math.sin(i);let M=b.lab(l,g,w),L=M.rgb().array(),x=m;for(;(L[0]<0||L[0]>255||L[1]<0||L[1]>255||L[2]<0||L[2]>255)&&x>0;){x-=1;const p=x*Math.cos(i),y=x*Math.sin(i);M=b.lab(l,p,y),L=M.rgb().array()}h.push(C(M,a))}return h}function rt(t,e,r={}){const{steps:n=10,format:a="hex",includeEnds:o=!0}=r;if(n<2)throw new Error("步数必须至少为2");const s=b(t),c=b(e),i=[],h=o?n:n+2,f=1/(h-1);let u=s.hue()||0,l=c.hue()||0;const m=l-u;Math.abs(m)>180&&(m>0?u+=360:l+=360);const g=s.saturationl(),w=c.saturationl(),M=s.lightness(),L=c.lightness();for(let x=0;x<h;x++){const p=x*f;let y=u+(l-u)*p;const S=g+(w-g)*p,H=M+(L-M)*p;y=y%360,y<0&&(y+=360);const k=b({h:y,s:S,l:H});!o&&(x===0||x===h-1)||i.push(C(k,a))}return i}function R(t){if(!t||typeof t!="string")throw new Error("Invalid RGB color: must be a string");let e;try{e=b(t)}catch{throw new Error("Invalid RGB color format")}const r=e.l(),n=e.a(),a=e.b();let o=Math.atan2(a,n)*(180/Math.PI);o<0&&(o+=360);const s=Math.sqrt(n*n+a*a);return{h:o,c:s,t:r}}function v(t,e={}){if(!t||typeof t!="object"||t.h===void 0||t.c===void 0||t.t===void 0)throw new Error("Invalid HCT color: must be an object with h, c, t properties");const{gamutMapping:r="reduce-chroma"}=e;let{h:n,c:a,t:o}=t;n=(n%360+360)%360,a=Math.max(0,a),o=Math.max(0,Math.min(100,o));const s=n*(Math.PI/180),c=a*Math.cos(s),i=a*Math.sin(s);try{let h=b.lab(o,c,i);if(r==="reduce-chroma"){let g=a,w=h.rgb().array();for(;(w[0]<0||w[0]>255||w[1]<0||w[1]>255||w[2]<0||w[2]>255)&&g>0;){g-=1;const M=g*Math.cos(s),L=g*Math.sin(s);h=b.lab(o,M,L),w=h.rgb().array()}}const f=h.rgb().array(),u=Math.max(0,Math.min(255,Math.round(f[0]))),l=Math.max(0,Math.min(255,Math.round(f[1]))),m=Math.max(0,Math.min(255,Math.round(f[2])));return`#${u.toString(16).padStart(2,"0")}${l.toString(16).padStart(2,"0")}${m.toString(16).padStart(2,"0")}`}catch{return b.lab(o,c,i).hex().toLowerCase()}}function B(t,e,r=.5,n={}){if(!t||!e)throw new Error("Both colors are required for blending");const{mode:a="lab"}=n,o=Math.max(0,Math.min(1,r));return a==="lab"?at(t,e,o):a==="hue-only"?V(t,e,o):ot(t,e,o)}function at(t,e,r){const n=b(t),a=b(e),o=n.l(),s=n.a(),c=n.b(),i=a.l(),h=a.a(),f=a.b(),u=o+(i-o)*r,l=s+(h-s)*r,m=c+(f-c)*r;return b.lab(u,l,m).hex().toLowerCase()}function ot(t,e,r){const n=R(t),a=R(e),o=U(n.h,a.h,r),s=n.c+(a.c-n.c)*r,c=n.t+(a.t-n.t)*r;return v({h:o,c:Math.max(0,s),t:Math.max(0,Math.min(100,c))})}function V(t,e,r){const n=R(t),a=R(e),o=U(n.h,a.h,r);return v({h:o,c:n.c,t:n.t})}function U(t,e,r){let n=e-t;n>180?n-=360:n<-180&&(n+=360);let a=t+n*r;return a<0&&(a+=360),a>=360&&(a-=360),a}function st(t,e){const r=b(t),n=b(e),a=r.l(),o=r.a(),s=r.b(),c=n.l(),i=n.a(),h=n.b();return Math.sqrt(Math.pow(c-a,2)+Math.pow(i-o,2)+Math.pow(h-s,2))}function it(t,e){const r=R(t);return v({h:r.h,c:r.c,t:Math.max(0,Math.min(100,e))})}function ct(t,e){const r=R(t);return v({h:r.h,c:Math.max(0,e),t:r.t})}function lt(t,e){const r=R(t);return v({h:(e%360+360)%360,c:r.c,t:r.t})}function E(t,e){const r=R(t);let n=r.h+e;return n=(n%360+360)%360,v({h:n,c:r.c,t:r.t})}function ht(t){return E(t,180)}function ut(t){return[t,E(t,120),E(t,240)]}function ft(t,e=30){return[t,E(t,180-e),E(t,180+e)]}function mt(t,e=3,r=30){const n=[],a=-r*Math.floor(e/2);for(let o=0;o<e;o++)n.push(E(t,a+r*o));return n}function dt(t,e,r=.15){if(!t||!e)throw new Error("Both theme color and target color are required");const n=Math.max(0,Math.min(1,r));return V(e,t,n)}function gt(t,e){if(!t)throw new Error("Theme color is required");const r=R(t);let n;if(Array.isArray(e)?n=e:e&&e.tones&&Array.isArray(e.tones)?n=e.tones:n=[10,20,30,40,50,60,70,80,90],!Array.isArray(n)||n.length===0)throw new Error("Tone steps must be a non-empty array");const a=n.filter(o=>typeof o=="number"&&o>=0&&o<=100);if(a.length===0)throw new Error("No valid tone values found (must be numbers between 0-100)");return a.map(o=>v({h:r.h,c:r.c,t:o}))}function K(t,e,r=.2){if(!t)throw new Error("Theme color is required");if(!e||typeof e!="object")throw new Error("UI colors must be an object");const n=Math.max(0,Math.min(1,r)),a={};for(const[o,s]of Object.entries(e))try{a[o]=B(t,s,n)}catch(c){console.warn(`Failed to blend color for key "${o}": ${c.message}`),a[o]=s}return a}function j(t,e={}){if(!t)throw new Error("Theme color is required");const{baseGray:r="#989898",blendRatio:n=.08,isDark:a=!1,steps:o=12,lightnessRange:s=85,minLightness:c=null,maxLightness:i=null}=e,h=Math.max(0,Math.min(1,n)),f=Math.max(2,Math.min(100,Math.round(o))),u=B(r,t,h),l={steps:f,format:"hex"};if(c!==null&&i!==null)l.minLightness=c,l.maxLightness=i;else{const M=Math.max(20,Math.min(95,s));l.lightnessRange=M}const m=T(u,l),g=a?m.reverse():m,w={};return g.forEach((M,L)=>{w[`gray-${L+1}`]=M}),w}function W(t,e={}){if(!t)throw new Error("Theme color is required");const{baseGray:r="#f5f5f5",blendRatio:n=.03,steps:a=6,minLightness:o=92,maxLightness:s=100,prefix:c="neutral"}=e,i=Math.max(0,Math.min(1,n)),h=Math.max(2,Math.min(20,Math.round(a))),f=Math.max(80,Math.min(99,o)),u=Math.max(f+1,Math.min(100,s)),l=B(r,t,i),m=T(l,{steps:h,format:"hex",minLightness:f,maxLightness:u}),g={};return m.forEach((w,M)=>{g[`${c}-${M+1}`]=w}),g}function O(t,e={}){if(!t)throw new Error("Theme color is required");const{semanticColors:r={success:"#52c41a",warning:"#faad14",error:"#ff4d4f",info:"#1890ff"},blendRatio:n=0,isDark:a=!1,steps:o=10,lightnessRange:s=80,minLightness:c=8,maxLightness:i=97,preserveChroma:h=!0}=e;if(!r||typeof r!="object")throw new Error("Semantic colors must be an object");const f=Math.max(0,Math.min(1,n)),u=Math.max(2,Math.min(100,Math.round(o))),l={};return Object.entries(r).forEach(([m,g])=>{if(!g||typeof g!="string"){console.warn(`Invalid color for semantic color "${m}": ${g}`);return}try{const w=B(g,t,f),M={steps:u,format:"hex",preserveChroma:h};if(c!==null&&i!==null)M.minLightness=c,M.maxLightness=i;else{const p=Math.max(20,Math.min(95,s));M.lightnessRange=p}const L=T(w,M);(a?L.reverse():L).forEach((p,y)=>{l[`${m}-${y+1}`]=p})}catch(w){console.warn(`Failed to generate variants for semantic color "${m}": ${w.message}`)}}),l}function z(t,e={}){if(!t)throw new Error("Theme color is required");const{isDark:r=!1,steps:n=10,lightnessRange:a=80,minLightness:o=8,maxLightness:s=97,preserveChroma:c=!0}=e,h={steps:Math.max(2,Math.min(100,Math.round(n))),format:"hex",preserveChroma:c};if(o!==null&&s!==null)h.minLightness=o,h.maxLightness=s;else{const m=Math.max(20,Math.min(95,a));h.lightnessRange=m}const f=T(t,h),u=r?f.reverse():f,l={};return u.forEach((m,g)=>{l[`theme-${g+1}`]=m}),l}function Mt(t,e={}){if(!t)throw new Error("Theme color is required");const{baseGray:r="#666666",isDark:n=!1,semanticColors:a,controlBlendRatio:o=.08,semanticBlendRatio:s=.12,controlSteps:c=12,controlLightnessRange:i=85,controlMinLightness:h=null,controlMaxLightness:f=null,semanticSteps:u=10,semanticLightnessRange:l=80,semanticMinLightness:m=null,semanticMaxLightness:g=null,semanticPreserveChroma:w=!0,themeSteps:M=10,themeLightnessRange:L=80,themeMinLightness:x=null,themeMaxLightness:p=null,themePreserveChroma:y=!0,neutralSteps:S=6,neutralMinLightness:H=92,neutralMaxLightness:k=100,neutralBlendRatio:pt=.03}=e,Lt=Math.max(0,Math.min(1,o)),yt=Math.max(0,Math.min(1,s)),D={baseGray:r,blendRatio:Lt,isDark:n,steps:c};h!==null&&f!==null?(D.minLightness=h,D.maxLightness=f):D.lightnessRange=i;const I={semanticColors:a,blendRatio:yt,isDark:n,steps:u,preserveChroma:w};m!==null&&g!==null?(I.minLightness=m,I.maxLightness=g):I.lightnessRange=l;const A={isDark:n,steps:M,preserveChroma:y};return x!==null&&p!==null?(A.minLightness=x,A.maxLightness=p):A.lightnessRange=L,{controls:j(t,D),neutrals:W(t,{blendRatio:pt,steps:S,minLightness:H,maxLightness:k}),semantic:O(t,I),theme:z(t,A)}}function bt(t,e={}){if(!t)throw new Error("Theme color is required");const{semanticColors:r={success:"#52c41a",warning:"#faad14",error:"#ff4d4f",info:"#1890ff"},uiColors:n={background:"#ffffff",surface:"#fafafa",border:"#d9d9d9",disabled:"#f5f5f5"},harmonizeRatio:a=.15,blendRatio:o=.12,isDark:s=!1}=e,c=Math.max(0,Math.min(1,a)),i=Math.max(0,Math.min(1,o)),h=z(t,{isDark:s}),f=j(t,{blendRatio:i*.5,isDark:s}),u=O(t,{semanticColors:r,blendRatio:c,isDark:s}),l={};return Object.entries(r).forEach(([g])=>{l[g]={};for(let w=1;w<=10;w++){const M=`${g}-${w}`;u[M]&&(l[g][w]=u[M])}}),{theme:h,controls:f,semantic:l,ui:K(t,n,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 wt(){const t={};return Object.keys(F).forEach(e=>{t[e]={},t[e].light=q(F[e],{list:!0}),t[e].dark=q(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}d.adjustChroma=ct,d.adjustHue=lt,d.adjustTone=it,d.blendInHct=B,d.blendUIColors=K,d.colorDifference=st,d.colorList=F,d.extractColorFromFile=tt,d.extractColorFromImage=N,d.generate=q,d.generateControlColors=j,d.generateGrayLinear=et,d.generateInterfaceColorSystem=Mt,d.generateLinear=P,d.generateLinearHSL=rt,d.generateMonochromeLinear=T,d.generateNeutralColors=W,d.generateSemanticColors=O,d.generateThemeColors=z,d.generateThemePalette=bt,d.generateThemeVariants=gt,d.getAnalogous=mt,d.getComplementary=ht,d.getPresetColors=wt,d.getRgbStr=J,d.getSplitComplementary=ft,d.getTriadic=ut,d.harmonizeColor=dt,d.hctToRgb=v,d.rgbToHct=R,d.rotateHue=E,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})});
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
- import g from "color";
2
- function Y(t) {
3
- return g(t).rgb().round().color.join(",");
1
+ import b from "color";
2
+ function st(t) {
3
+ return b(t).rgb().round().color.join(",");
4
4
  }
5
- const j = ["hex", "rgb", "hsl"];
6
- function G(t) {
7
- return !t || !j.includes(
5
+ const W = ["hex", "rgb", "hsl"];
6
+ function J(t) {
7
+ return !t || !W.includes(
8
8
  /** @type {any} */
9
9
  t
10
10
  ) ? "hex" : (
@@ -12,39 +12,39 @@ function G(t) {
12
12
  t
13
13
  );
14
14
  }
15
- function F(t, n) {
16
- const r = G(n);
15
+ function E(t, n) {
16
+ const r = J(n);
17
17
  return r === "hex" ? t[r]().toLowerCase() : t[r]().round().string();
18
18
  }
19
- function B(t, n, r) {
20
- const e = g(t), o = e.hue(), s = e.saturationv(), a = e.value(), c = ((b) => b >= 60 && b <= 240 ? 2.5 : b >= 0 && b < 60 || b > 300 && b <= 360 ? 1.5 : 2)(o), h = 100, f = 9, u = 100, l = 30;
21
- function m(b, w) {
22
- let x;
23
- return o >= 60 && o <= 240 ? x = b ? o - c * w : o + c * w : x = b ? o + c * w : o - c * w, x < 0 ? x += 360 : x >= 360 && (x -= 360), Math.round(x);
19
+ function T(t, n, r) {
20
+ const e = b(t), o = e.hue(), s = e.saturationv(), a = e.value(), i = ((p) => p >= 60 && p <= 240 ? 2.5 : p >= 0 && p < 60 || p > 300 && p <= 360 ? 1.5 : 2)(o), h = 100, f = 9, u = 100, l = 30;
21
+ function m(p, x) {
22
+ let y;
23
+ return o >= 60 && o <= 240 ? y = p ? o - i * x : o + i * x : y = p ? o + i * x : o - i * x, y < 0 ? y += 360 : y >= 360 && (y -= 360), Math.round(y);
24
24
  }
25
- function M(b, w) {
26
- let x;
27
- if (b)
28
- x = s <= f ? s : s - (s - f) / 5.5 * Math.pow(w, 1.05);
25
+ function d(p, x) {
26
+ let y;
27
+ if (p)
28
+ y = s <= f ? s : s - (s - f) / 5.5 * Math.pow(x, 1.05);
29
29
  else {
30
- const S = Math.min(h, s + 30);
31
- x = s + (S - s) / 4.2 * Math.pow(w, 0.95);
30
+ const v = Math.min(h, s + 30);
31
+ y = s + (v - s) / 4.2 * Math.pow(x, 0.95);
32
32
  }
33
- return Math.max(0, Math.min(100, x));
33
+ return Math.max(0, Math.min(100, y));
34
34
  }
35
- function d(b, w) {
36
- return b ? Math.min(u, a + (u - a) / 5.2 * Math.pow(w, 0.9)) : a <= l ? a : Math.max(l, a - (a - l) / 4.2 * Math.pow(w, 1.05));
35
+ function M(p, x) {
36
+ return p ? Math.min(u, a + (u - a) / 5.2 * Math.pow(x, 0.9)) : a <= l ? a : Math.max(l, a - (a - l) / 4.2 * Math.pow(x, 1.05));
37
37
  }
38
- const p = n < 6, L = p ? 6 - n : n - 6, y = n === 6 ? e : g({
39
- h: m(p, L),
40
- s: M(p, L),
41
- v: d(p, L)
38
+ const g = n < 6, w = g ? 6 - n : n - 6, L = n === 6 ? e : b({
39
+ h: m(g, w),
40
+ s: d(g, w),
41
+ v: M(g, w)
42
42
  });
43
- return F(y, r);
43
+ return E(L, r);
44
44
  }
45
- function T(t, n, r) {
46
- const e = g(B(t, 10 - n + 1, "hex")), o = g(t), s = o.hue(), a = o.saturationv();
47
- function i(m) {
45
+ function q(t, n, r) {
46
+ const e = b(T(t, 10 - n + 1, "hex")), o = b(t), s = o.hue(), a = o.saturationv();
47
+ function c(m) {
48
48
  if (m < 6)
49
49
  return h + (6 - m) * u;
50
50
  if (m === 6) {
@@ -57,36 +57,36 @@ function T(t, n, r) {
57
57
  }
58
58
  return h - f * (m - 6);
59
59
  }
60
- const h = g({
60
+ const h = b({
61
61
  h: o.hue(),
62
- s: i(6),
62
+ s: c(6),
63
63
  v: o.value()
64
- }).saturationv(), f = Math.ceil((h - 9) / 4), u = Math.ceil((100 - h) / 5), l = g({
64
+ }).saturationv(), f = Math.ceil((h - 9) / 4), u = Math.ceil((100 - h) / 5), l = b({
65
65
  h: e.hue(),
66
- s: i(n),
66
+ s: c(n),
67
67
  v: e.value()
68
68
  });
69
- return F(l, r);
69
+ return E(l, r);
70
70
  }
71
- function $(t, n = {}) {
71
+ function P(t, n = {}) {
72
72
  const { dark: r, list: e, index: o = 6, format: s = "hex" } = n;
73
73
  if (e) {
74
- const a = [], i = r ? T : B;
75
- for (let c = 1; c <= 10; c++)
76
- a.push(i(t, c, s));
74
+ const a = [], c = r ? q : T;
75
+ for (let i = 1; i <= 10; i++)
76
+ a.push(c(t, i, s));
77
77
  return a;
78
78
  }
79
- return r ? T(t, o, s) : B(t, o, s);
79
+ return r ? q(t, o, s) : T(t, o, s);
80
80
  }
81
- async function N(t) {
81
+ async function Q(t) {
82
82
  try {
83
- const n = await V(t), r = U(n);
84
- return K(r);
83
+ const n = await X(t), r = Y(n);
84
+ return Z(r);
85
85
  } catch (n) {
86
86
  throw console.error("提取图片颜色失败:", n), n;
87
87
  }
88
88
  }
89
- async function V(t) {
89
+ async function X(t) {
90
90
  return new Promise((n, r) => {
91
91
  try {
92
92
  if (typeof document > "u") {
@@ -98,38 +98,38 @@ async function V(t) {
98
98
  r(new Error("无法获取canvas 2d context"));
99
99
  return;
100
100
  }
101
- const s = Math.min(t.width, 100), a = Math.min(t.height, 100), i = Math.min(s / t.width, a / t.height);
102
- e.width = t.width * i, e.height = t.height * i, o.drawImage(t, 0, 0, e.width, e.height);
103
- const c = o.getImageData(0, 0, e.width, e.height);
104
- n(c);
101
+ const s = Math.min(t.width, 100), a = Math.min(t.height, 100), c = Math.min(s / t.width, a / t.height);
102
+ e.width = t.width * c, e.height = t.height * c, o.drawImage(t, 0, 0, e.width, e.height);
103
+ const i = o.getImageData(0, 0, e.width, e.height);
104
+ n(i);
105
105
  } catch (e) {
106
106
  r(e);
107
107
  }
108
108
  });
109
109
  }
110
- function U(t) {
110
+ function Y(t) {
111
111
  const n = t.data, r = /* @__PURE__ */ new Map();
112
112
  for (let o = 0; o < n.length; o += 4) {
113
- const s = n[o], a = n[o + 1], i = n[o + 2];
113
+ const s = n[o], a = n[o + 1], c = n[o + 2];
114
114
  if (n[o + 3] < 128) continue;
115
- const h = Math.round(s / 16) * 16, f = Math.round(a / 16) * 16, u = Math.round(i / 16) * 16, l = `${h},${f},${u}`;
115
+ const h = Math.round(s / 16) * 16, f = Math.round(a / 16) * 16, u = Math.round(c / 16) * 16, l = `${h},${f},${u}`;
116
116
  r.has(l) ? r.set(l, r.get(l) + 1) : r.set(l, 1);
117
117
  }
118
118
  const e = [];
119
119
  return r.forEach((o, s) => {
120
- const [a, i, c] = s.split(",").map(Number);
121
- e.push({ r: a, g: i, b: c, count: o });
120
+ const [a, c, i] = s.split(",").map(Number);
121
+ e.push({ r: a, g: c, b: i, count: o });
122
122
  }), e;
123
123
  }
124
- function K(t) {
124
+ function Z(t) {
125
125
  t.sort((o, s) => s.count - o.count);
126
126
  const n = t.filter((o) => {
127
- const { r: s, g: a, b: i } = o, c = Math.max(s, a, i), h = Math.min(s, a, i), f = c - h, u = c === 0 ? 0 : f / c, l = c / 255;
127
+ const { r: s, g: a, b: c } = o, i = Math.max(s, a, c), h = Math.min(s, a, c), f = i - h, u = i === 0 ? 0 : f / i, l = i / 255;
128
128
  return u > 0.15 && l > 0.2 && l < 0.8;
129
129
  }), r = n.length > 0 ? n[0] : t[0];
130
- return g({ r: r.r, g: r.g, b: r.b }).hex();
130
+ return b({ r: r.r, g: r.g, b: r.b }).hex();
131
131
  }
132
- function Z(t) {
132
+ function at(t) {
133
133
  return new Promise((n, r) => {
134
134
  if (typeof FileReader > "u" || typeof Image > "u") {
135
135
  r(new Error("文件读取功能仅在浏览器环境中可用"));
@@ -146,93 +146,119 @@ function Z(t) {
146
146
  const a = new Image();
147
147
  a.onload = async () => {
148
148
  try {
149
- const c = await N(a);
150
- n(c);
151
- } catch (c) {
152
- r(c);
149
+ const i = await Q(a);
150
+ n(i);
151
+ } catch (i) {
152
+ r(i);
153
153
  }
154
154
  }, a.onerror = () => r(new Error("图片加载失败"));
155
- const i = (s = o.target) == null ? void 0 : s.result;
156
- typeof i == "string" ? a.src = i : r(new Error("无法读取图片数据"));
155
+ const c = (s = o.target) == null ? void 0 : s.result;
156
+ typeof c == "string" ? a.src = c : r(new Error("无法读取图片数据"));
157
157
  } catch (a) {
158
158
  r(a);
159
159
  }
160
160
  }, e.onerror = () => r(new Error("文件读取失败")), e.readAsDataURL(t);
161
161
  });
162
162
  }
163
- function q(t, n, r = {}) {
163
+ function O(t, n, r = {}) {
164
164
  const { steps: e = 10, format: o = "hex", includeEnds: s = !0 } = r;
165
165
  if (e < 2)
166
166
  throw new Error("步数必须至少为2");
167
- const a = g(t), i = g(n), c = [], h = s ? e : e + 2, f = 1 / (h - 1);
167
+ const a = b(t), c = b(n), i = [], h = s ? e : e + 2, f = 1 / (h - 1);
168
168
  for (let u = 0; u < h; u++) {
169
- const l = u * f, m = Math.round(a.red() + (i.red() - a.red()) * l), M = Math.round(a.green() + (i.green() - a.green()) * l), d = Math.round(a.blue() + (i.blue() - a.blue()) * l), p = g({ r: m, g: M, b: d });
170
- !s && (u === 0 || u === h - 1) || c.push(F(p, o));
169
+ const l = u * f, m = Math.round(a.red() + (c.red() - a.red()) * l), d = Math.round(a.green() + (c.green() - a.green()) * l), M = Math.round(a.blue() + (c.blue() - a.blue()) * l), g = b({ r: m, g: d, b: M });
170
+ !s && (u === 0 || u === h - 1) || i.push(E(g, o));
171
171
  }
172
- return c;
172
+ return i;
173
173
  }
174
- function _(t = {}) {
174
+ function it(t = {}) {
175
175
  const {
176
176
  startGray: n = "#ffffff",
177
177
  endGray: r = "#000000",
178
178
  steps: e = 10,
179
179
  format: o = "hex"
180
180
  } = t;
181
- return q(n, r, { steps: e, format: o, includeEnds: !0 });
181
+ return O(n, r, { steps: e, format: o, includeEnds: !0 });
182
182
  }
183
- function H(t, n = {}) {
183
+ function I(t, n = {}) {
184
184
  const {
185
185
  steps: r = 10,
186
186
  format: e = "hex",
187
187
  lightnessRange: o = 80,
188
188
  minLightness: s = null,
189
- maxLightness: a = null
190
- } = n, i = g(t);
191
- let c, h;
189
+ maxLightness: a = null,
190
+ preserveChroma: c = !1
191
+ } = n, i = b(t);
192
+ let h, f;
192
193
  if (s !== null && a !== null) {
193
194
  if (s > a)
194
195
  throw new Error("minLightness 不能大于 maxLightness");
195
- c = Math.max(0, Math.min(100, a)), h = Math.max(0, Math.min(100, s));
196
+ h = Math.max(0, Math.min(100, a)), f = Math.max(0, Math.min(100, s));
196
197
  } else {
197
- const l = i.lightness();
198
- c = Math.min(95, l + o / 2), h = Math.max(5, l - o / 2);
198
+ const m = i.lightness();
199
+ h = Math.min(95, m + o / 2), f = Math.max(5, m - o / 2);
199
200
  }
200
- const f = g({
201
+ if (c)
202
+ return _(i, h, f, r, e);
203
+ const u = b({
201
204
  h: i.hue(),
202
205
  s: i.saturationl(),
203
- l: c
204
- }), u = g({
206
+ l: h
207
+ }), l = b({
205
208
  h: i.hue(),
206
209
  s: i.saturationl(),
207
- l: h
210
+ l: f
208
211
  });
209
- return q(f.hex(), u.hex(), { steps: r, format: e, includeEnds: !0 });
212
+ return O(u.hex(), l.hex(), { steps: r, format: e, includeEnds: !0 });
213
+ }
214
+ function _(t, n, r, e, o) {
215
+ const s = t.a(), a = t.b(), c = Math.sqrt(s * s + a * a), i = Math.atan2(a, s), h = [], f = (n - r) / (e - 1);
216
+ for (let u = 0; u < e; u++) {
217
+ const l = n - f * u;
218
+ let m = c;
219
+ if (l > 85) {
220
+ const p = Math.max(0, (100 - l) / 15);
221
+ m = c * p;
222
+ } else if (l < 15) {
223
+ const p = Math.max(0, l / 15);
224
+ m = c * p;
225
+ }
226
+ const d = m * Math.cos(i), M = m * Math.sin(i);
227
+ let g = b.lab(l, d, M), w = g.rgb().array(), L = m;
228
+ for (; (w[0] < 0 || w[0] > 255 || w[1] < 0 || w[1] > 255 || w[2] < 0 || w[2] > 255) && L > 0; ) {
229
+ L -= 1;
230
+ const p = L * Math.cos(i), x = L * Math.sin(i);
231
+ g = b.lab(l, p, x), w = g.rgb().array();
232
+ }
233
+ h.push(E(g, o));
234
+ }
235
+ return h;
210
236
  }
211
- function tt(t, n, r = {}) {
237
+ function ct(t, n, r = {}) {
212
238
  const { steps: e = 10, format: o = "hex", includeEnds: s = !0 } = r;
213
239
  if (e < 2)
214
240
  throw new Error("步数必须至少为2");
215
- const a = g(t), i = g(n), c = [], h = s ? e : e + 2, f = 1 / (h - 1);
216
- let u = a.hue() || 0, l = i.hue() || 0;
241
+ const a = b(t), c = b(n), i = [], h = s ? e : e + 2, f = 1 / (h - 1);
242
+ let u = a.hue() || 0, l = c.hue() || 0;
217
243
  const m = l - u;
218
244
  Math.abs(m) > 180 && (m > 0 ? u += 360 : l += 360);
219
- const M = a.saturationl(), d = i.saturationl(), p = a.lightness(), L = i.lightness();
220
- for (let y = 0; y < h; y++) {
221
- const b = y * f;
222
- let w = u + (l - u) * b;
223
- const x = M + (d - M) * b, S = p + (L - p) * b;
224
- w = w % 360, w < 0 && (w += 360);
225
- const C = g({ h: w, s: x, l: S });
226
- !s && (y === 0 || y === h - 1) || c.push(F(C, o));
245
+ const d = a.saturationl(), M = c.saturationl(), g = a.lightness(), w = c.lightness();
246
+ for (let L = 0; L < h; L++) {
247
+ const p = L * f;
248
+ let x = u + (l - u) * p;
249
+ const y = d + (M - d) * p, v = g + (w - g) * p;
250
+ x = x % 360, x < 0 && (x += 360);
251
+ const A = b({ h: x, s: y, l: v });
252
+ !s && (L === 0 || L === h - 1) || i.push(E(A, o));
227
253
  }
228
- return c;
254
+ return i;
229
255
  }
230
256
  function R(t) {
231
257
  if (!t || typeof t != "string")
232
258
  throw new Error("Invalid RGB color: must be a string");
233
259
  let n;
234
260
  try {
235
- n = g(t);
261
+ n = b(t);
236
262
  } catch {
237
263
  throw new Error("Invalid RGB color format");
238
264
  }
@@ -246,50 +272,50 @@ function R(t) {
246
272
  t: r
247
273
  };
248
274
  }
249
- function E(t, n = {}) {
275
+ function C(t, n = {}) {
250
276
  if (!t || typeof t != "object" || t.h === void 0 || t.c === void 0 || t.t === void 0)
251
277
  throw new Error("Invalid HCT color: must be an object with h, c, t properties");
252
278
  const { gamutMapping: r = "reduce-chroma" } = n;
253
279
  let { h: e, c: o, t: s } = t;
254
280
  e = (e % 360 + 360) % 360, o = Math.max(0, o), s = Math.max(0, Math.min(100, s));
255
- const a = e * (Math.PI / 180), i = o * Math.cos(a), c = o * Math.sin(a);
281
+ const a = e * (Math.PI / 180), c = o * Math.cos(a), i = o * Math.sin(a);
256
282
  try {
257
- let h = g.lab(s, i, c);
283
+ let h = b.lab(s, c, i);
258
284
  if (r === "reduce-chroma") {
259
- let M = o, d = h.rgb().array();
260
- for (; (d[0] < 0 || d[0] > 255 || d[1] < 0 || d[1] > 255 || d[2] < 0 || d[2] > 255) && M > 0; ) {
261
- M -= 1;
262
- const p = M * Math.cos(a), L = M * Math.sin(a);
263
- h = g.lab(s, p, L), d = h.rgb().array();
285
+ let d = o, M = h.rgb().array();
286
+ for (; (M[0] < 0 || M[0] > 255 || M[1] < 0 || M[1] > 255 || M[2] < 0 || M[2] > 255) && d > 0; ) {
287
+ d -= 1;
288
+ const g = d * Math.cos(a), w = d * Math.sin(a);
289
+ h = b.lab(s, g, w), M = h.rgb().array();
264
290
  }
265
291
  }
266
292
  const f = h.rgb().array(), u = Math.max(0, Math.min(255, Math.round(f[0]))), l = Math.max(0, Math.min(255, Math.round(f[1]))), m = Math.max(0, Math.min(255, Math.round(f[2])));
267
293
  return `#${u.toString(16).padStart(2, "0")}${l.toString(16).padStart(2, "0")}${m.toString(16).padStart(2, "0")}`;
268
294
  } catch {
269
- return g.lab(s, i, c).hex().toLowerCase();
295
+ return b.lab(s, c, i).hex().toLowerCase();
270
296
  }
271
297
  }
272
- function I(t, n, r = 0.5, e = {}) {
298
+ function $(t, n, r = 0.5, e = {}) {
273
299
  if (!t || !n)
274
300
  throw new Error("Both colors are required for blending");
275
301
  const { mode: o = "lab" } = e, s = Math.max(0, Math.min(1, r));
276
- return o === "lab" ? W(t, n, s) : o === "hue-only" ? A(t, n, s) : J(t, n, s);
302
+ return o === "lab" ? tt(t, n, s) : o === "hue-only" ? j(t, n, s) : nt(t, n, s);
277
303
  }
278
- function W(t, n, r) {
279
- const e = g(t), o = g(n), s = e.l(), a = e.a(), i = e.b(), c = o.l(), h = o.a(), f = o.b(), u = s + (c - s) * r, l = a + (h - a) * r, m = i + (f - i) * r;
280
- return g.lab(u, l, m).hex().toLowerCase();
304
+ function tt(t, n, r) {
305
+ const e = b(t), o = b(n), s = e.l(), a = e.a(), c = e.b(), i = o.l(), h = o.a(), f = o.b(), u = s + (i - s) * r, l = a + (h - a) * r, m = c + (f - c) * r;
306
+ return b.lab(u, l, m).hex().toLowerCase();
281
307
  }
282
- function J(t, n, r) {
283
- const e = R(t), o = R(n), s = O(e.h, o.h, r), a = e.c + (o.c - e.c) * r, i = e.t + (o.t - e.t) * r;
284
- return E({
308
+ function nt(t, n, r) {
309
+ const e = R(t), o = R(n), s = k(e.h, o.h, r), a = e.c + (o.c - e.c) * r, c = e.t + (o.t - e.t) * r;
310
+ return C({
285
311
  h: s,
286
312
  c: Math.max(0, a),
287
- t: Math.max(0, Math.min(100, i))
313
+ t: Math.max(0, Math.min(100, c))
288
314
  });
289
315
  }
290
- function A(t, n, r) {
291
- const e = R(t), o = R(n), s = O(e.h, o.h, r);
292
- return E({
316
+ function j(t, n, r) {
317
+ const e = R(t), o = R(n), s = k(e.h, o.h, r);
318
+ return C({
293
319
  h: s,
294
320
  c: e.c,
295
321
  // 保持第一个颜色的色度
@@ -297,81 +323,81 @@ function A(t, n, r) {
297
323
  // 保持第一个颜色的明度
298
324
  });
299
325
  }
300
- function O(t, n, r) {
326
+ function k(t, n, r) {
301
327
  let e = n - t;
302
328
  e > 180 ? e -= 360 : e < -180 && (e += 360);
303
329
  let o = t + e * r;
304
330
  return o < 0 && (o += 360), o >= 360 && (o -= 360), o;
305
331
  }
306
- function nt(t, n) {
307
- const r = g(t), e = g(n), o = r.l(), s = r.a(), a = r.b(), i = e.l(), c = e.a(), h = e.b();
332
+ function lt(t, n) {
333
+ const r = b(t), e = b(n), o = r.l(), s = r.a(), a = r.b(), c = e.l(), i = e.a(), h = e.b();
308
334
  return Math.sqrt(
309
- Math.pow(i - o, 2) + Math.pow(c - s, 2) + Math.pow(h - a, 2)
335
+ Math.pow(c - o, 2) + Math.pow(i - s, 2) + Math.pow(h - a, 2)
310
336
  );
311
337
  }
312
- function et(t, n) {
338
+ function ht(t, n) {
313
339
  const r = R(t);
314
- return E({
340
+ return C({
315
341
  h: r.h,
316
342
  c: r.c,
317
343
  t: Math.max(0, Math.min(100, n))
318
344
  });
319
345
  }
320
- function rt(t, n) {
346
+ function ut(t, n) {
321
347
  const r = R(t);
322
- return E({
348
+ return C({
323
349
  h: r.h,
324
350
  c: Math.max(0, n),
325
351
  t: r.t
326
352
  });
327
353
  }
328
- function ot(t, n) {
354
+ function ft(t, n) {
329
355
  const r = R(t);
330
- return E({
356
+ return C({
331
357
  h: (n % 360 + 360) % 360,
332
358
  c: r.c,
333
359
  t: r.t
334
360
  });
335
361
  }
336
- function v(t, n) {
362
+ function S(t, n) {
337
363
  const r = R(t);
338
364
  let e = r.h + n;
339
- return e = (e % 360 + 360) % 360, E({
365
+ return e = (e % 360 + 360) % 360, C({
340
366
  h: e,
341
367
  c: r.c,
342
368
  t: r.t
343
369
  });
344
370
  }
345
- function st(t) {
346
- return v(t, 180);
371
+ function mt(t) {
372
+ return S(t, 180);
347
373
  }
348
- function at(t) {
374
+ function dt(t) {
349
375
  return [
350
376
  t,
351
- v(t, 120),
352
- v(t, 240)
377
+ S(t, 120),
378
+ S(t, 240)
353
379
  ];
354
380
  }
355
- function ct(t, n = 30) {
381
+ function gt(t, n = 30) {
356
382
  return [
357
383
  t,
358
- v(t, 180 - n),
359
- v(t, 180 + n)
384
+ S(t, 180 - n),
385
+ S(t, 180 + n)
360
386
  ];
361
387
  }
362
- function it(t, n = 3, r = 30) {
388
+ function Mt(t, n = 3, r = 30) {
363
389
  const e = [], o = -r * Math.floor(n / 2);
364
390
  for (let s = 0; s < n; s++)
365
- e.push(v(t, o + r * s));
391
+ e.push(S(t, o + r * s));
366
392
  return e;
367
393
  }
368
- function lt(t, n, r = 0.15) {
394
+ function pt(t, n, r = 0.15) {
369
395
  if (!t || !n)
370
396
  throw new Error("Both theme color and target color are required");
371
397
  const e = Math.max(0, Math.min(1, r));
372
- return A(n, t, e);
398
+ return j(n, t, e);
373
399
  }
374
- function ht(t, n) {
400
+ function bt(t, n) {
375
401
  if (!t)
376
402
  throw new Error("Theme color is required");
377
403
  const r = R(t);
@@ -381,13 +407,13 @@ function ht(t, n) {
381
407
  const o = e.filter((s) => typeof s == "number" && s >= 0 && s <= 100);
382
408
  if (o.length === 0)
383
409
  throw new Error("No valid tone values found (must be numbers between 0-100)");
384
- return o.map((s) => E({
410
+ return o.map((s) => C({
385
411
  h: r.h,
386
412
  c: r.c,
387
413
  t: s
388
414
  }));
389
415
  }
390
- function Q(t, n, r = 0.2) {
416
+ function et(t, n, r = 0.2) {
391
417
  if (!t)
392
418
  throw new Error("Theme color is required");
393
419
  if (!n || typeof n != "object")
@@ -395,14 +421,14 @@ function Q(t, n, r = 0.2) {
395
421
  const e = Math.max(0, Math.min(1, r)), o = {};
396
422
  for (const [s, a] of Object.entries(n))
397
423
  try {
398
- o[s] = I(t, a, e);
399
- } catch (i) {
424
+ o[s] = $(t, a, e);
425
+ } catch (c) {
400
426
  console.warn(`Failed to blend color for key "${s}": ${/** @type {Error} */
401
- i.message}`), o[s] = a;
427
+ c.message}`), o[s] = a;
402
428
  }
403
429
  return o;
404
430
  }
405
- function P(t, n = {}) {
431
+ function z(t, n = {}) {
406
432
  if (!t)
407
433
  throw new Error("Theme color is required");
408
434
  const {
@@ -413,26 +439,52 @@ function P(t, n = {}) {
413
439
  // 默认 12 个等级,可以增加到 24、36 等以获得更细腻的梯度
414
440
  lightnessRange: a = 85,
415
441
  // 亮度变化范围(中心扩展模式),默认 85
416
- minLightness: i = null,
442
+ minLightness: c = null,
417
443
  // 最小亮度(固定端点模式),优先级高于 lightnessRange
418
- maxLightness: c = null
444
+ maxLightness: i = null
419
445
  // 最大亮度(固定端点模式),优先级高于 lightnessRange
420
- } = n, h = Math.max(0, Math.min(1, e)), f = Math.max(2, Math.min(100, Math.round(s))), u = I(r, t, h), l = {
446
+ } = n, h = Math.max(0, Math.min(1, e)), f = Math.max(2, Math.min(100, Math.round(s))), u = $(r, t, h), l = {
421
447
  steps: f,
422
448
  format: "hex"
423
449
  };
424
- if (i !== null && c !== null)
425
- l.minLightness = i, l.maxLightness = c;
450
+ if (c !== null && i !== null)
451
+ l.minLightness = c, l.maxLightness = i;
426
452
  else {
427
- const p = Math.max(20, Math.min(95, a));
428
- l.lightnessRange = p;
453
+ const g = Math.max(20, Math.min(95, a));
454
+ l.lightnessRange = g;
429
455
  }
430
- const m = H(u, l), M = o ? m.reverse() : m, d = {};
431
- return M.forEach((p, L) => {
432
- d[`gray-${L + 1}`] = p;
456
+ const m = I(u, l), d = o ? m.reverse() : m, M = {};
457
+ return d.forEach((g, w) => {
458
+ M[`gray-${w + 1}`] = g;
459
+ }), M;
460
+ }
461
+ function rt(t, n = {}) {
462
+ if (!t)
463
+ throw new Error("Theme color is required");
464
+ const {
465
+ baseGray: r = "#f5f5f5",
466
+ // 使用浅灰作为基础,比控件色更浅
467
+ blendRatio: e = 0.03,
468
+ // 较低的混合比例,保持中性但带有品牌色调
469
+ steps: o = 6,
470
+ // 默认 6 个等级
471
+ minLightness: s = 92,
472
+ // 最深的浅灰亮度
473
+ maxLightness: a = 100,
474
+ // 最浅接近白色
475
+ prefix: c = "neutral"
476
+ // 颜色名称前缀
477
+ } = n, i = Math.max(0, Math.min(1, e)), h = Math.max(2, Math.min(20, Math.round(o))), f = Math.max(80, Math.min(99, s)), u = Math.max(f + 1, Math.min(100, a)), l = $(r, t, i), m = I(l, {
478
+ steps: h,
479
+ format: "hex",
480
+ minLightness: f,
481
+ maxLightness: u
482
+ }), d = {};
483
+ return m.forEach((M, g) => {
484
+ d[`${c}-${g + 1}`] = M;
433
485
  }), d;
434
486
  }
435
- function k(t, n = {}) {
487
+ function G(t, n = {}) {
436
488
  if (!t)
437
489
  throw new Error("Theme color is required");
438
490
  const {
@@ -448,41 +500,45 @@ function k(t, n = {}) {
448
500
  // 默认生成 10 个色阶
449
501
  lightnessRange: a = 80,
450
502
  // 亮度变化范围(中心扩展模式)
451
- minLightness: i = null,
452
- // 最小亮度(固定端点模式)
453
- maxLightness: c = null
454
- // 最大亮度(固定端点模式)
503
+ minLightness: c = 8,
504
+ // 最小亮度(固定端点模式)- 默认接近黑色
505
+ maxLightness: i = 97,
506
+ // 最大亮度(固定端点模式)- 默认接近白色
507
+ preserveChroma: h = !0
508
+ // 默认保持色度,避免灰蒙蒙
455
509
  } = n;
456
510
  if (!r || typeof r != "object")
457
511
  throw new Error("Semantic colors must be an object");
458
- const h = Math.max(0, Math.min(1, e)), f = Math.max(2, Math.min(100, Math.round(s))), u = {};
459
- return Object.entries(r).forEach(([l, m]) => {
460
- if (!m || typeof m != "string") {
461
- console.warn(`Invalid color for semantic color "${l}": ${m}`);
512
+ const f = Math.max(0, Math.min(1, e)), u = Math.max(2, Math.min(100, Math.round(s))), l = {};
513
+ return Object.entries(r).forEach(([m, d]) => {
514
+ if (!d || typeof d != "string") {
515
+ console.warn(`Invalid color for semantic color "${m}": ${d}`);
462
516
  return;
463
517
  }
464
518
  try {
465
- const M = I(m, t, h), d = {
466
- steps: f,
467
- format: "hex"
519
+ const M = $(d, t, f), g = {
520
+ steps: u,
521
+ format: "hex",
522
+ preserveChroma: h
523
+ // 保持色度,避免灰蒙蒙
468
524
  };
469
- if (i !== null && c !== null)
470
- d.minLightness = i, d.maxLightness = c;
525
+ if (c !== null && i !== null)
526
+ g.minLightness = c, g.maxLightness = i;
471
527
  else {
472
- const y = Math.max(20, Math.min(95, a));
473
- d.lightnessRange = y;
528
+ const p = Math.max(20, Math.min(95, a));
529
+ g.lightnessRange = p;
474
530
  }
475
- const p = H(M, d);
476
- (o ? p.reverse() : p).forEach((y, b) => {
477
- u[`${l}-${b + 1}`] = y;
531
+ const w = I(M, g);
532
+ (o ? w.reverse() : w).forEach((p, x) => {
533
+ l[`${m}-${x + 1}`] = p;
478
534
  });
479
535
  } catch (M) {
480
- console.warn(`Failed to generate variants for semantic color "${l}": ${/** @type {Error} */
536
+ console.warn(`Failed to generate variants for semantic color "${m}": ${/** @type {Error} */
481
537
  M.message}`);
482
538
  }
483
- }), u;
539
+ }), l;
484
540
  }
485
- function z(t, n = {}) {
541
+ function N(t, n = {}) {
486
542
  if (!t)
487
543
  throw new Error("Theme color is required");
488
544
  const {
@@ -491,26 +547,29 @@ function z(t, n = {}) {
491
547
  // 默认生成 10 个色阶
492
548
  lightnessRange: o = 80,
493
549
  // 亮度变化范围(中心扩展模式)
494
- minLightness: s = null,
495
- // 最小亮度(固定端点模式)
496
- maxLightness: a = null
497
- // 最大亮度(固定端点模式)
498
- } = n, c = {
550
+ minLightness: s = 8,
551
+ // 最小亮度(固定端点模式)- 默认接近黑色
552
+ maxLightness: a = 97,
553
+ // 最大亮度(固定端点模式)- 默认接近白色
554
+ preserveChroma: c = !0
555
+ // 默认保持色度
556
+ } = n, h = {
499
557
  steps: Math.max(2, Math.min(100, Math.round(e))),
500
- format: "hex"
558
+ format: "hex",
559
+ preserveChroma: c
501
560
  };
502
561
  if (s !== null && a !== null)
503
- c.minLightness = s, c.maxLightness = a;
562
+ h.minLightness = s, h.maxLightness = a;
504
563
  else {
505
- const l = Math.max(20, Math.min(95, o));
506
- c.lightnessRange = l;
564
+ const m = Math.max(20, Math.min(95, o));
565
+ h.lightnessRange = m;
507
566
  }
508
- const h = H(t, c), f = r ? h.reverse() : h, u = {};
509
- return f.forEach((l, m) => {
510
- u[`theme-${m + 1}`] = l;
511
- }), u;
567
+ const f = I(t, h), u = r ? f.reverse() : f, l = {};
568
+ return u.forEach((m, d) => {
569
+ l[`theme-${d + 1}`] = m;
570
+ }), l;
512
571
  }
513
- function ut(t, n = {}) {
572
+ function wt(t, n = {}) {
514
573
  if (!t)
515
574
  throw new Error("Theme color is required");
516
575
  const {
@@ -519,9 +578,9 @@ function ut(t, n = {}) {
519
578
  semanticColors: o,
520
579
  controlBlendRatio: s = 0.08,
521
580
  semanticBlendRatio: a = 0.12,
522
- controlSteps: i = 12,
581
+ controlSteps: c = 12,
523
582
  // 控件色灰度等级数
524
- controlLightnessRange: c = 85,
583
+ controlLightnessRange: i = 85,
525
584
  // 控件色亮度变化范围(中心扩展模式)
526
585
  controlMinLightness: h = null,
527
586
  // 控件色最小亮度(固定端点模式)
@@ -533,44 +592,66 @@ function ut(t, n = {}) {
533
592
  // 语义色亮度变化范围
534
593
  semanticMinLightness: m = null,
535
594
  // 语义色最小亮度
536
- semanticMaxLightness: M = null,
595
+ semanticMaxLightness: d = null,
537
596
  // 语义色最大亮度
538
- themeSteps: d = 10,
597
+ semanticPreserveChroma: M = !0,
598
+ // 语义色保持色度(默认开启)
599
+ themeSteps: g = 10,
539
600
  // 主题色等级数
540
- themeLightnessRange: p = 80,
601
+ themeLightnessRange: w = 80,
541
602
  // 主题色亮度变化范围
542
603
  themeMinLightness: L = null,
543
604
  // 主题色最小亮度
544
- themeMaxLightness: y = null
605
+ themeMaxLightness: p = null,
545
606
  // 主题色最大亮度
546
- } = n, b = Math.max(0, Math.min(1, s)), w = Math.max(0, Math.min(1, a)), x = {
607
+ themePreserveChroma: x = !0,
608
+ // 主题色保持色度(默认开启)
609
+ // 浅灰度颜色配置
610
+ neutralSteps: y = 6,
611
+ // 浅灰度等级数
612
+ neutralMinLightness: v = 92,
613
+ // 浅灰度最小亮度
614
+ neutralMaxLightness: A = 100,
615
+ // 浅灰度最大亮度
616
+ neutralBlendRatio: V = 0.03
617
+ // 浅灰度主题色混合比例
618
+ } = n, U = Math.max(0, Math.min(1, s)), K = Math.max(0, Math.min(1, a)), B = {
547
619
  baseGray: r,
548
- blendRatio: b,
620
+ blendRatio: U,
549
621
  isDark: e,
550
- steps: i
622
+ steps: c
551
623
  };
552
- h !== null && f !== null ? (x.minLightness = h, x.maxLightness = f) : x.lightnessRange = c;
553
- const S = {
624
+ h !== null && f !== null ? (B.minLightness = h, B.maxLightness = f) : B.lightnessRange = i;
625
+ const D = {
554
626
  semanticColors: o,
555
- blendRatio: w,
627
+ blendRatio: K,
556
628
  isDark: e,
557
- steps: u
629
+ steps: u,
630
+ preserveChroma: M
558
631
  };
559
- m !== null && M !== null ? (S.minLightness = m, S.maxLightness = M) : S.lightnessRange = l;
560
- const C = {
632
+ m !== null && d !== null ? (D.minLightness = m, D.maxLightness = d) : D.lightnessRange = l;
633
+ const F = {
561
634
  isDark: e,
562
- steps: d
635
+ steps: g,
636
+ preserveChroma: x
563
637
  };
564
- return L !== null && y !== null ? (C.minLightness = L, C.maxLightness = y) : C.lightnessRange = p, {
638
+ return L !== null && p !== null ? (F.minLightness = L, F.maxLightness = p) : F.lightnessRange = w, {
565
639
  // 1. 基础控件颜色(灰色系1-12或更多)
566
- controls: P(t, x),
567
- // 2. 表意色(1-10或更多)
568
- semantic: k(t, S),
569
- // 3. 主题色(1-10或更多)
570
- theme: z(t, C)
640
+ controls: z(t, B),
641
+ // 2. 浅灰度颜色(用于背景、卡片等)
642
+ neutrals: rt(t, {
643
+ blendRatio: V,
644
+ steps: y,
645
+ minLightness: v,
646
+ maxLightness: A
647
+ }),
648
+ // 3. 表意色(1-10或更多)
649
+ semantic: G(t, D),
650
+ // 4. 主题色(1-10或更多)
651
+ theme: N(t, F)
571
652
  };
572
653
  }
573
- function ft(t, n = {}) {
654
+ function xt(t, n = {}) {
574
655
  if (!t)
575
656
  throw new Error("Theme color is required");
576
657
  const {
@@ -592,20 +673,20 @@ function ft(t, n = {}) {
592
673
  } = (
593
674
  /** @type {any} */
594
675
  n
595
- ), i = Math.max(0, Math.min(1, o)), c = Math.max(0, Math.min(1, s)), h = z(t, { isDark: a }), f = P(t, {
596
- blendRatio: c * 0.5,
676
+ ), c = Math.max(0, Math.min(1, o)), i = Math.max(0, Math.min(1, s)), h = N(t, { isDark: a }), f = z(t, {
677
+ blendRatio: i * 0.5,
597
678
  // 中性色混合比例稍低
598
679
  isDark: a
599
- }), u = k(t, {
680
+ }), u = G(t, {
600
681
  semanticColors: r,
601
- blendRatio: i,
682
+ blendRatio: c,
602
683
  isDark: a
603
684
  }), l = {};
604
- return Object.entries(r).forEach(([M]) => {
605
- l[M] = {};
606
- for (let d = 1; d <= 10; d++) {
607
- const p = `${M}-${d}`;
608
- u[p] && (l[M][d] = u[p]);
685
+ return Object.entries(r).forEach(([d]) => {
686
+ l[d] = {};
687
+ for (let M = 1; M <= 10; M++) {
688
+ const g = `${d}-${M}`;
689
+ u[g] && (l[d][M] = u[g]);
609
690
  }
610
691
  }), {
611
692
  theme: h,
@@ -614,10 +695,10 @@ function ft(t, n = {}) {
614
695
  // 中性色阶 gray-1 到 gray-12
615
696
  semantic: l,
616
697
  // 功能色系
617
- ui: Q(t, e, c)
698
+ ui: et(t, e, i)
618
699
  };
619
700
  }
620
- const D = {
701
+ const H = {
621
702
  red: "#F53F3F",
622
703
  orangered: "#F77234",
623
704
  orange: "#FF7D00",
@@ -632,16 +713,16 @@ const D = {
632
713
  pinkpurple: "#D91AD9",
633
714
  magenta: "#F5319D"
634
715
  };
635
- function mt() {
716
+ function Lt() {
636
717
  const t = {};
637
- return Object.keys(D).forEach((n) => {
638
- t[n] = {}, t[n].light = $(D[
718
+ return Object.keys(H).forEach((n) => {
719
+ t[n] = {}, t[n].light = P(H[
639
720
  /** @type {keyof typeof colorList} */
640
721
  n
641
- ], { list: !0 }), t[n].dark = $(D[
722
+ ], { list: !0 }), t[n].dark = P(H[
642
723
  /** @type {keyof typeof colorList} */
643
724
  n
644
- ], { list: !0, dark: !0 }), t[n].primary = D[
725
+ ], { list: !0, dark: !0 }), t[n].primary = H[
645
726
  /** @type {keyof typeof colorList} */
646
727
  n
647
728
  ];
@@ -670,34 +751,35 @@ function mt() {
670
751
  ], t.gray.primary = t.gray.light[6], t;
671
752
  }
672
753
  export {
673
- rt as adjustChroma,
674
- ot as adjustHue,
675
- et as adjustTone,
676
- I as blendInHct,
677
- Q as blendUIColors,
678
- nt as colorDifference,
679
- D as colorList,
680
- Z as extractColorFromFile,
681
- N as extractColorFromImage,
682
- $ as generate,
683
- P as generateControlColors,
684
- _ as generateGrayLinear,
685
- ut as generateInterfaceColorSystem,
686
- q as generateLinear,
687
- tt as generateLinearHSL,
688
- H as generateMonochromeLinear,
689
- k as generateSemanticColors,
690
- z as generateThemeColors,
691
- ft as generateThemePalette,
692
- ht as generateThemeVariants,
693
- it as getAnalogous,
694
- st as getComplementary,
695
- mt as getPresetColors,
696
- Y as getRgbStr,
697
- ct as getSplitComplementary,
698
- at as getTriadic,
699
- lt as harmonizeColor,
700
- E as hctToRgb,
754
+ ut as adjustChroma,
755
+ ft as adjustHue,
756
+ ht as adjustTone,
757
+ $ as blendInHct,
758
+ et as blendUIColors,
759
+ lt as colorDifference,
760
+ H as colorList,
761
+ at as extractColorFromFile,
762
+ Q as extractColorFromImage,
763
+ P as generate,
764
+ z as generateControlColors,
765
+ it as generateGrayLinear,
766
+ wt as generateInterfaceColorSystem,
767
+ O as generateLinear,
768
+ ct as generateLinearHSL,
769
+ I as generateMonochromeLinear,
770
+ rt as generateNeutralColors,
771
+ G as generateSemanticColors,
772
+ N as generateThemeColors,
773
+ xt as generateThemePalette,
774
+ bt as generateThemeVariants,
775
+ Mt as getAnalogous,
776
+ mt as getComplementary,
777
+ Lt as getPresetColors,
778
+ st as getRgbStr,
779
+ gt as getSplitComplementary,
780
+ dt as getTriadic,
781
+ pt as harmonizeColor,
782
+ C as hctToRgb,
701
783
  R as rgbToHct,
702
- v as rotateHue
784
+ S as rotateHue
703
785
  };
package/dist/linear.d.ts CHANGED
@@ -73,7 +73,7 @@ export function generateGrayLinear(options?: {
73
73
  * 基于一个基础颜色,生成从浅到深的渐变
74
74
  *
75
75
  * @param {string} baseColor - 基础颜色
76
- * @param {{steps?: number, format?: string, lightnessRange?: number, minLightness?: number, maxLightness?: number}} options - 配置选项
76
+ * @param {{steps?: number, format?: string, lightnessRange?: number, minLightness?: number, maxLightness?: number, preserveChroma?: boolean}} options - 配置选项
77
77
  * @returns {string[]} 单色调颜色数组
78
78
  *
79
79
  * @example
@@ -100,6 +100,13 @@ export function generateGrayLinear(options?: {
100
100
  * // 推荐用于需要接近纯白/纯黑的场景
101
101
  *
102
102
  * @example
103
+ * // 保持感知色度(推荐用于鲜艳的颜色)
104
+ * const vibrantShades = generateMonochromeLinear('#FF0000', {
105
+ * steps: 10,
106
+ * preserveChroma: true // 在 Lab 空间保持色度,避免灰蒙蒙
107
+ * });
108
+ *
109
+ * @example
103
110
  * // 生成HSL格式
104
111
  * const hslShades = generateMonochromeLinear('#00b894', {
105
112
  * format: 'hsl',
@@ -112,6 +119,7 @@ export function generateMonochromeLinear(baseColor: string, options?: {
112
119
  lightnessRange?: number;
113
120
  minLightness?: number;
114
121
  maxLightness?: number;
122
+ preserveChroma?: boolean;
115
123
  }): string[];
116
124
  /**
117
125
  * 在HSL空间进行线性插值
@@ -1 +1 @@
1
- {"version":3,"file":"linear.d.ts","sourceRoot":"","sources":["../src/linear.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,2CA5BW,MAAM,YACN,MAAM,YACN;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAC,GACtD,MAAM,EAAE,CA4DpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,6CAtBW;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,GACrE,MAAM,EAAE,CA8BpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,oDAlCW,MAAM,YACN;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAC,GACtG,MAAM,EAAE,CAyEpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,8CA3BW,MAAM,YACN,MAAM,YACN;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAC,GACtD,MAAM,EAAE,CAkFpB"}
1
+ {"version":3,"file":"linear.d.ts","sourceRoot":"","sources":["../src/linear.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,2CA5BW,MAAM,YACN,MAAM,YACN;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAC,GACtD,MAAM,EAAE,CA4DpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,6CAtBW;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAC,GACrE,MAAM,EAAE,CA8BpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,oDAzCW,MAAM,YACN;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAAC,GAChI,MAAM,EAAE,CAsFpB;AAoED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,8CA3BW,MAAM,YACN,MAAM,YACN;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAC,GACtD,MAAM,EAAE,CAkFpB"}
@@ -347,10 +347,80 @@ export function generateControlColors(themeColor: string, options?: {
347
347
  }): {
348
348
  [key: string]: string;
349
349
  };
350
+ /**
351
+ * 生成浅灰度颜色系列(neutral colors)
352
+ * 专门用于生成浅色背景、卡片、分割线等 UI 元素的灰度色系
353
+ * 与 generateControlColors 的区别:
354
+ * - 亮度范围更窄,集中在浅色区域(默认 92-100)
355
+ * - 更适合作为背景色、hover 状态、边框等
356
+ * - 产生更细腻的浅色梯度变化
357
+ *
358
+ * @param {string} themeColor - 主题颜色
359
+ * @param {{baseGray?: string, blendRatio?: number, steps?: number, minLightness?: number, maxLightness?: number, prefix?: string}} [options] - 配置选项
360
+ * @returns {{[key: string]: string}} 浅灰度颜色对象
361
+ *
362
+ * @example
363
+ * import { generateNeutralColors } from '@aviala-design/color';
364
+ *
365
+ * // 生成默认的浅灰度色系(6个等级)
366
+ * const neutrals = generateNeutralColors('#3491FA');
367
+ * console.log(neutrals);
368
+ * // {
369
+ * // 'neutral-1': '#fafbfc', // 最浅,接近白色
370
+ * // 'neutral-2': '#f5f7f9',
371
+ * // 'neutral-3': '#f0f2f5',
372
+ * // 'neutral-4': '#ebeef2',
373
+ * // 'neutral-5': '#e6e9ee',
374
+ * // 'neutral-6': '#e1e5eb' // 最深的浅灰
375
+ * // }
376
+ *
377
+ * @example
378
+ * // 用于不同 UI 场景
379
+ * const neutrals = generateNeutralColors('#3491FA');
380
+ * // neutrals['neutral-1'] -> 页面背景
381
+ * // neutrals['neutral-2'] -> 卡片背景
382
+ * // neutrals['neutral-3'] -> hover 状态背景
383
+ * // neutrals['neutral-4'] -> 分割线
384
+ * // neutrals['neutral-5'] -> 边框
385
+ * // neutrals['neutral-6'] -> 禁用状态背景
386
+ *
387
+ * @example
388
+ * // 自定义亮度范围,生成更多等级
389
+ * const fineNeutrals = generateNeutralColors('#3491FA', {
390
+ * steps: 10,
391
+ * minLightness: 88,
392
+ * maxLightness: 100
393
+ * });
394
+ *
395
+ * @example
396
+ * // 增加主题色混合比例,让浅灰更有品牌感
397
+ * const brandedNeutrals = generateNeutralColors('#6200EE', {
398
+ * blendRatio: 0.06, // 增加主题色影响
399
+ * steps: 8
400
+ * });
401
+ *
402
+ * @example
403
+ * // 自定义前缀
404
+ * const bgColors = generateNeutralColors('#3491FA', {
405
+ * prefix: 'bg',
406
+ * steps: 4
407
+ * });
408
+ * // { 'bg-1': '...', 'bg-2': '...', 'bg-3': '...', 'bg-4': '...' }
409
+ */
410
+ export function generateNeutralColors(themeColor: string, options?: {
411
+ baseGray?: string;
412
+ blendRatio?: number;
413
+ steps?: number;
414
+ minLightness?: number;
415
+ maxLightness?: number;
416
+ prefix?: string;
417
+ }): {
418
+ [key: string]: string;
419
+ };
350
420
  /**
351
421
  * 生成表意色(1-10)
352
422
  * @param {string} themeColor - 主题颜色
353
- * @param {{semanticColors?: {[key: string]: string}, blendRatio?: number, isDark?: boolean, steps?: number, lightnessRange?: number, minLightness?: number, maxLightness?: number}} [options] - 配置选项
423
+ * @param {{semanticColors?: {[key: string]: string}, blendRatio?: number, isDark?: boolean, steps?: number, lightnessRange?: number, minLightness?: number, maxLightness?: number, preserveChroma?: boolean}} [options] - 配置选项
354
424
  * @returns {{[key: string]: string}} 表意色对象
355
425
  *
356
426
  * @example
@@ -374,6 +444,14 @@ export function generateControlColors(themeColor: string, options?: {
374
444
  * });
375
445
  *
376
446
  * @example
447
+ * // 保持鲜艳的色度(推荐:避免灰蒙蒙)
448
+ * const vibrant = generateSemanticColors('#3491FA', {
449
+ * preserveChroma: true, // 在 Lab 空间保持色度
450
+ * minLightness: 25,
451
+ * maxLightness: 95
452
+ * });
453
+ *
454
+ * @example
377
455
  * // 使用固定端点模式获得更广的亮度范围
378
456
  * const wideRange = generateSemanticColors('#3491FA', {
379
457
  * minLightness: 10,
@@ -391,13 +469,14 @@ export function generateSemanticColors(themeColor: string, options?: {
391
469
  lightnessRange?: number;
392
470
  minLightness?: number;
393
471
  maxLightness?: number;
472
+ preserveChroma?: boolean;
394
473
  }): {
395
474
  [key: string]: string;
396
475
  };
397
476
  /**
398
477
  * 生成主题色(1-10)
399
478
  * @param {string} themeColor - 主题颜色
400
- * @param {{isDark?: boolean, steps?: number, lightnessRange?: number, minLightness?: number, maxLightness?: number}} [options] - 配置选项
479
+ * @param {{isDark?: boolean, steps?: number, lightnessRange?: number, minLightness?: number, maxLightness?: number, preserveChroma?: boolean}} [options] - 配置选项
401
480
  * @returns {{[key: string]: string}} 主题色对象
402
481
  *
403
482
  * @example
@@ -414,6 +493,14 @@ export function generateSemanticColors(themeColor: string, options?: {
414
493
  * const darkTheme = generateThemeColors('#FF5722', { isDark: true });
415
494
  *
416
495
  * @example
496
+ * // 保持鲜艳色度
497
+ * const vibrant = generateThemeColors('#3491FA', {
498
+ * preserveChroma: true,
499
+ * minLightness: 20,
500
+ * maxLightness: 95
501
+ * });
502
+ *
503
+ * @example
417
504
  * // 使用固定端点模式
418
505
  * const wideRange = generateThemeColors('#3491FA', {
419
506
  * minLightness: 15,
@@ -427,6 +514,7 @@ export function generateThemeColors(themeColor: string, options?: {
427
514
  lightnessRange?: number;
428
515
  minLightness?: number;
429
516
  maxLightness?: number;
517
+ preserveChroma?: boolean;
430
518
  }): {
431
519
  [key: string]: string;
432
520
  };
@@ -434,14 +522,16 @@ export function generateThemeColors(themeColor: string, options?: {
434
522
  * 生成完整的界面色彩系统
435
523
  * @param {string} themeColor - 主题颜色
436
524
  * @param {*} [options] - 配置选项
437
- * @returns {{controls: object, semantic: object, theme: object}} 包含三个部分的完整色彩系统
525
+ * @returns {{controls: object, neutrals: object, semantic: object, theme: object}} 包含四个部分的完整色彩系统
438
526
  *
527
+ /**
439
528
  * @example
440
529
  * import { generateInterfaceColorSystem } from '@aviala-design/color';
441
530
  *
442
531
  * // 生成完整色彩系统
443
532
  * const colorSystem = generateInterfaceColorSystem('#3491FA');
444
533
  * console.log(colorSystem.controls); // 灰色系 1-12
534
+ * console.log(colorSystem.neutrals); // 浅灰度色系(背景、卡片用)
445
535
  * console.log(colorSystem.semantic); // 语义色系
446
536
  * console.log(colorSystem.theme); // 主题色系
447
537
  *
@@ -454,11 +544,10 @@ export function generateThemeColors(themeColor: string, options?: {
454
544
  * });
455
545
  *
456
546
  * @example
457
- * // 使用 lightnessRange(中心扩展模式)
458
- * const customSystem = generateInterfaceColorSystem('#3491FA', {
459
- * controlSteps: 24, // 24 级灰度
460
- * controlLightnessRange: 90, // 更接近纯白/纯黑
461
- * controlBlendRatio: 0.1
547
+ * // 保持鲜艳色度(推荐:避免灰蒙蒙)
548
+ * const vibrantSystem = generateInterfaceColorSystem('#3491FA', {
549
+ * semanticPreserveChroma: true, // 语义色保持色度
550
+ * themePreserveChroma: true // 主题色保持色度
462
551
  * });
463
552
  *
464
553
  * @example
@@ -476,6 +565,7 @@ export function generateThemeColors(themeColor: string, options?: {
476
565
  */
477
566
  export function generateInterfaceColorSystem(themeColor: string, options?: any): {
478
567
  controls: object;
568
+ neutrals: object;
479
569
  semantic: object;
480
570
  theme: object;
481
571
  };
@@ -1 +1 @@
1
- {"version":3,"file":"theme-blend.d.ts","sourceRoot":"","sources":["../src/theme-blend.js"],"names":[],"mappings":"AAeA;;;;;GAKG;AAEH;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,8BAjBW,MAAM,GACJ,GAAG,CAkDf;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,8BAjBW,GAAG,YACH;IAAC,YAAY,CAAC,EAAE,OAAO,GAAG,eAAe,CAAA;CAAC,GACxC,MAAM,CAkElB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,mCApBW,MAAM,UACN,MAAM,UACN,MAAM,YACN;IAAC,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,UAAU,CAAA;CAAC,GACjC,MAAM,CAqClB;AAkGD;;;;;;;;;;;;;GAaG;AACH,wCAVW,MAAM,UACN,MAAM,GACJ,MAAM,CAqBlB;AAED;;;;;;;;;;;;GAYG;AACH,kCAVW,MAAM,QACN,MAAM,GACJ,MAAM,CAelB;AAED;;;;;;;;;;;;GAYG;AACH,oCAVW,MAAM,UACN,MAAM,GACJ,MAAM,CAelB;AAED;;;;;;;;;;;;GAYG;AACH,iCAVW,MAAM,OACN,MAAM,GACJ,MAAM,CAelB;AAED;;;;;;;;;;;;;;;GAeG;AACH,iCAbW,MAAM,WACN,MAAM,GACJ,MAAM,CAoBlB;AAED;;;;;;;;;;GAUG;AACH,wCARW,MAAM,GACJ,MAAM,CASlB;AAED;;;;;;;;;;GAUG;AACH,kCARW,MAAM,GACJ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAapC;AAED;;;;;;;;;;;GAWG;AACH,6CATW,MAAM,UACN,MAAM,GACJ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAapC;AAED;;;;;;;;;;;;GAYG;AACH,oCAVW,MAAM,UACN,MAAM,UACN,MAAM,GACJ,MAAM,EAAE,CAgBpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,2CArBW,MAAM,eACN,MAAM,mBACN,MAAM,GACJ,MAAM,CA6BlB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,kDArBW,MAAM,YACN,MAAM,EAAE,GAAC;IAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAAC,GACzB,MAAM,EAAE,CA2DpB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,0CA1BW,MAAM,YACN;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAC,eACvB,MAAM,GACJ;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAC,CAkDnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,kDAzCW,MAAM,YACN;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAC,GAC/I;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAC,CA6FnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,mDAhCW,MAAM,YACN;IAAC,cAAc,CAAC,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAC,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAC,GACtK;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAC,CA4GnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,gDAzBW,MAAM,YACN;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAC,GACvG;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAC,CAqEnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,yDA1CW,MAAM,YACN,GAAC,GACC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CA4H/D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,iDAzBW,MAAM,YACN,GAAC,GACC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,CAwF3E;;;;;OAtoCa,MAAM;;;;OACN,MAAM;;;;OACN,MAAM;;;;;;OAKN,MAAM;;;;OACN,MAAM;;;;OACN,MAAM"}
1
+ {"version":3,"file":"theme-blend.d.ts","sourceRoot":"","sources":["../src/theme-blend.js"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aviala-design/color",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Aviala Design color utils",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",