Files
ghatreh_user/src/config/brand-theme.ts
T
2026-07-08 16:03:22 +03:30

134 lines
3.9 KiB
TypeScript

import { getConfig } from '@/config/app-config'
import { colors } from '@/themeConfig'
export const DEFAULT_PRIMARY_COLOR = '#a72b77'
export const DEFAULT_SECONDARY_COLOR = '#a72b77'
export const DEFAULT_TERTIARY_COLOR = '#e0be7f'
export const DEFAULT_BACKGROUND_COLOR = '#ffffff'
function normalizeHex(value: unknown): string | null {
if (typeof value !== 'string') return null
const trimmed = value.trim()
if (!trimmed) return null
const withHash = trimmed.startsWith('#') ? trimmed : `#${trimmed}`
if (!/^#[0-9a-fA-F]{6}$/.test(withHash) && !/^#[0-9a-fA-F]{3}$/.test(withHash)) {
return null
}
if (withHash.length === 4) {
const [, r, g, b] = withHash
return `#${r}${r}${g}${g}${b}${b}`.toLowerCase()
}
return withHash.toLowerCase()
}
function lightenHex(hex: string, amount = 0.22): string {
const normalized = normalizeHex(hex)
if (!normalized) return hex
const num = parseInt(normalized.slice(1), 16)
const r = (num >> 16) & 255
const g = (num >> 8) & 255
const b = num & 255
const mix = (channel: number) => Math.round(channel + (255 - channel) * amount)
return `#${[mix(r), mix(g), mix(b)]
.map((channel) => channel.toString(16).padStart(2, '0'))
.join('')}`
}
function darkenHex(hex: string, amount = 0.22): string {
const normalized = normalizeHex(hex)
if (!normalized) return hex
const num = parseInt(normalized.slice(1), 16)
const r = Math.round(((num >> 16) & 255) * (1 - amount))
const g = Math.round(((num >> 8) & 255) * (1 - amount))
const b = Math.round((num & 255) * (1 - amount))
return `#${[r, g, b].map((channel) => channel.toString(16).padStart(2, '0')).join('')}`
}
export function getAppPrimaryColor(fallback = DEFAULT_PRIMARY_COLOR): string {
return (
normalizeHex(getConfig('color')) ||
normalizeHex(getConfig('primary_color')) ||
normalizeHex(getConfig('primary')) ||
fallback
)
}
export function getAppSecondaryColor(fallback = DEFAULT_SECONDARY_COLOR): string {
return (
normalizeHex(getConfig('secondary_color')) ||
normalizeHex(getConfig('secondary')) ||
getAppPrimaryColor(fallback)
)
}
export function getAppTertiaryColor(fallback = DEFAULT_TERTIARY_COLOR): string {
return (
normalizeHex(getConfig('tertiary_color')) ||
normalizeHex(getConfig('tertiary')) ||
fallback
)
}
export function getAppBackgroundColor(fallback = DEFAULT_BACKGROUND_COLOR): string {
return (
normalizeHex(getConfig('background_color')) ||
normalizeHex(getConfig('background')) ||
fallback
)
}
export function getAppPrimaryDark(fallback = '#711d4d'): string {
return darkenHex(getAppPrimaryColor(), 0.22) || fallback
}
export function getAppPrimaryLight(fallback = '#c45f9a'): string {
return lightenHex(getAppPrimaryColor(), 0.22) || fallback
}
function setCssVar(name: string, value: string) {
document.documentElement.style.setProperty(name, value)
}
export function applyBrandTheme() {
const primary = getAppPrimaryColor()
const secondary = getAppSecondaryColor()
const tertiary = getAppTertiaryColor()
const background = getAppBackgroundColor()
const primaryDark = getAppPrimaryDark()
const primaryLight = getAppPrimaryLight()
setCssVar('--app-primary-color', primary)
setCssVar('--app-secondary-color', secondary)
setCssVar('--app-tertiary-color', tertiary)
setCssVar('--app-background-color', background)
setCssVar('--app-primary-dark', primaryDark)
setCssVar('--app-primary-light', primaryLight)
colors.primary = primary
colors['primary-rgba'] = primary
colors.secondary = secondary
colors['secondary-rgba'] = secondary
colors.tertiary = tertiary
colors['tertiary-rgba'] = tertiary
const themeMeta = document.querySelector<HTMLMetaElement>('meta[name="theme-color"]')
if (themeMeta) {
themeMeta.content = primary
} else {
const meta = document.createElement('meta')
meta.name = 'theme-color'
meta.content = primary
document.head.appendChild(meta)
}
}