mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-12 09:33:32 +01:00
feat: reintroduce outline navigation
This commit is contained in:
@@ -28,7 +28,9 @@ export function Badges({ item }: { readonly item: ApiDocumentedItem }) {
|
||||
const isAbstract = ApiAbstractMixin.isBaseClassOf(item) && item.isAbstract;
|
||||
const isDeprecated = Boolean(item.tsdocComment?.deprecatedBlock);
|
||||
|
||||
return (
|
||||
const isAny = isStatic || isProtected || isReadonly || isAbstract || isDeprecated;
|
||||
|
||||
return isAny ? (
|
||||
<div className="flex flex-row gap-1 md:ml-7">
|
||||
{isDeprecated ? <Badge color={BadgeColor.Danger}>Deprecated</Badge> : null}
|
||||
{isProtected ? <Badge>Protected</Badge> : null}
|
||||
@@ -36,5 +38,5 @@ export function Badges({ item }: { readonly item: ApiDocumentedItem }) {
|
||||
{isAbstract ? <Badge>Abstract</Badge> : null}
|
||||
{isReadonly ? <Badge>Readonly</Badge> : null}
|
||||
</div>
|
||||
);
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -35,10 +35,12 @@ export function Nav({
|
||||
universal
|
||||
>
|
||||
<div className="flex flex-col gap-4 p-3">
|
||||
<PackageSelect />
|
||||
<VersionSelect versions={versions} />
|
||||
<div className="flex flex-col gap-4">
|
||||
<PackageSelect />
|
||||
<VersionSelect versions={versions} />
|
||||
</div>
|
||||
<Sidebar members={members} />
|
||||
</div>
|
||||
<Sidebar members={members} />
|
||||
</Scrollbars>
|
||||
</nav>
|
||||
);
|
||||
|
||||
@@ -1,23 +1,32 @@
|
||||
'use client';
|
||||
|
||||
import { useOutline } from '~/contexts/outline';
|
||||
import { Scrollbars } from './Scrollbars';
|
||||
import type { TableOfContentsSerialized } from './TableOfContentItems';
|
||||
import { TableOfContentItems } from './TableOfContentItems';
|
||||
|
||||
export function Outline({ members }: { readonly members: TableOfContentsSerialized[] }) {
|
||||
export function Outline() {
|
||||
const { members } = useOutline();
|
||||
|
||||
if (!members) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<aside className="fixed bottom-0 right-0 top-[50px] z-20 hidden h-[calc(100vh_-_65px)] w-64 border-l border-light-800 bg-white pr-2 xl:block dark:border-dark-100 dark:bg-dark-600">
|
||||
<Scrollbars
|
||||
autoHide
|
||||
hideTracksWhenNotNeeded
|
||||
renderThumbVertical={(props) => <div {...props} className="z-30 rounded bg-light-900 dark:bg-dark-100" />}
|
||||
renderTrackVertical={(props) => (
|
||||
<div {...props} className="absolute bottom-0.5 right-0.5 top-0.5 z-30 w-1.5 rounded" />
|
||||
)}
|
||||
universal
|
||||
>
|
||||
<TableOfContentItems serializedMembers={members} />
|
||||
</Scrollbars>
|
||||
</aside>
|
||||
<div className="lg:sticky lg:top-23 lg:h-[calc(100vh_-_105px)]">
|
||||
<aside className="fixed bottom-4 left-4 right-4 top-22 z-20 mx-auto hidden max-w-5xl border border-light-900 rounded-md bg-white/75 shadow backdrop-blur-md lg:sticky lg:block lg:h-full lg:max-w-xs lg:min-w-xs lg:w-full dark:border-dark-100 dark:bg-dark-600/75">
|
||||
<Scrollbars
|
||||
autoHide
|
||||
className="[&>div]:overscroll-none"
|
||||
hideTracksWhenNotNeeded
|
||||
renderThumbVertical={(props) => <div {...props} className="z-30 rounded bg-light-900 dark:bg-dark-100" />}
|
||||
renderTrackVertical={(props) => (
|
||||
<div {...props} className="absolute bottom-0.5 right-0.5 top-0.5 z-30 w-1.5 rounded" />
|
||||
)}
|
||||
universal
|
||||
>
|
||||
<TableOfContentItems serializedMembers={members} />
|
||||
</Scrollbars>
|
||||
</aside>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ export function Sidebar({ members }: { readonly members: SidebarSectionItemData[
|
||||
const groupItems = useMemo(() => groupMembers(members), [members]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3 p-3">
|
||||
<div className="flex flex-col gap-4">
|
||||
{(Object.keys(groupItems) as (keyof GroupedMembers)[])
|
||||
.filter((group) => groupItems[group].length)
|
||||
.map((group, idx) => (
|
||||
@@ -99,7 +99,7 @@ export function Sidebar({ members }: { readonly members: SidebarSectionItemData[
|
||||
>
|
||||
{groupItems[group].map((member, index) => (
|
||||
<ItemLink
|
||||
className={`dark:border-dark-100 border-light-800 focus:ring-width-2 focus:ring-blurple ml-5 flex flex-col border-l p-[5px] pl-6 outline-none focus:rounded focus:border-0 focus:ring ${
|
||||
className={`dark:border-dark-100 border-light-800 focus:ring-width-2 focus:ring-blurple ml-5 flex flex-col border-l first:mt-1 p-[5px] pl-6 outline-none focus:rounded focus:border-0 focus:ring ${
|
||||
decodeURIComponent(segment ?? '') === member.href
|
||||
? 'bg-blurple text-white'
|
||||
: 'dark:hover:bg-dark-200 dark:active:bg-dark-100 hover:bg-light-700 active:bg-light-800'
|
||||
|
||||
@@ -4,5 +4,5 @@ import type { PropsWithChildren } from 'react';
|
||||
* Layout parent of documentation pages.
|
||||
*/
|
||||
export function Documentation({ children }: PropsWithChildren) {
|
||||
return <div className="w-full flex-col space-y-4">{children}</div>;
|
||||
return <div className="w-full flex flex-col gap-4">{children}</div>;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc:
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-2">
|
||||
<div className="flex flex-col gap-2">
|
||||
{comment.deprecatedBlock ? (
|
||||
<DeprecatedBlock>{createNode(comment.deprecatedBlock.content)}</DeprecatedBlock>
|
||||
) : null}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { ApiClass, ApiConstructor } from '@discordjs/api-extractor-model';
|
||||
import { ApiItemKind } from '@discordjs/api-extractor-model';
|
||||
// import { Outline } from '../Outline';
|
||||
import { Badges } from '../Badges';
|
||||
import { Documentation } from '../documentation/Documentation';
|
||||
import { HierarchyText } from '../documentation/HierarchyText';
|
||||
@@ -8,13 +7,16 @@ import { Members } from '../documentation/Members';
|
||||
import { ObjectHeader } from '../documentation/ObjectHeader';
|
||||
import { ConstructorSection } from '../documentation/section/ConstructorSection';
|
||||
import { TypeParameterSection } from '../documentation/section/TypeParametersSection';
|
||||
// import { serializeMembers } from '../documentation/util';
|
||||
import { serializeMembers } from '../documentation/util';
|
||||
import { OutlineSetter } from './OutlineSetter';
|
||||
|
||||
export function Class({ clazz }: { readonly clazz: ApiClass }) {
|
||||
const constructor = clazz.members.find((member) => member.kind === ApiItemKind.Constructor) as
|
||||
| ApiConstructor
|
||||
| undefined;
|
||||
|
||||
const outlineMembers = serializeMembers(clazz);
|
||||
|
||||
return (
|
||||
<Documentation>
|
||||
<Badges item={clazz} />
|
||||
@@ -24,7 +26,7 @@ export function Class({ clazz }: { readonly clazz: ApiClass }) {
|
||||
{clazz.typeParameters.length ? <TypeParameterSection item={clazz} /> : null}
|
||||
{constructor ? <ConstructorSection item={constructor} /> : null}
|
||||
<Members item={clazz} />
|
||||
{/* <Outline members={serializeMembers(clazz)} /> */}
|
||||
<OutlineSetter members={outlineMembers} />
|
||||
</Documentation>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import type { ApiInterface } from '@discordjs/api-extractor-model';
|
||||
// import { Outline } from '../Outline';
|
||||
import { Documentation } from '../documentation/Documentation';
|
||||
import { HierarchyText } from '../documentation/HierarchyText';
|
||||
import { Members } from '../documentation/Members';
|
||||
import { ObjectHeader } from '../documentation/ObjectHeader';
|
||||
import { TypeParameterSection } from '../documentation/section/TypeParametersSection';
|
||||
// import { serializeMembers } from '../documentation/util';
|
||||
import { serializeMembers } from '../documentation/util';
|
||||
import { OutlineSetter } from './OutlineSetter';
|
||||
|
||||
export function Interface({ item }: { readonly item: ApiInterface }) {
|
||||
const outlineMembers = serializeMembers(item);
|
||||
|
||||
return (
|
||||
<Documentation>
|
||||
<ObjectHeader item={item} />
|
||||
<HierarchyText item={item} type="Extends" />
|
||||
{item.typeParameters.length ? <TypeParameterSection item={item} /> : null}
|
||||
<Members item={item} />
|
||||
{/* <Outline members={serializeMembers(item)} /> */}
|
||||
<OutlineSetter members={outlineMembers} />
|
||||
</Documentation>
|
||||
);
|
||||
}
|
||||
|
||||
19
apps/website/src/components/model/OutlineSetter.tsx
Normal file
19
apps/website/src/components/model/OutlineSetter.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, type PropsWithChildren } from 'react';
|
||||
import { useOutline } from '~/contexts/outline';
|
||||
import type { TableOfContentsSerialized } from '../TableOfContentItems';
|
||||
|
||||
export function OutlineSetter({ members }: PropsWithChildren<{ readonly members: TableOfContentsSerialized[] }>) {
|
||||
const { setMembers } = useOutline();
|
||||
|
||||
useEffect(() => {
|
||||
setMembers(members);
|
||||
|
||||
return () => {
|
||||
setMembers(null);
|
||||
};
|
||||
}, [members, setMembers]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -1,37 +1,29 @@
|
||||
import type { ApiFunction } from '@discordjs/api-extractor-model';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Header } from '../../documentation/Header';
|
||||
import { Documentation } from '~/components/documentation/Documentation';
|
||||
import { ObjectHeader } from '~/components/documentation/ObjectHeader';
|
||||
import { FunctionBody } from './FunctionBody';
|
||||
|
||||
const OverloadSwitcher = dynamic(async () => import('../../OverloadSwitcher'));
|
||||
|
||||
export function Function({ item }: { readonly item: ApiFunction }) {
|
||||
const header = (
|
||||
<Header
|
||||
kind={item.kind}
|
||||
name={item.name}
|
||||
sourceURL={item.sourceLocation.fileUrl}
|
||||
sourceLine={item.sourceLocation.fileLine}
|
||||
/>
|
||||
);
|
||||
|
||||
if (item.getMergedSiblings().length > 1) {
|
||||
const overloads = item
|
||||
.getMergedSiblings()
|
||||
.map((sibling, idx) => <FunctionBody item={sibling as ApiFunction} key={`${sibling.displayName}-${idx}`} />);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{header}
|
||||
<Documentation>
|
||||
<ObjectHeader item={item} />
|
||||
<OverloadSwitcher methodName={item.displayName} overloads={overloads} />
|
||||
</div>
|
||||
</Documentation>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{header}
|
||||
<Documentation>
|
||||
<ObjectHeader item={item} />
|
||||
<FunctionBody item={item} />
|
||||
</div>
|
||||
</Documentation>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import type { ApiFunction } from '@discordjs/api-extractor-model';
|
||||
import { SyntaxHighlighter } from '../../SyntaxHighlighter';
|
||||
import { Documentation } from '../../documentation/Documentation';
|
||||
import { ParameterSection } from '../../documentation/section/ParametersSection';
|
||||
import { SummarySection } from '../../documentation/section/SummarySection';
|
||||
import { TypeParameterSection } from '../../documentation/section/TypeParametersSection';
|
||||
|
||||
export interface FunctionBodyProps {
|
||||
@@ -12,12 +9,9 @@ export interface FunctionBodyProps {
|
||||
|
||||
export function FunctionBody({ item }: { readonly item: ApiFunction }) {
|
||||
return (
|
||||
<Documentation>
|
||||
{/* @ts-expect-error async component */}
|
||||
<SyntaxHighlighter code={item.excerpt.text} />
|
||||
<SummarySection item={item} />
|
||||
<>
|
||||
{item.typeParameters.length ? <TypeParameterSection item={item} /> : null}
|
||||
{item.parameters.length ? <ParameterSection item={item} /> : null}
|
||||
</Documentation>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user