refactor #5

Merged
GauthierWebDev merged 8 commits from refactor into main 2025-04-18 09:55:16 +00:00
17 changed files with 35 additions and 32 deletions
Showing only changes of commit bc4729a5de - Show all commits

View File

@ -1,3 +1,4 @@
import React from "react";
import clsx from "clsx";
export function Prose<T extends React.ElementType = "div">({

View File

@ -1,5 +1,6 @@
import { Link } from "@/components/common/Link";
import { Icon } from "@syntax/Icon";
import React from "react";
export function QuickLinks({ children }: { children: React.ReactNode }) {
return <div className="not-prose my-12 grid grid-cols-1 gap-6 sm:grid-cols-2">{children}</div>;

View File

@ -1,7 +1,7 @@
import { Highlight, Prism } from "prism-react-renderer";
import { prismThemes } from "@/data/themes/prism";
import React, { Fragment, useMemo } from "react";
import { useTheme } from "@/hooks/useTheme";
import { Fragment, useMemo } from "react";
import clsx from "clsx";
export function SSRSnippet({

View File

@ -1,4 +1,4 @@
import { useId, useState, useEffect, createContext, useContext, Fragment } from "react";
import React, { useId, useState, useEffect, createContext, useContext, Fragment } from "react";
import { SearchResult } from "@/services/FlexSearchService";
import { Dialog, DialogPanel } from "@headlessui/react";
import { useDebounce } from "@/hooks/useDebounce";

View File

@ -3,6 +3,7 @@ import type { Data } from "@/pages/docs/+data";
import { clientOnly } from "vike-react/clientOnly";
import { useData } from "vike-react/useData";
import { SSRSnippet } from "./SSRSnippet";
import React from "react";
const CSRSnippet = clientOnly(() => import("./CSRSnippet"));

View File

@ -1,25 +1,23 @@
"use client";
import { useCallback, useEffect, useState } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { Link } from "@/components/common/Link";
import clsx from "clsx";
import { type Section, type Subsection } from "@/lib/sections";
export function TableOfContents({ tableOfContents }: { tableOfContents: Array<Section> }) {
let [currentSection, setCurrentSection] = useState(tableOfContents[0]?.id);
const [currentSection, setCurrentSection] = useState(tableOfContents[0]?.id);
let getHeadings = useCallback((tableOfContents: Array<Section>) => {
const getHeadings = useCallback((tableOfContents: Array<Section>) => {
return tableOfContents
.flatMap((node) => [node.id, ...node.children.map((child) => child.id)])
.map((id) => {
let el = document.getElementById(id);
const el = document.getElementById(id);
if (!el) return null;
let style = window.getComputedStyle(el);
let scrollMt = parseFloat(style.scrollMarginTop);
const style = window.getComputedStyle(el);
const scrollMt = parseFloat(style.scrollMarginTop);
let top = window.scrollY + el.getBoundingClientRect().top - scrollMt;
const top = window.scrollY + el.getBoundingClientRect().top - scrollMt;
return { id, top };
})
.filter((x): x is { id: string; top: number } => x !== null);
@ -35,11 +33,8 @@ export function TableOfContents({ tableOfContents }: { tableOfContents: Array<Se
let current = headings[0]?.id;
for (const heading of headings) {
if (top >= heading.top - 10) {
current = heading.id;
} else {
break;
}
if (top < heading.top - 10) break;
current = heading.id;
}
setCurrentSection(current);
}
@ -51,12 +46,9 @@ export function TableOfContents({ tableOfContents }: { tableOfContents: Array<Se
}, [getHeadings, tableOfContents]);
function isActive(section: Section | Subsection) {
if (section.id === currentSection) {
return true;
}
if (!section.children) {
return false;
}
if (section.id === currentSection) return true;
if (!section.children) return false;
return section.children.findIndex(isActive) > -1;
}

View File

@ -1,5 +1,5 @@
import { Label, Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/react";
import { useEffect, useState } from "react";
import React, { useEffect, useState } from "react";
import { useTheme } from "@/hooks/useTheme";
import clsx from "clsx";
@ -33,8 +33,8 @@ function DarkIcon(props: React.ComponentPropsWithoutRef<"svg">) {
}
export function ThemeSelector(props: React.ComponentPropsWithoutRef<typeof Listbox<"div">>) {
let [mounted, setMounted] = useState(false);
let { theme, setTheme } = useTheme();
const [mounted, setMounted] = useState(false);
const { theme, setTheme } = useTheme();
useEffect(() => {
setMounted(true);

View File

@ -1,4 +1,5 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon";
import React from "react";
export function InstallationIcon({
id,

View File

@ -1,4 +1,5 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon";
import React from "react";
export function LightbulbIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) {
return (

View File

@ -1,4 +1,5 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon";
import React from "react";
export function PluginsIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) {
return (

View File

@ -1,4 +1,5 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon";
import React from "react";
export function PresetsIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) {
return (

View File

@ -1,4 +1,5 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon";
import React from "react";
export function QuestionIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) {
return (

View File

@ -1,4 +1,5 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon";
import React from "react";
export function ThemingIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) {
return (

View File

@ -1,4 +1,5 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon";
import React from "react";
export function WarningIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) {
return (

View File

@ -3,10 +3,10 @@ import { usePageContext } from "vike-react/usePageContext";
import { ThemeProvider } from "@/providers/ThemeProvider";
import { ThemeSelector } from "@syntax/ThemeSelector";
import { clientOnly } from "vike-react/clientOnly";
import React, { useEffect, useState } from "react";
import { ToastContainer } from "react-toastify";
import { Navigation } from "@syntax/Navigation";
import { Link } from "@/components/common/Link";
import { useEffect, useState } from "react";
import { Hero } from "@syntax/Hero";
import { Logo } from "@syntax/Logo";
import clsx from "clsx";

View File

@ -119,16 +119,17 @@ export const navigation: NavigationSection[] = [
},
];
export function doesLinkSubitemExist(link: NavigationLink, subitemHref: string): boolean {
return link.subitems.some((subitem) => subitem.href === subitemHref);
}
export function findNavigationLink(namespace: string, href: string): NavigationLink | undefined {
const currentUrl = `/${namespace}/${href}`.replace(/\/+/g, "/").replace(/\/$/, "");
const foundLink = navigation
.flatMap((section) => section.links)
.find((link) => {
link.href === currentUrl ||
link.subitems.some((subitem) => {
subitem.href === currentUrl;
});
return link.href === currentUrl || doesLinkSubitemExist(link, currentUrl);
});
return foundLink;

View File

@ -50,8 +50,8 @@ function extractSections(node: Node, sections: Section[], isRoot: boolean = true
if (node.type === "heading" || node.type === "paragraph") {
const content = toString(node).trim();
if (node.type === "heading" && node.attributes?.level! <= 2) {
let hash = node.attributes?.id ?? slugify(content);
if (node.attributes?.level && node.type === "heading" && node.attributes.level <= 2) {
const hash = node.attributes?.id ?? slugify(content);
sections.push({ content, hash, subsections: [] });
} else {
sections[sections.length - 1].subsections.push(content);