aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils/hooks/use-prism-theme/use-prism-theme.ts
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2023-10-28 17:12:58 +0200
committerArmand Philippot <git@armandphilippot.com>2023-11-11 18:15:27 +0100
commit60c49f18389ff625177a57277ef8f292a31097bf (patch)
tree76b0f1f1792b57659e54d282f93df70088446e3c /src/utils/hooks/use-prism-theme/use-prism-theme.ts
parent05f1dfc6896d3affa7c494a1b955f230d836a4b7 (diff)
refactor(providers,hooks): rewrite PrismThemeProvider & usePrismTheme
* reuse Theme provider logic * move DOM mutation from provider to hook * add a script to init theme before page load
Diffstat (limited to 'src/utils/hooks/use-prism-theme/use-prism-theme.ts')
-rw-r--r--src/utils/hooks/use-prism-theme/use-prism-theme.ts54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/utils/hooks/use-prism-theme/use-prism-theme.ts b/src/utils/hooks/use-prism-theme/use-prism-theme.ts
new file mode 100644
index 0000000..4caec6c
--- /dev/null
+++ b/src/utils/hooks/use-prism-theme/use-prism-theme.ts
@@ -0,0 +1,54 @@
+import { useCallback, useContext, useEffect } from 'react';
+import { themeValidator as isValidTheme } from '../../helpers';
+import { PrismThemeContext } from '../../providers/prism-theme-provider';
+
+export const usePrismTheme = () => {
+ const { attribute, resolvedTheme, setTheme, theme } =
+ useContext(PrismThemeContext);
+ const currentTheme = theme === 'system' ? resolvedTheme : theme;
+
+ const handleMutations: MutationCallback = useCallback(
+ (mutations) => {
+ for (const mutation of mutations) {
+ if (mutation.target.nodeName.toLowerCase() !== 'pre') return;
+
+ const newTheme = (mutation.target as HTMLPreElement).getAttribute(
+ attribute
+ );
+
+ if (isValidTheme(newTheme) && newTheme !== theme) setTheme(newTheme);
+ }
+ },
+ [attribute, setTheme, theme]
+ );
+
+ useEffect(() => {
+ if (typeof window === 'undefined') return undefined;
+
+ const preElements = document.getElementsByTagName('pre');
+ const observer = new MutationObserver(handleMutations);
+
+ for (const preEl of Array.from(preElements)) {
+ if (preEl.className.includes('language-')) {
+ preEl.setAttribute(attribute, theme);
+ observer.observe(preEl, {
+ attributes: true,
+ attributeFilter: [attribute],
+ });
+ }
+ }
+
+ return () => {
+ observer.disconnect();
+ };
+ }, [attribute, handleMutations, theme]);
+
+ const toggleTheme = useCallback(() => {
+ setTheme(() => {
+ if (currentTheme === 'dark') return 'light';
+ return 'dark';
+ });
+ }, [currentTheme, setTheme]);
+
+ return { currentTheme, resolvedTheme, setTheme, theme, toggleTheme };
+};