add primary color and splash screen
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
|
||||
interface UseThemeColorProps {
|
||||
primaryColor?: string | null;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* تبدیل hex به RGB normalized (0-1)
|
||||
*/
|
||||
function hexToRgbNormalized(
|
||||
hex: string
|
||||
): { r: number; g: number; b: number } | null {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
return result
|
||||
? {
|
||||
r: parseInt(result[1], 16) / 255,
|
||||
g: parseInt(result[2], 16) / 255,
|
||||
b: parseInt(result[3], 16) / 255,
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* تبدیل RGB به OKLCH (تقریبی)
|
||||
*/
|
||||
function rgbToOklch(r: number, g: number, b: number): string {
|
||||
// محاسبه Lightness تقریبی
|
||||
const lightness = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
||||
|
||||
// محاسبه Chroma و Hue (ساده شده)
|
||||
const max = Math.max(r, g, b);
|
||||
const min = Math.min(r, g, b);
|
||||
const chroma = (max - min) * 0.15; // مقدار تقریبی
|
||||
|
||||
let hue = 0;
|
||||
if (chroma !== 0) {
|
||||
if (max === r) {
|
||||
hue = ((g - b) / (max - min) + (g < b ? 6 : 0)) * 60;
|
||||
} else if (max === g) {
|
||||
hue = ((b - r) / (max - min) + 2) * 60;
|
||||
} else {
|
||||
hue = ((r - g) / (max - min) + 4) * 60;
|
||||
}
|
||||
}
|
||||
|
||||
return `oklch(${lightness.toFixed(3)} ${chroma.toFixed(3)} ${hue.toFixed(
|
||||
1
|
||||
)})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* هوک برای تغییر دینامیک رنگ primary بر اساس رنگ دریافتی از about
|
||||
*/
|
||||
export function useThemeColor({
|
||||
primaryColor,
|
||||
enabled = true,
|
||||
}: UseThemeColorProps) {
|
||||
useEffect(() => {
|
||||
if (!enabled || !primaryColor) return;
|
||||
|
||||
try {
|
||||
const root = document.documentElement;
|
||||
|
||||
// اگر رنگ hex هست، آن را به oklch تبدیل میکنیم
|
||||
if (primaryColor.startsWith("#")) {
|
||||
const rgb = hexToRgbNormalized(primaryColor);
|
||||
if (rgb) {
|
||||
const oklchColor = rgbToOklch(rgb.r, rgb.g, rgb.b);
|
||||
|
||||
// اعمال رنگ primary
|
||||
root.style.setProperty("--primary", oklchColor);
|
||||
|
||||
// محاسبه رنگ foreground متناسب
|
||||
const brightness = (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
|
||||
const foregroundOklch =
|
||||
brightness > 0.5 ? "oklch(0 0 0)" : "oklch(1 0 0)";
|
||||
root.style.setProperty("--primary-foreground", foregroundOklch);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error setting theme color:", error);
|
||||
}
|
||||
}, [primaryColor, enabled]);
|
||||
}
|
||||
Reference in New Issue
Block a user