import { useMantineTheme, AppShell, Navbar, MediaQuery, Header, Burger, Anchor, Breadcrumbs, ScrollArea, Group, Text, ThemeIcon, Box, UnstyledButton, createStyles, Menu, ActionIcon, useMantineColorScheme, Stack, Skeleton, LoadingOverlay, Container, Title, } from '@mantine/core'; import { NextLink } from '@mantine/next'; import type { MDXRemoteSerializeResult } from 'next-mdx-remote'; import Image from 'next/future/image'; import Link from 'next/link'; import { useRouter } from 'next/router'; import { type PropsWithChildren, useState, useEffect } from 'react'; import { VscChevronDown, VscGithubInverted, VscPackage, VscVersions } from 'react-icons/vsc'; import { WiDaySunny, WiNightClear } from 'react-icons/wi'; import useSWR from 'swr'; import { SidebarItems } from './SidebarItems'; import type { ApiItemJSON } from '~/DocModel/ApiNodeJSONEncoder'; import type { findMember } from '~/util/model.server'; import { PACKAGES } from '~/util/packages'; import type { getMembers } from '~/util/parse.server'; const fetcher = (url: string) => fetch(url).then((res) => res.json()); export interface SidebarLayoutProps { packageName: string; branchName: string; data: { members: ReturnType; member: ReturnType; source: MDXRemoteSerializeResult; }; selectedMember?: ApiItemJSON | undefined; } export type Members = SidebarLayoutProps['data']['members']; export interface GroupedMembers { Classes: Members; Functions: Members; Enums: Members; Interfaces: Members; Types: Members; Variables: Members; } const useStyles = createStyles( (theme, { openedLib, openedVersion }: { openedLib: boolean; openedVersion: boolean }) => ({ control: { display: 'block', width: '100%', padding: theme.spacing.xs, color: theme.colorScheme === 'dark' ? theme.colors.dark![0] : theme.black, backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark![6] : theme.colors.gray![1], borderRadius: theme.radius.xs, '&:hover': { backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark![5] : theme.colors.gray![2], color: theme.colorScheme === 'dark' ? theme.white : theme.black, }, }, iconLib: { transition: 'transform 150ms ease', transform: openedLib ? 'rotate(180deg)' : 'rotate(0deg)', }, iconVersion: { transition: 'transform 150ms ease', transform: openedVersion ? 'rotate(180deg)' : 'rotate(0deg)', }, content: { position: 'relative', minHeight: 'calc(100vh - 50px)', zIndex: 1, background: theme.colorScheme === 'dark' ? theme.colors.dark![8] : theme.colors.gray![0], boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)', }, footer: { position: 'fixed', bottom: 0, left: 0, right: 0, height: 200, background: theme.colorScheme === 'dark' ? theme.colors.dark![7] : theme.colors.gray![0], paddingLeft: 324, [theme.fn.smallerThan('lg')]: { paddingRight: 54, }, [theme.fn.smallerThan('md')]: { paddingLeft: 24, }, [theme.fn.smallerThan('sm')]: { paddingRight: 24, height: 300, }, }, links: { display: 'flex', justifyContent: 'space-between', [theme.fn.smallerThan('sm')]: { flexDirection: 'column', alignItems: 'center', gap: 50, }, }, }), ); const packageMenuItems = PACKAGES.map((pkg) => ( {pkg} )); export function SidebarLayout({ packageName, branchName, data, children, }: PropsWithChildren>) { const router = useRouter(); const [asPathWithoutQueryAndAnchor, setAsPathWithoutQueryAndAnchor] = useState(''); const { data: versions } = useSWR( `https://docs.discordjs.dev/api/info?package=${packageName ?? 'builders'}`, fetcher, ); const theme = useMantineTheme(); const { colorScheme, toggleColorScheme } = useMantineColorScheme(); const [opened, setOpened] = useState(false); const [openedLibPicker, setOpenedLibPicker] = useState(false); const [openedVersionPicker, setOpenedVersionPicker] = useState(false); useEffect(() => { setOpened(false); setOpenedLibPicker(false); setOpenedVersionPicker(false); }, []); useEffect(() => { setAsPathWithoutQueryAndAnchor(router.asPath.split('?')[0]?.split('#')[0]?.split(':')[0] ?? ''); }, [router.asPath]); const { classes } = useStyles({ openedLib: openedLibPicker, openedVersion: openedVersionPicker }); const versionMenuItems = versions?.map((item) => ( {item} )) ?? []; const breadcrumbs = asPathWithoutQueryAndAnchor.split('/').map((path, idx, original) => ( {path} )); return ( ({ main: { background: theme.colorScheme === 'dark' ? theme.colors.dark![8] : theme.colors.gray![0], overflowX: 'auto', }, })} padding={0} navbarOffsetBreakpoint="md" asideOffsetBreakpoint="md" navbar={ <> } header={
({ boxShadow: theme.colorScheme === 'dark' ? '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)' : 'unset', })} height={70} p="md" > (router.isFallback ? null : setOpened((o) => !o))} size="sm" color={theme.colors.gray![6]} mr="xl" /> {breadcrumbs} toggleColorScheme()} title="Toggle color scheme" radius="sm" > {colorScheme === 'dark' ? : }
} >
{children} ({ height: 200, [theme.fn.smallerThan('sm')]: { height: 300 } })}> Vercel ({ gap: 50, [theme.fn.smallerThan('sm')]: { gap: 25 } })} align="flex-start"> Community Discord GitHub discussions Project discord.js discord.js guide discord-api-types
); }