diff --git a/packages/react-component/src/theme/MusmaProvider/ColorType.ts b/packages/react-component/src/theme/MusmaProvider/ColorType.ts new file mode 100644 index 00000000..d35217f4 --- /dev/null +++ b/packages/react-component/src/theme/MusmaProvider/ColorType.ts @@ -0,0 +1,139 @@ +interface DefaultColorSet { + /** + * @default + * lighter: '#F2F8FB', + * light: '#118EE5', + * main: '#036DB7', + * dark: '#025996', + * darker: '#003E6A', + */ + primary: { + lighter: string + light: string + main: string + dark: string + darker: string + } + /** + * @default + * lighter: '#F2F8FB', + * light: '#118EE5', + * main: '#036DB7', + * dark: '#025996', + * darker: '#003E6A', + */ + blue: { + lighter: string + light: string + main: string + dark: string + darker: string + } + /** + * @default + * lighter: '#667085', + light: '#475467', + main: '#44505C', + dark: '#242E40', + darker: '#0E1C31', + */ + black: { + lighter: string + light: string + main: string + dark: string + darker: string + } + /** + * @default + lighter: '#EFE7EB', + light: '#D9E1E5', + main: '#D0D5DD', + dark: '#C4D2E0', + darker: '#BAC7D5', + */ + gray: { + lighter: string + light: string + main: string + dark: string + darker: string + } + /** + * @default + lighter: '#F4F6F9', + light: '#F9FAFB', + main: '#FFFFFF', + dark: '#EEEEEE', + darker: '#EAEAEA', + */ + white: { + lighter: string + light: string + main: string + dark: string + darker: string + } + /** + * @default + lighter: '#EDDDDD', + light: '#FF4D4F', + main: '#CA3C3D', + dark: '#A63132', + darker: '#940E0F', + */ + red: { + lighter: string + light: string + main: string + dark: string + darker: string + } + /** + * @default + lighter: '#E6E8D8', + light: '#00AA52', + main: '#107C41', + dark: '#066B36', + darker: '#054522', + */ + green: { + lighter: string + light: string + main: string + dark: string + darker: string + } + /** + * @default + lighter: '#FD9009', + light: '#FFAB43', + main: '#FD9009', + dark: '#E76F00', + darker: '#DB6900', + */ + orange: { + lighter: string + light: string + main: string + dark: string + darker: string + } + /** + * @default + * transparent: 'transparent' + */ + transparent: string +} + +export interface Pallet extends DefaultColorSet { + [key: string]: + | { + lighter: string + light: string + main: string + dark: string + darker: string + } + | string +} diff --git a/packages/react-component/src/theme/MusmaProvider/MusmaProvider.tsx b/packages/react-component/src/theme/MusmaProvider/MusmaProvider.tsx index ec1641cd..17daab95 100644 --- a/packages/react-component/src/theme/MusmaProvider/MusmaProvider.tsx +++ b/packages/react-component/src/theme/MusmaProvider/MusmaProvider.tsx @@ -5,20 +5,32 @@ import { EmotionCache, ThemeProvider } from '@emotion/react' import { NormalizeCSS, PretendardFont, MusmaTheme } from 'src/theme' import { DefaultTheme } from './DefaultTheme' +import { ThemeObject, useMultiTheme } from './useMultiTheme' interface MusmaProviderContextType { theme?: MusmaTheme emotionCache?: EmotionCache + currentTheme?: string + themeOptions: { label: string; value: string }[] + handleThemeChange?: (themeName?: string) => void } const MusmaProviderContext = createContext({ theme: DefaultTheme, + themeOptions: [], }) +/** + * @deprecated + */ export function useMusmaTheme() { return useContext(MusmaProviderContext)?.theme || DefaultTheme } +export function useThemeContext() { + return useContext(MusmaProviderContext) +} + export interface MusmaProviderProps { /** * NormalizeCSS 사용 여부 @@ -35,6 +47,10 @@ export interface MusmaProviderProps { * @default true */ theme?: MusmaTheme + /** + * 여러 테마가 필요할 때 사용합니다. 일단 전달하면 첫 번째 항목이 기본 테마가 됩니다 + */ + themeList?: ThemeObject[] /** * SSR 환경에서 사용할 시 EmotionCache 객체를 생성하여 넣습니다. * @default undefined @@ -50,11 +66,14 @@ export const MusmaProvider = ({ withNormalizeCSS = true, withPretendardFont = true, theme = DefaultTheme, + themeList = [], children, }: MusmaProviderProps) => { + const { value, currentThemeObject } = useMultiTheme({ theme, themeList }) + return ( - - + + {withNormalizeCSS && } {withPretendardFont && } {children} diff --git a/packages/react-component/src/theme/MusmaProvider/MusmaTheme.ts b/packages/react-component/src/theme/MusmaProvider/MusmaTheme.ts index 9de25a6c..9fe26907 100644 --- a/packages/react-component/src/theme/MusmaProvider/MusmaTheme.ts +++ b/packages/react-component/src/theme/MusmaProvider/MusmaTheme.ts @@ -1,133 +1,9 @@ import { Size } from 'src/types' +import { Pallet } from './ColorType' + export interface MusmaTheme { - colors: { - /** - * @default - * lighter: '#F2F8FB', - * light: '#118EE5', - * main: '#036DB7', - * dark: '#025996', - * darker: '#003E6A', - */ - primary: { - lighter: string - light: string - main: string - dark: string - darker: string - } - /** - * @default - * lighter: '#F2F8FB', - * light: '#118EE5', - * main: '#036DB7', - * dark: '#025996', - * darker: '#003E6A', - */ - blue: { - lighter: string - light: string - main: string - dark: string - darker: string - } - /** - * @default - * lighter: '#667085', - light: '#475467', - main: '#44505C', - dark: '#242E40', - darker: '#0E1C31', - */ - black: { - lighter: string - light: string - main: string - dark: string - darker: string - } - /** - * @default - lighter: '#EFE7EB', - light: '#D9E1E5', - main: '#D0D5DD', - dark: '#C4D2E0', - darker: '#BAC7D5', - */ - gray: { - lighter: string - light: string - main: string - dark: string - darker: string - } - /** - * @default - lighter: '#F4F6F9', - light: '#F9FAFB', - main: '#FFFFFF', - dark: '#EEEEEE', - darker: '#EAEAEA', - */ - white: { - lighter: string - light: string - main: string - dark: string - darker: string - } - /** - * @default - lighter: '#EDDDDD', - light: '#FF4D4F', - main: '#CA3C3D', - dark: '#A63132', - darker: '#940E0F', - */ - red: { - lighter: string - light: string - main: string - dark: string - darker: string - } - /** - * @default - lighter: '#E6E8D8', - light: '#00AA52', - main: '#107C41', - dark: '#066B36', - darker: '#054522', - */ - green: { - lighter: string - light: string - main: string - dark: string - darker: string - } - /** - * @default - lighter: '#FD9009', - light: '#FFAB43', - main: '#FD9009', - dark: '#E76F00', - darker: '#DB6900', - */ - orange: { - lighter: string - light: string - main: string - dark: string - darker: string - } - /** - * @default - * transparent: 'transparent' - */ - transparent: string - } + colors: Pallet /** * @default sm: 2, diff --git a/packages/react-component/src/theme/MusmaProvider/useMultiTheme.ts b/packages/react-component/src/theme/MusmaProvider/useMultiTheme.ts new file mode 100644 index 00000000..df386e26 --- /dev/null +++ b/packages/react-component/src/theme/MusmaProvider/useMultiTheme.ts @@ -0,0 +1,50 @@ +import { useState, useMemo, useCallback } from 'react' + +import { MusmaTheme } from './MusmaTheme' + +export type ThemeObject = { name: string; theme: MusmaTheme } + +interface UseStoreParams { + theme: MusmaTheme + themeList: ThemeObject[] +} +export const useMultiTheme = ({ theme, themeList }: UseStoreParams) => { + const [currentTheme, setCurrentTheme] = useState( + themeList.length === 0 ? 'default' : themeList[0].name, + ) + + const currentThemeObject = useMemo(() => { + if (themeList.length === 0) { + return theme + } + return themeList.find(({ name }) => name === currentTheme)?.theme || theme + }, [currentTheme, theme, themeList]) + + const handleThemeChange = useCallback((theme?: string) => { + if (!theme) { + setCurrentTheme('default') + return + } + setCurrentTheme(theme) + }, []) + + const themeOptions = useMemo(() => { + if (themeList.length === 0) { + return [{ label: 'default', value: 'default' }] + } + return themeList.map(({ name }) => ({ label: name, value: name })) + }, [theme, themeList]) + + const value = useMemo(() => { + return { + themeOptions, + currentTheme, + handleThemeChange, + } + }, [currentTheme, themeOptions, handleThemeChange]) + + return { + currentThemeObject, + value, + } +}