Skip to content

Instantly share code, notes, and snippets.

@Avi-E-Koenig
Created May 23, 2025 10:58
Show Gist options
  • Save Avi-E-Koenig/24cc6388a9029f3e3d2234a6f7ca8ea9 to your computer and use it in GitHub Desktop.
Save Avi-E-Koenig/24cc6388a9029f3e3d2234a6f7ca8ea9 to your computer and use it in GitHub Desktop.
'use client';
import React, { createContext, JSX, useCallback, useContext, useEffect, useState } from "react";
import { useLocalStorage } from "@/hooks/useLocalStorage";
import { THEME, LOCALE } from "@/theme";
// import type { ThemeMode, LocaleType } from '@/theme';
interface ApplicationConfigsProps {
children: JSX.Element;
}
interface ApplicationConfigsContextInterface {
changeTheme: (theme: THEME) => void;
changeLocale: (locale: LOCALE) => void;
theme: THEME;
locale: LOCALE;
isDark: boolean;
dir: 'ltr' | 'rtl';
systemChanged: boolean;
}
export const defaultApplicationConfigsContext: ApplicationConfigsContextInterface = {
theme: THEME.LIGHT,
locale: LOCALE.EN,
isDark: false,
dir: 'ltr',
// eslint-disable-next-line @typescript-eslint/no-unused-vars
changeTheme: (theme: THEME) => { },
// eslint-disable-next-line @typescript-eslint/no-unused-vars
changeLocale: (locale: LOCALE) => { },
systemChanged: false
};
const MEDIA = '(prefers-color-scheme: dark)'
export const ApplicationConfigsContext = createContext(defaultApplicationConfigsContext);
export const useApplicationConfigs = () => {
const context = useContext(ApplicationConfigsContext);
if (!context) {
throw new Error('useApplicationConfigs must be used within an ApplicationConfigsProvider');
}
return context;
};
const ApplicationConfigs = ({ children }: ApplicationConfigsProps) => {
const defaultConfig = {
theme: THEME.SYSTEM,
locale: LOCALE.EN
};
const [config, setConfig] = useLocalStorage<typeof defaultConfig>("config", defaultConfig);
const [systemChanged, setSystemChanged] = useState(false);
const changeTheme = useCallback(
(theme: THEME) => {
setConfig((prev) => ({ ...prev, theme }));
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
const changeLocale = useCallback(
(locale: LOCALE) => {
setConfig((prev) => ({ ...prev, locale }));
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
const handleMediaQuery = useCallback(() => {
if (config.theme === THEME.SYSTEM) {
setSystemChanged(prevState => !prevState);
}
},
[config.theme]
);
useEffect(() => {
const media = window.matchMedia(MEDIA)
media.addEventListener('change', handleMediaQuery)
return () => media.removeEventListener('change', handleMediaQuery)
}, [handleMediaQuery]);
return (
<ApplicationConfigsContext.Provider
value={{
theme: config.theme,
locale: config.locale,
isDark: config.theme === THEME.DARK,
dir: config.locale === LOCALE.HE ? 'rtl' : 'ltr',
changeTheme,
changeLocale,
systemChanged
}}
>
{children}
</ApplicationConfigsContext.Provider>
);
};
export default ApplicationConfigs;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment