ConceptPortal-public/rsconcept/frontend/src/context/ConceptOptionsContext.tsx

176 lines
5.0 KiB
TypeScript
Raw Normal View History

'use client';
import { createContext, useCallback, useContext, useLayoutEffect, useMemo, useState } from 'react';
2023-07-15 17:46:19 +03:00
import Tooltip from '@/components/ui/Tooltip';
import useLocalStorage from '@/hooks/useLocalStorage';
import { animationDuration } from '@/styling/animations';
import { darkT, IColorTheme, lightT } from '@/styling/color';
import { globals, storage } from '@/utils/constants';
import { contextOutsideScope } from '@/utils/labels';
2023-07-15 17:46:19 +03:00
2024-04-01 19:07:20 +03:00
interface IOptionsContext {
2023-12-28 14:04:44 +03:00
viewportHeight: string;
mainHeight: string;
colors: IColorTheme;
darkMode: boolean;
toggleDarkMode: () => void;
adminMode: boolean;
toggleAdminMode: () => void;
2023-12-28 14:04:44 +03:00
noNavigationAnimation: boolean;
noNavigation: boolean;
toggleNoNavigation: () => void;
noFooter: boolean;
2024-04-01 19:07:20 +03:00
setNoFooter: React.Dispatch<React.SetStateAction<boolean>>;
2023-12-28 14:04:44 +03:00
showScroll: boolean;
2024-04-01 19:07:20 +03:00
setShowScroll: React.Dispatch<React.SetStateAction<boolean>>;
showHelp: boolean;
toggleShowHelp: () => void;
2024-03-12 19:54:10 +03:00
2024-09-15 21:19:17 +03:00
folderMode: boolean;
setFolderMode: React.Dispatch<React.SetStateAction<boolean>>;
location: string;
setLocation: React.Dispatch<React.SetStateAction<string>>;
2024-06-04 14:20:43 +03:00
calculateHeight: (offset: string, minimum?: string) => string;
2023-07-15 17:46:19 +03:00
}
2024-04-01 19:07:20 +03:00
const OptionsContext = createContext<IOptionsContext | null>(null);
export const useConceptOptions = () => {
const context = useContext(OptionsContext);
if (!context) {
throw new Error(contextOutsideScope('useConceptTheme', 'ThemeState'));
}
return context;
2023-12-28 14:04:44 +03:00
};
2023-07-15 17:46:19 +03:00
2024-09-19 17:49:25 +03:00
export const OptionsState = ({ children }: React.PropsWithChildren) => {
const [darkMode, setDarkMode] = useLocalStorage(storage.themeDark, false);
2024-05-02 17:33:53 +03:00
const [adminMode, setAdminMode] = useLocalStorage(storage.optionsAdmin, false);
2024-04-01 19:07:20 +03:00
const [showHelp, setShowHelp] = useLocalStorage(storage.optionsHelp, true);
const [noNavigation, setNoNavigation] = useState(false);
2024-04-01 19:07:20 +03:00
2024-09-15 21:19:17 +03:00
const [folderMode, setFolderMode] = useLocalStorage<boolean>(storage.librarySearchFolderMode, true);
const [location, setLocation] = useLocalStorage<string>(storage.librarySearchLocation, '');
2024-04-01 19:07:20 +03:00
const [colors, setColors] = useState<IColorTheme>(lightT);
const [noNavigationAnimation, setNoNavigationAnimation] = useState(false);
2023-08-27 15:39:49 +03:00
const [noFooter, setNoFooter] = useState(false);
2023-09-05 00:23:53 +03:00
const [showScroll, setShowScroll] = useState(false);
2023-07-15 17:46:19 +03:00
2023-08-27 15:39:49 +03:00
function setDarkClass(isDark: boolean) {
2023-07-15 17:46:19 +03:00
const root = window.document.documentElement;
if (isDark) {
root.classList.add('dark');
} else {
root.classList.remove('dark');
}
2023-07-20 17:11:03 +03:00
root.setAttribute('data-color-scheme', !isDark ? 'light' : 'dark');
2023-08-27 15:39:49 +03:00
}
2023-07-15 17:46:19 +03:00
2023-08-24 14:23:17 +03:00
useLayoutEffect(() => {
setDarkClass(darkMode);
2023-07-15 17:46:19 +03:00
}, [darkMode]);
2023-08-27 00:19:19 +03:00
useLayoutEffect(() => {
2023-12-28 14:04:44 +03:00
setColors(darkMode ? darkT : lightT);
2023-08-27 00:19:19 +03:00
}, [darkMode, setColors]);
2023-12-28 14:04:44 +03:00
const toggleNoNavigation = useCallback(() => {
if (noNavigation) {
setNoNavigationAnimation(false);
setNoNavigation(false);
} else {
setNoNavigationAnimation(true);
setTimeout(() => setNoNavigation(true), animationDuration.navigationToggle);
}
}, [noNavigation]);
2024-03-12 19:54:10 +03:00
const calculateHeight = useCallback(
2024-06-04 14:20:43 +03:00
(offset: string, minimum: string = '0px') => {
2024-03-12 19:54:10 +03:00
if (noNavigation) {
2024-06-05 18:07:02 +03:00
return `max(calc(100dvh - (${offset})), ${minimum})`;
2024-03-12 19:54:10 +03:00
} else if (noFooter) {
2024-06-05 18:07:02 +03:00
return `max(calc(100dvh - 3rem - (${offset})), ${minimum})`;
2024-03-12 19:54:10 +03:00
} else {
2024-06-05 18:07:02 +03:00
return `max(calc(100dvh - 6.75rem - (${offset})), ${minimum})`;
2024-03-12 19:54:10 +03:00
}
},
[noNavigation, noFooter]
);
2024-04-01 19:07:20 +03:00
const toggleDarkMode = useCallback(() => {
setDarkMode(prev => !prev);
window.location.reload();
}, [setDarkMode]);
2023-12-28 14:04:44 +03:00
const mainHeight = useMemo(() => {
if (noNavigation) {
return '100dvh';
} else if (noFooter) {
return 'calc(100dvh - 3rem)';
} else {
return 'calc(100dvh - 6.75rem)';
}
}, [noNavigation, noFooter]);
2023-08-24 14:23:17 +03:00
2023-12-28 14:04:44 +03:00
const viewportHeight = useMemo(() => {
2024-06-05 18:07:02 +03:00
return !noNavigation ? 'calc(100dvh - 3rem)' : '100dvh';
2023-08-24 14:23:17 +03:00
}, [noNavigation]);
2023-07-15 17:46:19 +03:00
return (
2024-04-01 19:07:20 +03:00
<OptionsContext.Provider
2023-12-28 14:04:44 +03:00
value={{
darkMode,
adminMode,
2023-12-28 14:04:44 +03:00
colors,
noNavigationAnimation,
noNavigation,
noFooter,
2024-09-15 21:19:17 +03:00
folderMode,
setFolderMode,
location,
setLocation,
2023-12-28 14:04:44 +03:00
showScroll,
2024-04-01 19:07:20 +03:00
showHelp,
toggleDarkMode: toggleDarkMode,
toggleAdminMode: () => setAdminMode(prev => !prev),
2023-12-28 14:04:44 +03:00
toggleNoNavigation: toggleNoNavigation,
setNoFooter,
setShowScroll,
2024-04-01 19:07:20 +03:00
toggleShowHelp: () => setShowHelp(prev => !prev),
2023-12-28 14:04:44 +03:00
viewportHeight,
2024-03-12 19:54:10 +03:00
mainHeight,
calculateHeight
2023-12-28 14:04:44 +03:00
}}
>
<>
<Tooltip
2024-09-12 11:17:01 +03:00
float // prettier: split-lines
id={`${globals.tooltip}`}
2023-12-28 14:04:44 +03:00
layer='z-topmost'
place='right-start'
2024-11-20 21:01:42 +03:00
className='mt-8 max-w-[20rem] break-words'
2023-12-28 14:04:44 +03:00
/>
<Tooltip
float
id={`${globals.value_tooltip}`}
layer='z-topmost'
2024-09-12 11:17:01 +03:00
className='max-w-[calc(min(40rem,100dvw-2rem))] text-justify'
/>
2023-12-28 14:04:44 +03:00
{children}
</>
2024-04-01 19:07:20 +03:00
</OptionsContext.Provider>
2023-12-28 14:04:44 +03:00
);
};