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
|
@@ -257,7 +257,7 @@ const renderedCodeLinesHtml = normalizedTokenLines
|
|
|
257
257
|
<div
|
|
258
258
|
class:list={[
|
|
259
259
|
"group/prose-code not-prose relative w-full max-w-full min-w-0 rounded-xl",
|
|
260
|
-
parsedInCodeGroup ? "my-0" : "
|
|
260
|
+
parsedInCodeGroup ? "my-0" : "rd-prose-block shadow-xs",
|
|
261
261
|
]}
|
|
262
262
|
data-rd-code-block-root="true"
|
|
263
263
|
data-rd-collapsed-lines={collapsedLinesValue}
|
|
@@ -4,7 +4,7 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<div
|
|
7
|
-
class="group/prose-code-group not-prose relative
|
|
7
|
+
class="rd-prose-block group/prose-code-group not-prose relative w-full max-w-full min-w-0 shadow-xs rounded-xl"
|
|
8
8
|
data-rd-code-group-root="true"
|
|
9
9
|
>
|
|
10
10
|
<div
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
const columnProps = Astro.props as Record<string, unknown>;
|
|
3
|
+
|
|
4
|
+
function getSourceFile(pathname: string): string {
|
|
5
|
+
const pagePath = pathname
|
|
6
|
+
.replace(/^\/documentation\//, "")
|
|
7
|
+
.replace(/\/$/, "");
|
|
8
|
+
return `${pagePath}.mdx`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const unknownProps = Object.keys(columnProps);
|
|
12
|
+
if (unknownProps.length > 0) {
|
|
13
|
+
const propLabel = unknownProps.length === 1 ? "prop" : "props";
|
|
14
|
+
const unknownLabel = unknownProps.map((name) => `"${name}"`).join(", ");
|
|
15
|
+
throw new Error(
|
|
16
|
+
`[USER_ERROR]: <Column>: Unsupported ${propLabel}: ${unknownLabel}. <Column> does not accept props; render another <Columns> block for a new row. (in ${getSourceFile(Astro.url.pathname)})`,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<div data-rd-column class="min-w-0">
|
|
22
|
+
<div class="prose-rules max-w-none! *:max-w-none!">
|
|
23
|
+
<slot />
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
validateNoUnknownProps,
|
|
4
|
+
validateProps,
|
|
5
|
+
} from "../../lib/component-error";
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
columns?: 2 | 3;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const columnsProps = Astro.props as Record<string, unknown>;
|
|
12
|
+
|
|
13
|
+
validateNoUnknownProps(
|
|
14
|
+
"Columns",
|
|
15
|
+
columnsProps,
|
|
16
|
+
["columns"],
|
|
17
|
+
Astro.url.pathname,
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
validateProps(
|
|
21
|
+
"Columns",
|
|
22
|
+
columnsProps,
|
|
23
|
+
{
|
|
24
|
+
columns: { type: ["number", "string"] },
|
|
25
|
+
},
|
|
26
|
+
Astro.url.pathname,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
function normalizeColumns(value: unknown): 2 | 3 {
|
|
30
|
+
if (value === undefined) return 2;
|
|
31
|
+
|
|
32
|
+
const normalizedValue =
|
|
33
|
+
typeof value === "number"
|
|
34
|
+
? value
|
|
35
|
+
: typeof value === "string"
|
|
36
|
+
? Number(value.trim())
|
|
37
|
+
: Number.NaN;
|
|
38
|
+
|
|
39
|
+
if (normalizedValue !== 2 && normalizedValue !== 3) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`[USER_ERROR]: <Columns>: Invalid prop "columns": expected 2 or 3 (in ${Astro.url.pathname})`,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return normalizedValue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getSourceFile(pathname: string): string {
|
|
49
|
+
const pagePath = pathname
|
|
50
|
+
.replace(/^\/documentation\//, "")
|
|
51
|
+
.replace(/\/$/, "");
|
|
52
|
+
return `${pagePath}.mdx`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function createColumnsError(message: string): Error {
|
|
56
|
+
return new Error(
|
|
57
|
+
`[USER_ERROR]: <Columns>: ${message} (in ${getSourceFile(Astro.url.pathname)})`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const VOID_ELEMENTS = new Set([
|
|
62
|
+
"area",
|
|
63
|
+
"base",
|
|
64
|
+
"br",
|
|
65
|
+
"col",
|
|
66
|
+
"embed",
|
|
67
|
+
"hr",
|
|
68
|
+
"img",
|
|
69
|
+
"input",
|
|
70
|
+
"link",
|
|
71
|
+
"meta",
|
|
72
|
+
"param",
|
|
73
|
+
"source",
|
|
74
|
+
"track",
|
|
75
|
+
"wbr",
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
function getTopLevelElements(html: string): Array<{
|
|
79
|
+
tagName: string;
|
|
80
|
+
attributes: string;
|
|
81
|
+
}> {
|
|
82
|
+
const elements: Array<{ tagName: string; attributes: string }> = [];
|
|
83
|
+
let depth = 0;
|
|
84
|
+
let index = 0;
|
|
85
|
+
|
|
86
|
+
while (index < html.length) {
|
|
87
|
+
const nextTagStart = html.indexOf("<", index);
|
|
88
|
+
if (nextTagStart === -1) break;
|
|
89
|
+
|
|
90
|
+
if (html.startsWith("<!--", nextTagStart)) {
|
|
91
|
+
const commentEnd = html.indexOf("-->", nextTagStart + 4);
|
|
92
|
+
index = commentEnd === -1 ? html.length : commentEnd + 3;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const tagEnd = html.indexOf(">", nextTagStart + 1);
|
|
97
|
+
if (tagEnd === -1) break;
|
|
98
|
+
|
|
99
|
+
const rawTag = html.slice(nextTagStart + 1, tagEnd).trim();
|
|
100
|
+
index = tagEnd + 1;
|
|
101
|
+
|
|
102
|
+
if (!rawTag || rawTag.startsWith("!") || rawTag.startsWith("?")) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (rawTag.startsWith("/")) {
|
|
107
|
+
depth = Math.max(0, depth - 1);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const tagMatch = rawTag.match(/^([A-Za-z][\w:-]*)([\s\S]*)$/);
|
|
112
|
+
if (!tagMatch) continue;
|
|
113
|
+
|
|
114
|
+
const tagName = tagMatch[1].toLowerCase();
|
|
115
|
+
const attributes = tagMatch[2] ?? "";
|
|
116
|
+
const isSelfClosing = /\/\s*$/.test(rawTag);
|
|
117
|
+
|
|
118
|
+
if (depth === 0) {
|
|
119
|
+
elements.push({ tagName, attributes });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!isSelfClosing && !VOID_ELEMENTS.has(tagName)) {
|
|
123
|
+
depth += 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return elements;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function isColumnElement(element: { tagName: string; attributes: string }) {
|
|
131
|
+
return (
|
|
132
|
+
element.tagName === "div" &&
|
|
133
|
+
/(?:^|\s)data-rd-column(?:\s|=|$)/.test(element.attributes)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function validateColumnChildren(html: string, expectedColumns: 2 | 3): void {
|
|
138
|
+
const topLevelElements = getTopLevelElements(html);
|
|
139
|
+
const columnElements = topLevelElements.filter(isColumnElement);
|
|
140
|
+
|
|
141
|
+
if (topLevelElements.length === 0) {
|
|
142
|
+
throw createColumnsError(
|
|
143
|
+
`Must contain exactly ${expectedColumns} <Column> children.`,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (columnElements.length !== topLevelElements.length) {
|
|
148
|
+
throw createColumnsError(
|
|
149
|
+
"Only direct <Column> children are allowed. Wrap each column's content in <Column>.",
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (columnElements.length !== expectedColumns) {
|
|
154
|
+
throw createColumnsError(
|
|
155
|
+
`Expected exactly ${expectedColumns} <Column> children for columns={${expectedColumns}}, but found ${columnElements.length}. Render another <Columns> block for a new row.`,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const columns = normalizeColumns(columnsProps.columns);
|
|
161
|
+
const html = Astro.slots.has("default")
|
|
162
|
+
? await Astro.slots.render("default")
|
|
163
|
+
: "";
|
|
164
|
+
|
|
165
|
+
validateColumnChildren(html, columns);
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
<div class="rd-prose-block rd-columns-container w-full max-w-none!">
|
|
169
|
+
<div
|
|
170
|
+
class="rd-columns grid w-full max-w-none! gap-6"
|
|
171
|
+
data-rd-columns={columns}
|
|
172
|
+
set:html={html}
|
|
173
|
+
/>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
<style>
|
|
177
|
+
.rd-columns-container {
|
|
178
|
+
container: rd-columns / inline-size;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.rd-columns {
|
|
182
|
+
grid-template-columns: minmax(0, 1fr);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.rd-columns > :global(*) {
|
|
186
|
+
min-width: 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@container rd-columns (min-width: 36rem) {
|
|
190
|
+
.rd-columns[data-rd-columns="2"] {
|
|
191
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@container rd-columns (min-width: 664px) {
|
|
196
|
+
.rd-columns[data-rd-columns="3"] {
|
|
197
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
</style>
|
|
@@ -60,7 +60,7 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
|
|
|
60
60
|
---
|
|
61
61
|
|
|
62
62
|
<div
|
|
63
|
-
class="rd-component-preview
|
|
63
|
+
class="rd-prose-block rd-component-preview flex w-full max-w-full min-w-0 flex-col"
|
|
64
64
|
data-rd-component-preview-root="true"
|
|
65
65
|
>
|
|
66
66
|
<div
|
|
@@ -91,7 +91,7 @@ const captionHtml =
|
|
|
91
91
|
|
|
92
92
|
<figure
|
|
93
93
|
class:list={[
|
|
94
|
-
"p-1.5 pb-1 xs:pb-1.5 group border border-neutral-200 dark:border-neutral-800 shadow-xs bg-neutral-50 dark:bg-(--rd-code-surface) rounded-2xl",
|
|
94
|
+
"rd-prose-block p-1.5 pb-1 xs:pb-1.5 group border border-neutral-200 dark:border-neutral-800 shadow-xs bg-neutral-50 dark:bg-(--rd-code-surface) rounded-2xl",
|
|
95
95
|
hasCustomImageWidth ? "w-fit max-w-full mx-auto" : "w-full",
|
|
96
96
|
]}
|
|
97
97
|
x-data="{
|
|
@@ -131,7 +131,7 @@ if (labels.length === 0) {
|
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
133
|
}"
|
|
134
|
-
class="
|
|
134
|
+
class="rd-prose-block">
|
|
135
135
|
<ul
|
|
136
136
|
class="relative isolate not-prose flex w-full max-w-full min-w-0 rounded-lg border border-neutral-100 bg-neutral-100/80 p-[3px] dark:border-none dark:bg-neutral-800/50"
|
|
137
137
|
>
|
|
@@ -174,7 +174,7 @@ class="my-5">
|
|
|
174
174
|
<div
|
|
175
175
|
{...(index !== 0 ? { "x-cloak": true } : {})}
|
|
176
176
|
x-ref={`content-${index}`}
|
|
177
|
-
class="w-full"
|
|
177
|
+
class="prose-rules w-full max-w-none! *:max-w-none!"
|
|
178
178
|
:style={`getPanelStyle(${index})`}
|
|
179
179
|
style={index === 0 ? 'position: relative;' : ''}
|
|
180
180
|
set:html={content}
|
|
@@ -7,19 +7,15 @@ import googleSansLatinExtWoff2 from "../assets/fonts/google-sans-flex/latin-ext.
|
|
|
7
7
|
import geistMonoLatinWoff2 from "../assets/fonts/geist-mono/latin.woff2?url";
|
|
8
8
|
import geistMonoLatinExtWoff2 from "../assets/fonts/geist-mono/latin-ext.woff2?url";
|
|
9
9
|
import Sidebar from "../components/Sidebar.astro";
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
DEFAULT_THEME_COLOR_DARK,
|
|
13
|
-
DEFAULT_THEME_COLOR_LIGHT,
|
|
14
|
-
getConfig,
|
|
15
|
-
type BaseColorOption,
|
|
16
|
-
} from "../lib/validation";
|
|
10
|
+
import { getConfig } from "../lib/validation";
|
|
17
11
|
import Header from "../components/Header.astro";
|
|
18
12
|
import Footer from "../components/Footer.astro";
|
|
19
|
-
import
|
|
13
|
+
import AssistantDocsWidget from "../components/chat/AssistantDocsWidget.astro";
|
|
20
14
|
import { ClientRouter } from "astro:transitions";
|
|
21
|
-
import { prependBasePath, stripBasePath
|
|
15
|
+
import { prependBasePath, stripBasePath } from "../lib/base-path";
|
|
16
|
+
import { getFaviconConfig } from "../lib/favicon";
|
|
22
17
|
import { resolveStaticAssetUrl } from "../lib/static-asset-url";
|
|
18
|
+
import { getDocsThemeCss } from "../lib/theme-css";
|
|
23
19
|
|
|
24
20
|
interface Props {
|
|
25
21
|
pageTitle?: string;
|
|
@@ -43,117 +39,8 @@ function routePathToOgImagePath(routePath: string): string {
|
|
|
43
39
|
|
|
44
40
|
const { pageTitle, pageDescription } = Astro.props as Props;
|
|
45
41
|
const config = await getConfig();
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
const lightBaseColor: BaseColorOption =
|
|
49
|
-
typeof themeBaseColor === "string" ? themeBaseColor : themeBaseColor.light;
|
|
50
|
-
const darkBaseColor: BaseColorOption =
|
|
51
|
-
typeof themeBaseColor === "string" ? themeBaseColor : themeBaseColor.dark;
|
|
52
|
-
const lightThemeColor =
|
|
53
|
-
typeof themeThemeColor === "string"
|
|
54
|
-
? themeThemeColor
|
|
55
|
-
: (themeThemeColor?.light ?? DEFAULT_THEME_COLOR_LIGHT);
|
|
56
|
-
const darkThemeColor =
|
|
57
|
-
typeof themeThemeColor === "string"
|
|
58
|
-
? themeThemeColor
|
|
59
|
-
: (themeThemeColor?.dark ?? DEFAULT_THEME_COLOR_DARK);
|
|
60
|
-
const neutralColorShades = [
|
|
61
|
-
"50",
|
|
62
|
-
"100",
|
|
63
|
-
"200",
|
|
64
|
-
"300",
|
|
65
|
-
"400",
|
|
66
|
-
"500",
|
|
67
|
-
"600",
|
|
68
|
-
"700",
|
|
69
|
-
"800",
|
|
70
|
-
"900",
|
|
71
|
-
"950",
|
|
72
|
-
] as const;
|
|
73
|
-
const paletteColors = colors as unknown as Record<
|
|
74
|
-
string,
|
|
75
|
-
Record<(typeof neutralColorShades)[number], string>
|
|
76
|
-
>;
|
|
77
|
-
const getNeutralPaletteVariables = (baseColor: BaseColorOption): string[] => {
|
|
78
|
-
const palette = paletteColors[baseColor] ?? paletteColors.neutral;
|
|
79
|
-
return [
|
|
80
|
-
`--color-neutral: ${palette["500"]};`,
|
|
81
|
-
...neutralColorShades.map(
|
|
82
|
-
(shade) => `--color-neutral-${shade}: ${palette[shade]};`,
|
|
83
|
-
),
|
|
84
|
-
];
|
|
85
|
-
};
|
|
86
|
-
function normalizeHexColorToRgb(
|
|
87
|
-
hexColor: string,
|
|
88
|
-
): { r: number; g: number; b: number } | null {
|
|
89
|
-
const normalized = hexColor.replace("#", "").trim();
|
|
90
|
-
if (/^[a-fA-F0-9]{3,4}$/.test(normalized)) {
|
|
91
|
-
const [r, g, b] = normalized.split("");
|
|
92
|
-
if (!r || !g || !b) return null;
|
|
93
|
-
return {
|
|
94
|
-
r: Number.parseInt(`${r}${r}`, 16),
|
|
95
|
-
g: Number.parseInt(`${g}${g}`, 16),
|
|
96
|
-
b: Number.parseInt(`${b}${b}`, 16),
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (/^[a-fA-F0-9]{6,8}$/.test(normalized)) {
|
|
101
|
-
return {
|
|
102
|
-
r: Number.parseInt(normalized.slice(0, 2), 16),
|
|
103
|
-
g: Number.parseInt(normalized.slice(2, 4), 16),
|
|
104
|
-
b: Number.parseInt(normalized.slice(4, 6), 16),
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function getThemeForegroundColor(hexColor: string): "#ffffff" | "#111827" {
|
|
112
|
-
const rgb = normalizeHexColorToRgb(hexColor);
|
|
113
|
-
if (!rgb) return "#ffffff";
|
|
114
|
-
|
|
115
|
-
const toLinear = (channel: number): number => {
|
|
116
|
-
const normalized = channel / 255;
|
|
117
|
-
return normalized <= 0.03928
|
|
118
|
-
? normalized / 12.92
|
|
119
|
-
: ((normalized + 0.055) / 1.055) ** 2.4;
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
const luminance =
|
|
123
|
-
0.2126 * toLinear(rgb.r) +
|
|
124
|
-
0.7152 * toLinear(rgb.g) +
|
|
125
|
-
0.0722 * toLinear(rgb.b);
|
|
126
|
-
return luminance > 0.45 ? "#111827" : "#ffffff";
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const getThemeColorVariables = (themeColor: string): string[] => {
|
|
130
|
-
const foreground = getThemeForegroundColor(themeColor);
|
|
131
|
-
const iconFilter = foreground === "#ffffff" ? "invert(1)" : "none";
|
|
132
|
-
|
|
133
|
-
return [
|
|
134
|
-
`--color-theme: ${themeColor};`,
|
|
135
|
-
`--color-theme-foreground: ${foreground};`,
|
|
136
|
-
`--color-theme-icon-filter: ${iconFilter};`,
|
|
137
|
-
"--color-theme-top: color-mix(in oklab, var(--color-theme) 88%, white);",
|
|
138
|
-
"--color-theme-bottom: color-mix(in oklab, var(--color-theme) 90%, black);",
|
|
139
|
-
];
|
|
140
|
-
};
|
|
141
|
-
const lightNeutralVariables = getNeutralPaletteVariables(lightBaseColor);
|
|
142
|
-
const darkNeutralVariables = getNeutralPaletteVariables(darkBaseColor);
|
|
143
|
-
const lightThemeColorVariables = getThemeColorVariables(lightThemeColor);
|
|
144
|
-
const darkThemeColorVariables = getThemeColorVariables(darkThemeColor);
|
|
145
|
-
const neutralPaletteCss = [
|
|
146
|
-
"html[data-theme='light'], html:not(.dark):not([data-theme='dark']) {",
|
|
147
|
-
...[...lightNeutralVariables, ...lightThemeColorVariables].map(
|
|
148
|
-
(declaration) => ` ${declaration.replace(/;$/, " !important;")}`,
|
|
149
|
-
),
|
|
150
|
-
"}",
|
|
151
|
-
"html.dark, html[data-theme='dark'] {",
|
|
152
|
-
...[...darkNeutralVariables, ...darkThemeColorVariables].map(
|
|
153
|
-
(declaration) => ` ${declaration.replace(/;$/, " !important;")}`,
|
|
154
|
-
),
|
|
155
|
-
"}",
|
|
156
|
-
].join("\n");
|
|
42
|
+
const favicon = getFaviconConfig();
|
|
43
|
+
const neutralPaletteCss = getDocsThemeCss(config.theme);
|
|
157
44
|
const resolvedPageTitle = pageTitle?.trim();
|
|
158
45
|
const resolvedPageDescription =
|
|
159
46
|
typeof pageDescription === "string" && pageDescription.trim().length > 0
|
|
@@ -183,23 +70,7 @@ const parsedOrgTier = Number.parseInt(
|
|
|
183
70
|
const orgTier =
|
|
184
71
|
Number.isFinite(parsedOrgTier) && parsedOrgTier > 0 ? parsedOrgTier : 1;
|
|
185
72
|
const isDev = import.meta.env.DEV;
|
|
186
|
-
const askAiDevHost = (import.meta.env.ASK_AI_DEV_HOST ?? "s").toString().trim();
|
|
187
|
-
const askAiDevProxySecret = (import.meta.env.ASK_AI_DEV_PROXY_SECRET ?? "s")
|
|
188
|
-
.toString()
|
|
189
|
-
.trim();
|
|
190
|
-
const hasAskAiDevConfig =
|
|
191
|
-
askAiDevHost.length > 0 && askAiDevProxySecret.length > 0;
|
|
192
73
|
const askAiEnabled = isDev || orgTier >= 3;
|
|
193
|
-
const askAiChatAvailable = isDev ? hasAskAiDevConfig : orgTier >= 3;
|
|
194
|
-
let askAiApiPath = withBasePath("/_platform/ask-ai");
|
|
195
|
-
|
|
196
|
-
if (isDev && hasAskAiDevConfig) {
|
|
197
|
-
try {
|
|
198
|
-
askAiApiPath = new URL("/_platform/ask-ai", askAiDevHost).toString();
|
|
199
|
-
} catch {
|
|
200
|
-
askAiApiPath = withBasePath("/_platform/ask-ai");
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
74
|
---
|
|
204
75
|
|
|
205
76
|
<!doctype html>
|
|
@@ -357,8 +228,8 @@ if (isDev && hasAskAiDevConfig) {
|
|
|
357
228
|
<meta name="viewport" content="width=device-width" />
|
|
358
229
|
<link
|
|
359
230
|
rel="icon"
|
|
360
|
-
type=
|
|
361
|
-
href={resolveStaticAssetUrl(
|
|
231
|
+
type={favicon.type}
|
|
232
|
+
href={resolveStaticAssetUrl(favicon.href)}
|
|
362
233
|
/>
|
|
363
234
|
<meta name="generator" content={Astro.generator} />
|
|
364
235
|
<link rel="canonical" href={canonicalUrl} />
|
|
@@ -421,7 +292,7 @@ if (isDev && hasAskAiDevConfig) {
|
|
|
421
292
|
class="bg-background mx-[5px] min-h-[calc(100vh-68px)] mt-17 fixed inset-0 lg:hidden z-50 overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
|
422
293
|
x-transition.opacity
|
|
423
294
|
>
|
|
424
|
-
<Sidebar />
|
|
295
|
+
<Sidebar askAiEnabled={askAiEnabled} />
|
|
425
296
|
</div>
|
|
426
297
|
|
|
427
298
|
<!-- Main Content -->
|
|
@@ -429,25 +300,11 @@ if (isDev && hasAskAiDevConfig) {
|
|
|
429
300
|
class="mx-1 mt-1 px-4 sm:px-6 lg:pl-[calc(288px+32px)] pt-16 lg:pr-8 bg-background"
|
|
430
301
|
data-vaul-scale-chrome
|
|
431
302
|
>
|
|
432
|
-
<main
|
|
433
|
-
class="max-w-2xl xl:max-w-5xl mx-auto pt-16 pb-16 min-h-[calc(100vh-64px)]"
|
|
434
|
-
>
|
|
303
|
+
<main class="mx-auto pt-16 pb-16 min-h-[calc(100vh-64px)]">
|
|
435
304
|
<slot />
|
|
436
305
|
</main>
|
|
437
|
-
<Footer askAiEnabled />
|
|
306
|
+
<Footer askAiEnabled={askAiEnabled} />
|
|
438
307
|
</div>
|
|
439
|
-
{
|
|
440
|
-
askAiEnabled ? (
|
|
441
|
-
<div transition:persist>
|
|
442
|
-
<AskAiWidget
|
|
443
|
-
client:only="preact"
|
|
444
|
-
apiPath={askAiApiPath}
|
|
445
|
-
isChatAvailable={askAiChatAvailable}
|
|
446
|
-
devProxyToken={isDev ? askAiDevProxySecret : undefined}
|
|
447
|
-
unavailableMessage="This feature is available on production sites for Pro tier organizations."
|
|
448
|
-
/>
|
|
449
|
-
</div>
|
|
450
|
-
) : null
|
|
451
|
-
}
|
|
308
|
+
{askAiEnabled ? <AssistantDocsWidget /> : null}
|
|
452
309
|
</body>
|
|
453
310
|
</html>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export type AssistantChromeConfig = {
|
|
2
|
+
zIndex: string;
|
|
3
|
+
side: "left" | "right";
|
|
4
|
+
offsetX: string;
|
|
5
|
+
offsetY: string;
|
|
6
|
+
mobileOffsetX: string;
|
|
7
|
+
mobileOffsetY: string;
|
|
8
|
+
launcherSize: string;
|
|
9
|
+
launcherIconSize: string;
|
|
10
|
+
launcherShadow: string;
|
|
11
|
+
panelWidth: string;
|
|
12
|
+
panelHeight: string;
|
|
13
|
+
panelExpandedWidth: string;
|
|
14
|
+
panelExpandedHeight: string;
|
|
15
|
+
panelViewportMargin: string;
|
|
16
|
+
panelGap: string;
|
|
17
|
+
panelRadius: string;
|
|
18
|
+
panelBorder: string;
|
|
19
|
+
panelBackground: string;
|
|
20
|
+
panelDarkBorder: string;
|
|
21
|
+
panelDarkBackground: string;
|
|
22
|
+
panelBackdropBlur: string;
|
|
23
|
+
panelShadow: string;
|
|
24
|
+
panelDarkShadow: string;
|
|
25
|
+
panelOpenScale: string;
|
|
26
|
+
panelOpenDuration: string;
|
|
27
|
+
panelOpenTiming: string;
|
|
28
|
+
panelSizeDuration: string;
|
|
29
|
+
panelSizeTiming: string;
|
|
30
|
+
panelCloseDuration: string;
|
|
31
|
+
panelCloseTiming: string;
|
|
32
|
+
mobileBreakpoint: string;
|
|
33
|
+
panelFullscreenHeightBreakpoint: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const ASSISTANT_PANEL_DARK_NEUTRAL_800_MIX = "20%";
|
|
37
|
+
const ASSISTANT_PANEL_DARK_NEUTRAL_900_MIX = "80%";
|
|
38
|
+
const ASSISTANT_PANEL_DARK_SURFACE_OPACITY = "92%";
|
|
39
|
+
|
|
40
|
+
export function getAssistantPanelDarkBackgroundCss({
|
|
41
|
+
neutral800,
|
|
42
|
+
neutral900,
|
|
43
|
+
}: {
|
|
44
|
+
neutral800: string;
|
|
45
|
+
neutral900: string;
|
|
46
|
+
}): string {
|
|
47
|
+
return `color-mix(in srgb, color-mix(in srgb, ${neutral800} ${ASSISTANT_PANEL_DARK_NEUTRAL_800_MIX}, ${neutral900} ${ASSISTANT_PANEL_DARK_NEUTRAL_900_MIX}) ${ASSISTANT_PANEL_DARK_SURFACE_OPACITY}, transparent)`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const DEFAULT_ASSISTANT_CHROME_CONFIG: AssistantChromeConfig = {
|
|
51
|
+
zIndex: "2147483000",
|
|
52
|
+
side: "right",
|
|
53
|
+
offsetX: "20px",
|
|
54
|
+
offsetY: "20px",
|
|
55
|
+
mobileOffsetX: "16px",
|
|
56
|
+
mobileOffsetY: "16px",
|
|
57
|
+
launcherSize: "48px",
|
|
58
|
+
launcherIconSize: "20px",
|
|
59
|
+
launcherShadow: "0 16px 32px -8px rgb(0 0 0 / 24%)",
|
|
60
|
+
panelWidth: "420px",
|
|
61
|
+
panelHeight: "640px",
|
|
62
|
+
panelExpandedWidth: "640px",
|
|
63
|
+
panelExpandedHeight: "760px",
|
|
64
|
+
panelViewportMargin: "16px",
|
|
65
|
+
panelGap: "12px",
|
|
66
|
+
panelRadius: "16px",
|
|
67
|
+
panelBorder: "1px solid rgb(9 14 21 / 8%)",
|
|
68
|
+
panelBackground: "rgb(255 255 255 / 90%)",
|
|
69
|
+
panelDarkBorder: "1px solid rgb(255 255 255 / 8%)",
|
|
70
|
+
panelDarkBackground: getAssistantPanelDarkBackgroundCss({
|
|
71
|
+
neutral800: "var(--color-neutral-800, oklch(26.9% 0 0))",
|
|
72
|
+
neutral900: "var(--color-neutral-900, oklch(20.5% 0 0))",
|
|
73
|
+
}),
|
|
74
|
+
panelBackdropBlur: "48px",
|
|
75
|
+
panelShadow: "rgba(9, 14, 21, 0.16) 0px 5px 40px 0px",
|
|
76
|
+
panelDarkShadow: "rgba(0, 0, 0, 0.36) 0px 8px 44px 0px",
|
|
77
|
+
panelOpenScale: ".9",
|
|
78
|
+
panelOpenDuration: ".5s",
|
|
79
|
+
panelOpenTiming: "cubic-bezier(.34, 1.56, .64, 1)",
|
|
80
|
+
panelSizeDuration: ".46s",
|
|
81
|
+
panelSizeTiming: "cubic-bezier(.22, 1.26, .36, 1)",
|
|
82
|
+
panelCloseDuration: ".2s",
|
|
83
|
+
panelCloseTiming: "cubic-bezier(.25, 1, .5, 1)",
|
|
84
|
+
mobileBreakpoint: "640px",
|
|
85
|
+
panelFullscreenHeightBreakpoint: "560px",
|
|
86
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { DocsConfig } from "./validation";
|
|
2
|
+
import { getDocsDarkBaseColorShade } from "./theme-css";
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_ASSISTANT_CHROME_CONFIG,
|
|
5
|
+
getAssistantPanelDarkBackgroundCss,
|
|
6
|
+
type AssistantChromeConfig,
|
|
7
|
+
} from "./assistant-chrome-defaults";
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
DEFAULT_ASSISTANT_CHROME_CONFIG,
|
|
11
|
+
getAssistantPanelDarkBackgroundCss,
|
|
12
|
+
type AssistantChromeConfig,
|
|
13
|
+
} from "./assistant-chrome-defaults";
|
|
14
|
+
|
|
15
|
+
function getAssistantPanelDarkBackground(theme: DocsConfig["theme"]): string {
|
|
16
|
+
const neutral800 = getDocsDarkBaseColorShade(theme, "800");
|
|
17
|
+
const neutral900 = getDocsDarkBaseColorShade(theme, "900");
|
|
18
|
+
|
|
19
|
+
return getAssistantPanelDarkBackgroundCss({ neutral800, neutral900 });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getAssistantChromeConfig(
|
|
23
|
+
config: DocsConfig,
|
|
24
|
+
): AssistantChromeConfig {
|
|
25
|
+
const chromeConfig = {
|
|
26
|
+
...DEFAULT_ASSISTANT_CHROME_CONFIG,
|
|
27
|
+
panelDarkBackground: getAssistantPanelDarkBackground(config.theme),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
if (config.assistant?.button?.size === "small") {
|
|
31
|
+
return {
|
|
32
|
+
...chromeConfig,
|
|
33
|
+
launcherSize: "36px",
|
|
34
|
+
launcherIconSize: "16px",
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return chromeConfig;
|
|
39
|
+
}
|