"use client" import { createContext, useContext, useState, useEffect, type ReactNode } from "react" import type { CSSProperties } from "react" type ShadowDepth = "none" | "subtle" | "medium" | "pronounced" type ShadowContextType = { shadowDepth: ShadowDepth setShadowDepth: (value: ShadowDepth) => void shadowColor: string setShadowColor: (value: string) => void getElevationClass: (level: number) => string getElevationStyle: (level: number) => CSSProperties } const ShadowContext = createContext(undefined) export function ShadowProvider({ children }: { children: ReactNode }) { const [shadowDepth, setShadowDepth] = useState("medium") const [shadowColor, setShadowColor] = useState("#000000") useEffect(() => { // Only run on client-side if (typeof window === "undefined") return const root = document.documentElement // Define shadow values based on depth const shadowValues = { none: { light: "none", dark: "none", }, subtle: { light: `0 1px 2px rgba(${hexToRgb(shadowColor)}, 0.05)`, dark: `0 1px 2px rgba(${hexToRgb(shadowColor)}, 0.15)`, }, medium: { light: `0 1px 3px rgba(${hexToRgb(shadowColor)}, 0.1), 0 1px 2px rgba(${hexToRgb(shadowColor)}, 0.06)`, dark: `0 1px 3px rgba(${hexToRgb(shadowColor)}, 0.25), 0 1px 2px rgba(${hexToRgb(shadowColor)}, 0.15)`, }, pronounced: { light: `0 4px 6px rgba(${hexToRgb(shadowColor)}, 0.1), 0 2px 4px rgba(${hexToRgb(shadowColor)}, 0.06)`, dark: `0 4px 6px rgba(${hexToRgb(shadowColor)}, 0.25), 0 2px 4px rgba(${hexToRgb(shadowColor)}, 0.15)`, }, } // Set CSS variables for shadows root.style.setProperty("--shadow-sm", shadowValues[shadowDepth].light) root.style.setProperty("--shadow-md", shadowValues[shadowDepth].light) root.style.setProperty("--shadow-lg", shadowValues[shadowDepth].light) root.style.setProperty("--shadow-xl", shadowValues[shadowDepth].light) // Set dark mode shadow variables root.style.setProperty("--shadow-sm-dark", shadowValues[shadowDepth].dark) root.style.setProperty("--shadow-md-dark", shadowValues[shadowDepth].dark) root.style.setProperty("--shadow-lg-dark", shadowValues[shadowDepth].dark) root.style.setProperty("--shadow-xl-dark", shadowValues[shadowDepth].dark) }, [shadowDepth, shadowColor]) return ( { const classes = ["shadow-none", "shadow-sm", "shadow-md", "shadow-lg"] return classes[Math.min(level, classes.length - 1)] }, getElevationStyle: (level: number) => { if (level === 0) return { boxShadow: "none" } const shadowValues = { subtle: { 1: `0 1px 2px rgba(${hexToRgb(shadowColor)}, 0.05)`, 2: `0 1px 3px rgba(${hexToRgb(shadowColor)}, 0.1)`, 3: `0 4px 6px rgba(${hexToRgb(shadowColor)}, 0.1)`, }, medium: { 1: `0 1px 3px rgba(${hexToRgb(shadowColor)}, 0.1), 0 1px 2px rgba(${hexToRgb(shadowColor)}, 0.06)`, 2: `0 4px 6px rgba(${hexToRgb(shadowColor)}, 0.1), 0 2px 4px rgba(${hexToRgb(shadowColor)}, 0.06)`, 3: `0 10px 15px rgba(${hexToRgb(shadowColor)}, 0.1), 0 4px 6px rgba(${hexToRgb(shadowColor)}, 0.05)`, }, pronounced: { 1: `0 2px 4px rgba(${hexToRgb(shadowColor)}, 0.15)`, 2: `0 4px 8px rgba(${hexToRgb(shadowColor)}, 0.15), 0 2px 4px rgba(${hexToRgb(shadowColor)}, 0.1)`, 3: `0 15px 25px rgba(${hexToRgb(shadowColor)}, 0.15), 0 5px 10px rgba(${hexToRgb(shadowColor)}, 0.05)`, }, } return { boxShadow: shadowValues[shadowDepth][Math.min(level, 3) as 1 | 2 | 3], } }, }} > {children} ) } export function useShadow() { const context = useContext(ShadowContext) if (context === undefined) { throw new Error("useShadow must be used within a ShadowProvider") } return context } // Helper function to convert hex to RGB function hexToRgb(hex: string): string { // Remove # if present hex = hex.replace(/^#/, "") // Parse hex values let r, g, b if (hex.length === 3) { r = Number.parseInt(hex[0] + hex[0], 16) g = Number.parseInt(hex[1] + hex[1], 16) b = Number.parseInt(hex[2] + hex[2], 16) } else { r = Number.parseInt(hex.substring(0, 2), 16) g = Number.parseInt(hex.substring(2, 4), 16) b = Number.parseInt(hex.substring(4, 6), 16) } return `${r}, ${g}, ${b}` }