this repo has no description
1"use client";
2
3import { Link, useNavigate, useRouterState } from "@tanstack/react-router";
4import {
5 chapters,
6 getChapterByPath,
7 getChapterNeighbors,
8 type ChapterPath,
9} from "~/chapters/chapters";
10import { cn } from "~/design-system/utils/cn";
11
12export function ChapterSelect() {
13 const navigate = useNavigate();
14 const pathname = useRouterState({ select: (state) => state.location.pathname });
15 const currentChapter = getChapterByPath(pathname);
16
17 return (
18 <label className="chapter-select">
19 <span className="sr-only">Jump to chapter</span>
20 <select
21 value={currentChapter?.to ?? "/"}
22 onChange={(event) => {
23 const to = event.currentTarget.value;
24
25 if (to === "/") {
26 void navigate({ to: "/" });
27 return;
28 }
29
30 void navigate({ to: to as ChapterPath });
31 }}
32 className="chapter-select__control"
33 aria-label="Jump to chapter"
34 >
35 <option value="/">Contents</option>
36 {chapters.map((chapter) => (
37 <option key={chapter.to} value={chapter.to}>
38 {chapter.navLabel}
39 </option>
40 ))}
41 </select>
42 </label>
43 );
44}
45
46export function ChapterPager() {
47 const pathname = useRouterState({ select: (state) => state.location.pathname });
48 const { current, previous, next } = getChapterNeighbors(pathname);
49
50 if (!current) {
51 return null;
52 }
53
54 return (
55 <nav className="chapter-pager" aria-label="Chapter navigation">
56 <ChapterPagerLink direction="previous" chapter={previous} />
57
58 <Link
59 to="/"
60 className="chapter-pager__contents focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--ring-color)"
61 >
62 Contents
63 </Link>
64
65 <ChapterPagerLink direction="next" chapter={next} />
66 </nav>
67 );
68}
69
70function ChapterPagerLink(props: {
71 direction: "previous" | "next";
72 chapter: (typeof chapters)[number] | undefined;
73}) {
74 const { direction, chapter } = props;
75 const isPrevious = direction === "previous";
76
77 if (!chapter) {
78 return (
79 <span
80 className={cn(
81 "chapter-pager__link chapter-pager__link--disabled",
82 !isPrevious && "text-right",
83 )}
84 >
85 <span className="chapter-pager__kicker">{isPrevious ? "Previous" : "Next"}</span>
86 <span className="chapter-pager__title">End of sequence</span>
87 </span>
88 );
89 }
90
91 return (
92 <Link
93 to={chapter.to}
94 preload="intent"
95 className={cn(
96 "chapter-pager__link focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--ring-color)",
97 !isPrevious && "text-right",
98 )}
99 >
100 <span className="chapter-pager__kicker">{isPrevious ? "Previous" : "Next"}</span>
101 <span className="chapter-pager__title">
102 {isPrevious ? "< " : ""}
103 {chapter.number} / {chapter.title}
104 {!isPrevious ? " >" : ""}
105 </span>
106 </Link>
107 );
108}