boltdocs 1.10.2 → 1.11.0
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 +29 -7
- package/src/client/app/config-context.tsx +18 -0
- package/src/client/app/docs-layout.tsx +14 -0
- package/src/client/app/index.tsx +132 -260
- package/src/client/app/mdx-component.tsx +52 -0
- package/src/client/app/mdx-components-context.tsx +23 -0
- package/src/client/app/mdx-page.tsx +20 -0
- package/src/client/app/preload.tsx +38 -30
- package/src/client/app/router.tsx +30 -0
- package/src/client/app/scroll-handler.tsx +40 -0
- package/src/client/app/theme-context.tsx +75 -0
- package/src/client/components/default-layout.tsx +80 -0
- package/src/client/components/docs-layout.tsx +105 -0
- package/src/client/components/icons-dev.tsx +74 -0
- package/src/client/components/mdx/admonition.tsx +107 -0
- package/src/client/components/mdx/badge.tsx +41 -0
- package/src/client/components/mdx/button.tsx +35 -0
- package/src/client/components/mdx/card.tsx +124 -0
- package/src/client/components/mdx/code-block.tsx +119 -0
- package/src/client/components/mdx/component-preview.tsx +47 -0
- package/src/client/components/mdx/component-props.tsx +83 -0
- package/src/client/components/mdx/field.tsx +66 -0
- package/src/client/components/mdx/file-tree.tsx +287 -0
- package/src/client/components/mdx/hooks/use-code-block.ts +56 -0
- package/src/client/components/mdx/hooks/use-component-preview.ts +16 -0
- package/src/client/components/mdx/hooks/useTable.ts +74 -0
- package/src/client/components/mdx/hooks/useTabs.ts +68 -0
- package/src/client/components/mdx/image.tsx +23 -0
- package/src/client/components/mdx/index.ts +53 -0
- package/src/client/components/mdx/link.tsx +38 -0
- package/src/client/components/mdx/list.tsx +192 -0
- package/src/client/components/mdx/table.tsx +156 -0
- package/src/client/components/mdx/tabs.tsx +135 -0
- package/src/client/components/mdx/video.tsx +68 -0
- package/src/client/components/primitives/breadcrumbs.tsx +79 -0
- package/src/client/components/primitives/button-group.tsx +54 -0
- package/src/client/components/primitives/button.tsx +145 -0
- package/src/client/components/primitives/helpers/observer.ts +120 -0
- package/src/client/components/primitives/index.ts +17 -0
- package/src/client/components/primitives/link.tsx +122 -0
- package/src/client/components/primitives/menu.tsx +159 -0
- package/src/client/components/primitives/navbar.tsx +359 -0
- package/src/client/components/primitives/navigation-menu.tsx +116 -0
- package/src/client/components/primitives/on-this-page.tsx +461 -0
- package/src/client/components/primitives/page-nav.tsx +87 -0
- package/src/client/components/primitives/popover.tsx +47 -0
- package/src/client/components/primitives/search-dialog.tsx +183 -0
- package/src/client/components/primitives/sidebar.tsx +154 -0
- package/src/client/components/primitives/tabs.tsx +90 -0
- package/src/client/components/primitives/tooltip.tsx +83 -0
- package/src/client/components/primitives/types.ts +11 -0
- package/src/client/components/ui-base/breadcrumbs.tsx +42 -0
- package/src/client/components/ui-base/copy-markdown.tsx +112 -0
- package/src/client/components/ui-base/error-boundary.tsx +52 -0
- package/src/client/components/ui-base/github-stars.tsx +27 -0
- package/src/client/components/ui-base/head.tsx +69 -0
- package/src/client/components/ui-base/loading.tsx +87 -0
- package/src/client/components/ui-base/navbar.tsx +138 -0
- package/src/client/components/ui-base/not-found.tsx +24 -0
- package/src/client/components/ui-base/on-this-page.tsx +152 -0
- package/src/client/components/ui-base/page-nav.tsx +39 -0
- package/src/client/components/ui-base/powered-by.tsx +19 -0
- package/src/client/components/ui-base/progress-bar.tsx +67 -0
- package/src/client/components/ui-base/search-dialog.tsx +82 -0
- package/src/client/components/ui-base/sidebar.tsx +104 -0
- package/src/client/components/ui-base/tabs.tsx +65 -0
- package/src/client/components/ui-base/theme-toggle.tsx +32 -0
- package/src/client/hooks/index.ts +12 -0
- package/src/client/hooks/use-breadcrumbs.ts +22 -0
- package/src/client/hooks/use-i18n.ts +84 -0
- package/src/client/hooks/use-localized-to.ts +95 -0
- package/src/client/hooks/use-location.ts +5 -0
- package/src/client/hooks/use-navbar.ts +60 -0
- package/src/client/hooks/use-onthispage.ts +23 -0
- package/src/client/hooks/use-page-nav.ts +22 -0
- package/src/client/hooks/use-routes.ts +72 -0
- package/src/client/hooks/use-search.ts +71 -0
- package/src/client/hooks/use-sidebar.ts +49 -0
- package/src/client/hooks/use-tabs.ts +43 -0
- package/src/client/hooks/use-version.ts +78 -0
- package/src/client/index.ts +55 -17
- package/src/client/integrations/codesandbox.ts +179 -0
- package/src/client/ssr.tsx +27 -16
- package/src/client/theme/neutral.css +360 -0
- package/src/client/types.ts +131 -27
- package/src/client/utils/cn.ts +6 -0
- package/src/client/utils/copy-clipboard.ts +22 -0
- package/src/client/utils/get-base-file-path.ts +21 -0
- package/src/client/utils/github.ts +121 -0
- package/src/client/utils/use-on-change.ts +15 -0
- package/src/client/virtual.d.ts +24 -0
- package/src/node/cache.ts +156 -156
- package/src/node/config.ts +159 -103
- package/src/node/index.ts +13 -13
- package/src/node/mdx.ts +213 -61
- package/src/node/plugin/entry.ts +29 -18
- package/src/node/plugin/html.ts +11 -11
- package/src/node/plugin/index.ts +161 -83
- package/src/node/plugin/types.ts +2 -4
- package/src/node/routes/cache.ts +6 -6
- package/src/node/routes/index.ts +206 -113
- package/src/node/routes/parser.ts +106 -81
- package/src/node/routes/sorter.ts +15 -15
- package/src/node/routes/types.ts +24 -24
- package/src/node/ssg/index.ts +46 -46
- package/src/node/ssg/meta.ts +4 -4
- package/src/node/ssg/options.ts +5 -5
- package/src/node/ssg/sitemap.ts +14 -14
- package/src/node/utils.ts +31 -31
- package/tsconfig.json +25 -20
- package/tsup.config.ts +23 -14
- package/dist/PackageManagerTabs-NVT7G625.mjs +0 -99
- package/dist/SearchDialog-AGVF6JBO.mjs +0 -194
- package/dist/SearchDialog-YPDOM7Q6.css +0 -2847
- package/dist/Video-KNTY5BNO.mjs +0 -6
- package/dist/cache-KNL5B4EE.mjs +0 -12
- package/dist/chunk-7SFUJWTB.mjs +0 -211
- package/dist/chunk-FFBNU6IJ.mjs +0 -386
- package/dist/chunk-FMTOYQLO.mjs +0 -37
- package/dist/chunk-TKLQWU7H.mjs +0 -1920
- package/dist/chunk-Z7JHYNAS.mjs +0 -57
- package/dist/client/index.css +0 -2847
- package/dist/client/index.d.mts +0 -372
- package/dist/client/index.d.ts +0 -372
- package/dist/client/index.js +0 -3630
- package/dist/client/index.mjs +0 -697
- package/dist/client/ssr.css +0 -2847
- package/dist/client/ssr.d.mts +0 -27
- package/dist/client/ssr.d.ts +0 -27
- package/dist/client/ssr.js +0 -2928
- package/dist/client/ssr.mjs +0 -33
- package/dist/config-BsFQ-ErD.d.mts +0 -159
- package/dist/config-BsFQ-ErD.d.ts +0 -159
- package/dist/node/index.d.mts +0 -91
- package/dist/node/index.d.ts +0 -91
- package/dist/node/index.js +0 -1187
- package/dist/node/index.mjs +0 -762
- package/dist/types-Dj-bfnC3.d.mts +0 -74
- package/dist/types-Dj-bfnC3.d.ts +0 -74
- package/src/client/theme/components/CodeBlock/CodeBlock.tsx +0 -61
- package/src/client/theme/components/CodeBlock/index.ts +0 -1
- package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +0 -131
- package/src/client/theme/components/PackageManagerTabs/index.ts +0 -1
- package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +0 -64
- package/src/client/theme/components/Playground/Playground.tsx +0 -180
- package/src/client/theme/components/Playground/index.ts +0 -1
- package/src/client/theme/components/Playground/playground.css +0 -238
- package/src/client/theme/components/Video/Video.tsx +0 -84
- package/src/client/theme/components/Video/index.ts +0 -1
- package/src/client/theme/components/Video/video.css +0 -41
- package/src/client/theme/components/mdx/Admonition.tsx +0 -80
- package/src/client/theme/components/mdx/Badge.tsx +0 -31
- package/src/client/theme/components/mdx/Button.tsx +0 -50
- package/src/client/theme/components/mdx/Card.tsx +0 -80
- package/src/client/theme/components/mdx/Field.tsx +0 -60
- package/src/client/theme/components/mdx/FileTree.tsx +0 -229
- package/src/client/theme/components/mdx/List.tsx +0 -57
- package/src/client/theme/components/mdx/Table.tsx +0 -151
- package/src/client/theme/components/mdx/Tabs.tsx +0 -123
- package/src/client/theme/components/mdx/index.ts +0 -27
- package/src/client/theme/components/mdx/mdx-components.css +0 -764
- package/src/client/theme/icons/bun.tsx +0 -62
- package/src/client/theme/icons/deno.tsx +0 -20
- package/src/client/theme/icons/discord.tsx +0 -12
- package/src/client/theme/icons/github.tsx +0 -15
- package/src/client/theme/icons/npm.tsx +0 -13
- package/src/client/theme/icons/pnpm.tsx +0 -72
- package/src/client/theme/icons/twitter.tsx +0 -12
- package/src/client/theme/styles/markdown.css +0 -394
- package/src/client/theme/styles/variables.css +0 -175
- package/src/client/theme/styles.css +0 -39
- package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +0 -68
- package/src/client/theme/ui/Breadcrumbs/index.ts +0 -1
- package/src/client/theme/ui/CopyMarkdown/CopyMarkdown.tsx +0 -82
- package/src/client/theme/ui/CopyMarkdown/copy-markdown.css +0 -112
- package/src/client/theme/ui/CopyMarkdown/index.ts +0 -1
- package/src/client/theme/ui/ErrorBoundary/ErrorBoundary.tsx +0 -50
- package/src/client/theme/ui/ErrorBoundary/error-boundary.css +0 -55
- package/src/client/theme/ui/ErrorBoundary/index.ts +0 -1
- package/src/client/theme/ui/Footer/footer.css +0 -32
- package/src/client/theme/ui/Head/Head.tsx +0 -69
- package/src/client/theme/ui/Head/index.ts +0 -1
- package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +0 -125
- package/src/client/theme/ui/LanguageSwitcher/index.ts +0 -1
- package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +0 -98
- package/src/client/theme/ui/Layout/Layout.tsx +0 -203
- package/src/client/theme/ui/Layout/base.css +0 -106
- package/src/client/theme/ui/Layout/index.ts +0 -2
- package/src/client/theme/ui/Layout/pagination.css +0 -72
- package/src/client/theme/ui/Layout/responsive.css +0 -47
- package/src/client/theme/ui/Link/Link.tsx +0 -392
- package/src/client/theme/ui/Link/LinkPreview.tsx +0 -59
- package/src/client/theme/ui/Link/index.ts +0 -2
- package/src/client/theme/ui/Link/link-preview.css +0 -48
- package/src/client/theme/ui/Loading/Loading.tsx +0 -10
- package/src/client/theme/ui/Loading/index.ts +0 -1
- package/src/client/theme/ui/Loading/loading.css +0 -30
- package/src/client/theme/ui/Navbar/GithubStars.tsx +0 -27
- package/src/client/theme/ui/Navbar/Navbar.tsx +0 -193
- package/src/client/theme/ui/Navbar/Tabs.tsx +0 -99
- package/src/client/theme/ui/Navbar/index.ts +0 -2
- package/src/client/theme/ui/Navbar/navbar.css +0 -347
- package/src/client/theme/ui/NotFound/NotFound.tsx +0 -19
- package/src/client/theme/ui/NotFound/index.ts +0 -1
- package/src/client/theme/ui/NotFound/not-found.css +0 -64
- package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +0 -244
- package/src/client/theme/ui/OnThisPage/index.ts +0 -1
- package/src/client/theme/ui/OnThisPage/toc.css +0 -152
- package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +0 -18
- package/src/client/theme/ui/PoweredBy/index.ts +0 -1
- package/src/client/theme/ui/PoweredBy/powered-by.css +0 -76
- package/src/client/theme/ui/ProgressBar/ProgressBar.css +0 -17
- package/src/client/theme/ui/ProgressBar/ProgressBar.tsx +0 -51
- package/src/client/theme/ui/ProgressBar/index.ts +0 -1
- package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +0 -209
- package/src/client/theme/ui/SearchDialog/index.ts +0 -1
- package/src/client/theme/ui/SearchDialog/search.css +0 -152
- package/src/client/theme/ui/Sidebar/Sidebar.tsx +0 -244
- package/src/client/theme/ui/Sidebar/index.ts +0 -1
- package/src/client/theme/ui/Sidebar/sidebar.css +0 -230
- package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +0 -69
- package/src/client/theme/ui/ThemeToggle/index.ts +0 -1
- package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +0 -136
- package/src/client/theme/ui/VersionSwitcher/index.ts +0 -1
- package/src/client/utils.ts +0 -49
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Metadata provided by the server for a specific route.
|
|
5
|
-
* Maps closely to the `RouteMeta` type in the Node environment.
|
|
6
|
-
*/
|
|
7
|
-
interface ComponentRoute {
|
|
8
|
-
/** The final URL path */
|
|
9
|
-
path: string;
|
|
10
|
-
/** The absolute filesystem path of the source file */
|
|
11
|
-
componentPath: string;
|
|
12
|
-
/** The page title */
|
|
13
|
-
title: string;
|
|
14
|
-
/** Explicit order in the sidebar */
|
|
15
|
-
sidebarPosition?: number;
|
|
16
|
-
/** The relative path from the docs directory */
|
|
17
|
-
filePath: string;
|
|
18
|
-
/** The group directory name */
|
|
19
|
-
group?: string;
|
|
20
|
-
/** The display title of the group */
|
|
21
|
-
groupTitle?: string;
|
|
22
|
-
/** Explicit order of the group in the sidebar */
|
|
23
|
-
groupPosition?: number;
|
|
24
|
-
/** Extracted markdown headings for search indexing */
|
|
25
|
-
headings?: {
|
|
26
|
-
level: number;
|
|
27
|
-
text: string;
|
|
28
|
-
id: string;
|
|
29
|
-
}[];
|
|
30
|
-
/** The page summary or description */
|
|
31
|
-
description?: string;
|
|
32
|
-
/** The locale this route belongs to, if i18n is configured */
|
|
33
|
-
locale?: string;
|
|
34
|
-
/** The version this route belongs to, if versioning is configured */
|
|
35
|
-
version?: string;
|
|
36
|
-
/** Optional icon to display (Lucide icon name or raw SVG) */
|
|
37
|
-
icon?: string;
|
|
38
|
-
/** The tab this route belongs to, if tabs are configured */
|
|
39
|
-
tab?: string;
|
|
40
|
-
/** Optional badge to display next to the sidebar item */
|
|
41
|
-
badge?: string | {
|
|
42
|
-
text: string;
|
|
43
|
-
expires?: string;
|
|
44
|
-
};
|
|
45
|
-
/** Optional icon for the route's group */
|
|
46
|
-
groupIcon?: string;
|
|
47
|
-
/** The extracted plain-text content of the page for search indexing */
|
|
48
|
-
_content?: string;
|
|
49
|
-
/** The raw markdown content of the page */
|
|
50
|
-
_rawContent?: string;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Configuration options for initializing the Boltdocs client app.
|
|
54
|
-
*/
|
|
55
|
-
interface CreateBoltdocsAppOptions {
|
|
56
|
-
/** CSS selector for the DOM element where the app should mount (e.g. '#root') */
|
|
57
|
-
target: string;
|
|
58
|
-
/** Initial routes generated by the Vite plugin (`virtual:boltdocs-routes`) */
|
|
59
|
-
routes: ComponentRoute[];
|
|
60
|
-
/** The name of the documentation directory (e.g. 'docs') */
|
|
61
|
-
docsDirName: string;
|
|
62
|
-
/** Site configuration (`virtual:boltdocs-config`) */
|
|
63
|
-
config: any;
|
|
64
|
-
/** Dynamic import mapping from `import.meta.glob` for the documentation pages */
|
|
65
|
-
modules: Record<string, () => Promise<any>>;
|
|
66
|
-
/** The `import.meta.hot` instance necessary for fast refresh/HMR updates */
|
|
67
|
-
hot?: any;
|
|
68
|
-
/** Optional custom React component to render when visiting the root path ('/') */
|
|
69
|
-
homePage?: React.ComponentType;
|
|
70
|
-
/** Optional custom MDX components provided by plugins */
|
|
71
|
-
components?: Record<string, React.ComponentType<any>>;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export type { CreateBoltdocsAppOptions as C, ComponentRoute as a };
|
package/dist/types-Dj-bfnC3.d.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Metadata provided by the server for a specific route.
|
|
5
|
-
* Maps closely to the `RouteMeta` type in the Node environment.
|
|
6
|
-
*/
|
|
7
|
-
interface ComponentRoute {
|
|
8
|
-
/** The final URL path */
|
|
9
|
-
path: string;
|
|
10
|
-
/** The absolute filesystem path of the source file */
|
|
11
|
-
componentPath: string;
|
|
12
|
-
/** The page title */
|
|
13
|
-
title: string;
|
|
14
|
-
/** Explicit order in the sidebar */
|
|
15
|
-
sidebarPosition?: number;
|
|
16
|
-
/** The relative path from the docs directory */
|
|
17
|
-
filePath: string;
|
|
18
|
-
/** The group directory name */
|
|
19
|
-
group?: string;
|
|
20
|
-
/** The display title of the group */
|
|
21
|
-
groupTitle?: string;
|
|
22
|
-
/** Explicit order of the group in the sidebar */
|
|
23
|
-
groupPosition?: number;
|
|
24
|
-
/** Extracted markdown headings for search indexing */
|
|
25
|
-
headings?: {
|
|
26
|
-
level: number;
|
|
27
|
-
text: string;
|
|
28
|
-
id: string;
|
|
29
|
-
}[];
|
|
30
|
-
/** The page summary or description */
|
|
31
|
-
description?: string;
|
|
32
|
-
/** The locale this route belongs to, if i18n is configured */
|
|
33
|
-
locale?: string;
|
|
34
|
-
/** The version this route belongs to, if versioning is configured */
|
|
35
|
-
version?: string;
|
|
36
|
-
/** Optional icon to display (Lucide icon name or raw SVG) */
|
|
37
|
-
icon?: string;
|
|
38
|
-
/** The tab this route belongs to, if tabs are configured */
|
|
39
|
-
tab?: string;
|
|
40
|
-
/** Optional badge to display next to the sidebar item */
|
|
41
|
-
badge?: string | {
|
|
42
|
-
text: string;
|
|
43
|
-
expires?: string;
|
|
44
|
-
};
|
|
45
|
-
/** Optional icon for the route's group */
|
|
46
|
-
groupIcon?: string;
|
|
47
|
-
/** The extracted plain-text content of the page for search indexing */
|
|
48
|
-
_content?: string;
|
|
49
|
-
/** The raw markdown content of the page */
|
|
50
|
-
_rawContent?: string;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Configuration options for initializing the Boltdocs client app.
|
|
54
|
-
*/
|
|
55
|
-
interface CreateBoltdocsAppOptions {
|
|
56
|
-
/** CSS selector for the DOM element where the app should mount (e.g. '#root') */
|
|
57
|
-
target: string;
|
|
58
|
-
/** Initial routes generated by the Vite plugin (`virtual:boltdocs-routes`) */
|
|
59
|
-
routes: ComponentRoute[];
|
|
60
|
-
/** The name of the documentation directory (e.g. 'docs') */
|
|
61
|
-
docsDirName: string;
|
|
62
|
-
/** Site configuration (`virtual:boltdocs-config`) */
|
|
63
|
-
config: any;
|
|
64
|
-
/** Dynamic import mapping from `import.meta.glob` for the documentation pages */
|
|
65
|
-
modules: Record<string, () => Promise<any>>;
|
|
66
|
-
/** The `import.meta.hot` instance necessary for fast refresh/HMR updates */
|
|
67
|
-
hot?: any;
|
|
68
|
-
/** Optional custom React component to render when visiting the root path ('/') */
|
|
69
|
-
homePage?: React.ComponentType;
|
|
70
|
-
/** Optional custom MDX components provided by plugins */
|
|
71
|
-
components?: Record<string, React.ComponentType<any>>;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export type { CreateBoltdocsAppOptions as C, ComponentRoute as a };
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import React, { useState, useRef, useCallback } from "react";
|
|
2
|
-
import { Copy, Check } from "lucide-react";
|
|
3
|
-
import { copyToClipboard } from "../../../utils";
|
|
4
|
-
|
|
5
|
-
interface CodeBlockProps {
|
|
6
|
-
children?: React.ReactNode;
|
|
7
|
-
className?: string;
|
|
8
|
-
[key: string]: any;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* A specialized wrapper for code snippets compiled from MDX blocks.
|
|
13
|
-
* Provides syntax highlighting styling scaffolding and a "Copy to Clipboard" button.
|
|
14
|
-
*/
|
|
15
|
-
export function CodeBlock({ children, ...props }: CodeBlockProps) {
|
|
16
|
-
const [copied, setCopied] = useState(false);
|
|
17
|
-
const [isExpanded, setIsExpanded] = useState(false);
|
|
18
|
-
const [isExpandable, setIsExpandable] = useState(false);
|
|
19
|
-
const preRef = useRef<HTMLPreElement>(null);
|
|
20
|
-
|
|
21
|
-
const handleCopy = useCallback(async () => {
|
|
22
|
-
const code = preRef.current?.textContent || "";
|
|
23
|
-
copyToClipboard(code);
|
|
24
|
-
setCopied(true);
|
|
25
|
-
setTimeout(() => setCopied(false), 2000);
|
|
26
|
-
}, []);
|
|
27
|
-
|
|
28
|
-
React.useEffect(() => {
|
|
29
|
-
if (preRef.current) {
|
|
30
|
-
const codeLength = preRef.current.textContent?.length || 0;
|
|
31
|
-
setIsExpandable(codeLength > 500);
|
|
32
|
-
}
|
|
33
|
-
}, [children]);
|
|
34
|
-
|
|
35
|
-
const shouldTruncate = isExpandable && !isExpanded;
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<div className={`code-block-wrapper ${shouldTruncate ? "is-truncated" : ""}`}>
|
|
39
|
-
<button
|
|
40
|
-
className={`code-block-copy ${copied ? "copied" : ""}`}
|
|
41
|
-
onClick={handleCopy}
|
|
42
|
-
aria-label="Copy code"
|
|
43
|
-
>
|
|
44
|
-
{copied ? <Check size={16} /> : <Copy size={16} />}
|
|
45
|
-
</button>
|
|
46
|
-
<pre ref={preRef} {...props}>
|
|
47
|
-
{children}
|
|
48
|
-
</pre>
|
|
49
|
-
{isExpandable && (
|
|
50
|
-
<div className="code-block-expand-wrapper">
|
|
51
|
-
<button
|
|
52
|
-
className="code-block-expand-btn"
|
|
53
|
-
onClick={() => setIsExpanded(!isExpanded)}
|
|
54
|
-
>
|
|
55
|
-
{isExpanded ? "Show less" : "Expand code"}
|
|
56
|
-
</button>
|
|
57
|
-
</div>
|
|
58
|
-
)}
|
|
59
|
-
</div>
|
|
60
|
-
);
|
|
61
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { CodeBlock } from "./CodeBlock";
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { useState, useCallback } from "react";
|
|
2
|
-
import { Copy, Check } from "lucide-react";
|
|
3
|
-
import { NPM } from "../../icons/npm";
|
|
4
|
-
import { Pnpm } from "../../icons/pnpm";
|
|
5
|
-
import { Bun } from "../../icons/bun";
|
|
6
|
-
import { Deno } from "../../icons/deno";
|
|
7
|
-
import { copyToClipboard } from "../../../utils";
|
|
8
|
-
|
|
9
|
-
interface PackageManagerTabsProps {
|
|
10
|
-
command: string;
|
|
11
|
-
pkg?: string;
|
|
12
|
-
className?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
type PackageManager = "npm" | "pnpm" | "bun" | "deno";
|
|
16
|
-
|
|
17
|
-
const MANAGERS: {
|
|
18
|
-
id: PackageManager;
|
|
19
|
-
label: string;
|
|
20
|
-
icon: any;
|
|
21
|
-
}[] = [
|
|
22
|
-
{ id: "npm", label: "npm", icon: NPM },
|
|
23
|
-
{ id: "pnpm", label: "pnpm", icon: Pnpm },
|
|
24
|
-
{ id: "bun", label: "bun", icon: Bun },
|
|
25
|
-
{ id: "deno", label: "deno", icon: Deno },
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Returns the exact command for a specific package manager based on the action.
|
|
30
|
-
* Maps generic actions like 'install' to their specific permutations (e.g., yarn add, npm install).
|
|
31
|
-
*/
|
|
32
|
-
function getCommandForManager(
|
|
33
|
-
manager: PackageManager,
|
|
34
|
-
command: string,
|
|
35
|
-
pkg: string,
|
|
36
|
-
): string {
|
|
37
|
-
const isInstall =
|
|
38
|
-
command === "install" || command === "add" || command === "i";
|
|
39
|
-
const isCreate = command === "create" || command === "init";
|
|
40
|
-
const isRun = command === "run" || command === "exec";
|
|
41
|
-
|
|
42
|
-
// Installation commands
|
|
43
|
-
if (isInstall) {
|
|
44
|
-
const pkgArgs = pkg ? ` ${pkg}` : "";
|
|
45
|
-
if (manager === "npm") return `npm install${pkgArgs}`;
|
|
46
|
-
if (manager === "pnpm") return pkg ? `pnpm add${pkgArgs}` : `pnpm install`;
|
|
47
|
-
if (manager === "bun") return pkg ? `bun add${pkgArgs}` : `bun install`;
|
|
48
|
-
if (manager === "deno")
|
|
49
|
-
return pkg ? `deno install npm:${pkg}` : `deno install`;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Create/Init commands
|
|
53
|
-
if (isCreate) {
|
|
54
|
-
const pkgArgs = pkg ? ` ${pkg}` : "";
|
|
55
|
-
if (manager === "npm") return `npm create${pkgArgs}`;
|
|
56
|
-
if (manager === "pnpm") return `pnpm create${pkgArgs}`;
|
|
57
|
-
if (manager === "bun") return `bun create${pkgArgs}`;
|
|
58
|
-
if (manager === "deno") return `deno run -A npm:create-${pkg}`; // Approximation
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Run/Exec commands
|
|
62
|
-
if (isRun) {
|
|
63
|
-
const pkgArgs = pkg ? ` ${pkg}` : "";
|
|
64
|
-
if (manager === "npm") return `npm run${pkgArgs}`;
|
|
65
|
-
if (manager === "pnpm") return `pnpm run${pkgArgs}`;
|
|
66
|
-
if (manager === "bun") return `bun run${pkgArgs}`;
|
|
67
|
-
if (manager === "deno") return `deno task ${pkg}`;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Fallback: just prefix the manager
|
|
71
|
-
const pkgArgs = pkg ? ` ${pkg}` : "";
|
|
72
|
-
return `${manager} ${command}${pkgArgs}`;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function PackageManagerTabs({
|
|
76
|
-
command,
|
|
77
|
-
pkg = "",
|
|
78
|
-
className = "",
|
|
79
|
-
}: PackageManagerTabsProps) {
|
|
80
|
-
const [activeTab, setActiveTab] = useState<PackageManager>("npm");
|
|
81
|
-
const [copied, setCopied] = useState(false);
|
|
82
|
-
|
|
83
|
-
const activeCommand = getCommandForManager(activeTab, command, pkg);
|
|
84
|
-
|
|
85
|
-
const handleCopy = useCallback(async () => {
|
|
86
|
-
copyToClipboard(activeCommand);
|
|
87
|
-
setCopied(true);
|
|
88
|
-
setTimeout(() => setCopied(false), 2000);
|
|
89
|
-
}, [activeCommand]);
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<div className={`pkg-tabs-wrapper ${className}`}>
|
|
93
|
-
{/* Tab Headers */}
|
|
94
|
-
<div className="pkg-tabs-header">
|
|
95
|
-
{MANAGERS.map((mgr) => {
|
|
96
|
-
const Icon = mgr.icon;
|
|
97
|
-
const isActive = activeTab === mgr.id;
|
|
98
|
-
return (
|
|
99
|
-
<button
|
|
100
|
-
key={mgr.id}
|
|
101
|
-
className={`pkg-tab-btn ${isActive ? "active" : ""}`}
|
|
102
|
-
onClick={() => setActiveTab(mgr.id)}
|
|
103
|
-
aria-selected={isActive}
|
|
104
|
-
role="tab"
|
|
105
|
-
>
|
|
106
|
-
<Icon className="pkg-tab-icon" width="16" height="16" />
|
|
107
|
-
<span>{mgr.label}</span>
|
|
108
|
-
</button>
|
|
109
|
-
);
|
|
110
|
-
})}
|
|
111
|
-
</div>
|
|
112
|
-
|
|
113
|
-
{/* Code Block Content */}
|
|
114
|
-
<div className="code-block-wrapper pkg-tabs-content">
|
|
115
|
-
<button
|
|
116
|
-
className={`code-block-copy ${copied ? "copied" : ""}`}
|
|
117
|
-
onClick={handleCopy}
|
|
118
|
-
type="button"
|
|
119
|
-
aria-label="Copy code"
|
|
120
|
-
>
|
|
121
|
-
{copied ? <Check size={14} /> : <Copy size={14} />}
|
|
122
|
-
</button>
|
|
123
|
-
<pre>
|
|
124
|
-
<code>
|
|
125
|
-
<span className="line">{activeCommand}</span>
|
|
126
|
-
</code>
|
|
127
|
-
</pre>
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
);
|
|
131
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { PackageManagerTabs } from "./PackageManagerTabs";
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/* ═══════════════════════════════════════════════════════════
|
|
3
|
-
PACKAGE MANAGER TABS
|
|
4
|
-
═══════════════════════════════════════════════════════════ */
|
|
5
|
-
.pkg-tabs-wrapper {
|
|
6
|
-
margin: 1.5rem 0;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.pkg-tabs-header {
|
|
10
|
-
display: flex;
|
|
11
|
-
gap: 0.25rem;
|
|
12
|
-
overflow-x: auto;
|
|
13
|
-
padding-bottom: 0.5rem;
|
|
14
|
-
margin-bottom: -0.5rem; /* pull down to meet code block */
|
|
15
|
-
scrollbar-width: none;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
.pkg-tabs-header::-webkit-scrollbar {
|
|
19
|
-
display: none;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.pkg-tab-btn {
|
|
23
|
-
display: inline-flex;
|
|
24
|
-
align-items: center;
|
|
25
|
-
gap: 0.4rem;
|
|
26
|
-
padding: 0.5rem 1rem;
|
|
27
|
-
background-color: var(--ld-bg-soft);
|
|
28
|
-
border: 1px solid var(--ld-border-subtle);
|
|
29
|
-
border-bottom: none;
|
|
30
|
-
border-radius: var(--ld-radius-md) var(--ld-radius-md) 0 0;
|
|
31
|
-
color: var(--ld-text-muted);
|
|
32
|
-
font-family: var(--ld-font-sans);
|
|
33
|
-
font-size: 0.8125rem;
|
|
34
|
-
font-weight: 500;
|
|
35
|
-
cursor: pointer;
|
|
36
|
-
transition: all 0.2s;
|
|
37
|
-
opacity: 0.7;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.pkg-tab-btn:hover {
|
|
41
|
-
color: var(--ld-text-main);
|
|
42
|
-
background-color: var(--ld-bg-mute);
|
|
43
|
-
opacity: 1;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.pkg-tab-btn.active {
|
|
47
|
-
background-color: var(--ld-code-bg);
|
|
48
|
-
color: var(--ld-text-main);
|
|
49
|
-
border-color: var(--ld-border-subtle);
|
|
50
|
-
opacity: 1;
|
|
51
|
-
position: relative;
|
|
52
|
-
z-index: 2;
|
|
53
|
-
margin-bottom: -1px; /* Overlap border */
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.pkg-tab-icon {
|
|
57
|
-
display: inline-block;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/* Ensure tab content sits seamlessly below the tabs */
|
|
61
|
-
.pkg-tabs-content {
|
|
62
|
-
margin-top: 0 !important;
|
|
63
|
-
border-top-left-radius: 0 !important;
|
|
64
|
-
}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import React, { useState, useMemo } from "react";
|
|
2
|
-
import { LiveProvider, LiveEditor, LiveError, LivePreview } from "react-live";
|
|
3
|
-
import { Copy, Check, Terminal, Play } from "lucide-react";
|
|
4
|
-
import { CodeBlock } from "../CodeBlock";
|
|
5
|
-
|
|
6
|
-
interface PlaygroundProps {
|
|
7
|
-
code?: string;
|
|
8
|
-
children?: string | React.ReactNode;
|
|
9
|
-
preview?: React.ReactNode;
|
|
10
|
-
scope?: Record<string, any>;
|
|
11
|
-
readonly?: boolean;
|
|
12
|
-
noInline?: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Transforms code that uses `export default` into a format compatible
|
|
17
|
-
* with react-live's `noInline` mode by stripping the export and
|
|
18
|
-
* appending a `render(<ComponentName />)` call.
|
|
19
|
-
*/
|
|
20
|
-
function prepareCode(raw: string): { code: string; noInline: boolean } {
|
|
21
|
-
const trimmed = (raw || "").trim();
|
|
22
|
-
|
|
23
|
-
// Match: export default function Name(...)
|
|
24
|
-
const fnMatch = trimmed.match(/export\s+default\s+function\s+(\w+)/);
|
|
25
|
-
if (fnMatch) {
|
|
26
|
-
const name = fnMatch[1];
|
|
27
|
-
const code =
|
|
28
|
-
trimmed.replace(/export\s+default\s+/, "") + `\n\nrender(<${name} />);`;
|
|
29
|
-
return { code, noInline: true };
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Match: export default ComponentName (at the end)
|
|
33
|
-
const varMatch = trimmed.match(/export\s+default\s+(\w+)\s*;?\s*$/);
|
|
34
|
-
if (varMatch) {
|
|
35
|
-
const name = varMatch[1];
|
|
36
|
-
const code =
|
|
37
|
-
trimmed.replace(/export\s+default\s+\w+\s*;?\s*$/, "") +
|
|
38
|
-
`\nrender(<${name} />);`;
|
|
39
|
-
return { code, noInline: true };
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// No export default — use inline mode (simple JSX expression)
|
|
43
|
-
return { code: trimmed, noInline: false };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function Playground({
|
|
47
|
-
code: propsCode,
|
|
48
|
-
children,
|
|
49
|
-
preview,
|
|
50
|
-
scope = {},
|
|
51
|
-
readonly = false,
|
|
52
|
-
noInline: forceNoInline,
|
|
53
|
-
}: PlaygroundProps) {
|
|
54
|
-
// Extract code from either `code` prop or `children`
|
|
55
|
-
const initialCode = useMemo(() => {
|
|
56
|
-
let base = propsCode || "";
|
|
57
|
-
if (!base && typeof children === "string") {
|
|
58
|
-
base = children;
|
|
59
|
-
}
|
|
60
|
-
return base.trim();
|
|
61
|
-
}, [propsCode, children]);
|
|
62
|
-
|
|
63
|
-
const prepared = useMemo(() => prepareCode(initialCode), [initialCode]);
|
|
64
|
-
const useNoInline = forceNoInline ?? prepared.noInline;
|
|
65
|
-
|
|
66
|
-
const [copied, setCopied] = useState(false);
|
|
67
|
-
const [activeCode, setActiveCode] = useState(prepared.code);
|
|
68
|
-
const [isExpanded, setIsExpanded] = useState(false);
|
|
69
|
-
|
|
70
|
-
// Sync activeCode when initialCode changes (e.g. in static mode)
|
|
71
|
-
React.useEffect(() => {
|
|
72
|
-
setActiveCode(prepared.code);
|
|
73
|
-
}, [prepared.code]);
|
|
74
|
-
|
|
75
|
-
const handleCopy = () => {
|
|
76
|
-
const textToCopy = !!preview ? initialCode : activeCode;
|
|
77
|
-
navigator.clipboard.writeText(textToCopy);
|
|
78
|
-
setCopied(true);
|
|
79
|
-
setTimeout(() => setCopied(false), 2000);
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// Provide React generically
|
|
83
|
-
const extendedScope = { React, ...scope };
|
|
84
|
-
|
|
85
|
-
const charLimit = 800; // Adjust as needed
|
|
86
|
-
const isExpandable = (propsCode || initialCode).length > charLimit;
|
|
87
|
-
const shouldTruncate = isExpandable && !isExpanded;
|
|
88
|
-
|
|
89
|
-
const isStatic = !!preview;
|
|
90
|
-
|
|
91
|
-
// Transformer to prevent ReferenceError: require is not defined
|
|
92
|
-
// only used in static mode to allow highlighting without execution
|
|
93
|
-
const staticTransform = (code: string) => {
|
|
94
|
-
// Return empty or a simple dummy to avoid running the code
|
|
95
|
-
return "render(<div style={{display:'none'}} />)";
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
return (
|
|
99
|
-
<div className={`boltdocs-playground ${shouldTruncate ? "is-truncated" : ""}`} data-readonly={readonly || isStatic}>
|
|
100
|
-
<div className="playground-split-container">
|
|
101
|
-
{/* Preview Side - Now on top */}
|
|
102
|
-
<div className="playground-panel playground-preview-panel">
|
|
103
|
-
<div className="playground-panel-header">
|
|
104
|
-
<div className="playground-panel-title">
|
|
105
|
-
<Play size={14} />
|
|
106
|
-
<span>Preview</span>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
<div className="playground-panel-content playground-preview">
|
|
110
|
-
{isStatic ? (
|
|
111
|
-
preview
|
|
112
|
-
) : (
|
|
113
|
-
<LiveProvider
|
|
114
|
-
code={activeCode}
|
|
115
|
-
scope={extendedScope}
|
|
116
|
-
theme={undefined}
|
|
117
|
-
noInline={useNoInline}
|
|
118
|
-
>
|
|
119
|
-
<LivePreview />
|
|
120
|
-
<LiveError className="playground-error" />
|
|
121
|
-
</LiveProvider>
|
|
122
|
-
)}
|
|
123
|
-
</div>
|
|
124
|
-
</div>
|
|
125
|
-
|
|
126
|
-
{/* Editor Side - Now on bottom */}
|
|
127
|
-
<div className="playground-panel playground-editor-panel">
|
|
128
|
-
{!isStatic && (
|
|
129
|
-
<div className="playground-panel-header">
|
|
130
|
-
<div className="playground-panel-title">
|
|
131
|
-
<Terminal size={14} />
|
|
132
|
-
<span>{readonly ? "Code Example" : "Live Editor"}</span>
|
|
133
|
-
</div>
|
|
134
|
-
</div>
|
|
135
|
-
)}
|
|
136
|
-
<div className="playground-panel-content playground-editor">
|
|
137
|
-
{/* Copy button moved inside code area */}
|
|
138
|
-
<button
|
|
139
|
-
className="playground-copy-btn-inner"
|
|
140
|
-
onClick={handleCopy}
|
|
141
|
-
title="Copy code"
|
|
142
|
-
>
|
|
143
|
-
{copied ? <Check size={14} /> : <Copy size={14} />}
|
|
144
|
-
</button>
|
|
145
|
-
|
|
146
|
-
{isStatic ? (
|
|
147
|
-
<LiveProvider
|
|
148
|
-
code={initialCode}
|
|
149
|
-
noInline={true}
|
|
150
|
-
transformCode={staticTransform}
|
|
151
|
-
>
|
|
152
|
-
<LiveEditor disabled />
|
|
153
|
-
</LiveProvider>
|
|
154
|
-
) : (
|
|
155
|
-
<LiveProvider
|
|
156
|
-
code={activeCode}
|
|
157
|
-
scope={extendedScope}
|
|
158
|
-
theme={undefined}
|
|
159
|
-
noInline={useNoInline}
|
|
160
|
-
>
|
|
161
|
-
<LiveEditor disabled={readonly} onChange={setActiveCode} />
|
|
162
|
-
</LiveProvider>
|
|
163
|
-
)}
|
|
164
|
-
</div>
|
|
165
|
-
|
|
166
|
-
{isExpandable && (
|
|
167
|
-
<div className="playground-expand-wrapper">
|
|
168
|
-
<button
|
|
169
|
-
className="playground-expand-btn"
|
|
170
|
-
onClick={() => setIsExpanded(!isExpanded)}
|
|
171
|
-
>
|
|
172
|
-
{isExpanded ? "Show less" : "Expand code"}
|
|
173
|
-
</button>
|
|
174
|
-
</div>
|
|
175
|
-
)}
|
|
176
|
-
</div>
|
|
177
|
-
</div>
|
|
178
|
-
</div>
|
|
179
|
-
);
|
|
180
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { Playground } from "./Playground";
|