radiant-docs 0.1.41 → 0.1.43
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 +44 -40
- package/template/package-lock.json +7 -0
- package/template/package.json +1 -0
- package/template/src/components/Header.astro +150 -16
- package/template/src/components/MdxPage.astro +82 -23
- 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.tsx +221 -8
- package/template/src/components/chat/AssistantEmbedPanel.tsx +1090 -104
- 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 +2 -2
- 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 +11 -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 +2 -4
- package/template/src/lib/assistant-chrome-defaults.ts +12 -0
- package/template/src/lib/assistant-embed-script.ts +209 -18
- package/template/src/lib/mdx/rehype-prefix-preview-heading-ids.ts +52 -0
- package/template/src/lib/mdx/remark-code-block-component.ts +14 -8
- package/template/src/lib/validation.ts +325 -75
- package/template/src/styles/global.css +81 -4
- package/template/src/components/chat/AskAiWidget.tsx +0 -2011
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { JSX } from "preact";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import { navigate } from "astro:transitions/client";
|
|
3
|
+
import { useEffect, useRef, useState } from "preact/hooks";
|
|
4
|
+
import AssistantEmbedPanel, {
|
|
5
|
+
ASSISTANT_PANEL_STORAGE_KEY,
|
|
6
|
+
AssistantPanelIcon,
|
|
7
|
+
type AssistantPanelSize,
|
|
8
|
+
} from "./AssistantEmbedPanel";
|
|
4
9
|
import {
|
|
5
10
|
DEFAULT_ASSISTANT_CHROME_CONFIG,
|
|
6
11
|
type AssistantChromeConfig,
|
|
@@ -30,8 +35,32 @@ type AssistantDocsWidgetProps = {
|
|
|
30
35
|
|
|
31
36
|
type AssistantOpenRequestWindow = Window & {
|
|
32
37
|
__assistantOpenRequested?: boolean;
|
|
38
|
+
__assistantToggleRequested?: boolean;
|
|
39
|
+
__assistantDocsLauncherEntered?: boolean;
|
|
33
40
|
};
|
|
34
41
|
|
|
42
|
+
function normalizePanelSize(value: unknown): AssistantPanelSize {
|
|
43
|
+
return value === "expanded" ? "expanded" : "default";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function readPersistedPanelSize(): AssistantPanelSize {
|
|
47
|
+
if (typeof window === "undefined") {
|
|
48
|
+
return "default";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const rawState = window.localStorage.getItem(ASSISTANT_PANEL_STORAGE_KEY);
|
|
53
|
+
if (!rawState) {
|
|
54
|
+
return "default";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const parsed = JSON.parse(rawState) as { panelSize?: unknown };
|
|
58
|
+
return normalizePanelSize(parsed.panelSize);
|
|
59
|
+
} catch {
|
|
60
|
+
return "default";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
35
64
|
export default function AssistantDocsWidget({
|
|
36
65
|
apiPath,
|
|
37
66
|
docsTitle,
|
|
@@ -48,7 +77,28 @@ export default function AssistantDocsWidget({
|
|
|
48
77
|
chrome,
|
|
49
78
|
}: AssistantDocsWidgetProps) {
|
|
50
79
|
const [isOpen, setIsOpen] = useState(false);
|
|
80
|
+
const [panelSize, setPanelSize] = useState<AssistantPanelSize>(() =>
|
|
81
|
+
readPersistedPanelSize(),
|
|
82
|
+
);
|
|
83
|
+
const [panelSizeTransition, setPanelSizeTransition] = useState<
|
|
84
|
+
"expand" | "collapse" | ""
|
|
85
|
+
>("");
|
|
51
86
|
const [openSignal, setOpenSignal] = useState(0);
|
|
87
|
+
const [isNavigationTransitionSuppressed, setIsNavigationTransitionSuppressed] =
|
|
88
|
+
useState(false);
|
|
89
|
+
const [hasLauncherEntered, setHasLauncherEntered] = useState(() => {
|
|
90
|
+
if (typeof window === "undefined") {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return Boolean(
|
|
95
|
+
(window as AssistantOpenRequestWindow).__assistantDocsLauncherEntered,
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
const widgetRef = useRef<HTMLDivElement | null>(null);
|
|
99
|
+
const navigationTransitionCleanupRef = useRef<(() => void) | null>(null);
|
|
100
|
+
const navigationTransitionTimeoutRef = useRef<number | null>(null);
|
|
101
|
+
const panelSizeTransitionTimeoutRef = useRef<number | null>(null);
|
|
52
102
|
const chromeConfig = chrome ?? DEFAULT_ASSISTANT_CHROME_CONFIG;
|
|
53
103
|
const numericZIndex =
|
|
54
104
|
Number.parseInt(chromeConfig.zIndex, 10) ||
|
|
@@ -78,6 +128,9 @@ export default function AssistantDocsWidget({
|
|
|
78
128
|
"--assistant-docs-launcher-shadow": chromeConfig.launcherShadow,
|
|
79
129
|
"--assistant-docs-panel-width": chromeConfig.panelWidth,
|
|
80
130
|
"--assistant-docs-panel-height": chromeConfig.panelHeight,
|
|
131
|
+
"--assistant-docs-panel-expanded-width": chromeConfig.panelExpandedWidth,
|
|
132
|
+
"--assistant-docs-panel-expanded-height": chromeConfig.panelExpandedHeight,
|
|
133
|
+
"--assistant-docs-panel-viewport-margin": chromeConfig.panelViewportMargin,
|
|
81
134
|
"--assistant-docs-panel-gap": chromeConfig.panelGap,
|
|
82
135
|
"--assistant-docs-panel-radius": chromeConfig.panelRadius,
|
|
83
136
|
"--assistant-docs-panel-border": chromeConfig.panelBorder,
|
|
@@ -90,6 +143,8 @@ export default function AssistantDocsWidget({
|
|
|
90
143
|
"--assistant-docs-panel-open-scale": chromeConfig.panelOpenScale,
|
|
91
144
|
"--assistant-docs-panel-open-duration": chromeConfig.panelOpenDuration,
|
|
92
145
|
"--assistant-docs-panel-open-timing": chromeConfig.panelOpenTiming,
|
|
146
|
+
"--assistant-docs-panel-size-duration": chromeConfig.panelSizeDuration,
|
|
147
|
+
"--assistant-docs-panel-size-timing": chromeConfig.panelSizeTiming,
|
|
93
148
|
"--assistant-docs-panel-close-duration": chromeConfig.panelCloseDuration,
|
|
94
149
|
"--assistant-docs-panel-close-timing": chromeConfig.panelCloseTiming,
|
|
95
150
|
} as JSX.CSSProperties;
|
|
@@ -107,32 +162,150 @@ export default function AssistantDocsWidget({
|
|
|
107
162
|
setIsOpen(false);
|
|
108
163
|
};
|
|
109
164
|
|
|
165
|
+
const togglePanel = () => {
|
|
166
|
+
setIsOpen((wasOpen) => {
|
|
167
|
+
if (!wasOpen) {
|
|
168
|
+
setOpenSignal((previous) => previous + 1);
|
|
169
|
+
}
|
|
170
|
+
return !wasOpen;
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const handlePanelSizeChange = (nextPanelSize: AssistantPanelSize) => {
|
|
175
|
+
setPanelSize((previousSize) => {
|
|
176
|
+
if (previousSize === nextPanelSize) {
|
|
177
|
+
return previousSize;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (panelSizeTransitionTimeoutRef.current !== null) {
|
|
181
|
+
window.clearTimeout(panelSizeTransitionTimeoutRef.current);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
setPanelSizeTransition(
|
|
185
|
+
nextPanelSize === "expanded" ? "expand" : "collapse",
|
|
186
|
+
);
|
|
187
|
+
panelSizeTransitionTimeoutRef.current = window.setTimeout(() => {
|
|
188
|
+
panelSizeTransitionTimeoutRef.current = null;
|
|
189
|
+
setPanelSizeTransition("");
|
|
190
|
+
}, 480);
|
|
191
|
+
|
|
192
|
+
return nextPanelSize;
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const setPanelTransitionSuppressed = (isSuppressed: boolean) => {
|
|
197
|
+
setIsNavigationTransitionSuppressed(isSuppressed);
|
|
198
|
+
if (widgetRef.current) {
|
|
199
|
+
widgetRef.current.dataset.suppressTransition = String(isSuppressed);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const handleCurrentLinkNavigate = (href: string, sourceElement?: Element) => {
|
|
204
|
+
if (typeof window === "undefined") {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
navigationTransitionCleanupRef.current?.();
|
|
209
|
+
setPanelTransitionSuppressed(true);
|
|
210
|
+
|
|
211
|
+
const finishTransitionSuppression = () => {
|
|
212
|
+
document.removeEventListener(
|
|
213
|
+
"astro:after-swap",
|
|
214
|
+
finishTransitionSuppression,
|
|
215
|
+
);
|
|
216
|
+
if (navigationTransitionTimeoutRef.current !== null) {
|
|
217
|
+
window.clearTimeout(navigationTransitionTimeoutRef.current);
|
|
218
|
+
navigationTransitionTimeoutRef.current = null;
|
|
219
|
+
}
|
|
220
|
+
navigationTransitionCleanupRef.current = null;
|
|
221
|
+
|
|
222
|
+
window.requestAnimationFrame(() => {
|
|
223
|
+
setPanelTransitionSuppressed(false);
|
|
224
|
+
});
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
document.addEventListener("astro:after-swap", finishTransitionSuppression, {
|
|
228
|
+
once: true,
|
|
229
|
+
});
|
|
230
|
+
navigationTransitionTimeoutRef.current = window.setTimeout(
|
|
231
|
+
finishTransitionSuppression,
|
|
232
|
+
1200,
|
|
233
|
+
);
|
|
234
|
+
navigationTransitionCleanupRef.current = finishTransitionSuppression;
|
|
235
|
+
|
|
236
|
+
void navigate(
|
|
237
|
+
href,
|
|
238
|
+
sourceElement ? { sourceElement } : undefined,
|
|
239
|
+
).catch(() => {
|
|
240
|
+
finishTransitionSuppression();
|
|
241
|
+
window.location.assign(href);
|
|
242
|
+
});
|
|
243
|
+
};
|
|
244
|
+
|
|
110
245
|
useEffect(() => {
|
|
111
246
|
const handleOpen = () => {
|
|
112
247
|
(window as AssistantOpenRequestWindow).__assistantOpenRequested = false;
|
|
113
248
|
openPanel();
|
|
114
249
|
};
|
|
250
|
+
const handleToggle = () => {
|
|
251
|
+
(window as AssistantOpenRequestWindow).__assistantToggleRequested = false;
|
|
252
|
+
togglePanel();
|
|
253
|
+
};
|
|
115
254
|
|
|
116
255
|
window.addEventListener("ask-ai:open", handleOpen);
|
|
256
|
+
window.addEventListener("ask-ai:toggle", handleToggle);
|
|
117
257
|
if ((window as AssistantOpenRequestWindow).__assistantOpenRequested) {
|
|
118
258
|
handleOpen();
|
|
119
259
|
}
|
|
260
|
+
if ((window as AssistantOpenRequestWindow).__assistantToggleRequested) {
|
|
261
|
+
handleToggle();
|
|
262
|
+
}
|
|
120
263
|
|
|
121
264
|
return () => {
|
|
122
265
|
window.removeEventListener("ask-ai:open", handleOpen);
|
|
266
|
+
window.removeEventListener("ask-ai:toggle", handleToggle);
|
|
123
267
|
};
|
|
124
268
|
}, []);
|
|
125
269
|
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
return () => {
|
|
272
|
+
navigationTransitionCleanupRef.current?.();
|
|
273
|
+
if (panelSizeTransitionTimeoutRef.current !== null) {
|
|
274
|
+
window.clearTimeout(panelSizeTransitionTimeoutRef.current);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
}, []);
|
|
278
|
+
|
|
279
|
+
useEffect(() => {
|
|
280
|
+
if (typeof window === "undefined" || hasLauncherEntered) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
(window as AssistantOpenRequestWindow).__assistantDocsLauncherEntered = true;
|
|
285
|
+
const launcherEntranceTimeout = window.setTimeout(() => {
|
|
286
|
+
setHasLauncherEntered(true);
|
|
287
|
+
}, 520);
|
|
288
|
+
|
|
289
|
+
return () => {
|
|
290
|
+
window.clearTimeout(launcherEntranceTimeout);
|
|
291
|
+
};
|
|
292
|
+
}, [hasLauncherEntered]);
|
|
293
|
+
|
|
126
294
|
return (
|
|
127
295
|
<div
|
|
296
|
+
ref={widgetRef}
|
|
128
297
|
data-pagefind-ignore
|
|
129
298
|
className="assistant-docs-widget"
|
|
130
299
|
data-side={chromeConfig.side}
|
|
300
|
+
data-launcher-entered={String(hasLauncherEntered)}
|
|
301
|
+
data-suppress-transition={String(isNavigationTransitionSuppressed)}
|
|
131
302
|
style={rootStyle}
|
|
132
303
|
>
|
|
133
304
|
<div
|
|
134
305
|
className="assistant-docs-panel-shell"
|
|
135
306
|
data-state={isOpen ? "open" : "closed"}
|
|
307
|
+
data-size={panelSize}
|
|
308
|
+
data-size-transition={panelSizeTransition}
|
|
136
309
|
>
|
|
137
310
|
<AssistantEmbedPanel
|
|
138
311
|
apiPath={apiPath}
|
|
@@ -151,7 +324,10 @@ export default function AssistantDocsWidget({
|
|
|
151
324
|
linkTarget="current"
|
|
152
325
|
allowApiPathQueryOverride={false}
|
|
153
326
|
openSignal={openSignal}
|
|
327
|
+
onRequestOpen={openPanel}
|
|
154
328
|
onRequestClose={closePanel}
|
|
329
|
+
onRequestPanelSizeToggle={handlePanelSizeChange}
|
|
330
|
+
onCurrentLinkNavigate={handleCurrentLinkNavigate}
|
|
155
331
|
/>
|
|
156
332
|
</div>
|
|
157
333
|
|
|
@@ -230,11 +406,14 @@ export default function AssistantDocsWidget({
|
|
|
230
406
|
);
|
|
231
407
|
box-shadow: var(--assistant-docs-launcher-shadow);
|
|
232
408
|
cursor: pointer;
|
|
233
|
-
animation: assistant-docs-launcher-enter 460ms linear backwards;
|
|
234
409
|
transition: transform 180ms ease, opacity 160ms ease;
|
|
235
410
|
transform-origin: center center;
|
|
236
411
|
}
|
|
237
412
|
|
|
413
|
+
.assistant-docs-widget[data-launcher-entered="false"] .assistant-docs-launcher {
|
|
414
|
+
animation: assistant-docs-launcher-enter 460ms linear backwards;
|
|
415
|
+
}
|
|
416
|
+
|
|
238
417
|
html.dark .assistant-docs-launcher,
|
|
239
418
|
html[data-theme="dark"] .assistant-docs-launcher {
|
|
240
419
|
--assistant-docs-theme: var(--assistant-docs-theme-dark);
|
|
@@ -297,6 +476,13 @@ export default function AssistantDocsWidget({
|
|
|
297
476
|
}
|
|
298
477
|
|
|
299
478
|
.assistant-docs-panel-shell {
|
|
479
|
+
--assistant-docs-panel-available-height: calc(
|
|
480
|
+
100dvh -
|
|
481
|
+
var(--assistant-docs-offset-y) -
|
|
482
|
+
var(--assistant-docs-launcher-size) -
|
|
483
|
+
var(--assistant-docs-panel-gap) -
|
|
484
|
+
var(--assistant-docs-panel-viewport-margin)
|
|
485
|
+
);
|
|
300
486
|
position: fixed;
|
|
301
487
|
bottom: calc(
|
|
302
488
|
var(--assistant-docs-offset-y) +
|
|
@@ -306,7 +492,10 @@ export default function AssistantDocsWidget({
|
|
|
306
492
|
z-index: var(--assistant-docs-z-index);
|
|
307
493
|
box-sizing: border-box;
|
|
308
494
|
width: min(var(--assistant-docs-panel-width), calc(100vw - 32px));
|
|
309
|
-
height: min(
|
|
495
|
+
height: min(
|
|
496
|
+
var(--assistant-docs-panel-height),
|
|
497
|
+
var(--assistant-docs-panel-available-height)
|
|
498
|
+
);
|
|
310
499
|
overflow: hidden;
|
|
311
500
|
border: var(--assistant-docs-panel-border);
|
|
312
501
|
border-radius: var(--assistant-docs-panel-radius);
|
|
@@ -318,12 +507,30 @@ export default function AssistantDocsWidget({
|
|
|
318
507
|
pointer-events: auto;
|
|
319
508
|
transform: scale(1);
|
|
320
509
|
transform-origin: bottom right;
|
|
321
|
-
transition-property: transform, opacity, display;
|
|
322
|
-
transition-duration:
|
|
323
|
-
|
|
510
|
+
transition-property: width, height, transform, opacity, display;
|
|
511
|
+
transition-duration:
|
|
512
|
+
var(--assistant-docs-panel-size-duration),
|
|
513
|
+
var(--assistant-docs-panel-size-duration),
|
|
514
|
+
var(--assistant-docs-panel-open-duration),
|
|
515
|
+
var(--assistant-docs-panel-open-duration),
|
|
516
|
+
var(--assistant-docs-panel-open-duration);
|
|
517
|
+
transition-timing-function:
|
|
518
|
+
var(--assistant-docs-panel-size-timing),
|
|
519
|
+
var(--assistant-docs-panel-size-timing),
|
|
520
|
+
var(--assistant-docs-panel-open-timing),
|
|
521
|
+
var(--assistant-docs-panel-open-timing),
|
|
522
|
+
var(--assistant-docs-panel-open-timing);
|
|
324
523
|
transition-behavior: allow-discrete;
|
|
325
524
|
}
|
|
326
525
|
|
|
526
|
+
.assistant-docs-panel-shell[data-size="expanded"] {
|
|
527
|
+
width: min(var(--assistant-docs-panel-expanded-width), calc(100vw - 32px));
|
|
528
|
+
height: min(
|
|
529
|
+
var(--assistant-docs-panel-expanded-height),
|
|
530
|
+
var(--assistant-docs-panel-available-height)
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
|
|
327
534
|
.dark .assistant-docs-panel-shell {
|
|
328
535
|
border: var(--assistant-docs-panel-dark-border);
|
|
329
536
|
background: var(--assistant-docs-panel-dark-background);
|
|
@@ -358,7 +565,11 @@ export default function AssistantDocsWidget({
|
|
|
358
565
|
transition-behavior: allow-discrete;
|
|
359
566
|
}
|
|
360
567
|
|
|
361
|
-
|
|
568
|
+
.assistant-docs-widget[data-suppress-transition="true"] .assistant-docs-panel-shell {
|
|
569
|
+
transition: none !important;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
@media (max-width: ${chromeConfig.mobileBreakpoint}), (max-height: ${chromeConfig.panelFullscreenHeightBreakpoint}) {
|
|
362
573
|
.assistant-docs-panel-shell {
|
|
363
574
|
inset: 0 !important;
|
|
364
575
|
z-index: var(--assistant-docs-mobile-panel-z-index) !important;
|
|
@@ -371,7 +582,9 @@ export default function AssistantDocsWidget({
|
|
|
371
582
|
.assistant-docs-panel-shell > div {
|
|
372
583
|
border-radius: 0;
|
|
373
584
|
}
|
|
585
|
+
}
|
|
374
586
|
|
|
587
|
+
@media (max-width: ${chromeConfig.mobileBreakpoint}) {
|
|
375
588
|
.assistant-docs-launcher {
|
|
376
589
|
bottom: var(--assistant-docs-mobile-offset-y) !important;
|
|
377
590
|
}
|