use-next-themes.tsx 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import { isClient, ColorScheme } from '@growi/core';
  2. import { ThemeProvider, useTheme } from 'next-themes';
  3. import { ThemeProviderProps, UseThemeProps } from 'next-themes/dist/types';
  4. import { useForcedColorScheme } from './context';
  5. export const Themes = {
  6. ...ColorScheme,
  7. SYSTEM: 'system',
  8. } as const;
  9. export type Themes = typeof Themes[keyof typeof Themes];
  10. const ATTRIBUTE = 'data-theme';
  11. export const NextThemesProvider: React.FC<ThemeProviderProps> = (props) => {
  12. const { data: forcedColorScheme } = useForcedColorScheme();
  13. return <ThemeProvider {...props} forcedTheme={forcedColorScheme} attribute={ATTRIBUTE} />;
  14. };
  15. type UseThemeExtendedProps = Omit<UseThemeProps, 'theme'|'resolvedTheme'> & {
  16. theme: Themes,
  17. resolvedTheme: ColorScheme,
  18. useOsSettings: boolean,
  19. isDarkMode: boolean,
  20. isForcedByGrowiTheme: boolean,
  21. resolvedThemeByAttributes?: ColorScheme,
  22. }
  23. export const useNextThemes = (): UseThemeProps & UseThemeExtendedProps => {
  24. const props = useTheme();
  25. const { data: forcedColorScheme } = useForcedColorScheme();
  26. const resolvedTheme = forcedColorScheme ?? props.resolvedTheme as ColorScheme;
  27. return Object.assign(props, {
  28. theme: props.theme as Themes,
  29. resolvedTheme,
  30. useOsSettings: props.theme === Themes.SYSTEM,
  31. isDarkMode: resolvedTheme === ColorScheme.DARK,
  32. isForcedByGrowiTheme: forcedColorScheme != null,
  33. resolvedThemeByAttributes: isClient() ? document.documentElement.getAttribute(ATTRIBUTE) as ColorScheme : undefined,
  34. });
  35. };