aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/pages/projets/[slug].tsx9
-rw-r--r--src/utils/hooks/use-headings-tree.tsx13
-rw-r--r--src/utils/hooks/use-mutation-observer.tsx28
3 files changed, 47 insertions, 3 deletions
diff --git a/src/pages/projets/[slug].tsx b/src/pages/projets/[slug].tsx
index b396fc3..7539b55 100644
--- a/src/pages/projets/[slug].tsx
+++ b/src/pages/projets/[slug].tsx
@@ -33,6 +33,7 @@ import useGithubApi, { type RepoData } from '@utils/hooks/use-github-api';
import useSettings from '@utils/hooks/use-settings';
import { MDXComponents, NestedMDXComponents } from 'mdx/types';
import { GetStaticPaths, GetStaticProps } from 'next';
+import dynamic from 'next/dynamic';
import Head from 'next/head';
import { useRouter } from 'next/router';
import Script from 'next/script';
@@ -56,8 +57,12 @@ const ProjectPage: NextPageWithLayout<ProjectPageProps> = ({ project }) => {
url: `/projets/${id}`,
});
- const ProjectContent: ComponentType<MDXComponents> =
- require(`../../content/projects/${id}.mdx`).default;
+ const ProjectContent: ComponentType<MDXComponents> = dynamic(
+ () => import(`../../content/projects/${id}.mdx`),
+ {
+ loading: () => <Spinner />,
+ }
+ );
const components: NestedMDXComponents = {
Code: (props) => <Code {...props} />,
diff --git a/src/utils/hooks/use-headings-tree.tsx b/src/utils/hooks/use-headings-tree.tsx
index 4646b4a..f7ab452 100644
--- a/src/utils/hooks/use-headings-tree.tsx
+++ b/src/utils/hooks/use-headings-tree.tsx
@@ -1,5 +1,6 @@
import { slugify } from '@utils/helpers/strings';
import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useMutationObserver } from './use-mutation-observer';
export type Heading = {
/**
@@ -32,13 +33,23 @@ const useHeadingsTree = (wrapper: HTMLElement): Heading[] => {
useState<NodeListOf<HTMLHeadingElement>>();
const [headingsTree, setHeadingsTree] = useState<Heading[]>([]);
- useEffect(() => {
+ const getHeadingsInWrapper = useCallback(() => {
const query = depths.join(', ');
const result: NodeListOf<HTMLHeadingElement> =
wrapper.querySelectorAll(query);
setAllHeadings(result);
}, [depths, wrapper]);
+ useEffect(() => {
+ getHeadingsInWrapper();
+ }, [getHeadingsInWrapper]);
+
+ useMutationObserver({
+ callback: getHeadingsInWrapper,
+ options: { childList: true },
+ nodeOrSelector: wrapper,
+ });
+
const getDepth = useCallback(
/**
* Retrieve the heading element depth.
diff --git a/src/utils/hooks/use-mutation-observer.tsx b/src/utils/hooks/use-mutation-observer.tsx
new file mode 100644
index 0000000..c56f7aa
--- /dev/null
+++ b/src/utils/hooks/use-mutation-observer.tsx
@@ -0,0 +1,28 @@
+import { useEffect } from 'react';
+
+type UseMutationObserverProps = {
+ callback: () => void;
+ options: MutationObserverInit;
+ nodeOrSelector: string | HTMLElement;
+};
+
+export const useMutationObserver = ({
+ callback,
+ options,
+ nodeOrSelector,
+}: UseMutationObserverProps) => {
+ useEffect(() => {
+ const targetNode =
+ typeof nodeOrSelector === 'string'
+ ? document.querySelector(nodeOrSelector)!
+ : nodeOrSelector;
+
+ const observer = new MutationObserver(callback);
+
+ observer.observe(targetNode, options);
+
+ return () => {
+ observer.disconnect();
+ };
+ }, [nodeOrSelector, options, callback]);
+};