rsuite
Version:
A suite of react components
109 lines (100 loc) • 3.46 kB
JavaScript
'use client';
import { Colours } from "../types/colours.js";
import { createStyleGetter } from "./style-sheet/index.js";
/**
* Checks if a color value matches the pattern like 'red', 'gray.50', etc.,
* and returns the appropriate CSS variable format.
* @param color The color value to check
* @returns The CSS variable if it's a valid color type, or the original value
*/
export const getColorValue = color => {
if (!color) return undefined;
// Check if color is a base color (e.g., 'red', 'blue')
const baseColorRegex = /^(red|orange|yellow|green|cyan|blue|violet|gray)$/;
if (baseColorRegex.test(color)) {
return `var(--rs-color-${color})`;
}
// Check if color is a color with shade (e.g., 'red.50', 'gray.900')
const colorWithShadeRegex = /^(red|orange|yellow|green|cyan|blue|violet|gray)\.([1-9]00|50)$/;
const match = color === null || color === void 0 ? void 0 : color.match(colorWithShadeRegex);
if (match) {
const [, colorName, shade] = match;
return `var(--rs-${colorName}-${shade})`;
}
// Return the original value if it's not a recognized color pattern
return color;
};
export const isPresetColor = color => {
if (!color) {
return false;
}
if (color === 'default') {
return true;
}
return Object.values(Colours).includes(color);
};
const colorConfig = {
prop: 'color',
useGlobalVar: true,
presetChecker: isPresetColor,
valueTransformer: getColorValue
};
export const getColorStyle = createStyleGetter(colorConfig);
/**
* Convert short hex color to full hex color
* e.g. #fff -> #ffffff
*/
export const expandHexColor = color => {
const hex = color.toLowerCase().replace('#', '');
if (hex.length === 3) {
return `#${hex[0]}${hex[0]}${hex[1]}${hex[1]}${hex[2]}${hex[2]}`;
}
return `#${hex}`;
};
/**
* Calculate relative luminance of a color
* Using the formula from WCAG 2.0
*/
export const getLuminance = color => {
// Convert hex to rgb
const fullHex = expandHexColor(color);
const hex = fullHex.replace('#', '');
const r = parseInt(hex.substring(0, 2), 16) / 255;
const g = parseInt(hex.substring(2, 4), 16) / 255;
const b = parseInt(hex.substring(4, 6), 16) / 255;
// Convert rgb to relative luminance
const rs = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
const gs = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4);
const bs = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4);
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
};
/**
* Get contrasting text color (black or white) based on background color
*/
export const getContrastText = bgColor => {
// For non-hex colors, return default dark text
if (!bgColor.startsWith('#')) {
return 'var(--rs-text-primary)';
}
const luminance = getLuminance(bgColor);
return luminance > 0.5 ? '#000000' : '#ffffff';
};
/**
* Create CSS color variables for custom colors
* Returns background and optional text color variables
*/
export const createColorVariables = (color, bgFieldName = '--rs-color-bg', textFieldName) => {
if (color && !isPresetColor(color)) {
const colorStr = color.toString();
// Only convert to hex if it's a hex color
const bgColor = colorStr.startsWith('#') ? expandHexColor(colorStr) : colorStr;
const styles = {
[bgFieldName]: bgColor
};
if (textFieldName) {
styles[textFieldName] = getContrastText(bgColor);
}
return styles;
}
return undefined;
};