radiant-docs 0.1.40 → 0.1.42
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/package.json +1 -1
- package/template/astro.config.mjs +42 -40
- package/template/package-lock.json +7 -0
- package/template/package.json +3 -2
- package/template/public/favicon.svg +16 -8
- package/template/scripts/remove-assistant-for-non-pro.mjs +28 -0
- package/template/src/components/Header.astro +151 -17
- package/template/src/components/MdxPage.astro +76 -22
- package/template/src/components/PagePagination.astro +44 -8
- package/template/src/components/Sidebar.astro +10 -1
- package/template/src/components/TableOfContents.astro +159 -53
- package/template/src/components/chat/AssistantDocsWidget.astro +16 -0
- package/template/src/components/chat/AssistantDocsWidget.tsx +615 -0
- package/template/src/components/chat/AssistantEmbedPanel.tsx +2679 -0
- package/template/src/components/chat/AssistantEmbedPanelPage.astro +95 -0
- package/template/src/components/user/Accordion.astro +2 -2
- package/template/src/components/user/AccordionGroup.astro +1 -1
- package/template/src/components/user/Callout.astro +10 -4
- package/template/src/components/user/Card.astro +488 -0
- package/template/src/components/user/CardGradient.astro +964 -0
- package/template/src/components/user/CodeBlock.astro +1 -1
- package/template/src/components/user/CodeGroup.astro +1 -1
- package/template/src/components/user/Column.astro +25 -0
- package/template/src/components/user/Columns.astro +200 -0
- package/template/src/components/user/ComponentPreviewBlock.astro +1 -1
- package/template/src/components/user/Image.astro +1 -1
- package/template/src/components/user/Step.astro +1 -1
- package/template/src/components/user/Steps.astro +1 -1
- package/template/src/components/user/Tab.astro +1 -3
- package/template/src/components/user/Tabs.astro +2 -2
- package/template/src/layouts/Layout.astro +13 -156
- package/template/src/lib/assistant-chrome-defaults.ts +86 -0
- package/template/src/lib/assistant-chrome.ts +39 -0
- package/template/src/lib/assistant-embed-script.ts +1088 -0
- package/template/src/lib/assistant-panel-config.ts +80 -0
- package/template/src/lib/favicon.ts +31 -0
- package/template/src/lib/theme-css.ts +176 -0
- package/template/src/lib/validation.ts +668 -41
- package/template/src/pages/-/assistant/embed.js.ts +15 -0
- package/template/src/pages/-/assistant/panel.astro +5 -0
- package/template/src/pages/404.astro +4 -4
- package/template/src/styles/global.css +81 -4
- package/template/src/components/chat/AskAiWidget.tsx +0 -2011
|
@@ -3,6 +3,12 @@ import { getConfig, type DocsConfig } from "../lib/validation";
|
|
|
3
3
|
import ThemeSwitcher from "./ThemeSwitcher.astro";
|
|
4
4
|
import SidebarMenu from "./SidebarMenu.astro";
|
|
5
5
|
|
|
6
|
+
interface Props {
|
|
7
|
+
askAiEnabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { askAiEnabled = false } = Astro.props as Props;
|
|
11
|
+
|
|
6
12
|
const config: DocsConfig = await getConfig();
|
|
7
13
|
---
|
|
8
14
|
|
|
@@ -13,7 +19,10 @@ const config: DocsConfig = await getConfig();
|
|
|
13
19
|
<SidebarMenu navigation={config.navigation} />
|
|
14
20
|
</nav>
|
|
15
21
|
<div
|
|
16
|
-
class=
|
|
22
|
+
class:list={[
|
|
23
|
+
"mt-auto bg-background z-10 p-3 border-t border-t-border-light flex gap-1.5 items-center",
|
|
24
|
+
askAiEnabled ? "justify-start" : "justify-end",
|
|
25
|
+
]}
|
|
17
26
|
>
|
|
18
27
|
<span class="text-neutral-400 text-xs font-light">Theme</span>
|
|
19
28
|
<ThemeSwitcher />
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { MarkdownHeading } from "astro";
|
|
3
|
+
import { Icon } from "astro-icon/components";
|
|
3
4
|
|
|
4
5
|
interface Props {
|
|
5
6
|
headings: MarkdownHeading[];
|
|
@@ -29,19 +30,32 @@ for (const heading of headings) {
|
|
|
29
30
|
---
|
|
30
31
|
|
|
31
32
|
<nav
|
|
32
|
-
class="sticky top-
|
|
33
|
+
class="sticky top-[calc(68px+64px)] text-[13px]/5"
|
|
33
34
|
aria-label="Table of Contents"
|
|
34
35
|
data-slugs={JSON.stringify(headings.map((h) => h.slug))}
|
|
35
36
|
>
|
|
36
|
-
<div
|
|
37
|
+
<div
|
|
38
|
+
class="pl-[22px] relative font-medium mb-3 text-neutral-900 dark:text-neutral-100"
|
|
39
|
+
>
|
|
40
|
+
<Icon
|
|
41
|
+
name="lucide:text-align-start"
|
|
42
|
+
class="absolute left-0 top-1/2 -translate-y-1/2 size-3"
|
|
43
|
+
/>On this page
|
|
44
|
+
</div>
|
|
37
45
|
<div class="flex text-neutral-600/90 dark:text-neutral-300/90">
|
|
38
|
-
<svg
|
|
46
|
+
<svg
|
|
47
|
+
data-rd-toc-rail
|
|
48
|
+
viewBox="0 0 22 100"
|
|
49
|
+
width="22px"
|
|
50
|
+
height="100"
|
|
51
|
+
class="shrink-0"
|
|
52
|
+
>
|
|
39
53
|
<path
|
|
40
54
|
id="toc-bg-path"
|
|
41
55
|
d=""
|
|
42
|
-
stroke-width="1
|
|
56
|
+
stroke-width="1"
|
|
43
57
|
vector-effect="non-scaling-stroke"
|
|
44
|
-
class="stroke-neutral-200 dark:stroke-neutral-700/70"
|
|
58
|
+
class="stroke-neutral-200/80 dark:stroke-neutral-700/70"
|
|
45
59
|
fill="none"
|
|
46
60
|
stroke-linecap="round"
|
|
47
61
|
stroke-linejoin="round"></path>
|
|
@@ -50,14 +64,13 @@ for (const heading of headings) {
|
|
|
50
64
|
d=""
|
|
51
65
|
stroke-width="1.4"
|
|
52
66
|
vector-effect="non-scaling-stroke"
|
|
53
|
-
class="transition-[stroke-dasharray] duration-200"
|
|
54
|
-
style="stroke: var(--color-theme);"
|
|
67
|
+
class="transition-[stroke-dasharray] duration-200 stroke-(--color-theme)/50"
|
|
55
68
|
fill="none"
|
|
56
69
|
stroke-linecap="round"
|
|
57
70
|
stroke-linejoin="round"></path>
|
|
58
71
|
<g id="toc-circles"></g>
|
|
59
72
|
</svg>
|
|
60
|
-
<ol id="toc-list">
|
|
73
|
+
<ol id="toc-list" class="text-neutral-500/80 dark:text-neutral-400/70">
|
|
61
74
|
{
|
|
62
75
|
groupedHeadings.map((heading) => (
|
|
63
76
|
<li class="mt-3 first:mt-0">
|
|
@@ -94,7 +107,7 @@ for (const heading of headings) {
|
|
|
94
107
|
<script>
|
|
95
108
|
function initTableOfContents() {
|
|
96
109
|
const nav = document.querySelector('nav[aria-label="Table of Contents"]');
|
|
97
|
-
const svg = nav?.querySelector("
|
|
110
|
+
const svg = nav?.querySelector("[data-rd-toc-rail]");
|
|
98
111
|
const ol = nav?.querySelector("#toc-list");
|
|
99
112
|
|
|
100
113
|
if (!svg || !ol) return;
|
|
@@ -109,12 +122,15 @@ for (const heading of headings) {
|
|
|
109
122
|
let path = "";
|
|
110
123
|
let currentY = 0;
|
|
111
124
|
const gap = 12; // mt-3 = 12px
|
|
112
|
-
const
|
|
125
|
+
const markerOffset = 10; // Half of the inherited 20px line-height
|
|
126
|
+
const linkPositions: Map<string, { pathLengthAtMarker: number }> =
|
|
127
|
+
new Map();
|
|
113
128
|
|
|
114
129
|
// First pass: collect all items with their positions
|
|
115
130
|
interface ItemInfo {
|
|
116
131
|
x: number;
|
|
117
132
|
height: number;
|
|
133
|
+
markerY: number;
|
|
118
134
|
slug?: string;
|
|
119
135
|
yStart: number;
|
|
120
136
|
}
|
|
@@ -123,7 +139,7 @@ for (const heading of headings) {
|
|
|
123
139
|
// Iterate through top-level items to collect data
|
|
124
140
|
ol.querySelectorAll(":scope > li").forEach((li) => {
|
|
125
141
|
const topLink = li.querySelector(
|
|
126
|
-
":scope > a"
|
|
142
|
+
":scope > a",
|
|
127
143
|
) as HTMLAnchorElement | null;
|
|
128
144
|
const subOl = li.querySelector(":scope > ol");
|
|
129
145
|
|
|
@@ -134,6 +150,7 @@ for (const heading of headings) {
|
|
|
134
150
|
items.push({
|
|
135
151
|
x: 0.5,
|
|
136
152
|
height,
|
|
153
|
+
markerY: currentY + Math.min(markerOffset, height / 2),
|
|
137
154
|
slug: topLink.dataset.slug,
|
|
138
155
|
yStart: currentY,
|
|
139
156
|
});
|
|
@@ -144,7 +161,7 @@ for (const heading of headings) {
|
|
|
144
161
|
if (subOl) {
|
|
145
162
|
subOl.querySelectorAll(":scope > li").forEach((subLi) => {
|
|
146
163
|
const subLink = subLi.querySelector(
|
|
147
|
-
"a"
|
|
164
|
+
"a",
|
|
148
165
|
) as HTMLAnchorElement | null;
|
|
149
166
|
if (!subLink) return;
|
|
150
167
|
|
|
@@ -155,6 +172,7 @@ for (const heading of headings) {
|
|
|
155
172
|
items.push({
|
|
156
173
|
x: 12,
|
|
157
174
|
height,
|
|
175
|
+
markerY: currentY + Math.min(markerOffset, height / 2),
|
|
158
176
|
slug: subLink.dataset.slug,
|
|
159
177
|
yStart: currentY,
|
|
160
178
|
});
|
|
@@ -163,59 +181,121 @@ for (const heading of headings) {
|
|
|
163
181
|
}
|
|
164
182
|
});
|
|
165
183
|
|
|
166
|
-
// Second pass: build path with
|
|
184
|
+
// Second pass: build path with first-line anchors, tracking cumulative path length
|
|
167
185
|
let pathLength = 0;
|
|
168
186
|
let prevX: number | null = null;
|
|
169
187
|
let prevY: number | null = null;
|
|
170
188
|
|
|
189
|
+
function getCubicPoint(
|
|
190
|
+
start: number,
|
|
191
|
+
control1: number,
|
|
192
|
+
control2: number,
|
|
193
|
+
end: number,
|
|
194
|
+
progress: number,
|
|
195
|
+
) {
|
|
196
|
+
const inverse = 1 - progress;
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
inverse ** 3 * start +
|
|
200
|
+
3 * inverse ** 2 * progress * control1 +
|
|
201
|
+
3 * inverse * progress ** 2 * control2 +
|
|
202
|
+
progress ** 3 * end
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function getCubicLength(
|
|
207
|
+
x1: number,
|
|
208
|
+
y1: number,
|
|
209
|
+
c1x: number,
|
|
210
|
+
c1y: number,
|
|
211
|
+
c2x: number,
|
|
212
|
+
c2y: number,
|
|
213
|
+
x2: number,
|
|
214
|
+
y2: number,
|
|
215
|
+
) {
|
|
216
|
+
let length = 0;
|
|
217
|
+
let previousX = x1;
|
|
218
|
+
let previousY = y1;
|
|
219
|
+
|
|
220
|
+
for (let step = 1; step <= 12; step += 1) {
|
|
221
|
+
const progress = step / 12;
|
|
222
|
+
const x = getCubicPoint(x1, c1x, c2x, x2, progress);
|
|
223
|
+
const y = getCubicPoint(y1, c1y, c2y, y2, progress);
|
|
224
|
+
length += Math.hypot(x - previousX, y - previousY);
|
|
225
|
+
previousX = x;
|
|
226
|
+
previousY = y;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return length;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function appendConnector(x: number, y: number) {
|
|
233
|
+
if (prevX === null || prevY === null) return;
|
|
234
|
+
|
|
235
|
+
const dx = x - prevX;
|
|
236
|
+
const dy = y - prevY;
|
|
237
|
+
|
|
238
|
+
if (Math.abs(dx) < 0.01 || Math.abs(dy) < 0.01) {
|
|
239
|
+
path += `L ${x} ${y} `;
|
|
240
|
+
pathLength += Math.hypot(dx, dy);
|
|
241
|
+
} else {
|
|
242
|
+
const bendOffset = Math.min(Math.abs(dy) * 0.6, 8);
|
|
243
|
+
const direction = dy > 0 ? 1 : -1;
|
|
244
|
+
const c1x = prevX;
|
|
245
|
+
const c1y = prevY + bendOffset * direction;
|
|
246
|
+
const c2x = x;
|
|
247
|
+
const c2y = y - bendOffset * direction;
|
|
248
|
+
|
|
249
|
+
path += `C ${c1x} ${c1y} ${c2x} ${c2y} ${x} ${y} `;
|
|
250
|
+
pathLength += getCubicLength(prevX, prevY, c1x, c1y, c2x, c2y, x, y);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
prevX = x;
|
|
254
|
+
prevY = y;
|
|
255
|
+
}
|
|
256
|
+
|
|
171
257
|
items.forEach((item, index) => {
|
|
172
258
|
const isFirst = index === 0;
|
|
173
259
|
const isLast = index === items.length - 1;
|
|
174
|
-
const midY = item.yStart + item.height / 2;
|
|
175
260
|
|
|
176
261
|
if (isFirst) {
|
|
177
|
-
// Start at
|
|
178
|
-
path = `M ${item.x} ${
|
|
262
|
+
// Start at the center of the first rendered line.
|
|
263
|
+
path = `M ${item.x} ${item.markerY} `;
|
|
179
264
|
prevX = item.x;
|
|
180
|
-
prevY =
|
|
265
|
+
prevY = item.markerY;
|
|
181
266
|
|
|
182
|
-
// Path length at first item's
|
|
267
|
+
// Path length at first item's marker is 0
|
|
183
268
|
if (item.slug) {
|
|
184
|
-
linkPositions.set(item.slug, {
|
|
269
|
+
linkPositions.set(item.slug, { pathLengthAtMarker: 0 });
|
|
185
270
|
}
|
|
186
271
|
|
|
187
272
|
if (!isLast) {
|
|
188
|
-
// Draw from
|
|
273
|
+
// Draw from first-line center to bottom
|
|
189
274
|
path += `L ${item.x} ${item.yStart + item.height} `;
|
|
190
|
-
pathLength += item.height
|
|
275
|
+
pathLength += item.yStart + item.height - item.markerY;
|
|
191
276
|
prevY = item.yStart + item.height;
|
|
192
277
|
}
|
|
193
278
|
} else {
|
|
194
279
|
// Segment from previous position to this item's top
|
|
195
|
-
|
|
196
|
-
const dy = item.yStart - prevY!;
|
|
197
|
-
pathLength += Math.sqrt(dx * dx + dy * dy);
|
|
198
|
-
path += `L ${item.x} ${item.yStart} `;
|
|
199
|
-
prevX = item.x;
|
|
200
|
-
prevY = item.yStart;
|
|
280
|
+
appendConnector(item.x, item.yStart);
|
|
201
281
|
|
|
202
282
|
if (isLast) {
|
|
203
|
-
// Draw from top to
|
|
204
|
-
const
|
|
205
|
-
pathLength +=
|
|
206
|
-
path += `L ${item.x} ${
|
|
207
|
-
prevY =
|
|
283
|
+
// Draw from top to first-line center
|
|
284
|
+
const markerLength = item.markerY - item.yStart;
|
|
285
|
+
pathLength += markerLength;
|
|
286
|
+
path += `L ${item.x} ${item.markerY} `;
|
|
287
|
+
prevY = item.markerY;
|
|
208
288
|
|
|
209
289
|
if (item.slug) {
|
|
210
|
-
linkPositions.set(item.slug, {
|
|
290
|
+
linkPositions.set(item.slug, { pathLengthAtMarker: pathLength });
|
|
211
291
|
}
|
|
212
292
|
} else {
|
|
213
|
-
// Middle item: path length at
|
|
214
|
-
const
|
|
293
|
+
// Middle item: path length at marker is current + first-line offset
|
|
294
|
+
const pathLengthAtMarker = pathLength + item.markerY - item.yStart;
|
|
215
295
|
|
|
216
296
|
if (item.slug) {
|
|
217
297
|
linkPositions.set(item.slug, {
|
|
218
|
-
|
|
298
|
+
pathLengthAtMarker,
|
|
219
299
|
});
|
|
220
300
|
}
|
|
221
301
|
|
|
@@ -227,26 +307,25 @@ for (const heading of headings) {
|
|
|
227
307
|
}
|
|
228
308
|
});
|
|
229
309
|
|
|
230
|
-
// Create circles at each item's
|
|
310
|
+
// Create circles at each item's first-line center
|
|
231
311
|
const circlesGroup = svg.querySelector("#toc-circles");
|
|
232
312
|
if (circlesGroup) {
|
|
233
313
|
// Clear existing circles before creating new ones
|
|
234
314
|
circlesGroup.innerHTML = "";
|
|
235
315
|
items.forEach((item) => {
|
|
236
|
-
const midY = item.yStart + item.height / 2;
|
|
237
316
|
const circle = document.createElementNS(
|
|
238
317
|
"http://www.w3.org/2000/svg",
|
|
239
|
-
"circle"
|
|
318
|
+
"circle",
|
|
240
319
|
);
|
|
241
320
|
circle.setAttribute("cx", String(item.x));
|
|
242
|
-
circle.setAttribute("cy", String(
|
|
321
|
+
circle.setAttribute("cy", String(item.markerY));
|
|
243
322
|
circle.setAttribute("r", "2.25");
|
|
244
323
|
circle.setAttribute("fill", "currentColor");
|
|
245
324
|
circle.classList.add(
|
|
246
|
-
"fill-neutral-
|
|
247
|
-
"dark:fill-neutral-
|
|
325
|
+
"fill-neutral-200",
|
|
326
|
+
"dark:fill-neutral-700",
|
|
248
327
|
"transition-all",
|
|
249
|
-
"duration-200"
|
|
328
|
+
"duration-200",
|
|
250
329
|
);
|
|
251
330
|
if (item.slug) {
|
|
252
331
|
circle.dataset.slug = item.slug;
|
|
@@ -273,7 +352,7 @@ for (const heading of headings) {
|
|
|
273
352
|
// Initially hide the highlight (use same pattern as "0 visible" state)
|
|
274
353
|
fgPath.setAttribute(
|
|
275
354
|
"stroke-dasharray",
|
|
276
|
-
`0 ${totalLength} 0 ${totalLength}
|
|
355
|
+
`0 ${totalLength} 0 ${totalLength}`,
|
|
277
356
|
);
|
|
278
357
|
fgPath.setAttribute("stroke-dashoffset", "0");
|
|
279
358
|
}
|
|
@@ -289,8 +368,8 @@ for (const heading of headings) {
|
|
|
289
368
|
visibleSlugs.forEach((slug) => {
|
|
290
369
|
const pos = linkPositions.get(slug);
|
|
291
370
|
if (pos) {
|
|
292
|
-
minPathLength = Math.min(minPathLength, pos.
|
|
293
|
-
maxPathLength = Math.max(maxPathLength, pos.
|
|
371
|
+
minPathLength = Math.min(minPathLength, pos.pathLengthAtMarker);
|
|
372
|
+
maxPathLength = Math.max(maxPathLength, pos.pathLengthAtMarker);
|
|
294
373
|
}
|
|
295
374
|
});
|
|
296
375
|
|
|
@@ -312,14 +391,14 @@ for (const heading of headings) {
|
|
|
312
391
|
// 1 visible heading: position gap at this item, ready to grow down
|
|
313
392
|
fgPath.setAttribute(
|
|
314
393
|
"stroke-dasharray",
|
|
315
|
-
`0 ${minPathLength} 0 ${totalLength}
|
|
394
|
+
`0 ${minPathLength} 0 ${totalLength}`,
|
|
316
395
|
);
|
|
317
396
|
fgPath.setAttribute("stroke-dashoffset", "0");
|
|
318
397
|
} else {
|
|
319
398
|
// 0 visible headings: fully hidden
|
|
320
399
|
fgPath.setAttribute(
|
|
321
400
|
"stroke-dasharray",
|
|
322
|
-
`0 ${totalLength} 0 ${totalLength}
|
|
401
|
+
`0 ${totalLength} 0 ${totalLength}`,
|
|
323
402
|
);
|
|
324
403
|
fgPath.setAttribute("stroke-dashoffset", "0");
|
|
325
404
|
}
|
|
@@ -331,9 +410,11 @@ for (const heading of headings) {
|
|
|
331
410
|
const slug = (circle as SVGCircleElement).dataset.slug;
|
|
332
411
|
if (slug && visibleSlugs.has(slug)) {
|
|
333
412
|
(circle as SVGCircleElement).style.fill = "var(--color-theme)";
|
|
413
|
+
circle.setAttribute("fill-opacity", "0.8");
|
|
334
414
|
circle.setAttribute("r", "2.75");
|
|
335
415
|
} else {
|
|
336
416
|
(circle as SVGCircleElement).style.fill = "";
|
|
417
|
+
circle.removeAttribute("fill-opacity");
|
|
337
418
|
circle.setAttribute("r", "2.25");
|
|
338
419
|
}
|
|
339
420
|
});
|
|
@@ -343,21 +424,46 @@ for (const heading of headings) {
|
|
|
343
424
|
tocLinks?.forEach((link) => {
|
|
344
425
|
const slug = (link as HTMLAnchorElement).dataset.slug;
|
|
345
426
|
if (slug && visibleSlugs.has(slug)) {
|
|
346
|
-
link.classList.add("text-neutral-
|
|
427
|
+
link.classList.add("text-neutral-950", "dark:text-neutral-100");
|
|
347
428
|
} else {
|
|
348
|
-
link.classList.remove("text-neutral-
|
|
429
|
+
link.classList.remove("text-neutral-950", "dark:text-neutral-100");
|
|
349
430
|
}
|
|
350
431
|
});
|
|
351
432
|
}
|
|
352
433
|
|
|
353
434
|
// Intersection Observer to track headings in view
|
|
354
435
|
const slugs: string[] = JSON.parse(
|
|
355
|
-
(nav as HTMLElement).dataset.slugs || "[]"
|
|
436
|
+
(nav as HTMLElement).dataset.slugs || "[]",
|
|
356
437
|
);
|
|
357
438
|
const headings = slugs
|
|
358
439
|
.map((slug) => document.getElementById(slug))
|
|
359
440
|
.filter((el): el is HTMLElement => el !== null);
|
|
360
441
|
|
|
442
|
+
if ((ol as HTMLElement).dataset.smoothScrollBound !== "true") {
|
|
443
|
+
(ol as HTMLElement).dataset.smoothScrollBound = "true";
|
|
444
|
+
|
|
445
|
+
ol.addEventListener("click", (event) => {
|
|
446
|
+
if (!(event.target instanceof Element)) return;
|
|
447
|
+
|
|
448
|
+
const link = event.target.closest(
|
|
449
|
+
"a[data-slug]",
|
|
450
|
+
) as HTMLAnchorElement | null;
|
|
451
|
+
if (!link) return;
|
|
452
|
+
|
|
453
|
+
const slug = link.dataset.slug;
|
|
454
|
+
const target = slug ? document.getElementById(slug) : null;
|
|
455
|
+
if (!target) return;
|
|
456
|
+
|
|
457
|
+
event.preventDefault();
|
|
458
|
+
target.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
459
|
+
|
|
460
|
+
const hash = link.getAttribute("href");
|
|
461
|
+
if (hash) {
|
|
462
|
+
window.history.replaceState(null, "", hash);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
361
467
|
const headerOffset = 112;
|
|
362
468
|
|
|
363
469
|
// Calculate active headings based on scroll position
|
|
@@ -402,7 +508,7 @@ for (const heading of headings) {
|
|
|
402
508
|
{
|
|
403
509
|
rootMargin: `-${headerOffset}px 0px 0px 0px`,
|
|
404
510
|
threshold: 0,
|
|
405
|
-
}
|
|
511
|
+
},
|
|
406
512
|
);
|
|
407
513
|
|
|
408
514
|
headings.forEach((heading) => observer.observe(heading));
|
|
@@ -455,7 +561,7 @@ for (const heading of headings) {
|
|
|
455
561
|
|
|
456
562
|
// Re-initialize when TOC becomes visible (responsive breakpoint)
|
|
457
563
|
const tocNav = document.querySelector(
|
|
458
|
-
'nav[aria-label="Table of Contents"]'
|
|
564
|
+
'nav[aria-label="Table of Contents"]',
|
|
459
565
|
);
|
|
460
566
|
if (tocNav) {
|
|
461
567
|
let wasVisible = tocNav.getBoundingClientRect().width > 0;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import AssistantDocsWidget from "./AssistantDocsWidget";
|
|
3
|
+
import { getAssistantPanelRuntimeConfig } from "../../lib/assistant-panel-config";
|
|
4
|
+
import { getConfig } from "../../lib/validation";
|
|
5
|
+
|
|
6
|
+
const config = await getConfig();
|
|
7
|
+
const assistantConfig = getAssistantPanelRuntimeConfig(config);
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<div data-pagefind-ignore>
|
|
11
|
+
<AssistantDocsWidget
|
|
12
|
+
client:only="preact"
|
|
13
|
+
transition:persist="assistant-docs-widget"
|
|
14
|
+
{...assistantConfig}
|
|
15
|
+
/>
|
|
16
|
+
</div>
|