diff --git a/src/contexts/ThemeContext.tsx b/src/contexts/ThemeContext.tsx index 66fb865..025c76c 100644 --- a/src/contexts/ThemeContext.tsx +++ b/src/contexts/ThemeContext.tsx @@ -133,6 +133,12 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ extendedSchemeHues, fullOptions.syntaxSaturation, Object.fromEntries( + /** + * Filters the entries of syntaxColors object based on locked color keys + * @param {Object} syntaxColors - An object containing syntax highlighting color configurations + * @param {Set} lockedColorSet - A Set containing keys of locked colors + * @returns {Array} An array of key-value pairs for locked syntax colors + */ Object.entries(syntaxColors).filter(([key]) => lockedColorSet.has(key) ) @@ -160,6 +166,11 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ ] ); + /** + * Updates the dark mode state and generates corresponding colors + * @param {boolean} value - The new dark mode state (true for dark mode, false for light mode) + * @returns {void} This function doesn't return a value + */ const setIsDark = useCallback( (value: boolean) => { setIsDarkState(value); @@ -168,6 +179,11 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ [generateColors] ); + /** + * Updates the base hue state and generates new colors based on the provided value. + * @param {number} value - The new base hue value to set. + * @returns {void} This function doesn't return a value. + */ const setBaseHue = useCallback( (value: number) => { setBaseHueState(value); @@ -176,6 +192,12 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ [generateColors] ); + /** + * Updates the theme and syntax colors with new saturation values + * @param {number} newUiSaturation - The new saturation value for UI colors + * @param {number} newSyntaxSaturation - The new saturation value for syntax colors + * @returns {void} This function doesn't return a value, it updates state + */ const updateColorsWithSaturation = useCallback( (newUiSaturation: number, newSyntaxSaturation: number) => { const newColors = updateThemeColorsWithSaturation( @@ -197,6 +219,11 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ [colors, syntaxColors, lockedColors] ); + /** + * Updates the UI saturation state and applies the new saturation value to colors. + * @param {number} value - The new saturation value to be set. + * @returns {void} This function doesn't return a value. + */ const setUiSaturation = useCallback( (value: number) => { setUiSaturationState(value); @@ -205,6 +232,11 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ [syntaxSaturation, updateColorsWithSaturation] ); + /** + * Updates the syntax saturation state and refreshes colors with the new saturation value. + * @param {number} value - The new saturation value to be applied. + * @returns {void} This function doesn't return a value. + */ const setSyntaxSaturation = useCallback( (value: number) => { setSyntaxSaturationState(value); @@ -213,6 +245,11 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ [uiSaturation, updateColorsWithSaturation] ); + /** + * Updates the color scheme and generates new colors based on the selected scheme. + * @param {ColorScheme} value - The new color scheme to be applied. + * @returns {void} This function doesn't return a value. + */ const setScheme = useCallback( (value: ColorScheme) => { setSchemeState(value); @@ -221,7 +258,18 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ [generateColors] ); + /** + * Toggles the lock state of a color in the color palette. + * @param {string} colorKey - The key of the color to toggle the lock state for. + * @returns {void} This function doesn't return a value, it updates the state internally. + */ const toggleColorLock = useCallback((colorKey: string) => { + /** + * Toggles the locked state of a color in the set of locked colors + * @param {function} prev - The previous state of the locked colors set + * @param {string} colorKey - The key of the color to toggle + * @returns {Set} A new Set with the updated locked colors + */ setLockedColors((prev) => { const newSet = new Set(prev); if (newSet.has(colorKey)) { @@ -233,25 +281,51 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ }); }, []); + /** + * Updates color values based on the provided color key and new color. + * @param {string} colorKey - The key identifying which color to update (e.g., "ansi", "BG1", or syntax color keys). + * @param {string} newColor - The new color value to set. + * @returns {void} This function doesn't return a value, it updates state. + */ const handleColorChange = useCallback( (colorKey: string, newColor: string) => { if (colorKey.startsWith("ansi")) { + /** + * Updates a specific ANSI color in the state + * @param {function} prevColors - A function that receives the previous state of colors + * @returns {object} An updated object containing the new color for the specified key + */ setAnsiColors((prevColors) => ({ ...prevColors, [colorKey.slice(4)]: newColor, })); } else if (colorKey in colors) { + /** + * Updates a specific color in the colors state object + * @param {function} prevColors - Callback function that receives the previous colors state + * @returns {object} Updated colors state object with the new color value for the specified key + */ setColors((prevColors) => ({ ...prevColors, [colorKey]: newColor, })); if (colorKey === "BG1") { + /** + * Updates the syntax colors based on a new color and existing scheme parameters + * @param {function} prevSyntaxColors - Callback function to access the previous syntax colors state + * @returns {object} Updated syntax colors object + */ setSyntaxColors((prevSyntaxColors) => ({ ...prevSyntaxColors, ...generateSyntaxColors(newColor, schemeHues, syntaxSaturation), })); } } else if (colorKey in syntaxColors) { + /** + * Updates the syntax colors by setting a new color for a specific color key + * @param {function} prevSyntaxColors - A function that returns the previous syntax colors object + * @returns {object} An updated syntax colors object with the new color applied to the specified color key + */ setSyntaxColors((prevSyntaxColors) => ({ ...prevSyntaxColors, [colorKey]: newColor, @@ -261,10 +335,20 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ [colors, syntaxColors, schemeHues, syntaxSaturation] ); + /** + * Regenerates ANSI colors based on the current background color. + * @param {void} - This function doesn't take any parameters. + * @returns {void} This function doesn't return a value, but updates the state with new ANSI colors. + */ const regenerateAnsiColors = useCallback(() => { setAnsiColors(generateAnsiColors(colors.BG1)); }, [colors.BG1]); - + /** + * A React effect hook that regenerates ANSI colors when specific dependencies change. + * @param {Function} regenerateAnsiColors - Function to regenerate ANSI colors. + * @param {string} colors.BG1 - The background color that triggers regeneration when changed. + * @returns {void} This effect does not return anything. + */ useEffect(() => { regenerateAnsiColors(); }, [colors.BG1, regenerateAnsiColors]); @@ -299,6 +383,11 @@ export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ ); }; +/** + * A custom hook to access the current theme context + * @returns {Object} The current theme context + * @throws {Error} If used outside of a ThemeProvider + */ export const useTheme = () => { const context = useContext(ThemeContext); if (context === undefined) { diff --git a/src/lib/utils/ansiColors.ts b/src/lib/utils/ansiColors.ts index d08470e..de2b618 100644 --- a/src/lib/utils/ansiColors.ts +++ b/src/lib/utils/ansiColors.ts @@ -20,10 +20,21 @@ export interface AnsiColors { BrightWhite: string; } +/** + * Generates a set of ANSI colors based on a given background color. + * @param {string} backgroundColor - The background color to base the generated colors on. + * @returns {AnsiColors} An object containing generated ANSI colors with enhanced readability. + */ export function generateAnsiColors(backgroundColor: string): AnsiColors { const baseSaturation = 20 + Math.random() * 60; // 20-80 const baseLightness = 30 + Math.random() * 30; // 30-60 + /** + * Generates a color based on the given parameters. + * @param {number} baseHue - The base hue value to start from (0-360). + * @param {boolean} [isGrayscale=false] - Whether to generate a grayscale color. + * @returns {string} A hexadecimal color string. + */ const generateColor = (baseHue: number, isGrayscale: boolean = false) => { if (isGrayscale) { return Color.hsl(0, 0, baseLightness).hex(); @@ -40,6 +51,11 @@ export function generateAnsiColors(backgroundColor: string): AnsiColors { return Color.hsl(hue, saturation, lightness).hex(); }; + /** + * Brightens a given color by increasing its saturation and lightness. + * @param {string} color - The input color in any valid CSS color format. + * @returns {string} A new color in hexadecimal format with increased brightness. + */ const brightenColor = (color: string) => { const c = Color(color); const brightSaturation = Math.min( @@ -53,6 +69,12 @@ export function generateAnsiColors(backgroundColor: string): AnsiColors { return c.saturationl(brightSaturation).lightness(brightLightness).hex(); }; + /** + * Ensures the readability of a color against a background color, except for black. + * @param {string} color - The foreground color to check and potentially adjust. + * @param {string} bgColor - The background color to check against. + * @returns {string} The original color if it's black, otherwise a color with sufficient contrast against the background. + */ const ensureReadabilityExceptBlack = (color: string, bgColor: string) => { if (color.toLowerCase() === "#000000") return color; return ensureReadability(color, bgColor, 4.5); diff --git a/src/lib/utils/colorUtils.ts b/src/lib/utils/colorUtils.ts index b84b13e..110119c 100644 --- a/src/lib/utils/colorUtils.ts +++ b/src/lib/utils/colorUtils.ts @@ -4,6 +4,10 @@ export interface ColorAlphas { [key: string]: number; } +/** + * Generates a random color and returns its hexadecimal representation. + * @returns {string} A string representing the randomly generated color in hexadecimal format. + */ export function generateRandomColor(): string { return Color.rgb( Math.floor(Math.random() * 256), @@ -12,10 +16,21 @@ export function generateRandomColor(): string { ).hex(); } +/** + * Adjusts the brightness of a given color by a specified amount. + * @param {string} color - The color to adjust, in any valid CSS color format. + * @param {number} amount - The amount to lighten the color, typically between 0 and 1. + * @returns {string} The adjusted color in hexadecimal format. + */ export function adjustColorBrightness(color: string, amount: number): string { return Color(color).lighten(amount).hex(); } +/** + * Generates a contrasting color based on the given background color. + * @param {string} backgroundColor - The background color in a format parsable by the Color library. + * @returns {string} A contrasting color in hexadecimal format. + */ export function generateContrastingColor(backgroundColor: string): string { const bgColor = Color(backgroundColor); return bgColor.isLight() @@ -23,8 +38,12 @@ export function generateContrastingColor(backgroundColor: string): string { : bgColor.lighten(0.6).hex(); } -// Add these new functions: - +/** + * Generates a harmonized color based on a given base color and hue offset + * @param {string} baseColor - The starting color in any valid CSS color format + * @param {number} hueOffset - The amount to rotate the hue of the base color (in degrees) + * @returns {string} A new color in hexadecimal format that is harmonized with the base color + */ export function generateHarmonizedColor( baseColor: string, hueOffset: number @@ -32,6 +51,15 @@ export function generateHarmonizedColor( return Color(baseColor).rotate(hueOffset).saturate(0.1).hex(); } +/** + * Adjusts the color generated color for comments based on the background color to ensure proper contrast and readability. + * @param {string} commentColor - The initial color of the comment. + * @param {string} backgroundColor - The color of the background. + * @param {number} [minContrast=1.1] - The minimum contrast ratio between comment and background. + * @param {number} [maxContrast=1.5] - The maximum contrast ratio between comment and background. + * @param {number} [targetLuminanceRatio=0.1] - The target luminance ratio between comment and background. + * @returns {string} The adjusted comment color in hexadecimal format. + */ export function adjustCommentColor( commentColor: string, backgroundColor: string, @@ -87,6 +115,13 @@ export function adjustCommentColor( return comment.hex(); } +/** + * Adjusts the foreground color to ensure readability against a background color. + * @param {string} foreground - The initial foreground color in a format parsable by the Color function. + * @param {string} background - The background color to contrast against, in a format parsable by the Color function. + * @param {number} [minContrast=5.5] - The minimum contrast ratio to achieve between foreground and background. + * @returns {string} The adjusted foreground color as a hexadecimal string. + */ export function ensureReadability( foreground: string, background: string, @@ -125,6 +160,12 @@ export enum ColorScheme { SeedOfLife, } +/** + * Generates an array of hue values based on a given base hue and color scheme. + * @param {number} baseHue - The starting hue value (0-359) to generate the color scheme from. + * @param {ColorScheme} scheme - The color scheme to apply (e.g., Monochromatic, Analogous, Complementary, etc.). + * @returns {number[]} An array of hue values (0-359) representing the generated color scheme. + */ export function generateSchemeColors( baseHue: number, scheme: ColorScheme @@ -274,6 +315,12 @@ export const presets = { dracula: { baseHue: 260, scheme: ColorScheme.SplitComplementary }, }; +/** + * Converts a hexadecimal color code to HSL (Hue, Saturation, Lightness) values. + * @param {string} hex - The hexadecimal color code to convert (3 or 6 digits, with or without '#'). + * @returns {Object} An object containing the HSL values: { h: number, s: number, l: number }. + * h is in degrees (0-360), s and l are percentages (0-100). + */ export function hexToHSL(hex: string): { h: number; s: number; l: number } { let r = 0, g = 0, @@ -320,6 +367,13 @@ export function hexToHSL(hex: string): { h: number; s: number; l: number } { return { h: h * 360, s: s * 100, l: l * 100 }; } +/** + * Converts HSL (Hue, Saturation, Lightness) color values to hexadecimal color code. + * @param {number} h - The hue value (0-360). + * @param {number} s - The saturation value (0-100). + * @param {number} l - The lightness value (0-100). + * @returns {string} A hexadecimal color code string (e.g., "#RRGGBB"). + */ export function hslToHex(h: number, s: number, l: number): string { h /= 360; s /= 100; @@ -337,7 +391,7 @@ export function hslToHex(h: number, s: number, l: number): string { if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; return p; }; - + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; const p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3); @@ -353,18 +407,39 @@ export function hslToHex(h: number, s: number, l: number): string { return `#${toHex(r)}${toHex(g)}${toHex(b)}`; } +/** + * Adjusts the hue value to ensure it falls within the valid range of 0 to 359 degrees. + * @param {number} hue - The input hue value to be adjusted. + * @returns {number} The adjusted hue value within the range of 0 to 359 degrees. + */ export function adjustHue(hue: number): number { return (hue + 360) % 360; } +/** + * Adjusts the saturation value to ensure it falls within the range of 0 to 100. + * @param {number} saturation - The input saturation value to be adjusted. + * @returns {number} The adjusted saturation value, clamped between 0 and 100. + */ export function adjustSaturation(saturation: number): number { return Math.max(0, Math.min(100, saturation)); } +/** + * Adjusts the lightness value to ensure it falls within the valid range of 0 to 100. + * @param {number} lightness - The input lightness value to be adjusted. + * @returns {number} The adjusted lightness value, clamped between 0 and 100. + */ export function adjustLightness(lightness: number): number { return Math.max(0, Math.min(100, lightness)); } +/** + * Generates additional hues based on a given base hue and color scheme. + * @param {number} baseHue - The base hue value in degrees (0-359). + * @param {ColorScheme} scheme - The color scheme to use for generating additional hues. + * @returns {number[]} An array of additional hue values in degrees (0-359). + */ export function generateAdditionalHues( baseHue: number, scheme: ColorScheme diff --git a/src/lib/utils/exportTheme.ts b/src/lib/utils/exportTheme.ts index fe1547c..4242645 100644 --- a/src/lib/utils/exportTheme.ts +++ b/src/lib/utils/exportTheme.ts @@ -2,6 +2,13 @@ import { ColorAliases } from "./themeColors"; import { SyntaxColors } from "./syntaxColors"; import { AnsiColors } from "./ansiColors"; +/** + * Generates a JSON string representing a VS Code theme based on provided color configurations. + * @param {Object} colors - An object containing color aliases. + * @param {Object} syntaxColors - An object containing syntax-specific colors. + * @param {Object} ansiColors - An object containing ANSI color configurations. + * @returns {string} A JSON string representing the generated VS Code theme. + */ export function generateThemeJSON( colors: ColorAliases, syntaxColors: SyntaxColors, diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index bd0c391..d79ff03 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -1,6 +1,13 @@ import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge" +``` +/** + * Merges and combines CSS class names using the clsx and twMerge utilities + * @param {...ClassValue[]} inputs - An array of class values to be merged + * @returns {string} A string of combined and merged CSS class names + */ +``` export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } diff --git a/src/lib/utils/syntaxColors.ts b/src/lib/utils/syntaxColors.ts index e59ab7a..84d06a3 100644 --- a/src/lib/utils/syntaxColors.ts +++ b/src/lib/utils/syntaxColors.ts @@ -41,6 +41,14 @@ export interface SyntaxColors { datetime: string; } +/** + * Generates a harmonized color based on a base hue and color shift. + * @param {number} baseHue - The base hue value (0-359) to start from. + * @param {number} saturation - The saturation value (0-100) for the color. + * @param {number} lightness - The lightness value (0-100) for the color. + * @param {number} shift - The amount to shift the hue by. + * @returns {string} A hexadecimal color string representing the harmonized color. + */ function generateHarmonizedColor( baseHue: number, saturation: number, @@ -51,12 +59,28 @@ function generateHarmonizedColor( return Color.hsl(hue, saturation, lightness).hex(); } +/** + * Blends two colors together based on a given ratio. + * @param {string} color1 - The first color in hexadecimal or named color format. + * @param {string} color2 - The second color in hexadecimal or named color format. + * @param {number} ratio - The blending ratio between 0 and 1, where 0 is fully color1 and 1 is fully color2. + * @returns {string} The resulting blended color in hexadecimal format. + */ function blendColors(color1: string, color2: string, ratio: number): string { const c1 = Color(color1); const c2 = Color(color2); return c1.mix(c2, ratio).hex(); } +/** + * Generates syntax colors for a code editor based on the given background color and scheme hues. + * @param {string} backgroundColor - The background color of the editor. + * @param {number[]} schemeHues - An array of hue values for the color scheme. + * @param {number} [syntaxSaturation=70] - The base saturation for syntax colors. + * @param {Partial} [lockedColors={}] - A partial object of locked syntax colors. + * @param {boolean} [forceRegenerate=false] - Whether to force regeneration of colors without randomness. + * @returns {SyntaxColors} An object containing generated syntax colors. + */ export function generateSyntaxColors( backgroundColor: string, schemeHues: number[], @@ -68,6 +92,14 @@ export function generateSyntaxColors( const isDark = baseColor.isDark(); const baseLightness = isDark ? 70 : 40; + /** + * Generates a color based on the given parameters and color scheme. + * @param {number} hueIndex - The index of the hue in the color scheme. + * @param {number} [saturationMultiplier=1] - Multiplier for the saturation value. + * @param {number} [lightnessShift=0] - Shift value for the lightness. + * @param {number} [hueShift=0] - Shift value for the hue. + * @returns {string} A hexadecimal color code. + */ const generateColor = ( hueIndex: number, saturationMultiplier: number = 1, @@ -188,12 +220,26 @@ export function generateSyntaxColors( return syntaxColors; } +/** + * Updates the syntax colors with a new saturation level while respecting locked colors and ensuring readability. + * @param {SyntaxColors} currentColors - The current syntax color configuration. + * @param {number} newSyntaxSaturation - The new saturation level to apply to the colors. + * @param {string} backgroundColor - The background color used for ensuring readability. + * @param {Set} lockedColors - A set of color keys that should not be modified. + * @returns {SyntaxColors} The updated syntax colors with adjusted saturation and ensured readability. + */ export function updateSyntaxColorsWithSaturation( currentColors: SyntaxColors, newSyntaxSaturation: number, backgroundColor: string, lockedColors: Set ): SyntaxColors { + /** + * Updates the saturation of a given color + * @param {string} color - The color to be adjusted in any valid CSS color format + * @param {number} saturationMultiplier - The factor by which to multiply the saturation + * @returns {string} The adjusted color in hexadecimal format + */ const updateColorSaturation = ( color: string, saturationMultiplier: number @@ -245,6 +291,14 @@ export function updateSyntaxColorsWithSaturation( Object.keys(updatedColors).forEach((key) => { if (!lockedColors.has(key)) { + /** + * Updates the saturation of unlocked colors in a syntax color scheme + * @param {Object} updatedColors - Object containing the colors to be updated + * @param {Set} lockedColors - Set of color keys that should not be modified + * @param {Object} currentColors - Object containing the current color values + * @param {Object} saturationMultipliers - Object containing saturation multipliers for each color key + * @returns {void} This function does not return a value, it modifies the updatedColors object in place + */ updatedColors[key as keyof SyntaxColors] = updateColorSaturation( currentColors[key as keyof SyntaxColors], saturationMultipliers[key as keyof typeof saturationMultipliers] diff --git a/src/lib/utils/themeColors.ts b/src/lib/utils/themeColors.ts index 000a309..eb175af 100644 --- a/src/lib/utils/themeColors.ts +++ b/src/lib/utils/themeColors.ts @@ -25,6 +25,13 @@ export interface ColorAliases { findMatch: string; } +/** + * Generates theme colors based on provided options and initial colors. + * @param {ThemeGenerationOptions} options - Configuration options for theme generation. + * @param {Partial} initialColors - Initial color values to use (optional). + * @param {boolean} forceRegenerate - Flag to force color regeneration (optional). + * @returns {Object} An object containing generated colors, scheme hues, accent hues, and color scheme. + */ export function generateThemeColors( options: ThemeGenerationOptions, initialColors: Partial = {}, @@ -48,6 +55,13 @@ export function generateThemeColors( const bgBase = isDark ? 12 : 97; const fgBase = isDark ? 90 : 10; + /** + * Generates a color based on HSL values with optional randomness. + * @param {number} hue - The base hue value (0-360). + * @param {number} saturation - The base saturation value (0-100). + * @param {number} lightness - The base lightness value (0-100). + * @returns {string} A hexadecimal color string. + */ const generateColor = ( hue: number, saturation: number, @@ -188,11 +202,24 @@ export function generateThemeColors( return { colors, schemeHues, ac1Hue, ac2Hue, scheme }; } +/** + * Updates theme colors with new saturation values while respecting locked colors. + * @param {ColorAliases} currentColors - The current color aliases object. + * @param {number} newUiSaturation - The new UI saturation value to apply. + * @param {Set} lockedColors - Set of color keys that should not be modified. + * @returns {ColorAliases} Updated color aliases object with new saturation values. + */ export function updateThemeColorsWithSaturation( currentColors: ColorAliases, newUiSaturation: number, lockedColors: Set ): ColorAliases { + /** + * Updates the saturation of a given color by a specified multiplier. + * @param {string} color - The input color in any valid CSS color format. + * @param {number} saturationMultiplier - The factor by which to multiply the current saturation. + * @returns {string} The resulting color in hexadecimal format. + */ const updateColorSaturation = ( color: string, saturationMultiplier: number @@ -225,6 +252,14 @@ export function updateThemeColorsWithSaturation( Object.keys(updatedColors).forEach((key) => { if (!lockedColors.has(key)) { + /** + * Updates the saturation of non-locked colors in the updatedColors object + * @param {Object} updatedColors - The object containing color aliases to be updated + * @param {Set} lockedColors - A set of color keys that should not be modified + * @param {Object} currentColors - The current color values for each alias + * @param {Object} saturationMultipliers - Multipliers for adjusting saturation for each color key + * @returns {void} This function doesn't return a value, it modifies the updatedColors object in place + */ updatedColors[key as keyof ColorAliases] = updateColorSaturation( currentColors[key as keyof ColorAliases], saturationMultipliers[key as keyof typeof saturationMultipliers]