127 lines
5.9 KiB
TypeScript
127 lines
5.9 KiB
TypeScript
import { hexFromArgb, Theme } from "@material/material-color-utilities";
|
|
import React from "react";
|
|
import { createContext, useContext } from "react";
|
|
import { useScheme } from "./useScheme";
|
|
|
|
const ThemeContext = createContext<Theme | undefined>(undefined);
|
|
|
|
export function ThemeProvider({ children, theme, scheme }: { children: React.ReactNode, theme: Theme, scheme: 'dark' | 'light' }) {
|
|
return (
|
|
<ThemeContext.Provider value={theme}>
|
|
<style>
|
|
{`
|
|
body {
|
|
|
|
--md-ref-typeface-brand: 'Roboto Flex';
|
|
--md-ref-typeface-plain: 'Roboto Flex';
|
|
|
|
--md-sys-color-primary: ${hexFromArgb(theme.schemes[scheme].primary)};
|
|
--md-sys-color-primary-container: ${hexFromArgb(theme.schemes[scheme].primaryContainer)};
|
|
--md-sys-color-secondary: ${hexFromArgb(theme.schemes[scheme].secondary)};
|
|
--md-sys-color-secondary-container: ${hexFromArgb(theme.schemes[scheme].secondaryContainer)};
|
|
--md-sys-color-tertiary: ${hexFromArgb(theme.schemes[scheme].tertiary)};
|
|
--md-sys-color-tertiary-container: ${hexFromArgb(theme.schemes[scheme].tertiaryContainer)};
|
|
--md-sys-color-error: ${hexFromArgb(theme.schemes[scheme].error)};
|
|
--md-sys-color-error-container: ${hexFromArgb(theme.schemes[scheme].errorContainer)};
|
|
--md-sys-color-background: ${hexFromArgb(theme.schemes[scheme].background)};
|
|
--md-sys-color-surface: ${hexFromArgb(theme.schemes[scheme].surface)};
|
|
--md-sys-color-surface-bright: ${hexFromArgb(theme.schemes[scheme].surface)};
|
|
--md-sys-color-surface-dim: ${hexFromArgb(theme.schemes[scheme].surface)};
|
|
--md-sys-color-surface-container: ${hexFromArgb(theme.schemes[scheme].surface)};
|
|
--md-sys-color-surface-container-lowest: ${hexFromArgb(theme.schemes[scheme].surface)};
|
|
--md-sys-color-surface-container-low: ${hexFromArgb(theme.schemes[scheme].surface)};
|
|
--md-sys-color-surface-container-high: ${hexFromArgb(theme.schemes[scheme].surface)};
|
|
--md-sys-color-surface-container-highest: ${hexFromArgb(theme.schemes[scheme].surface)};
|
|
--md-sys-color-outline: ${hexFromArgb(theme.schemes[scheme].outline)};
|
|
--md-sys-color-outline-variant: ${hexFromArgb(theme.schemes[scheme].outlineVariant)};
|
|
--md-sys-color-scrim: ${hexFromArgb(theme.schemes[scheme].scrim)};
|
|
--md-sys-color-shadow: ${hexFromArgb(theme.schemes[scheme].shadow)};
|
|
--md-sys-color-on-surface: ${hexFromArgb(theme.schemes[scheme].onSurface)};
|
|
--md-sys-color-on-surface-variant: ${hexFromArgb(theme.schemes[scheme].onSurfaceVariant)};
|
|
--md-sys-color-on-surface-bright: ${hexFromArgb(theme.schemes[scheme].onSurface)};
|
|
--md-sys-color-on-surface-dim: ${hexFromArgb(theme.schemes[scheme].onSurface)};
|
|
--md-sys-color-background: ${hexFromArgb(theme.schemes[scheme].background)};
|
|
--md-sys-color-background-variant: ${hexFromArgb(theme.schemes[scheme].surface)};
|
|
|
|
--md-sys-color-on-primary: ${hexFromArgb(theme.schemes[scheme].onPrimary)};
|
|
--md-sys-color-on-primary-container: ${hexFromArgb(theme.schemes[scheme].onPrimaryContainer)};
|
|
--md-sys-color-on-secondary: ${hexFromArgb(theme.schemes[scheme].onSecondary)};
|
|
--md-sys-color-on-secondary-container: ${hexFromArgb(theme.schemes[scheme].onSecondaryContainer)};
|
|
--md-sys-color-on-tertiary: ${hexFromArgb(theme.schemes[scheme].onTertiary)};
|
|
--md-sys-color-on-tertiary-container: ${hexFromArgb(theme.schemes[scheme].onTertiaryContainer)};
|
|
--md-sys-color-on-error: ${hexFromArgb(theme.schemes[scheme].onError)};
|
|
--md-sys-color-on-error-container: ${hexFromArgb(theme.schemes[scheme].onErrorContainer)};
|
|
|
|
--md-sys-typescale-headline-small-font: 'Roboto Flex';
|
|
--md-sys-typescale-headline-medium-font: 'Roboto Flex';
|
|
--md-sys-typescale-headline-large-font: 'Roboto Flex';
|
|
|
|
--md-sys-typescale-headline-small-size: 24px;
|
|
--md-sys-typescale-headline-medium-size: 32px;
|
|
--md-sys-typescale-headline-large-size: 40px;
|
|
|
|
--md-sys-typescale-headline-small-weight: 400;
|
|
--md-sys-typescale-headline-medium-weight: 400;
|
|
--md-sys-typescale-headline-large-weight: 400;
|
|
|
|
--md-sys-typescale-headline-small-line-height: 32px;
|
|
--md-sys-typescale-headline-medium-line-height: 40px;
|
|
--md-sys-typescale-headline-large-line-height: 48px;
|
|
|
|
--md-sys-typescale-body-small-font: 'Roboto Flex';
|
|
--md-sys-typescale-body-medium-font: 'Roboto Flex';
|
|
--md-sys-typescale-body-large-font: 'Roboto Flex';
|
|
|
|
--md-sys-typescale-body-small-size: 12px;
|
|
--md-sys-typescale-body-medium-size: 14px;
|
|
--md-sys-typescale-body-large-size: 16px;
|
|
|
|
--md-sys-typescale-body-small-weight: 400;
|
|
--md-sys-typescale-body-medium-weight: 400;
|
|
--md-sys-typescale-body-large-weight: 400;
|
|
|
|
--md-sys-typescale-body-small-line-height: 16px;
|
|
--md-sys-typescale-body-medium-line-height: 20px;
|
|
--md-sys-typescale-body-large-line-height: 24px;
|
|
|
|
|
|
|
|
--md-sys-typescale-label-small-font: 'Roboto Flex';
|
|
--md-sys-typescale-label-medium-font: 'Roboto Flex';
|
|
--md-sys-typescale-label-large-font: 'Roboto Flex';
|
|
|
|
--md-sys-typescale-label-small-size: 12px;
|
|
--md-sys-typescale-label-medium-size: 14px;
|
|
--md-sys-typescale-label-large-size: 16px;
|
|
|
|
--md-sys-typescale-label-small-weight: 400;
|
|
--md-sys-typescale-label-medium-weight: 400;
|
|
--md-sys-typescale-label-large-weight: 400;
|
|
|
|
--md-sys-typescale-label-small-line-height: 16px;
|
|
--md-sys-typescale-label-medium-line-height: 20px;
|
|
--md-sys-typescale-label-large-line-height: 24px;
|
|
|
|
background-color: var(--md-sys-color-background);
|
|
}
|
|
`}
|
|
</style>
|
|
{children}
|
|
</ThemeContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useTheme() {
|
|
const context = useContext(ThemeContext);
|
|
if (context === undefined) {
|
|
throw new Error("useTheme must be used within a ThemeProvider");
|
|
}
|
|
return context;
|
|
}
|
|
|
|
export function usePalette() {
|
|
const theme = useTheme();
|
|
const scheme = useScheme();
|
|
return theme.schemes[scheme];
|
|
}
|