Switch to "colorSchemes" from "palette" API in mui theme
"colorSchemes" is the preferred api starting from mui v6
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { ThemeOptions } from '@mui/material/styles';
|
||||
import { CssVarsThemeOptions } from '@mui/material/styles';
|
||||
import WebFont from 'webfontloader';
|
||||
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||
import { ControlledPromise } from '@/lib/ControlledPromise.ts';
|
||||
@@ -66,12 +66,12 @@ const getFontsFromTheme = (obj: Record<string, any>, fonts: string[] = []): stri
|
||||
|
||||
const loadedFonts: string[] = [];
|
||||
|
||||
export const hasMissingFonts = (theme: ThemeOptions): boolean => {
|
||||
export const hasMissingFonts = (theme: CssVarsThemeOptions): boolean => {
|
||||
const themeFonts = getFontsFromTheme(theme.typography ?? {});
|
||||
return !!themeFonts.length && themeFonts.some((font) => !loadedFonts.includes(font));
|
||||
};
|
||||
|
||||
export const loadThemeFonts = async (theme: ThemeOptions): Promise<void> => {
|
||||
export const loadThemeFonts = async (theme: CssVarsThemeOptions): Promise<void> => {
|
||||
const themeFonts = getFontsFromTheme(theme.typography ?? {});
|
||||
const missingThemeFonts = themeFonts.filter((font) => !loadedFonts.includes(font));
|
||||
|
||||
|
||||
@@ -11,12 +11,16 @@ import {
|
||||
darken,
|
||||
Direction,
|
||||
lighten,
|
||||
Palette,
|
||||
responsiveFontSizes,
|
||||
Theme,
|
||||
TypeBackground,
|
||||
useTheme,
|
||||
} from '@mui/material/styles';
|
||||
import { useCallback } from 'react';
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies,no-restricted-imports
|
||||
import { deepmerge } from '@mui/utils';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { PaletteBackgroundChannel } from '@mui/material/styles/createThemeWithVars';
|
||||
import { ThemeMode } from '@/modules/theme/contexts/ThemeModeContext.tsx';
|
||||
import { MediaQuery } from '@/modules/core/utils/MediaQuery.tsx';
|
||||
import { AppTheme, loadThemeFonts } from '@/modules/theme/services/AppThemes.ts';
|
||||
@@ -25,6 +29,56 @@ import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts';
|
||||
|
||||
const SCROLLBAR_SIZE = 14;
|
||||
|
||||
declare module '@mui/material/styles' {
|
||||
interface CssThemeVariables {
|
||||
enabled: true;
|
||||
}
|
||||
}
|
||||
|
||||
const getBackgroundColor = (
|
||||
type: 'light' | 'dark',
|
||||
appTheme: AppTheme,
|
||||
theme: Theme,
|
||||
setPureBlackMode: boolean = false,
|
||||
): (Partial<TypeBackground> & Partial<PaletteBackgroundChannel>) | undefined => {
|
||||
if (setPureBlackMode) {
|
||||
return {
|
||||
paper: '#111',
|
||||
default: '#000',
|
||||
};
|
||||
}
|
||||
|
||||
if (type === 'light' && !!theme.colorSchemes.light) {
|
||||
if (
|
||||
typeof appTheme.muiTheme.colorSchemes?.light === 'object' &&
|
||||
appTheme.muiTheme.colorSchemes.light.palette?.background
|
||||
) {
|
||||
return appTheme.muiTheme.colorSchemes.light.palette.background;
|
||||
}
|
||||
|
||||
return {
|
||||
paper: lighten(theme.colorSchemes.light.palette.primary.dark, 0.8),
|
||||
default: lighten(theme.colorSchemes.light.palette.primary.dark, 0.9),
|
||||
};
|
||||
}
|
||||
|
||||
if (type === 'dark' && !!theme.colorSchemes.dark) {
|
||||
if (
|
||||
typeof appTheme.muiTheme.colorSchemes?.dark === 'object' &&
|
||||
appTheme.muiTheme.colorSchemes.dark.palette?.background
|
||||
) {
|
||||
return appTheme.muiTheme.colorSchemes.dark.palette.background;
|
||||
}
|
||||
|
||||
return {
|
||||
paper: darken(theme.colorSchemes.dark.palette.primary.dark, 0.8),
|
||||
default: darken(theme.colorSchemes.dark.palette.primary.dark, 0.9),
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const createTheme = (
|
||||
themeMode: ThemeMode,
|
||||
appTheme: AppTheme,
|
||||
@@ -33,93 +87,78 @@ export const createTheme = (
|
||||
) => {
|
||||
const systemMode = MediaQuery.getSystemThemeMode();
|
||||
|
||||
const appThemeType = (appTheme.muiTheme.palette as any)?.type ?? appTheme.muiTheme.palette?.mode;
|
||||
const isStaticThemeMode = !!appThemeType;
|
||||
const appThemeMode = appThemeType === 'dark' ? ThemeMode.DARK : ThemeMode.LIGHT;
|
||||
const staticThemeMode = isStaticThemeMode ? appThemeMode : undefined;
|
||||
|
||||
const mode = staticThemeMode ?? (themeMode === ThemeMode.SYSTEM ? systemMode : themeMode);
|
||||
const mode = themeMode === ThemeMode.SYSTEM ? systemMode : themeMode;
|
||||
const isDarkMode = mode === ThemeMode.DARK;
|
||||
const setPureBlackMode = isDarkMode && pureBlackMode;
|
||||
|
||||
const baseTheme = createMuiTheme({
|
||||
direction,
|
||||
...appTheme.muiTheme,
|
||||
palette: {
|
||||
mode,
|
||||
...(appTheme.muiTheme.palette ?? {}),
|
||||
},
|
||||
});
|
||||
const themeForColors = createMuiTheme({ ...appTheme.muiTheme, defaultColorScheme: mode });
|
||||
|
||||
const backgroundTrueBlack: Palette['background'] = {
|
||||
paper: '#111',
|
||||
default: '#000',
|
||||
};
|
||||
const backgroundDark: Palette['background'] = {
|
||||
paper: darken(baseTheme.palette.primary.dark, 0.75),
|
||||
default: darken(baseTheme.palette.primary.dark, 0.85),
|
||||
};
|
||||
const backgroundLight: Palette['background'] = {
|
||||
paper: lighten(baseTheme.palette.primary.dark, 0.8),
|
||||
default: lighten(baseTheme.palette.primary.dark, 0.9),
|
||||
};
|
||||
const backgroundThemeMode = isDarkMode ? backgroundDark : backgroundLight;
|
||||
const automaticBackground = setPureBlackMode ? backgroundTrueBlack : backgroundThemeMode;
|
||||
const appThemeBackground = appTheme.muiTheme.palette?.background;
|
||||
|
||||
const requiresAutomaticBackground = setPureBlackMode || !appThemeBackground;
|
||||
const background = requiresAutomaticBackground ? automaticBackground : appThemeBackground;
|
||||
|
||||
const colorTheme = createMuiTheme(baseTheme, {
|
||||
palette: {
|
||||
background,
|
||||
},
|
||||
});
|
||||
|
||||
const suwayomiTheme = createMuiTheme(colorTheme, {
|
||||
components: {
|
||||
...appTheme.muiTheme.components,
|
||||
MuiUseMediaQuery: {
|
||||
defaultProps: {
|
||||
noSsr: true,
|
||||
},
|
||||
const suwayomiTheme = createMuiTheme(
|
||||
deepmerge(appTheme.muiTheme, {
|
||||
defaultColorScheme: mode,
|
||||
direction,
|
||||
colorSchemes: {
|
||||
light: appTheme.muiTheme.colorSchemes?.light
|
||||
? {
|
||||
palette: {
|
||||
background: getBackgroundColor('light', appTheme, themeForColors),
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
dark: appTheme.muiTheme.colorSchemes?.dark
|
||||
? {
|
||||
palette: {
|
||||
background: getBackgroundColor('dark', appTheme, themeForColors, setPureBlackMode),
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
MuiCssBaseline: {
|
||||
...appTheme.muiTheme.components?.MuiCssBaseline,
|
||||
styleOverrides:
|
||||
typeof appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides === 'object'
|
||||
? {
|
||||
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides,
|
||||
'*::-webkit-scrollbar': applyStyles(CSS.supports('-webkit-touch-callout', 'none'), {
|
||||
width: `${SCROLLBAR_SIZE}px`,
|
||||
height: `${SCROLLBAR_SIZE}px`,
|
||||
// @ts-ignore - '*::-webkit-scrollbar' is a valid key
|
||||
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides?.[
|
||||
'*::-webkit-scrollbar'
|
||||
],
|
||||
}),
|
||||
'*::-webkit-scrollbar-thumb': applyStyles(CSS.supports('-webkit-touch-callout', 'none'), {
|
||||
border: '4px solid rgba(0, 0, 0, 0)',
|
||||
backgroundClip: 'padding-box',
|
||||
borderRadius: '9999px',
|
||||
backgroundColor: `${colorTheme.palette.primary[isDarkMode ? 'dark' : 'light']}`,
|
||||
// @ts-ignore - '*::-webkit-scrollbar-thumb' is a valid key
|
||||
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides?.[
|
||||
'*::-webkit-scrollbar-thumb'
|
||||
],
|
||||
}),
|
||||
'*::-webkit-scrollbar-thumb:hover': applyStyles(
|
||||
CSS.supports('-webkit-touch-callout', 'none'),
|
||||
{
|
||||
borderWidth: '2px',
|
||||
// @ts-ignore - '*::-webkit-scrollbar-thumb:hover' is a valid key
|
||||
components: {
|
||||
...appTheme.muiTheme.components,
|
||||
MuiUseMediaQuery: {
|
||||
defaultProps: {
|
||||
noSsr: true,
|
||||
},
|
||||
},
|
||||
MuiCssBaseline: {
|
||||
...appTheme.muiTheme.components?.MuiCssBaseline,
|
||||
styleOverrides:
|
||||
typeof appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides === 'object'
|
||||
? {
|
||||
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides,
|
||||
'*::-webkit-scrollbar': applyStyles(CSS.supports('-webkit-touch-callout', 'none'), {
|
||||
width: `${SCROLLBAR_SIZE}px`,
|
||||
height: `${SCROLLBAR_SIZE}px`,
|
||||
// @ts-ignore - '*::-webkit-scrollbar' is a valid key
|
||||
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides?.[
|
||||
'*::-webkit-scrollbar-thumb:hover'
|
||||
'*::-webkit-scrollbar'
|
||||
],
|
||||
},
|
||||
),
|
||||
}
|
||||
: `
|
||||
}),
|
||||
'*::-webkit-scrollbar-thumb': applyStyles(
|
||||
CSS.supports('-webkit-touch-callout', 'none'),
|
||||
{
|
||||
border: '4px solid rgba(0, 0, 0, 0)',
|
||||
backgroundClip: 'padding-box',
|
||||
borderRadius: '9999px',
|
||||
backgroundColor: `${themeForColors.palette.primary[isDarkMode ? 'dark' : 'light']}`,
|
||||
// @ts-ignore - '*::-webkit-scrollbar-thumb' is a valid key
|
||||
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides?.[
|
||||
'*::-webkit-scrollbar-thumb'
|
||||
],
|
||||
},
|
||||
),
|
||||
'*::-webkit-scrollbar-thumb:hover': applyStyles(
|
||||
CSS.supports('-webkit-touch-callout', 'none'),
|
||||
{
|
||||
borderWidth: '2px',
|
||||
// @ts-ignore - '*::-webkit-scrollbar-thumb:hover' is a valid key
|
||||
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides?.[
|
||||
'*::-webkit-scrollbar-thumb:hover'
|
||||
],
|
||||
},
|
||||
),
|
||||
}
|
||||
: `
|
||||
@supports not (-webkit-touch-callout: none) {
|
||||
/* CSS for other than iOS devices */
|
||||
*::-webkit-scrollbar {
|
||||
@@ -130,7 +169,7 @@ export const createTheme = (
|
||||
border: 4px solid rgba(0, 0, 0, 0);
|
||||
background-clip: padding-box;
|
||||
border-radius: 9999px;
|
||||
background-color: ${colorTheme.palette.primary[isDarkMode ? 'dark' : 'light']};
|
||||
background-color: ${themeForColors.palette.primary[isDarkMode ? 'dark' : 'light']};
|
||||
}
|
||||
*::-webkit-scrollbar-thumb:hover {
|
||||
border-width: 2px;
|
||||
@@ -139,9 +178,10 @@ export const createTheme = (
|
||||
${appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides ?? ''}
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
return responsiveFontSizes(suwayomiTheme);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user