boltdocs 1.3.0 → 1.3.2
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/dist/{cache-EHR7SXRU.mjs → cache-GQHF6BXI.mjs} +1 -1
- package/dist/{chunk-GSYECEZY.mjs → chunk-CYBWLFOG.mjs} +5 -1
- package/dist/node/index.js +36 -20
- package/dist/node/index.mjs +34 -22
- package/package.json +1 -1
- package/src/client/app/index.tsx +344 -344
- package/src/client/app/preload.tsx +56 -56
- package/src/client/index.ts +40 -40
- package/src/client/ssr.tsx +51 -51
- package/src/client/theme/components/CodeBlock/CodeBlock.tsx +76 -76
- package/src/client/theme/components/CodeBlock/index.ts +1 -1
- package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +154 -154
- package/src/client/theme/components/PackageManagerTabs/index.ts +1 -1
- package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +64 -64
- package/src/client/theme/components/Playground/Playground.tsx +124 -124
- package/src/client/theme/components/Playground/index.ts +1 -1
- package/src/client/theme/components/Playground/playground.css +168 -168
- package/src/client/theme/components/Video/Video.tsx +84 -84
- package/src/client/theme/components/Video/index.ts +1 -1
- package/src/client/theme/components/Video/video.css +41 -41
- package/src/client/theme/components/mdx/Admonition.tsx +80 -80
- package/src/client/theme/components/mdx/Badge.tsx +31 -31
- package/src/client/theme/components/mdx/Button.tsx +50 -50
- package/src/client/theme/components/mdx/Card.tsx +80 -80
- package/src/client/theme/components/mdx/List.tsx +57 -57
- package/src/client/theme/components/mdx/Tabs.tsx +94 -94
- package/src/client/theme/components/mdx/index.ts +18 -18
- package/src/client/theme/components/mdx/mdx-components.css +424 -424
- package/src/client/theme/icons/bun.tsx +62 -62
- package/src/client/theme/icons/deno.tsx +20 -20
- package/src/client/theme/icons/discord.tsx +12 -12
- package/src/client/theme/icons/github.tsx +15 -15
- package/src/client/theme/icons/npm.tsx +13 -13
- package/src/client/theme/icons/pnpm.tsx +72 -72
- package/src/client/theme/icons/twitter.tsx +12 -12
- package/src/client/theme/styles/markdown.css +343 -343
- package/src/client/theme/styles/variables.css +162 -162
- package/src/client/theme/styles.css +37 -37
- package/src/client/theme/ui/BackgroundGradient/BackgroundGradient.tsx +10 -10
- package/src/client/theme/ui/BackgroundGradient/index.ts +1 -1
- package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +68 -68
- package/src/client/theme/ui/Breadcrumbs/index.ts +1 -1
- package/src/client/theme/ui/Footer/footer.css +32 -32
- package/src/client/theme/ui/Head/Head.tsx +69 -69
- package/src/client/theme/ui/Head/index.ts +1 -1
- package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +125 -125
- package/src/client/theme/ui/LanguageSwitcher/index.ts +1 -1
- package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +98 -98
- package/src/client/theme/ui/Layout/Layout.tsx +202 -202
- package/src/client/theme/ui/Layout/base.css +76 -76
- package/src/client/theme/ui/Layout/index.ts +2 -2
- package/src/client/theme/ui/Layout/pagination.css +72 -72
- package/src/client/theme/ui/Layout/responsive.css +36 -36
- package/src/client/theme/ui/Link/Link.tsx +254 -254
- package/src/client/theme/ui/Link/index.ts +2 -2
- package/src/client/theme/ui/Loading/Loading.tsx +10 -10
- package/src/client/theme/ui/Loading/index.ts +1 -1
- package/src/client/theme/ui/Loading/loading.css +30 -30
- package/src/client/theme/ui/Navbar/GithubStars.tsx +27 -27
- package/src/client/theme/ui/Navbar/Navbar.tsx +145 -145
- package/src/client/theme/ui/Navbar/index.ts +2 -2
- package/src/client/theme/ui/Navbar/navbar.css +233 -233
- package/src/client/theme/ui/NotFound/NotFound.tsx +19 -19
- package/src/client/theme/ui/NotFound/index.ts +1 -1
- package/src/client/theme/ui/NotFound/not-found.css +64 -64
- package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +235 -235
- package/src/client/theme/ui/OnThisPage/index.ts +1 -1
- package/src/client/theme/ui/OnThisPage/toc.css +132 -132
- package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +18 -18
- package/src/client/theme/ui/PoweredBy/index.ts +1 -1
- package/src/client/theme/ui/PoweredBy/powered-by.css +76 -76
- package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +199 -199
- package/src/client/theme/ui/SearchDialog/index.ts +1 -1
- package/src/client/theme/ui/SearchDialog/search.css +152 -152
- package/src/client/theme/ui/Sidebar/Sidebar.tsx +204 -204
- package/src/client/theme/ui/Sidebar/index.ts +1 -1
- package/src/client/theme/ui/Sidebar/sidebar.css +236 -236
- package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +69 -69
- package/src/client/theme/ui/ThemeToggle/index.ts +1 -1
- package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +136 -136
- package/src/client/theme/ui/VersionSwitcher/index.ts +1 -1
- package/src/client/types.ts +50 -50
- package/src/client/utils.ts +26 -26
- package/src/node/cache.ts +408 -408
- package/src/node/config.ts +192 -192
- package/src/node/index.ts +21 -21
- package/src/node/mdx.ts +120 -120
- package/src/node/plugin/entry.ts +58 -58
- package/src/node/plugin/html.ts +55 -55
- package/src/node/plugin/index.ts +193 -193
- package/src/node/plugin/types.ts +11 -11
- package/src/node/routes/cache.ts +28 -28
- package/src/node/routes/index.ts +167 -167
- package/src/node/routes/parser.ts +153 -127
- package/src/node/routes/sorter.ts +42 -42
- package/src/node/routes/types.ts +49 -49
- package/src/node/ssg/index.ts +114 -114
- package/src/node/ssg/meta.ts +33 -34
- package/src/node/ssg/options.ts +13 -13
- package/src/node/ssg/sitemap.ts +55 -54
- package/src/node/utils.ts +145 -134
- package/tsconfig.json +20 -20
- package/tsup.config.ts +22 -22
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { LiveProvider, LiveEditor, LiveError, LivePreview } from "react-live";
|
|
3
|
-
import { Copy, Check, Terminal, Play } from "lucide-react";
|
|
4
|
-
|
|
5
|
-
interface PlaygroundProps {
|
|
6
|
-
code?: string;
|
|
7
|
-
children?: string | React.ReactNode;
|
|
8
|
-
scope?: Record<string, any>;
|
|
9
|
-
readonly?: boolean;
|
|
10
|
-
noInline?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Transforms code that uses `export default` into a format compatible
|
|
15
|
-
* with react-live's `noInline` mode by stripping the export and
|
|
16
|
-
* appending a `render(<ComponentName />)` call.
|
|
17
|
-
*/
|
|
18
|
-
function prepareCode(raw: string): { code: string; noInline: boolean } {
|
|
19
|
-
const trimmed = raw.trim();
|
|
20
|
-
|
|
21
|
-
// Match: export default function Name(...)
|
|
22
|
-
const fnMatch = trimmed.match(/export\s+default\s+function\s+(\w+)/);
|
|
23
|
-
if (fnMatch) {
|
|
24
|
-
const name = fnMatch[1];
|
|
25
|
-
const code =
|
|
26
|
-
trimmed.replace(/export\s+default\s+/, "") + `\n\nrender(<${name} />);`;
|
|
27
|
-
return { code, noInline: true };
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Match: export default ComponentName (at the end)
|
|
31
|
-
const varMatch = trimmed.match(/export\s+default\s+(\w+)\s*;?\s*$/);
|
|
32
|
-
if (varMatch) {
|
|
33
|
-
const name = varMatch[1];
|
|
34
|
-
const code =
|
|
35
|
-
trimmed.replace(/export\s+default\s+\w+\s*;?\s*$/, "") +
|
|
36
|
-
`\nrender(<${name} />);`;
|
|
37
|
-
return { code, noInline: true };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// No export default — use inline mode (simple JSX expression)
|
|
41
|
-
return { code: trimmed, noInline: false };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* A live React playground component.
|
|
46
|
-
* Features a split layout with a live editor and a preview section.
|
|
47
|
-
*
|
|
48
|
-
* Supports `export default function App()` style code out of the box.
|
|
49
|
-
*/
|
|
50
|
-
export function Playground({
|
|
51
|
-
code,
|
|
52
|
-
children,
|
|
53
|
-
scope = {},
|
|
54
|
-
readonly = false,
|
|
55
|
-
noInline: forceNoInline,
|
|
56
|
-
}: PlaygroundProps) {
|
|
57
|
-
// Extract code from either `code` prop or `children`
|
|
58
|
-
let initialCode = code || "";
|
|
59
|
-
if (!initialCode && typeof children === "string") {
|
|
60
|
-
initialCode = children;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const prepared = prepareCode(initialCode);
|
|
64
|
-
const useNoInline = forceNoInline ?? prepared.noInline;
|
|
65
|
-
|
|
66
|
-
const [copied, setCopied] = useState(false);
|
|
67
|
-
const [activeCode, setActiveCode] = useState(prepared.code);
|
|
68
|
-
|
|
69
|
-
const handleCopy = () => {
|
|
70
|
-
navigator.clipboard.writeText(activeCode);
|
|
71
|
-
setCopied(true);
|
|
72
|
-
setTimeout(() => setCopied(false), 2000);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// Provide React generically
|
|
76
|
-
const extendedScope = { React, ...scope };
|
|
77
|
-
|
|
78
|
-
return (
|
|
79
|
-
<div className="boltdocs-playground" data-readonly={readonly}>
|
|
80
|
-
<LiveProvider
|
|
81
|
-
code={activeCode}
|
|
82
|
-
scope={extendedScope}
|
|
83
|
-
theme={undefined}
|
|
84
|
-
noInline={useNoInline}
|
|
85
|
-
>
|
|
86
|
-
<div className="playground-split-container">
|
|
87
|
-
{/* Editor Side */}
|
|
88
|
-
<div className="playground-panel playground-editor-panel">
|
|
89
|
-
<div className="playground-panel-header">
|
|
90
|
-
<div className="playground-panel-title">
|
|
91
|
-
<Terminal size={14} />
|
|
92
|
-
<span>{readonly ? "Code Example" : "Live Editor"}</span>
|
|
93
|
-
</div>
|
|
94
|
-
<button
|
|
95
|
-
className="playground-copy-btn"
|
|
96
|
-
onClick={handleCopy}
|
|
97
|
-
title="Copy code"
|
|
98
|
-
>
|
|
99
|
-
{copied ? <Check size={14} /> : <Copy size={14} />}
|
|
100
|
-
</button>
|
|
101
|
-
</div>
|
|
102
|
-
<div className="playground-panel-content playground-editor">
|
|
103
|
-
<LiveEditor disabled={readonly} onChange={setActiveCode} />
|
|
104
|
-
</div>
|
|
105
|
-
</div>
|
|
106
|
-
|
|
107
|
-
{/* Preview Side */}
|
|
108
|
-
<div className="playground-panel playground-preview-panel">
|
|
109
|
-
<div className="playground-panel-header">
|
|
110
|
-
<div className="playground-panel-title">
|
|
111
|
-
<Play size={14} />
|
|
112
|
-
<span>Preview</span>
|
|
113
|
-
</div>
|
|
114
|
-
</div>
|
|
115
|
-
<div className="playground-panel-content playground-preview">
|
|
116
|
-
<LivePreview />
|
|
117
|
-
<LiveError className="playground-error" />
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
</LiveProvider>
|
|
122
|
-
</div>
|
|
123
|
-
);
|
|
124
|
-
}
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { LiveProvider, LiveEditor, LiveError, LivePreview } from "react-live";
|
|
3
|
+
import { Copy, Check, Terminal, Play } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
interface PlaygroundProps {
|
|
6
|
+
code?: string;
|
|
7
|
+
children?: string | React.ReactNode;
|
|
8
|
+
scope?: Record<string, any>;
|
|
9
|
+
readonly?: boolean;
|
|
10
|
+
noInline?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Transforms code that uses `export default` into a format compatible
|
|
15
|
+
* with react-live's `noInline` mode by stripping the export and
|
|
16
|
+
* appending a `render(<ComponentName />)` call.
|
|
17
|
+
*/
|
|
18
|
+
function prepareCode(raw: string): { code: string; noInline: boolean } {
|
|
19
|
+
const trimmed = raw.trim();
|
|
20
|
+
|
|
21
|
+
// Match: export default function Name(...)
|
|
22
|
+
const fnMatch = trimmed.match(/export\s+default\s+function\s+(\w+)/);
|
|
23
|
+
if (fnMatch) {
|
|
24
|
+
const name = fnMatch[1];
|
|
25
|
+
const code =
|
|
26
|
+
trimmed.replace(/export\s+default\s+/, "") + `\n\nrender(<${name} />);`;
|
|
27
|
+
return { code, noInline: true };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Match: export default ComponentName (at the end)
|
|
31
|
+
const varMatch = trimmed.match(/export\s+default\s+(\w+)\s*;?\s*$/);
|
|
32
|
+
if (varMatch) {
|
|
33
|
+
const name = varMatch[1];
|
|
34
|
+
const code =
|
|
35
|
+
trimmed.replace(/export\s+default\s+\w+\s*;?\s*$/, "") +
|
|
36
|
+
`\nrender(<${name} />);`;
|
|
37
|
+
return { code, noInline: true };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// No export default — use inline mode (simple JSX expression)
|
|
41
|
+
return { code: trimmed, noInline: false };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* A live React playground component.
|
|
46
|
+
* Features a split layout with a live editor and a preview section.
|
|
47
|
+
*
|
|
48
|
+
* Supports `export default function App()` style code out of the box.
|
|
49
|
+
*/
|
|
50
|
+
export function Playground({
|
|
51
|
+
code,
|
|
52
|
+
children,
|
|
53
|
+
scope = {},
|
|
54
|
+
readonly = false,
|
|
55
|
+
noInline: forceNoInline,
|
|
56
|
+
}: PlaygroundProps) {
|
|
57
|
+
// Extract code from either `code` prop or `children`
|
|
58
|
+
let initialCode = code || "";
|
|
59
|
+
if (!initialCode && typeof children === "string") {
|
|
60
|
+
initialCode = children;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const prepared = prepareCode(initialCode);
|
|
64
|
+
const useNoInline = forceNoInline ?? prepared.noInline;
|
|
65
|
+
|
|
66
|
+
const [copied, setCopied] = useState(false);
|
|
67
|
+
const [activeCode, setActiveCode] = useState(prepared.code);
|
|
68
|
+
|
|
69
|
+
const handleCopy = () => {
|
|
70
|
+
navigator.clipboard.writeText(activeCode);
|
|
71
|
+
setCopied(true);
|
|
72
|
+
setTimeout(() => setCopied(false), 2000);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Provide React generically
|
|
76
|
+
const extendedScope = { React, ...scope };
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div className="boltdocs-playground" data-readonly={readonly}>
|
|
80
|
+
<LiveProvider
|
|
81
|
+
code={activeCode}
|
|
82
|
+
scope={extendedScope}
|
|
83
|
+
theme={undefined}
|
|
84
|
+
noInline={useNoInline}
|
|
85
|
+
>
|
|
86
|
+
<div className="playground-split-container">
|
|
87
|
+
{/* Editor Side */}
|
|
88
|
+
<div className="playground-panel playground-editor-panel">
|
|
89
|
+
<div className="playground-panel-header">
|
|
90
|
+
<div className="playground-panel-title">
|
|
91
|
+
<Terminal size={14} />
|
|
92
|
+
<span>{readonly ? "Code Example" : "Live Editor"}</span>
|
|
93
|
+
</div>
|
|
94
|
+
<button
|
|
95
|
+
className="playground-copy-btn"
|
|
96
|
+
onClick={handleCopy}
|
|
97
|
+
title="Copy code"
|
|
98
|
+
>
|
|
99
|
+
{copied ? <Check size={14} /> : <Copy size={14} />}
|
|
100
|
+
</button>
|
|
101
|
+
</div>
|
|
102
|
+
<div className="playground-panel-content playground-editor">
|
|
103
|
+
<LiveEditor disabled={readonly} onChange={setActiveCode} />
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
{/* Preview Side */}
|
|
108
|
+
<div className="playground-panel playground-preview-panel">
|
|
109
|
+
<div className="playground-panel-header">
|
|
110
|
+
<div className="playground-panel-title">
|
|
111
|
+
<Play size={14} />
|
|
112
|
+
<span>Preview</span>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
<div className="playground-panel-content playground-preview">
|
|
116
|
+
<LivePreview />
|
|
117
|
+
<LiveError className="playground-error" />
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
</LiveProvider>
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { Playground } from "./Playground";
|
|
1
|
+
export { Playground } from "./Playground";
|
|
@@ -1,168 +1,168 @@
|
|
|
1
|
-
/* ═══════════════════════════════════════════════════════════
|
|
2
|
-
PLAYGROUND (SPLIT UI)
|
|
3
|
-
═══════════════════════════════════════════════════════════ */
|
|
4
|
-
.boltdocs-playground {
|
|
5
|
-
display: flex;
|
|
6
|
-
flex-direction: column;
|
|
7
|
-
margin: 2rem 0;
|
|
8
|
-
border-radius: var(--ld-radius-lg);
|
|
9
|
-
border: 1px solid var(--ld-border-subtle);
|
|
10
|
-
background: var(--ld-code-bg);
|
|
11
|
-
overflow: hidden;
|
|
12
|
-
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
|
13
|
-
backdrop-filter: blur(10px);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.playground-split-container {
|
|
17
|
-
display: flex;
|
|
18
|
-
flex-direction: column;
|
|
19
|
-
width: 100%;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
@media (min-width: 1024px) {
|
|
23
|
-
.playground-split-container {
|
|
24
|
-
flex-direction: row;
|
|
25
|
-
min-height: 350px;
|
|
26
|
-
align-items: stretch;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.playground-panel {
|
|
31
|
-
display: flex;
|
|
32
|
-
flex-direction: column;
|
|
33
|
-
flex: 1;
|
|
34
|
-
min-width: 0;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.playground-editor-panel {
|
|
38
|
-
border-bottom: 1px solid var(--ld-border-subtle);
|
|
39
|
-
background: var(--ld-code-bg);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
@media (min-width: 1024px) {
|
|
43
|
-
.playground-editor-panel {
|
|
44
|
-
border-bottom: none;
|
|
45
|
-
border-right: 1px solid var(--ld-border-subtle);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.playground-preview-panel {
|
|
50
|
-
background: var(--ld-bg-mute);
|
|
51
|
-
position: relative;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/* Header */
|
|
55
|
-
.playground-panel-header {
|
|
56
|
-
display: flex;
|
|
57
|
-
align-items: center;
|
|
58
|
-
justify-content: space-between;
|
|
59
|
-
padding: 0.5rem 1rem;
|
|
60
|
-
border-bottom: 1px solid var(--ld-border-subtle);
|
|
61
|
-
background: rgba(0, 0, 0, 0.1);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.playground-panel-title {
|
|
65
|
-
display: flex;
|
|
66
|
-
align-items: center;
|
|
67
|
-
gap: 0.5rem;
|
|
68
|
-
font-size: 0.75rem;
|
|
69
|
-
font-weight: 600;
|
|
70
|
-
color: var(--ld-text-muted);
|
|
71
|
-
text-transform: uppercase;
|
|
72
|
-
letter-spacing: 0.05em;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/* Copy Button */
|
|
76
|
-
.playground-copy-btn {
|
|
77
|
-
background: transparent;
|
|
78
|
-
border: none;
|
|
79
|
-
color: var(--ld-text-muted);
|
|
80
|
-
cursor: pointer;
|
|
81
|
-
padding: 0.25rem;
|
|
82
|
-
border-radius: var(--ld-radius-sm);
|
|
83
|
-
display: flex;
|
|
84
|
-
align-items: center;
|
|
85
|
-
justify-content: center;
|
|
86
|
-
transition: all 0.2s;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.playground-copy-btn:hover {
|
|
90
|
-
background: rgba(255, 255, 255, 0.1);
|
|
91
|
-
color: var(--ld-text-main);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/* Content Area */
|
|
95
|
-
.playground-panel-content {
|
|
96
|
-
flex: 1;
|
|
97
|
-
overflow: auto;
|
|
98
|
-
position: relative;
|
|
99
|
-
display: flex;
|
|
100
|
-
flex-direction: column;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/* Editor Specifics */
|
|
104
|
-
.playground-editor {
|
|
105
|
-
background: transparent;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
.playground-editor > div {
|
|
109
|
-
font-family: var(--ld-font-mono) !important;
|
|
110
|
-
font-size: 0.85rem !important;
|
|
111
|
-
line-height: 1.5 !important;
|
|
112
|
-
min-height: 100%;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.playground-editor pre {
|
|
116
|
-
padding: 1.5rem !important;
|
|
117
|
-
margin: 0 !important;
|
|
118
|
-
background: transparent !important;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.playground-editor textarea {
|
|
122
|
-
outline: none !important;
|
|
123
|
-
padding: 1.5rem !important;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/* Prevent editing styles if read-only */
|
|
127
|
-
.boltdocs-playground[data-readonly="true"] .playground-editor textarea {
|
|
128
|
-
cursor: default !important;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/* Preview Specifics */
|
|
132
|
-
.playground-preview {
|
|
133
|
-
padding: 2rem;
|
|
134
|
-
display: flex;
|
|
135
|
-
align-items: center;
|
|
136
|
-
justify-content: center;
|
|
137
|
-
background-color: var(--ld-bg-mute);
|
|
138
|
-
background-image: radial-gradient(
|
|
139
|
-
var(--ld-border-subtle) 1.5px,
|
|
140
|
-
transparent 1.5px
|
|
141
|
-
);
|
|
142
|
-
background-size: 24px 24px;
|
|
143
|
-
color: var(--ld-text-main);
|
|
144
|
-
min-height: 200px;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/* Error Specifics */
|
|
148
|
-
.playground-error {
|
|
149
|
-
margin: 0;
|
|
150
|
-
padding: 1rem;
|
|
151
|
-
background: #7f1d1d;
|
|
152
|
-
color: #fca5a5;
|
|
153
|
-
font-size: 0.8rem;
|
|
154
|
-
font-family: var(--ld-font-mono);
|
|
155
|
-
white-space: pre-wrap;
|
|
156
|
-
border-top: 1px solid #991b1b;
|
|
157
|
-
z-index: 10;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/* Loading Skeleton */
|
|
161
|
-
.playground-skeleton {
|
|
162
|
-
height: 350px;
|
|
163
|
-
background: var(--ld-bg-mute);
|
|
164
|
-
border-radius: var(--ld-radius-lg);
|
|
165
|
-
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
166
|
-
margin: 2rem 0;
|
|
167
|
-
border: 1px solid var(--ld-border-subtle);
|
|
168
|
-
}
|
|
1
|
+
/* ═══════════════════════════════════════════════════════════
|
|
2
|
+
PLAYGROUND (SPLIT UI)
|
|
3
|
+
═══════════════════════════════════════════════════════════ */
|
|
4
|
+
.boltdocs-playground {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
margin: 2rem 0;
|
|
8
|
+
border-radius: var(--ld-radius-lg);
|
|
9
|
+
border: 1px solid var(--ld-border-subtle);
|
|
10
|
+
background: var(--ld-code-bg);
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
|
13
|
+
backdrop-filter: blur(10px);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.playground-split-container {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
width: 100%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@media (min-width: 1024px) {
|
|
23
|
+
.playground-split-container {
|
|
24
|
+
flex-direction: row;
|
|
25
|
+
min-height: 350px;
|
|
26
|
+
align-items: stretch;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.playground-panel {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
flex: 1;
|
|
34
|
+
min-width: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.playground-editor-panel {
|
|
38
|
+
border-bottom: 1px solid var(--ld-border-subtle);
|
|
39
|
+
background: var(--ld-code-bg);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@media (min-width: 1024px) {
|
|
43
|
+
.playground-editor-panel {
|
|
44
|
+
border-bottom: none;
|
|
45
|
+
border-right: 1px solid var(--ld-border-subtle);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.playground-preview-panel {
|
|
50
|
+
background: var(--ld-bg-mute);
|
|
51
|
+
position: relative;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Header */
|
|
55
|
+
.playground-panel-header {
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: space-between;
|
|
59
|
+
padding: 0.5rem 1rem;
|
|
60
|
+
border-bottom: 1px solid var(--ld-border-subtle);
|
|
61
|
+
background: rgba(0, 0, 0, 0.1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.playground-panel-title {
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: 0.5rem;
|
|
68
|
+
font-size: 0.75rem;
|
|
69
|
+
font-weight: 600;
|
|
70
|
+
color: var(--ld-text-muted);
|
|
71
|
+
text-transform: uppercase;
|
|
72
|
+
letter-spacing: 0.05em;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* Copy Button */
|
|
76
|
+
.playground-copy-btn {
|
|
77
|
+
background: transparent;
|
|
78
|
+
border: none;
|
|
79
|
+
color: var(--ld-text-muted);
|
|
80
|
+
cursor: pointer;
|
|
81
|
+
padding: 0.25rem;
|
|
82
|
+
border-radius: var(--ld-radius-sm);
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
transition: all 0.2s;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.playground-copy-btn:hover {
|
|
90
|
+
background: rgba(255, 255, 255, 0.1);
|
|
91
|
+
color: var(--ld-text-main);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Content Area */
|
|
95
|
+
.playground-panel-content {
|
|
96
|
+
flex: 1;
|
|
97
|
+
overflow: auto;
|
|
98
|
+
position: relative;
|
|
99
|
+
display: flex;
|
|
100
|
+
flex-direction: column;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Editor Specifics */
|
|
104
|
+
.playground-editor {
|
|
105
|
+
background: transparent;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.playground-editor > div {
|
|
109
|
+
font-family: var(--ld-font-mono) !important;
|
|
110
|
+
font-size: 0.85rem !important;
|
|
111
|
+
line-height: 1.5 !important;
|
|
112
|
+
min-height: 100%;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.playground-editor pre {
|
|
116
|
+
padding: 1.5rem !important;
|
|
117
|
+
margin: 0 !important;
|
|
118
|
+
background: transparent !important;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.playground-editor textarea {
|
|
122
|
+
outline: none !important;
|
|
123
|
+
padding: 1.5rem !important;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Prevent editing styles if read-only */
|
|
127
|
+
.boltdocs-playground[data-readonly="true"] .playground-editor textarea {
|
|
128
|
+
cursor: default !important;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* Preview Specifics */
|
|
132
|
+
.playground-preview {
|
|
133
|
+
padding: 2rem;
|
|
134
|
+
display: flex;
|
|
135
|
+
align-items: center;
|
|
136
|
+
justify-content: center;
|
|
137
|
+
background-color: var(--ld-bg-mute);
|
|
138
|
+
background-image: radial-gradient(
|
|
139
|
+
var(--ld-border-subtle) 1.5px,
|
|
140
|
+
transparent 1.5px
|
|
141
|
+
);
|
|
142
|
+
background-size: 24px 24px;
|
|
143
|
+
color: var(--ld-text-main);
|
|
144
|
+
min-height: 200px;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Error Specifics */
|
|
148
|
+
.playground-error {
|
|
149
|
+
margin: 0;
|
|
150
|
+
padding: 1rem;
|
|
151
|
+
background: #7f1d1d;
|
|
152
|
+
color: #fca5a5;
|
|
153
|
+
font-size: 0.8rem;
|
|
154
|
+
font-family: var(--ld-font-mono);
|
|
155
|
+
white-space: pre-wrap;
|
|
156
|
+
border-top: 1px solid #991b1b;
|
|
157
|
+
z-index: 10;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* Loading Skeleton */
|
|
161
|
+
.playground-skeleton {
|
|
162
|
+
height: 350px;
|
|
163
|
+
background: var(--ld-bg-mute);
|
|
164
|
+
border-radius: var(--ld-radius-lg);
|
|
165
|
+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
166
|
+
margin: 2rem 0;
|
|
167
|
+
border: 1px solid var(--ld-border-subtle);
|
|
168
|
+
}
|