astryx-dracula 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/astryx.integration.mjs +1 -1
- package/icons.mjs +17 -17
- package/icons.tsx +61 -62
- package/package.json +120 -116
- package/shared/auth-chrome-config.ts +6 -6
- package/shared/auth-chrome.tsx +168 -19
- package/shared/auth-copy.ts +14 -14
- package/shared/chaptered-doc-config.ts +48 -51
- package/shared/chaptered-doc.tsx +270 -292
- package/shared/chart-hues.ts +10 -15
- package/shared/chart-labels.tsx +31 -30
- package/shared/chart-legend.tsx +55 -57
- package/shared/chart-panel-style.ts +3 -3
- package/shared/data-bar.tsx +97 -102
- package/shared/format-money.ts +3 -0
- package/shared/gallery-image.ts +6 -6
- package/shared/login-demo.ts +1 -1
- package/shared/metric-card.tsx +123 -0
- package/shared/metric-delta.tsx +28 -27
- package/shared/order-desk.tsx +205 -216
- package/shared/revenue-chart.tsx +145 -165
- package/shared/scene-castle.tsx +206 -291
- package/shared/scene-frame.tsx +33 -32
- package/shared/scene-hues.ts +17 -25
- package/shared/scene-tile.tsx +88 -100
- package/shared/settings-data.ts +132 -104
- package/shared/settings-rows.tsx +143 -163
- package/shared/sparkline.tsx +75 -88
- package/shared/sso-icons.tsx +10 -22
- package/shared/stars.tsx +19 -0
- package/templates/ai-chat-landing.template.mjs +4 -4
- package/templates/ai-chat-landing.tsx +468 -447
- package/templates/ai-chat.template.mjs +4 -4
- package/templates/ai-chat.tsx +561 -645
- package/templates/blank.template.mjs +4 -4
- package/templates/blank.tsx +14 -12
- package/templates/centered-hero.template.mjs +4 -4
- package/templates/centered-hero.tsx +52 -67
- package/templates/classic-gallery.template.mjs +4 -4
- package/templates/classic-gallery.tsx +92 -101
- package/templates/contact-form.template.mjs +4 -4
- package/templates/contact-form.tsx +243 -280
- package/templates/dashboard-portfolio.template.mjs +4 -4
- package/templates/dashboard-portfolio.tsx +723 -634
- package/templates/dashboard.template.mjs +4 -4
- package/templates/dashboard.tsx +592 -682
- package/templates/detail-page.template.mjs +4 -4
- package/templates/detail-page.tsx +537 -598
- package/templates/documentation-design.template.mjs +4 -4
- package/templates/documentation-design.tsx +242 -709
- package/templates/documentation-technical.template.mjs +4 -4
- package/templates/documentation-technical.tsx +233 -258
- package/templates/documentation.template.mjs +4 -4
- package/templates/documentation.tsx +263 -277
- package/templates/editor.template.mjs +4 -4
- package/templates/editor.tsx +847 -899
- package/templates/file-explorer.template.mjs +4 -4
- package/templates/file-explorer.tsx +562 -602
- package/templates/form-two-column.template.mjs +4 -4
- package/templates/form-two-column.tsx +187 -208
- package/templates/gallery-hero.template.mjs +4 -4
- package/templates/gallery-hero.tsx +89 -112
- package/templates/ide.template.mjs +4 -4
- package/templates/ide.tsx +405 -462
- package/templates/incident-console.template.mjs +4 -4
- package/templates/incident-console.tsx +559 -581
- package/templates/kanban-board.template.mjs +4 -4
- package/templates/kanban-board.tsx +660 -729
- package/templates/library.template.mjs +4 -4
- package/templates/library.tsx +405 -452
- package/templates/login-card.template.mjs +4 -4
- package/templates/login-card.tsx +59 -163
- package/templates/login-split.template.mjs +4 -4
- package/templates/login-split.tsx +196 -232
- package/templates/login-sso.template.mjs +4 -4
- package/templates/login-sso.tsx +253 -277
- package/templates/login.template.mjs +4 -4
- package/templates/login.tsx +51 -149
- package/templates/messaging-shell.template.mjs +4 -4
- package/templates/messaging-shell.tsx +596 -624
- package/templates/mixed-gallery.template.mjs +4 -4
- package/templates/mixed-gallery.tsx +56 -56
- package/templates/payment-form.template.mjs +4 -4
- package/templates/payment-form.tsx +877 -990
- package/templates/product-detail.template.mjs +4 -4
- package/templates/product-detail.tsx +251 -302
- package/templates/product-gallery.template.mjs +4 -4
- package/templates/product-gallery.tsx +122 -135
- package/templates/product-tour.template.mjs +4 -4
- package/templates/product-tour.tsx +737 -794
- package/templates/settings-dialog.template.mjs +4 -4
- package/templates/settings-dialog.tsx +694 -747
- package/templates/settings-sidebar.template.mjs +4 -4
- package/templates/settings-sidebar.tsx +768 -848
- package/templates/settings.template.mjs +4 -4
- package/templates/settings.tsx +306 -230
- package/templates/shell-nav.template.mjs +4 -4
- package/templates/shell-nav.tsx +217 -277
- package/templates/shell-side-nav.template.mjs +4 -4
- package/templates/shell-side-nav.tsx +130 -231
- package/templates/shell-top-nav.template.mjs +4 -4
- package/templates/shell-top-nav.tsx +192 -248
- package/templates/side-gallery.template.mjs +4 -4
- package/templates/side-gallery.tsx +87 -94
- package/templates/table-grouped.template.mjs +4 -4
- package/templates/table-grouped.tsx +999 -1201
- package/templates/table-page-chart.template.mjs +4 -4
- package/templates/table-page-chart.tsx +398 -397
- package/templates/table-page-heatmap-status.template.mjs +4 -4
- package/templates/table-page-heatmap-status.tsx +479 -527
- package/templates/table-page-shoe-store-heatmap.template.mjs +4 -4
- package/templates/table-page-shoe-store-heatmap.tsx +746 -746
- package/templates/table-page.template.mjs +4 -4
- package/templates/table-page.tsx +393 -431
- package/templates/table.template.mjs +4 -4
- package/templates/table.tsx +93 -99
- package/templates/tech-report.template.mjs +4 -4
- package/templates/tech-report.tsx +1320 -1324
- package/templates/theme-showcase.template.mjs +4 -4
- package/templates/theme-showcase.tsx +869 -1246
- package/tokens.css +340 -343
package/shared/chaptered-doc.tsx
CHANGED
|
@@ -5,328 +5,306 @@
|
|
|
5
5
|
// Scene systems stay local too: product-tour keeps BAT_WING/BAT_BODY/FIR +
|
|
6
6
|
// NightScene/PaletteScene/TypeScene/PagesScene, tech-report keeps its own.
|
|
7
7
|
|
|
8
|
+
import { AppShell } from "@astryxdesign/core/AppShell";
|
|
9
|
+
import { AspectRatio } from "@astryxdesign/core/AspectRatio";
|
|
10
|
+
import { Button } from "@astryxdesign/core/Button";
|
|
11
|
+
import { CodeBlock } from "@astryxdesign/core/CodeBlock";
|
|
12
|
+
import { Divider } from "@astryxdesign/core/Divider";
|
|
13
|
+
import { useMediaQuery } from "@astryxdesign/core/hooks";
|
|
14
|
+
import type { IconType } from "@astryxdesign/core/Icon";
|
|
15
|
+
import { Icon } from "@astryxdesign/core/Icon";
|
|
8
16
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} from
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
SideNav,
|
|
25
|
-
SideNavHeading,
|
|
26
|
-
SideNavItem,
|
|
27
|
-
SideNavSection,
|
|
28
|
-
} from '@astryxdesign/core/SideNav';
|
|
29
|
-
import {NavIcon} from '@astryxdesign/core/NavIcon';
|
|
17
|
+
HStack,
|
|
18
|
+
Layout,
|
|
19
|
+
LayoutContent,
|
|
20
|
+
LayoutPanel,
|
|
21
|
+
StackItem,
|
|
22
|
+
VStack,
|
|
23
|
+
} from "@astryxdesign/core/Layout";
|
|
24
|
+
import { List, ListItem } from "@astryxdesign/core/List";
|
|
25
|
+
import { MobileNavToggle } from "@astryxdesign/core/MobileNav";
|
|
26
|
+
import { NavIcon } from "@astryxdesign/core/NavIcon";
|
|
27
|
+
import { Outline } from "@astryxdesign/core/Outline";
|
|
28
|
+
import { Selector } from "@astryxdesign/core/Selector";
|
|
29
|
+
import { SideNav, SideNavHeading, SideNavItem, SideNavSection } from "@astryxdesign/core/SideNav";
|
|
30
|
+
import { Heading, Text } from "@astryxdesign/core/Text";
|
|
30
31
|
import {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
import {
|
|
41
|
-
import type
|
|
42
|
-
import {AspectRatio} from '@astryxdesign/core/AspectRatio';
|
|
43
|
-
import {CodeBlock} from '@astryxdesign/core/CodeBlock';
|
|
44
|
-
import {Divider} from '@astryxdesign/core/Divider';
|
|
45
|
-
import {List, ListItem} from '@astryxdesign/core/List';
|
|
46
|
-
import {Outline} from '@astryxdesign/core/Outline';
|
|
47
|
-
import {Selector} from '@astryxdesign/core/Selector';
|
|
48
|
-
import {useMediaQuery} from '@astryxdesign/core/hooks';
|
|
49
|
-
|
|
50
|
-
import {ChevronLeft, ChevronRight} from 'lucide-react';
|
|
32
|
+
buildOutlineByChapter,
|
|
33
|
+
type ChapterGroup,
|
|
34
|
+
type DocChapter,
|
|
35
|
+
type DocSection,
|
|
36
|
+
outlinePanel,
|
|
37
|
+
sceneClip,
|
|
38
|
+
scrollToSection,
|
|
39
|
+
sectionId,
|
|
40
|
+
} from "astryx-dracula/shared/chaptered-doc-config";
|
|
41
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
42
|
+
import { type CSSProperties, type ReactNode, useState } from "react";
|
|
51
43
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
44
|
+
function ChapterRail({
|
|
45
|
+
groups,
|
|
46
|
+
activeId,
|
|
47
|
+
onSelect,
|
|
48
|
+
heading,
|
|
49
|
+
subheading,
|
|
50
|
+
headingHref,
|
|
51
|
+
headingIcon,
|
|
60
52
|
}: {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
groups: ChapterGroup[];
|
|
54
|
+
activeId: string;
|
|
55
|
+
onSelect: (id: string) => void;
|
|
56
|
+
heading: string;
|
|
57
|
+
subheading: string;
|
|
58
|
+
headingHref: string;
|
|
59
|
+
headingIcon: ReactNode;
|
|
68
60
|
}) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
61
|
+
// Resizable like the shell-side-nav template: 264 default, 220-400 range.
|
|
62
|
+
// The AppShell drawer owns the rail below 1024px (see MobileNavToggle),
|
|
63
|
+
// so the handle only matters at desktop widths.
|
|
64
|
+
return (
|
|
65
|
+
<SideNav
|
|
66
|
+
collapsible
|
|
67
|
+
resizable={{ defaultWidth: 264, minWidth: 220, maxWidth: 400 }}
|
|
68
|
+
header={
|
|
69
|
+
<SideNavHeading
|
|
70
|
+
icon={<NavIcon icon={headingIcon} />}
|
|
71
|
+
heading={heading}
|
|
72
|
+
subheading={subheading}
|
|
73
|
+
headingHref={headingHref}
|
|
74
|
+
/>
|
|
75
|
+
}
|
|
76
|
+
>
|
|
77
|
+
{groups.map((group) => (
|
|
78
|
+
<SideNavSection key={group.title} title={group.title}>
|
|
79
|
+
{group.chapters.map((chapter) => (
|
|
80
|
+
<SideNavItem
|
|
81
|
+
key={chapter.id}
|
|
82
|
+
label={chapter.title}
|
|
83
|
+
icon={chapter.icon}
|
|
84
|
+
isSelected={chapter.id === activeId}
|
|
85
|
+
onClick={() => onSelect(chapter.id)}
|
|
86
|
+
/>
|
|
87
|
+
))}
|
|
88
|
+
</SideNavSection>
|
|
89
|
+
))}
|
|
90
|
+
</SideNav>
|
|
91
|
+
);
|
|
99
92
|
}
|
|
100
93
|
|
|
101
94
|
// ─── Chapter body ────────────────────────────────────────────────────────────
|
|
102
95
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
title={section.code.title}
|
|
130
|
-
width="100%"
|
|
131
|
-
/>
|
|
132
|
-
)}
|
|
133
|
-
</VStack>
|
|
134
|
-
);
|
|
96
|
+
function SectionBlock({ chapterId, section }: { chapterId: string; section: DocSection }) {
|
|
97
|
+
return (
|
|
98
|
+
<VStack gap={3}>
|
|
99
|
+
<Heading level={2} id={sectionId(chapterId, section.key)}>
|
|
100
|
+
{section.heading}
|
|
101
|
+
</Heading>
|
|
102
|
+
<Text type="body" color="secondary" display="block">
|
|
103
|
+
{section.body}
|
|
104
|
+
</Text>
|
|
105
|
+
{section.bullets != null && (
|
|
106
|
+
<List listStyle="disc">
|
|
107
|
+
{section.bullets.map((bullet) => (
|
|
108
|
+
<ListItem key={bullet} label={bullet} />
|
|
109
|
+
))}
|
|
110
|
+
</List>
|
|
111
|
+
)}
|
|
112
|
+
{section.code != null && (
|
|
113
|
+
<CodeBlock
|
|
114
|
+
code={section.code.source}
|
|
115
|
+
language={section.code.language}
|
|
116
|
+
title={section.code.title}
|
|
117
|
+
width="100%"
|
|
118
|
+
/>
|
|
119
|
+
)}
|
|
120
|
+
</VStack>
|
|
121
|
+
);
|
|
135
122
|
}
|
|
136
123
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
124
|
+
function ChapterNav({
|
|
125
|
+
chapters,
|
|
126
|
+
chapter,
|
|
127
|
+
onSelect,
|
|
141
128
|
}: {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
129
|
+
chapters: DocChapter[];
|
|
130
|
+
chapter: DocChapter;
|
|
131
|
+
onSelect: (id: string) => void;
|
|
145
132
|
}) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
133
|
+
const index = chapters.findIndex((entry) => entry.id === chapter.id);
|
|
134
|
+
const previous = index > 0 ? chapters[index - 1] : undefined;
|
|
135
|
+
const next = index < chapters.length - 1 ? chapters[index + 1] : undefined;
|
|
136
|
+
return (
|
|
137
|
+
<HStack gap={3} hAlign="between" vAlign="center">
|
|
138
|
+
{previous != null ? (
|
|
139
|
+
<Button
|
|
140
|
+
label={previous.title}
|
|
141
|
+
variant="secondary"
|
|
142
|
+
icon={<Icon icon={ChevronLeft} size="sm" />}
|
|
143
|
+
onClick={() => onSelect(previous.id)}
|
|
144
|
+
/>
|
|
145
|
+
) : (
|
|
146
|
+
<StackItem size="fill" />
|
|
147
|
+
)}
|
|
148
|
+
{next != null ? (
|
|
149
|
+
<Button
|
|
150
|
+
label={next.title}
|
|
151
|
+
variant="secondary"
|
|
152
|
+
endContent={<Icon icon={ChevronRight} size="sm" />}
|
|
153
|
+
onClick={() => onSelect(next.id)}
|
|
154
|
+
/>
|
|
155
|
+
) : (
|
|
156
|
+
<StackItem size="fill" />
|
|
157
|
+
)}
|
|
158
|
+
</HStack>
|
|
159
|
+
);
|
|
173
160
|
}
|
|
174
161
|
|
|
175
162
|
// ─── Page ────────────────────────────────────────────────────────────────────
|
|
176
163
|
|
|
177
|
-
export function ChapterArtFrame({children}: {children: ReactNode}) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
164
|
+
export function ChapterArtFrame({ children }: { children: ReactNode }) {
|
|
165
|
+
return (
|
|
166
|
+
<AspectRatio ratio={16 / 9} style={sceneClip}>
|
|
167
|
+
{children}
|
|
168
|
+
</AspectRatio>
|
|
169
|
+
);
|
|
183
170
|
}
|
|
184
171
|
|
|
185
172
|
export default function ChapteredDoc({
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
173
|
+
groups,
|
|
174
|
+
defaultChapter,
|
|
175
|
+
railHeading,
|
|
176
|
+
railSubheading,
|
|
177
|
+
railHref,
|
|
178
|
+
railIcon,
|
|
179
|
+
eyebrow,
|
|
180
|
+
badge,
|
|
181
|
+
art,
|
|
182
|
+
footer,
|
|
196
183
|
}: {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
184
|
+
groups: ChapterGroup[];
|
|
185
|
+
defaultChapter: string;
|
|
186
|
+
railHeading: string;
|
|
187
|
+
railSubheading: string;
|
|
188
|
+
railHref: string;
|
|
189
|
+
railIcon: ReactNode;
|
|
190
|
+
eyebrow: string;
|
|
191
|
+
badge: (chapter: DocChapter, index: number, total: number) => ReactNode;
|
|
192
|
+
art: (chapterId: string) => ReactNode;
|
|
193
|
+
footer?: ReactNode;
|
|
207
194
|
}) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
195
|
+
const chapters = groups.flatMap((group) => group.chapters);
|
|
196
|
+
const [outlineByChapter] = useState(() => buildOutlineByChapter(chapters));
|
|
197
|
+
const [chapterId, setChapterId] = useState(defaultChapter);
|
|
198
|
+
const [activeSection, setActiveSection] = useState(
|
|
199
|
+
outlineByChapter[defaultChapter]?.[0]?.id ?? "",
|
|
200
|
+
);
|
|
214
201
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
202
|
+
// Responsive contract: below 1024px the outline stops being a column, since
|
|
203
|
+
// a narrow viewport has nothing to outline against.
|
|
204
|
+
const isNarrow = useMediaQuery("(max-width: 1024px)");
|
|
218
205
|
|
|
219
|
-
|
|
220
|
-
|
|
206
|
+
const chapter = chapters.find((entry) => entry.id === chapterId) ?? chapters[0];
|
|
207
|
+
const outlineItems = outlineByChapter[chapter.id] ?? [];
|
|
221
208
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
209
|
+
const openChapter = (id: string) => {
|
|
210
|
+
setChapterId(id);
|
|
211
|
+
setActiveSection(outlineByChapter[id]?.[0]?.id ?? "");
|
|
212
|
+
// A chapter reads as a new page, so the document goes back to the top
|
|
213
|
+
// instead of keeping the previous chapter's scroll offset.
|
|
214
|
+
window.scrollTo({ top: 0 });
|
|
215
|
+
};
|
|
229
216
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
</VStack>
|
|
217
|
+
return (
|
|
218
|
+
<AppShell
|
|
219
|
+
height="auto"
|
|
220
|
+
contentPadding={0}
|
|
221
|
+
mobileNav={{ hasToggle: false }}
|
|
222
|
+
sideNav={
|
|
223
|
+
<ChapterRail
|
|
224
|
+
groups={groups}
|
|
225
|
+
activeId={chapter.id}
|
|
226
|
+
onSelect={openChapter}
|
|
227
|
+
heading={railHeading}
|
|
228
|
+
subheading={railSubheading}
|
|
229
|
+
headingHref={railHref}
|
|
230
|
+
headingIcon={railIcon}
|
|
231
|
+
/>
|
|
232
|
+
}
|
|
233
|
+
>
|
|
234
|
+
<Layout
|
|
235
|
+
height="auto"
|
|
236
|
+
contentWidth={960}
|
|
237
|
+
end={
|
|
238
|
+
isNarrow ? undefined : (
|
|
239
|
+
<LayoutPanel
|
|
240
|
+
isScrollable={false}
|
|
241
|
+
label="On this page"
|
|
242
|
+
role="complementary"
|
|
243
|
+
style={outlinePanel}
|
|
244
|
+
>
|
|
245
|
+
<Outline items={outlineItems} onActiveIdChange={setActiveSection} />
|
|
246
|
+
</LayoutPanel>
|
|
247
|
+
)
|
|
248
|
+
}
|
|
249
|
+
content={
|
|
250
|
+
<LayoutContent isScrollable={false} padding={8}>
|
|
251
|
+
<VStack gap={8}>
|
|
252
|
+
<VStack gap={2}>
|
|
253
|
+
<HStack gap={2} vAlign="center">
|
|
254
|
+
<MobileNavToggle />
|
|
255
|
+
<Text type="supporting" color="secondary">
|
|
256
|
+
{eyebrow}
|
|
257
|
+
</Text>
|
|
258
|
+
</HStack>
|
|
259
|
+
<Heading level={1} type="display-2">
|
|
260
|
+
{chapter.title}
|
|
261
|
+
</Heading>
|
|
262
|
+
<Text type="supporting" color="secondary" hasTabularNumbers>
|
|
263
|
+
{badge(
|
|
264
|
+
chapter,
|
|
265
|
+
chapters.findIndex((entry) => entry.id === chapter.id),
|
|
266
|
+
chapters.length,
|
|
267
|
+
)}
|
|
268
|
+
</Text>
|
|
269
|
+
{isNarrow && (
|
|
270
|
+
<Selector
|
|
271
|
+
label="On this page"
|
|
272
|
+
isLabelHidden
|
|
273
|
+
options={outlineItems.map((item) => ({
|
|
274
|
+
value: item.id,
|
|
275
|
+
label: item.label,
|
|
276
|
+
}))}
|
|
277
|
+
value={activeSection}
|
|
278
|
+
onChange={(id: string) => {
|
|
279
|
+
setActiveSection(id);
|
|
280
|
+
scrollToSection(id);
|
|
281
|
+
}}
|
|
282
|
+
width="100%"
|
|
283
|
+
/>
|
|
284
|
+
)}
|
|
285
|
+
</VStack>
|
|
300
286
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
287
|
+
<Text type="large" color="secondary" display="block">
|
|
288
|
+
{chapter.intro}
|
|
289
|
+
</Text>
|
|
304
290
|
|
|
305
|
-
|
|
291
|
+
{art(chapter.id)}
|
|
306
292
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
section={section}
|
|
313
|
-
/>
|
|
314
|
-
))}
|
|
315
|
-
</VStack>
|
|
293
|
+
<VStack gap={8}>
|
|
294
|
+
{chapter.sections.map((section) => (
|
|
295
|
+
<SectionBlock key={section.key} chapterId={chapter.id} section={section} />
|
|
296
|
+
))}
|
|
297
|
+
</VStack>
|
|
316
298
|
|
|
317
|
-
|
|
299
|
+
<Divider />
|
|
318
300
|
|
|
319
|
-
|
|
320
|
-
chapters={chapters}
|
|
321
|
-
chapter={chapter}
|
|
322
|
-
onSelect={openChapter}
|
|
323
|
-
/>
|
|
301
|
+
<ChapterNav chapters={chapters} chapter={chapter} onSelect={openChapter} />
|
|
324
302
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
303
|
+
{footer}
|
|
304
|
+
</VStack>
|
|
305
|
+
</LayoutContent>
|
|
306
|
+
}
|
|
307
|
+
/>
|
|
308
|
+
</AppShell>
|
|
309
|
+
);
|
|
332
310
|
}
|
package/shared/chart-hues.ts
CHANGED
|
@@ -7,21 +7,16 @@
|
|
|
7
7
|
// legend row (dashboard.tsx:229, :253) -- a labelled data category, not chrome.
|
|
8
8
|
|
|
9
9
|
export const CHART_HUES = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
cyan: "var(--color-data-categorical-cyan)",
|
|
11
|
+
orange: "var(--color-data-categorical-orange)",
|
|
12
|
+
green: "var(--color-data-categorical-green)",
|
|
13
|
+
pink: "var(--color-data-categorical-pink)",
|
|
14
|
+
muted: "var(--color-data-categorical-blue)",
|
|
15
|
+
// Added because --color-data-categorical-red exists in the palette
|
|
16
|
+
// (tokens.css:276) and heat maps need a severity colour, but no module
|
|
17
|
+
// exposed it. Without this, a chart could not reach red through the
|
|
18
|
+
// sanctioned source at all.
|
|
19
|
+
red: "var(--color-data-categorical-red)",
|
|
20
20
|
} as const;
|
|
21
21
|
|
|
22
22
|
export type ChartHue = (typeof CHART_HUES)[keyof typeof CHART_HUES];
|
|
23
|
-
|
|
24
|
-
// The value list exists for the gate: it reads the object's VALUES, never a
|
|
25
|
-
// grep across shared/. A text-level filter cannot separate the sanctioned rows
|
|
26
|
-
// from a drifting neighbour, which is why the check is here and not in a lint.
|
|
27
|
-
export const CHART_HUE_VALUES: readonly ChartHue[] = Object.values(CHART_HUES);
|