Files
39e8ae8f-063e-4efd-a4df-9b5…/src/providers/themeProvider/ThemeProvider.tsx
2026-02-09 18:11:43 +02:00

127 lines
4.6 KiB
TypeScript

"use client";
import { createContext, useContext } from "react";
import type { ThemeConfig, ThemeProviderProps } from "./config/types";
import { borderRadiusMap, borderRadiusCappedMap, contentWidthMap, expandedContentWidthMap, baseVwMap, textSizingMap, backgroundComponents, headingFontWeightMap } from "./config/constants";
import { cardStyleMap, getGradientBorderedPseudo } from "./styles/cardStyles";
import { primaryButtonStyleMap } from "./styles/primaryButtonStyles";
import { secondaryButtonStyleMap } from "./styles/secondaryButtonStyles";
const ThemeContext = createContext<ThemeConfig | undefined>(undefined);
export const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error(
"useTheme must be used within a ThemeProvider. Wrap your sections in <ThemeProvider> at the app/page level."
);
}
return context;
};
export const ThemeProvider = ({
children,
defaultButtonVariant,
defaultTextAnimation,
borderRadius,
contentWidth,
sizing,
background,
cardStyle,
primaryButtonStyle,
secondaryButtonStyle,
headingFontWeight,
}: ThemeProviderProps) => {
const themeConfig: ThemeConfig = {
defaultButtonVariant,
defaultTextAnimation,
borderRadius,
contentWidth,
sizing,
background,
cardStyle,
primaryButtonStyle,
secondaryButtonStyle,
headingFontWeight,
};
const borderRadiusValue = borderRadiusMap[borderRadius];
const borderRadiusCappedValue = borderRadiusCappedMap[borderRadius];
const contentWidthValues = contentWidthMap[contentWidth];
const expandedContentWidthValues = expandedContentWidthMap[contentWidth];
const baseVwValues = baseVwMap[sizing];
const textSizingValues = textSizingMap[sizing];
const BackgroundComponent = backgroundComponents[background];
const headingFontWeightValue = headingFontWeightMap[headingFontWeight];
const cardStyles = cardStyleMap[cardStyle];
const primaryButtonStyles = primaryButtonStyleMap[primaryButtonStyle];
const secondaryButtonStyles = secondaryButtonStyleMap[secondaryButtonStyle];
const gradientBorderedPseudo = getGradientBorderedPseudo(cardStyle);
const styleString = `
:root {
--theme-border-radius: ${borderRadiusValue};
--theme-border-radius-capped: ${borderRadiusCappedValue};
--width-content-width: ${contentWidthValues.desktop};
--width-content-width-expanded: ${expandedContentWidthValues.desktop};
--vw: ${baseVwValues.desktop};
--heading-font-weight: ${headingFontWeightValue};
--text-2xs: ${textSizingValues.desktop.text2xs};
--text-xs: ${textSizingValues.desktop.textXs};
--text-sm: ${textSizingValues.desktop.textSm};
--text-base: ${textSizingValues.desktop.textBase};
--text-lg: ${textSizingValues.desktop.textLg};
--text-xl: ${textSizingValues.desktop.textXl};
--text-2xl: ${textSizingValues.desktop.text2xl};
--text-3xl: ${textSizingValues.desktop.text3xl};
--text-4xl: ${textSizingValues.desktop.text4xl};
--text-5xl: ${textSizingValues.desktop.text5xl};
--text-6xl: ${textSizingValues.desktop.text6xl};
--text-7xl: ${textSizingValues.desktop.text7xl};
--text-8xl: ${textSizingValues.desktop.text8xl};
--text-9xl: ${textSizingValues.desktop.text9xl};
}
@media (max-width: 768px) {
:root {
--width-content-width: ${contentWidthValues.mobile};
--width-content-width-expanded: ${expandedContentWidthValues.mobile};
--vw: ${baseVwValues.mobile};
--text-2xs: ${textSizingValues.mobile.text2xs};
--text-xs: ${textSizingValues.mobile.textXs};
--text-sm: ${textSizingValues.mobile.textSm};
--text-base: ${textSizingValues.mobile.textBase};
--text-lg: ${textSizingValues.mobile.textLg};
--text-xl: ${textSizingValues.mobile.textXl};
--text-2xl: ${textSizingValues.mobile.text2xl};
--text-3xl: ${textSizingValues.mobile.text3xl};
--text-4xl: ${textSizingValues.mobile.text4xl};
--text-5xl: ${textSizingValues.mobile.text5xl};
--text-6xl: ${textSizingValues.mobile.text6xl};
--text-7xl: ${textSizingValues.mobile.text7xl};
--text-8xl: ${textSizingValues.mobile.text8xl};
--text-9xl: ${textSizingValues.mobile.text9xl};
}
}
.card {
${cardStyles}
}
${gradientBorderedPseudo}
.primary-button {
${primaryButtonStyles}
}
.secondary-button {
${secondaryButtonStyles}
}
`;
return (
<ThemeContext.Provider value={themeConfig}>
<style>{styleString}</style>
{BackgroundComponent && <BackgroundComponent />}
{children}
</ThemeContext.Provider>
);
};