new features, bookstack

This commit is contained in:
Matthias Hochmeister
2026-03-03 21:30:38 +01:00
parent 817329db70
commit d3561c1109
32 changed files with 1923 additions and 207 deletions

View File

@@ -0,0 +1,76 @@
import React, { createContext, useContext, useState, useEffect, useMemo } from 'react';
import { ThemeProvider } from '@mui/material/styles';
import { CssBaseline } from '@mui/material';
import { lightTheme, darkTheme } from '../theme/theme';
type ThemeMode = 'system' | 'light' | 'dark';
interface ThemeModeContextValue {
themeMode: ThemeMode;
setThemeMode: (mode: ThemeMode) => void;
resolvedMode: 'light' | 'dark';
}
const ThemeModeContext = createContext<ThemeModeContextValue>({
themeMode: 'system',
setThemeMode: () => {},
resolvedMode: 'light',
});
export function useThemeMode(): ThemeModeContextValue {
return useContext(ThemeModeContext);
}
function getSystemPreference(): 'light' | 'dark' {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
}
const STORAGE_KEY = 'themeMode';
export const ThemeModeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [themeMode, setThemeModeState] = useState<ThemeMode>(() => {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored === 'light' || stored === 'dark' || stored === 'system') {
return stored;
}
return 'system';
});
const [systemPreference, setSystemPreference] = useState<'light' | 'dark'>(getSystemPreference);
useEffect(() => {
const mq = window.matchMedia('(prefers-color-scheme: dark)');
const handler = (e: MediaQueryListEvent) => {
setSystemPreference(e.matches ? 'dark' : 'light');
};
mq.addEventListener('change', handler);
return () => mq.removeEventListener('change', handler);
}, []);
const setThemeMode = (mode: ThemeMode) => {
setThemeModeState(mode);
localStorage.setItem(STORAGE_KEY, mode);
};
const resolvedMode: 'light' | 'dark' =
themeMode === 'system' ? systemPreference : themeMode;
const theme = resolvedMode === 'dark' ? darkTheme : lightTheme;
const value = useMemo(
() => ({ themeMode, setThemeMode, resolvedMode }),
[themeMode, resolvedMode],
);
return (
<ThemeModeContext.Provider value={value}>
<ThemeProvider theme={theme}>
<CssBaseline />
{children}
</ThemeProvider>
</ThemeModeContext.Provider>
);
};