Browse Source

refactor: use @ant-design/fast-color instead (#4070)

* refactor: Use @ant-design/fast-color instead

* fix: test failed

* chore: remove isValidColor

All FastColor objects are valid. So isValid is always true.
FastColor("not-a-color") -> `#000000`

* refactor: rename directory `colorful` to `color`

* fix: ci fail
Li Kui 7 months ago
parent
commit
1d38fb647e

+ 1 - 1
packages/@core/base/shared/build.config.ts

@@ -7,7 +7,7 @@ export default defineBuildConfig({
     'src/index',
     'src/constants/index',
     'src/utils/index',
-    'src/colorful/index',
+    'src/color/index',
     'src/cache/index',
   ],
 });

+ 5 - 5
packages/@core/base/shared/package.json

@@ -35,10 +35,10 @@
       "development": "./src/utils/index.ts",
       "default": "./dist/utils/index.mjs"
     },
-    "./colorful": {
-      "types": "./src/colorful/index.ts",
-      "development": "./src/colorful/index.ts",
-      "default": "./dist/colorful/index.mjs"
+    "./color": {
+      "types": "./src/color/index.ts",
+      "development": "./src/color/index.ts",
+      "default": "./dist/color/index.mjs"
     },
     "./cache": {
       "types": "./src/cache/index.ts",
@@ -55,7 +55,7 @@
     }
   },
   "dependencies": {
-    "@ctrl/tinycolor": "^4.1.0",
+    "@ant-design/fast-color": "^2.0.5",
     "@vue/shared": "^3.4.35",
     "clsx": "^2.1.1",
     "defu": "^6.1.4",

+ 10 - 10
packages/@core/base/shared/src/colorful/convert.test.ts → packages/@core/base/shared/src/color/convert.test.ts

@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest';
 
-import { convertToHsl, convertToHslCssVar, isValidColor } from './convert';
+import { convertToHsl, convertToHslCssVar, convertToRgb } from './convert';
 
 describe('color conversion functions', () => {
   it('should correctly convert color to HSL format', () => {
@@ -26,16 +26,16 @@ describe('color conversion functions', () => {
     const expectedHsl = '0 100% 50% / 0.5';
     expect(convertToHslCssVar(color)).toEqual(expectedHsl);
   });
-});
 
-describe('isValidColor', () => {
-  it('isValidColor function', () => {
-    // 测试有效颜色
-    expect(isValidColor('blue')).toBe(true);
-    expect(isValidColor('#000000')).toBe(true);
+  it('should correctly convert color to RGB CSS variable format', () => {
+    const color = 'hsl(284, 100%, 50%)';
+    const expectedRgb = 'rgb(187,0,255)';
+    expect(convertToRgb(color)).toEqual(expectedRgb);
+  });
 
-    // 测试无效颜色
-    expect(isValidColor('invalid color')).toBe(false);
-    expect(isValidColor()).toBe(false);
+  it('should correctly convert color with alpha to RGBA CSS variable format', () => {
+    const color = 'hsla(284, 100%, 50%, 0.92)';
+    const expectedRgba = 'rgba(187,0,255,0.92)';
+    expect(convertToRgb(color)).toEqual(expectedRgba);
   });
 });

+ 38 - 0
packages/@core/base/shared/src/color/convert.ts

@@ -0,0 +1,38 @@
+import { FastColor } from '@ant-design/fast-color';
+
+const Color = FastColor;
+
+/**
+ * 将颜色转换为HSL格式。
+ *
+ * HSL是一种颜色模型,包括色相(Hue)、饱和度(Saturation)和亮度(Lightness)三个部分。
+ *
+ * @param {string} color 输入的颜色。
+ * @returns {string} HSL格式的颜色字符串。
+ */
+function convertToHsl(color: string): string {
+  const { a, h, l, s } = new Color(color).toHsl();
+  const hsl = `hsl(${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%)`;
+  return a < 1 ? `${hsl} ${a}` : hsl;
+}
+
+/**
+ * 将颜色转换为HSL CSS变量。
+ *
+ * 这个函数与convertToHsl函数类似,但是返回的字符串格式稍有不同,
+ * 以便可以作为CSS变量使用。
+ *
+ * @param {string} color 输入的颜色。
+ * @returns {string} 可以作为CSS变量使用的HSL格式的颜色字符串。
+ */
+function convertToHslCssVar(color: string): string {
+  const { a, h, l, s } = new Color(color).toHsl();
+  const hsl = `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
+  return a < 1 ? `${hsl} / ${a}` : hsl;
+}
+
+function convertToRgb(color: string): string {
+  return new Color(color).toRgbString();
+}
+
+export { Color, convertToHsl, convertToHslCssVar, convertToRgb };

+ 2 - 3
packages/@core/base/shared/src/colorful/generator.ts → packages/@core/base/shared/src/color/generator.ts

@@ -1,7 +1,6 @@
-import { TinyColor } from '@ctrl/tinycolor';
 import { getColors } from 'theme-colors';
 
-import { convertToHslCssVar } from './convert';
+import { Color, convertToHslCssVar } from './convert';
 
 interface ColorItem {
   alias?: string;
@@ -14,7 +13,7 @@ function generatorColorVariables(colorItems: ColorItem[]) {
 
   colorItems.forEach(({ alias, color, name }) => {
     if (color) {
-      const colorsMap = getColors(new TinyColor(color).toHexString());
+      const colorsMap = getColors(new Color(color).toHexString());
       let mainColor = colorsMap['500'];
 
       const colorKeys = Object.keys(colorsMap);

+ 0 - 0
packages/@core/base/shared/src/colorful/index.ts → packages/@core/base/shared/src/color/index.ts


+ 0 - 73
packages/@core/base/shared/src/colorful/convert.ts

@@ -1,73 +0,0 @@
-import { TinyColor } from '@ctrl/tinycolor';
-/**
- * 将颜色转换为HSL格式。
- *
- * HSL是一种颜色模型,包括色相(Hue)、饱和度(Saturation)和亮度(Lightness)三个部分。
- * 这个函数使用TinyColor库将输入的颜色转换为HSL格式,并返回一个字符串。
- *
- * @param {string} color 输入的颜色,可以是任何TinyColor支持的颜色格式。
- * @returns {string} HSL格式的颜色字符串。
- */
-function convertToHsl(color: string): string {
-  const { a, h, l, s } = new TinyColor(color).toHsl();
-  const hsl = `hsl(${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%)`;
-  return a < 1 ? `${hsl} ${a}` : hsl;
-}
-
-/**
- * 将颜色转换为HSL CSS变量。
- *
- * 这个函数与convertToHsl函数类似,但是返回的字符串格式稍有不同,
- * 以便可以作为CSS变量使用。
- *
- * @param {string} color 输入的颜色,可以是任何TinyColor支持的颜色格式。
- * @returns {string} 可以作为CSS变量使用的HSL格式的颜色字符串。
- */
-function convertToHslCssVar(color: string): string {
-  const { a, h, l, s } = new TinyColor(color).toHsl();
-  const hsl = `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
-  return a < 1 ? `${hsl} / ${a}` : hsl;
-}
-
-/**
- * 检查颜色是否有效
- * @param {string} color - 待检查的颜色
- * 如果颜色有效返回true,否则返回false
- */
-function isValidColor(color?: string) {
-  if (!color) {
-    return false;
-  }
-  return new TinyColor(color).isValid;
-}
-/**
- * 将HLS字符串转换为RGB颜色字符串
- *
- * 本函数接收一个表示HLS值的字符串,移除其中的度量单位,
- * 并将其转换为TinyColor对象,以便进行颜色处理。
- * 如果转换后的颜色无效,则直接返回原始字符串;
- * 否则,返回转换后的RGB颜色字符串
- *
- * @param str 表示HLS颜色值的字符串,可能包含度量单位如'deg'、'grad'、'rad'或'turn'
- * @returns 如果颜色值有效,则返回对应的RGB颜色字符串;如果无效,则返回原始字符串
- */
-function hlsStringToRGBString(str: string): string {
-  // 移除HLS字符串中的度量单位,以便正确解析
-  const color = new TinyColor(
-    `hsl(${str.replaceAll(/deg|grad|rad|turn/g, '')})`,
-  );
-  // 检查颜色是否有效,如果无效则直接返回原始字符串
-  if (!color.isValid) {
-    return str;
-  }
-  // 返回转换后的RGB颜色字符串
-  return color.toRgbString();
-}
-
-export {
-  convertToHsl,
-  convertToHslCssVar,
-  hlsStringToRGBString,
-  isValidColor,
-  TinyColor,
-};

+ 1 - 1
packages/@core/base/shared/src/index.ts

@@ -1,4 +1,4 @@
 export * from './cache';
-export * from './colorful';
+export * from './color';
 export * from './constants';
 export * from './utils';

+ 3 - 3
packages/@core/ui-kit/shadcn-ui/src/components/menu-badge/menu-badge.vue

@@ -3,7 +3,7 @@ import type { MenuRecordBadgeRaw } from '@vben-core/typings';
 
 import { computed } from 'vue';
 
-import { isValidColor } from '@vben-core/shared';
+import { convertToRgb } from '@vben-core/shared';
 
 import BadgeDot from './menu-badge-dot.vue';
 
@@ -34,9 +34,9 @@ const badgeClass = computed(() => {
 });
 
 const badgeStyle = computed(() => {
-  if (badgeClass.value && isValidColor(badgeClass.value)) {
+  if (badgeClass.value) {
     return {
-      backgroundColor: badgeClass.value,
+      backgroundColor: convertToRgb(badgeClass.value),
     };
   }
   return {};

+ 3 - 5
packages/effects/hooks/src/use-design-tokens.ts

@@ -1,7 +1,7 @@
 import { reactive, watch } from 'vue';
 
 import { preferences } from '@vben/preferences';
-import { hlsStringToRGBString, updateCSSVariables } from '@vben/utils';
+import { convertToRgb, updateCSSVariables } from '@vben/utils';
 
 /**
  * 用于适配各个框架的设计系统
@@ -102,7 +102,7 @@ export function useNaiveDesignTokens() {
 
   const getCssVariableValue = (variable: string, isColor: boolean = true) => {
     const value = rootStyles.getPropertyValue(variable);
-    return isColor ? hlsStringToRGBString(value) : value;
+    return isColor ? convertToRgb(`hsl(${value})`) : value;
   };
 
   watch(
@@ -145,8 +145,6 @@ export function useNaiveDesignTokens() {
       commonTokens.invertedColor = getCssVariableValue('--background-deep');
 
       commonTokens.borderRadius = getCssVariableValue('--radius', false);
-
-      // antDesignTokens.colorBgMask = getCssVariableValue('--overlay');
     },
     { immediate: true },
   );
@@ -160,7 +158,7 @@ export function useElementPlusDesignTokens() {
 
   const getCssVariableValue = (variable: string, isColor: boolean = true) => {
     const value = rootStyles.getPropertyValue(variable);
-    return isColor ? `hsl(${value})` : value;
+    return isColor ? convertToRgb(`hsl(${value})`) : value;
   };
   watch(
     () => preferences.theme,

+ 3 - 9
packages/effects/layouts/src/widgets/preferences/blocks/theme/builtin.vue

@@ -9,7 +9,7 @@ import {
   BUILT_IN_THEME_PRESETS,
   type BuiltinThemePreset,
 } from '@vben/preferences';
-import { convertToHsl, TinyColor } from '@vben/utils';
+import { Color, convertToHsl } from '@vben/utils';
 
 defineOptions({
   name: 'PreferenceBuiltinTheme',
@@ -22,17 +22,11 @@ const modelValue = defineModel<BuiltinThemeType>({ default: 'default' });
 const themeColorPrimary = defineModel<string>('themeColorPrimary');
 
 const inputValue = computed(() => {
-  return new TinyColor(themeColorPrimary.value).toHexString();
+  return new Color(themeColorPrimary.value || '').toHexString();
 });
 
 const builtinThemePresets = computed(() => {
-  return [
-    // {
-    //   color: 'hsl(231 98% 65%)',
-    //   type: 'default',
-    // },
-    ...BUILT_IN_THEME_PRESETS,
-  ];
+  return [...BUILT_IN_THEME_PRESETS];
 });
 
 function typeView(name: BuiltinThemeType) {

+ 1 - 1
packages/utils/src/index.ts

@@ -1,3 +1,3 @@
 export * from './helpers';
-export * from '@vben-core/shared/colorful';
+export * from '@vben-core/shared/color';
 export * from '@vben-core/shared/utils';

File diff suppressed because it is too large
+ 160 - 234
pnpm-lock.yaml


Some files were not shown because too many files changed in this diff