radiant-docs 0.1.60 → 0.1.62
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/package-lock.json +10 -4
- package/template/package.json +11 -2
- package/template/scripts/generate-proxy-allowed-origins.mjs +14 -6
- package/template/scripts/publish-shiki-platform-assets.mjs +1151 -0
- package/template/src/components/Header.astro +6 -1
- package/template/src/components/NavigationTabList.astro +65 -0
- package/template/src/components/NavigationTabs.astro +109 -0
- package/template/src/components/OpenApiPage.astro +178 -14
- package/template/src/components/Sidebar.astro +2 -2
- package/template/src/components/SidebarDropdown.astro +105 -44
- package/template/src/components/SidebarMenu.astro +3 -0
- package/template/src/components/SidebarSegmented.astro +87 -52
- package/template/src/components/SidebarTabs.astro +86 -0
- package/template/src/components/chat/AssistantDocsWidget.tsx +127 -2
- package/template/src/components/chat/AssistantEmbedPanel.tsx +287 -290
- package/template/src/components/endpoint/PlaygroundBar.astro +54 -9
- package/template/src/components/endpoint/PlaygroundForm.astro +1 -1
- package/template/src/components/endpoint/RequestSnippets.astro +6 -1
- package/template/src/components/endpoint/ResponseFieldTree.astro +17 -13
- package/template/src/components/endpoint/ResponseFields.astro +4 -6
- package/template/src/components/endpoint/ResponseSnippets.astro +6 -1
- package/template/src/components/sidebar/SidebarEndpointLink.astro +9 -12
- package/template/src/components/sidebar/SidebarOpenApi.astro +3 -9
- package/template/src/components/ui/Field.astro +18 -15
- package/template/src/components/ui/Tag.astro +16 -2
- package/template/src/components/user/Accordion.astro +1 -1
- package/template/src/components/user/Callout.astro +2 -2
- package/template/src/components/user/CodeBlock.astro +58 -7
- package/template/src/components/user/CodeGroup.astro +52 -1
- package/template/src/components/user/Column.astro +1 -1
- package/template/src/components/user/Step.astro +1 -1
- package/template/src/components/user/Tabs.astro +1 -1
- package/template/src/generated/shiki-platform-assets.json +24 -0
- package/template/src/layouts/Layout.astro +111 -8
- package/template/src/lib/assistant-panel-config.ts +59 -0
- package/template/src/lib/assistant-shiki-client.ts +506 -0
- package/template/src/lib/mdx/remark-resolve-internal-links.ts +334 -17
- package/template/src/lib/routes.ts +66 -24
- package/template/src/lib/utils.ts +11 -0
- package/template/src/styles/global.css +12 -0
|
@@ -9,6 +9,7 @@ import SidebarOpenApi from "./sidebar/SidebarOpenApi.astro";
|
|
|
9
9
|
import SidebarOpenApiPageLink from "./sidebar/SidebarOpenApiPageLink.astro";
|
|
10
10
|
import SidebarDropdown from "./SidebarDropdown.astro";
|
|
11
11
|
import SidebarSegmented from "./SidebarSegmented.astro";
|
|
12
|
+
import SidebarTabs from "./SidebarTabs.astro";
|
|
12
13
|
import SidebarGroup from "./SidebarGroup.astro";
|
|
13
14
|
import SidebarLink from "./SidebarLink.astro";
|
|
14
15
|
|
|
@@ -58,5 +59,7 @@ let { navigation, parentSlug = "" } = Astro.props;
|
|
|
58
59
|
) : null
|
|
59
60
|
) : navigation.openapi ? (
|
|
60
61
|
<SidebarOpenApi openapi={navigation.openapi} parentSlug={parentSlug} />
|
|
62
|
+
) : navigation.tabs ? (
|
|
63
|
+
<SidebarTabs tabs={navigation.tabs} parentSlug={parentSlug} />
|
|
61
64
|
) : null
|
|
62
65
|
}
|
|
@@ -16,9 +16,15 @@ const { menu, parentSlug = "" } = Astro.props;
|
|
|
16
16
|
const pathname = stripBasePath(Astro.url.pathname);
|
|
17
17
|
const config = await getConfig();
|
|
18
18
|
const routes = (await getAllRoutes()).filter((route) => !route.hidden);
|
|
19
|
+
const normalizedPathParts = pathname
|
|
20
|
+
.replace(/^\/+/, "")
|
|
21
|
+
.replace(/\/+$/, "")
|
|
22
|
+
.split("/")
|
|
23
|
+
.filter(Boolean);
|
|
24
|
+
const parentParts = parentSlug.split("/").filter(Boolean);
|
|
19
25
|
|
|
20
26
|
let currentMenuIndex = menu.items.findIndex(
|
|
21
|
-
(i) => slugify(i.label) ===
|
|
27
|
+
(i) => slugify(i.label) === normalizedPathParts[parentParts.length],
|
|
22
28
|
);
|
|
23
29
|
|
|
24
30
|
if (pathname === "/" && config.home) {
|
|
@@ -27,9 +33,10 @@ if (pathname === "/" && config.home) {
|
|
|
27
33
|
);
|
|
28
34
|
|
|
29
35
|
if (homeRoute) {
|
|
30
|
-
const
|
|
36
|
+
const homeRouteParts = homeRoute.slug.split("/").filter(Boolean);
|
|
37
|
+
const homeMenuSegment = homeRouteParts[parentParts.length];
|
|
31
38
|
const homeMenuIndex = menu.items.findIndex(
|
|
32
|
-
(item) => slugify(item.label) ===
|
|
39
|
+
(item) => slugify(item.label) === homeMenuSegment,
|
|
33
40
|
);
|
|
34
41
|
if (homeMenuIndex !== -1) {
|
|
35
42
|
currentMenuIndex = homeMenuIndex;
|
|
@@ -39,62 +46,90 @@ if (pathname === "/" && config.home) {
|
|
|
39
46
|
|
|
40
47
|
currentMenuIndex = currentMenuIndex === -1 ? 0 : currentMenuIndex;
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
for (const route of routes) {
|
|
47
|
-
const slug = route.slug;
|
|
49
|
+
function getMenuItemPrefix(label: string): string {
|
|
50
|
+
const menuSlug = slugify(label);
|
|
51
|
+
return parentSlug ? `${parentSlug}/${menuSlug}` : menuSlug;
|
|
52
|
+
}
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
const
|
|
54
|
+
let firstHrefOfMenuItems = menu.items.map((item) => {
|
|
55
|
+
const itemPrefix = getMenuItemPrefix(item.label);
|
|
56
|
+
const firstRoute = routes.find(
|
|
57
|
+
(route) => route.slug === itemPrefix || route.slug.startsWith(`${itemPrefix}/`),
|
|
58
|
+
);
|
|
51
59
|
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
firstHrefOfMenuItems.push(href);
|
|
60
|
+
if (firstRoute) {
|
|
61
|
+
return firstRoute.type === "mdx" &&
|
|
62
|
+
config.home &&
|
|
63
|
+
firstRoute.filePath === config.home
|
|
64
|
+
? prependBasePath("/")
|
|
65
|
+
: prependBasePath(`/${firstRoute.slug}`);
|
|
59
66
|
}
|
|
60
|
-
|
|
67
|
+
|
|
68
|
+
return prependBasePath("/");
|
|
69
|
+
});
|
|
61
70
|
|
|
62
71
|
const selectedMenuItem = menu.items[currentMenuIndex];
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
const currentPrefix = getMenuItemPrefix(selectedMenuItem.label);
|
|
73
|
+
|
|
74
|
+
const controlBaseClass =
|
|
75
|
+
"items-center px-3 py-1.5 cursor-pointer text-sm rounded-md border-x border-t transition-colors duration-150";
|
|
76
|
+
const activeControlClass =
|
|
77
|
+
"bg-white dark:bg-neutral-700/30 border-neutral-200/70 dark:border-neutral-700/40 dark:border-b shadow-sm shadow-neutral-200/80 dark:shadow-neutral-950/20 text-neutral-900 dark:text-white";
|
|
78
|
+
const inactiveControlClass =
|
|
79
|
+
"text-neutral-600 dark:text-neutral-300 border-transparent hover:text-primary dark:hover:text-primary";
|
|
67
80
|
---
|
|
68
81
|
|
|
69
|
-
<div
|
|
70
|
-
{
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
<ul class="rounded-lg bg-neutral-100 dark:bg-neutral-800/60 p-[3px]">
|
|
82
|
+
<div
|
|
83
|
+
x-data={`{ selectedMenuIndex: ${currentMenuIndex} }`}
|
|
84
|
+
x-init={`$watch('open', (value) => { if (value) selectedMenuIndex = ${currentMenuIndex} })`}
|
|
85
|
+
>
|
|
86
|
+
<div class="mt-3 mx-2 z-10 relative dark:bg-neutral-900 rounded-lg">
|
|
76
87
|
{
|
|
77
|
-
menu.
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
class="flex items-center px-3 py-1.5 cursor-pointer text-sm rounded-md border-x border-t transition-colors duration-150"
|
|
81
|
-
class:list={[
|
|
82
|
-
index === currentMenuIndex
|
|
83
|
-
? "bg-white dark:bg-neutral-700/30 border-neutral-200/70 dark:border-neutral-700/40 dark:border-b shadow-sm shadow-neutral-200/80 dark:shadow-neutral-950/20 text-neutral-900 dark:text-white"
|
|
84
|
-
: "text-neutral-600 dark:text-neutral-300 border-transparent hover:text-primary dark:hover:text-primary",
|
|
85
|
-
]}
|
|
86
|
-
href={firstHrefOfMenuItems[index] ?? prependBasePath("/")}
|
|
87
|
-
>
|
|
88
|
-
{item.icon && <Icon class="mr-2 size-4" name={item.icon} />}
|
|
89
|
-
{item.label}
|
|
90
|
-
</a>
|
|
91
|
-
</li>
|
|
92
|
-
))
|
|
88
|
+
menu.label && (
|
|
89
|
+
<label class="font-semibold text-xs px-2 pb-1 block">{menu.label}</label>
|
|
90
|
+
)
|
|
93
91
|
}
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
<ul class="rounded-lg bg-neutral-100 dark:bg-neutral-800/60 p-[3px]">
|
|
93
|
+
{
|
|
94
|
+
menu.items.map((item, index) => (
|
|
95
|
+
<li>
|
|
96
|
+
<a
|
|
97
|
+
class:list={[
|
|
98
|
+
controlBaseClass,
|
|
99
|
+
"hidden lg:flex",
|
|
100
|
+
index === currentMenuIndex
|
|
101
|
+
? activeControlClass
|
|
102
|
+
: inactiveControlClass,
|
|
103
|
+
]}
|
|
104
|
+
href={firstHrefOfMenuItems[index] ?? prependBasePath("/")}
|
|
105
|
+
>
|
|
106
|
+
{item.icon && <Icon class="mr-2 size-4" name={item.icon} />}
|
|
107
|
+
{item.label}
|
|
108
|
+
</a>
|
|
109
|
+
<button
|
|
110
|
+
type="button"
|
|
111
|
+
class:list={[controlBaseClass, "flex lg:hidden w-full"]}
|
|
112
|
+
x-bind:class={`selectedMenuIndex === ${index} ? '${activeControlClass}' : '${inactiveControlClass}'`}
|
|
113
|
+
x-bind:aria-selected={`selectedMenuIndex === ${index}`}
|
|
114
|
+
x-on:click={`selectedMenuIndex = ${index}`}
|
|
115
|
+
>
|
|
116
|
+
{item.icon && <Icon class="mr-2 size-4" name={item.icon} />}
|
|
117
|
+
{item.label}
|
|
118
|
+
</button>
|
|
119
|
+
</li>
|
|
120
|
+
))
|
|
121
|
+
}
|
|
122
|
+
</ul>
|
|
123
|
+
</div>
|
|
96
124
|
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
125
|
+
<div class="hidden lg:block">
|
|
126
|
+
<SidebarMenu navigation={selectedMenuItem} parentSlug={currentPrefix} />
|
|
127
|
+
</div>
|
|
128
|
+
<div class="lg:hidden">
|
|
129
|
+
{menu.items.map((item, index) => (
|
|
130
|
+
<div x-show={`selectedMenuIndex === ${index}`} x-cloak>
|
|
131
|
+
<SidebarMenu navigation={item} parentSlug={getMenuItemPrefix(item.label)} />
|
|
132
|
+
</div>
|
|
133
|
+
))}
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { getConfig, type NavTabs } from "../lib/validation";
|
|
3
|
+
import SidebarMenu from "./SidebarMenu.astro";
|
|
4
|
+
import { slugify } from "../lib/utils";
|
|
5
|
+
import { stripBasePath } from "../lib/base-path";
|
|
6
|
+
import { getAllRoutes } from "../lib/routes";
|
|
7
|
+
import NavigationTabList from "./NavigationTabList.astro";
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
tabs: NavTabs;
|
|
11
|
+
parentSlug?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { tabs, parentSlug = "" } = Astro.props;
|
|
15
|
+
const tabItems = tabs.items ?? [];
|
|
16
|
+
const pathname = stripBasePath(Astro.url.pathname);
|
|
17
|
+
const config = await getConfig();
|
|
18
|
+
const routes = (await getAllRoutes()).filter((route) => !route.hidden);
|
|
19
|
+
const normalizedPathParts = pathname
|
|
20
|
+
.replace(/^\/+/, "")
|
|
21
|
+
.replace(/\/+$/, "")
|
|
22
|
+
.split("/")
|
|
23
|
+
.filter(Boolean);
|
|
24
|
+
const parentParts = parentSlug.split("/").filter(Boolean);
|
|
25
|
+
|
|
26
|
+
function getTabSlug(tab: (typeof tabItems)[number]): string {
|
|
27
|
+
return slugify(tab.slug || tab.label);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getTabPrefix(tab: (typeof tabItems)[number]): string {
|
|
31
|
+
const tabSlug = getTabSlug(tab);
|
|
32
|
+
return parentSlug ? `${parentSlug}/${tabSlug}` : tabSlug;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let currentTabIndex = tabItems.findIndex(
|
|
36
|
+
(item) => getTabSlug(item) === normalizedPathParts[parentParts.length],
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (pathname === "/" && config.home) {
|
|
40
|
+
const homeRoute = routes.find(
|
|
41
|
+
(route) => route.type === "mdx" && route.filePath === config.home,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if (homeRoute) {
|
|
45
|
+
const homeRouteParts = homeRoute.slug.split("/").filter(Boolean);
|
|
46
|
+
const homeTabSegment = homeRouteParts[parentParts.length];
|
|
47
|
+
const homeTabIndex = tabItems.findIndex(
|
|
48
|
+
(item) => getTabSlug(item) === homeTabSegment,
|
|
49
|
+
);
|
|
50
|
+
if (homeTabIndex !== -1) {
|
|
51
|
+
currentTabIndex = homeTabIndex;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
currentTabIndex = currentTabIndex === -1 ? 0 : currentTabIndex;
|
|
57
|
+
|
|
58
|
+
const selectedTabItem = tabItems[currentTabIndex];
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
{
|
|
62
|
+
selectedTabItem ? (
|
|
63
|
+
<div
|
|
64
|
+
x-data={`{ selectedTabIndex: ${currentTabIndex} }`}
|
|
65
|
+
x-init={`$watch('open', (value) => { if (value) selectedTabIndex = ${currentTabIndex} })`}
|
|
66
|
+
>
|
|
67
|
+
<div class="lg:hidden h-11 border-b border-border-light bg-background">
|
|
68
|
+
<nav
|
|
69
|
+
class="h-full overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
|
70
|
+
aria-label="Documentation sections"
|
|
71
|
+
>
|
|
72
|
+
<NavigationTabList
|
|
73
|
+
items={tabItems}
|
|
74
|
+
currentIndex={currentTabIndex}
|
|
75
|
+
mode="button"
|
|
76
|
+
/>
|
|
77
|
+
</nav>
|
|
78
|
+
</div>
|
|
79
|
+
{tabItems.map((item, index) => (
|
|
80
|
+
<div x-show={`selectedTabIndex === ${index}`} x-cloak>
|
|
81
|
+
<SidebarMenu navigation={item} parentSlug={getTabPrefix(item)} />
|
|
82
|
+
</div>
|
|
83
|
+
))}
|
|
84
|
+
</div>
|
|
85
|
+
) : null
|
|
86
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { JSX } from "preact";
|
|
2
2
|
import { navigate } from "astro:transitions/client";
|
|
3
|
-
import { useEffect, useRef, useState } from "preact/hooks";
|
|
3
|
+
import { useEffect, useLayoutEffect, useRef, useState } from "preact/hooks";
|
|
4
4
|
import AssistantEmbedPanel, {
|
|
5
5
|
ASSISTANT_PANEL_STORAGE_KEY,
|
|
6
6
|
AssistantPanelIcon,
|
|
7
7
|
type AssistantPanelSize,
|
|
8
8
|
} from "./AssistantEmbedPanel";
|
|
9
|
+
import type { AssistantShikiRuntimeConfig } from "../../lib/assistant-shiki-client";
|
|
9
10
|
import {
|
|
10
11
|
DEFAULT_ASSISTANT_CHROME_CONFIG,
|
|
11
12
|
type AssistantChromeConfig,
|
|
@@ -31,6 +32,7 @@ type AssistantDocsWidgetProps = {
|
|
|
31
32
|
emptyStateQuestions?: string[];
|
|
32
33
|
devProxyToken?: string;
|
|
33
34
|
chrome?: AssistantChromeConfig;
|
|
35
|
+
shiki?: AssistantShikiRuntimeConfig;
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
type AssistantOpenRequestWindow = Window & {
|
|
@@ -39,6 +41,20 @@ type AssistantOpenRequestWindow = Window & {
|
|
|
39
41
|
__assistantDocsLauncherEntered?: boolean;
|
|
40
42
|
};
|
|
41
43
|
|
|
44
|
+
type PageScrollLockState = {
|
|
45
|
+
scrollX: number;
|
|
46
|
+
scrollY: number;
|
|
47
|
+
htmlOverflow: string;
|
|
48
|
+
htmlOverscrollBehavior: string;
|
|
49
|
+
bodyOverflow: string;
|
|
50
|
+
bodyOverscrollBehavior: string;
|
|
51
|
+
bodyPosition: string;
|
|
52
|
+
bodyTop: string;
|
|
53
|
+
bodyLeft: string;
|
|
54
|
+
bodyRight: string;
|
|
55
|
+
bodyWidth: string;
|
|
56
|
+
};
|
|
57
|
+
|
|
42
58
|
function normalizePanelSize(value: unknown): AssistantPanelSize {
|
|
43
59
|
return value === "expanded" ? "expanded" : "default";
|
|
44
60
|
}
|
|
@@ -75,6 +91,7 @@ export default function AssistantDocsWidget({
|
|
|
75
91
|
emptyStateQuestions,
|
|
76
92
|
devProxyToken,
|
|
77
93
|
chrome,
|
|
94
|
+
shiki,
|
|
78
95
|
}: AssistantDocsWidgetProps) {
|
|
79
96
|
const [isOpen, setIsOpen] = useState(false);
|
|
80
97
|
const [panelSize, setPanelSize] = useState<AssistantPanelSize>(() =>
|
|
@@ -99,6 +116,7 @@ export default function AssistantDocsWidget({
|
|
|
99
116
|
const navigationTransitionCleanupRef = useRef<(() => void) | null>(null);
|
|
100
117
|
const navigationTransitionTimeoutRef = useRef<number | null>(null);
|
|
101
118
|
const panelSizeTransitionTimeoutRef = useRef<number | null>(null);
|
|
119
|
+
const pageScrollLockRef = useRef<PageScrollLockState | null>(null);
|
|
102
120
|
const chromeConfig = chrome ?? DEFAULT_ASSISTANT_CHROME_CONFIG;
|
|
103
121
|
const numericZIndex =
|
|
104
122
|
Number.parseInt(chromeConfig.zIndex, 10) ||
|
|
@@ -159,6 +177,13 @@ export default function AssistantDocsWidget({
|
|
|
159
177
|
};
|
|
160
178
|
|
|
161
179
|
const closePanel = () => {
|
|
180
|
+
if (typeof document !== "undefined") {
|
|
181
|
+
const activeElement = document.activeElement;
|
|
182
|
+
if (activeElement instanceof HTMLElement) {
|
|
183
|
+
activeElement.blur();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
162
187
|
setIsOpen(false);
|
|
163
188
|
};
|
|
164
189
|
|
|
@@ -267,6 +292,96 @@ export default function AssistantDocsWidget({
|
|
|
267
292
|
};
|
|
268
293
|
}, []);
|
|
269
294
|
|
|
295
|
+
useLayoutEffect(() => {
|
|
296
|
+
if (!isOpen || typeof window === "undefined") {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const unlockPageScroll = () => {
|
|
301
|
+
const lockState = pageScrollLockRef.current;
|
|
302
|
+
if (!lockState) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
document.documentElement.style.overflow = lockState.htmlOverflow;
|
|
307
|
+
document.documentElement.style.overscrollBehavior =
|
|
308
|
+
lockState.htmlOverscrollBehavior;
|
|
309
|
+
document.body.style.overflow = lockState.bodyOverflow;
|
|
310
|
+
document.body.style.overscrollBehavior =
|
|
311
|
+
lockState.bodyOverscrollBehavior;
|
|
312
|
+
document.body.style.position = lockState.bodyPosition;
|
|
313
|
+
document.body.style.top = lockState.bodyTop;
|
|
314
|
+
document.body.style.left = lockState.bodyLeft;
|
|
315
|
+
document.body.style.right = lockState.bodyRight;
|
|
316
|
+
document.body.style.width = lockState.bodyWidth;
|
|
317
|
+
pageScrollLockRef.current = null;
|
|
318
|
+
|
|
319
|
+
window.scrollTo(lockState.scrollX, lockState.scrollY);
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const lockPageScroll = () => {
|
|
323
|
+
if (pageScrollLockRef.current) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const html = document.documentElement;
|
|
328
|
+
const body = document.body;
|
|
329
|
+
const scrollX = window.scrollX;
|
|
330
|
+
const scrollY = window.scrollY;
|
|
331
|
+
pageScrollLockRef.current = {
|
|
332
|
+
scrollX,
|
|
333
|
+
scrollY,
|
|
334
|
+
htmlOverflow: html.style.overflow,
|
|
335
|
+
htmlOverscrollBehavior: html.style.overscrollBehavior,
|
|
336
|
+
bodyOverflow: body.style.overflow,
|
|
337
|
+
bodyOverscrollBehavior: body.style.overscrollBehavior,
|
|
338
|
+
bodyPosition: body.style.position,
|
|
339
|
+
bodyTop: body.style.top,
|
|
340
|
+
bodyLeft: body.style.left,
|
|
341
|
+
bodyRight: body.style.right,
|
|
342
|
+
bodyWidth: body.style.width,
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
html.style.overflow = "hidden";
|
|
346
|
+
html.style.overscrollBehavior = "none";
|
|
347
|
+
body.style.overflow = "hidden";
|
|
348
|
+
body.style.overscrollBehavior = "none";
|
|
349
|
+
body.style.position = "fixed";
|
|
350
|
+
body.style.top = `-${scrollY}px`;
|
|
351
|
+
body.style.left = "0";
|
|
352
|
+
body.style.right = "0";
|
|
353
|
+
body.style.width = "100%";
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
const fullscreenPanelQuery = window.matchMedia(
|
|
357
|
+
`(max-width: ${chromeConfig.mobileBreakpoint}), (max-height: ${chromeConfig.panelFullscreenHeightBreakpoint})`,
|
|
358
|
+
);
|
|
359
|
+
const syncPageScrollLock = () => {
|
|
360
|
+
if (fullscreenPanelQuery.matches) {
|
|
361
|
+
lockPageScroll();
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
unlockPageScroll();
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
syncPageScrollLock();
|
|
369
|
+
fullscreenPanelQuery.addEventListener("change", syncPageScrollLock);
|
|
370
|
+
window.addEventListener("resize", syncPageScrollLock);
|
|
371
|
+
window.addEventListener("orientationchange", syncPageScrollLock);
|
|
372
|
+
|
|
373
|
+
return () => {
|
|
374
|
+
fullscreenPanelQuery.removeEventListener("change", syncPageScrollLock);
|
|
375
|
+
window.removeEventListener("resize", syncPageScrollLock);
|
|
376
|
+
window.removeEventListener("orientationchange", syncPageScrollLock);
|
|
377
|
+
unlockPageScroll();
|
|
378
|
+
};
|
|
379
|
+
}, [
|
|
380
|
+
chromeConfig.mobileBreakpoint,
|
|
381
|
+
chromeConfig.panelFullscreenHeightBreakpoint,
|
|
382
|
+
isOpen,
|
|
383
|
+
]);
|
|
384
|
+
|
|
270
385
|
useEffect(() => {
|
|
271
386
|
return () => {
|
|
272
387
|
navigationTransitionCleanupRef.current?.();
|
|
@@ -320,10 +435,15 @@ export default function AssistantDocsWidget({
|
|
|
320
435
|
emptyStateHeading={emptyStateHeading}
|
|
321
436
|
emptyStateQuestions={emptyStateQuestions}
|
|
322
437
|
devProxyToken={devProxyToken}
|
|
438
|
+
shiki={shiki}
|
|
323
439
|
panelSurface="inline"
|
|
324
440
|
linkTarget="current"
|
|
325
441
|
allowApiPathQueryOverride={false}
|
|
326
442
|
openSignal={openSignal}
|
|
443
|
+
mobileBreakpoint={chromeConfig.mobileBreakpoint}
|
|
444
|
+
panelFullscreenHeightBreakpoint={
|
|
445
|
+
chromeConfig.panelFullscreenHeightBreakpoint
|
|
446
|
+
}
|
|
327
447
|
onRequestOpen={openPanel}
|
|
328
448
|
onRequestClose={closePanel}
|
|
329
449
|
onRequestPanelSizeToggle={handlePanelSizeChange}
|
|
@@ -571,12 +691,17 @@ export default function AssistantDocsWidget({
|
|
|
571
691
|
|
|
572
692
|
@media (max-width: ${chromeConfig.mobileBreakpoint}), (max-height: ${chromeConfig.panelFullscreenHeightBreakpoint}) {
|
|
573
693
|
.assistant-docs-panel-shell {
|
|
574
|
-
|
|
694
|
+
top: 0 !important;
|
|
695
|
+
right: auto !important;
|
|
696
|
+
bottom: auto !important;
|
|
697
|
+
left: 0 !important;
|
|
575
698
|
z-index: var(--assistant-docs-mobile-panel-z-index) !important;
|
|
576
699
|
width: 100vw !important;
|
|
577
700
|
height: 100dvh !important;
|
|
578
701
|
border: 0 !important;
|
|
579
702
|
border-radius: 0 !important;
|
|
703
|
+
transition: none !important;
|
|
704
|
+
transition-behavior: normal !important;
|
|
580
705
|
}
|
|
581
706
|
|
|
582
707
|
.assistant-docs-panel-shell > div {
|