blodemd 0.0.5 → 0.0.7
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/README.md +2 -2
- package/dev-server/app/[[...slug]]/page.tsx +139 -0
- package/dev-server/app/blodemd-dev/invalidate/route.ts +12 -0
- package/dev-server/app/blodemd-dev/static/[...path]/route.ts +32 -0
- package/dev-server/app/blodemd-dev/version/route.ts +14 -0
- package/dev-server/app/blodemd-internal/proxy/route.ts +86 -0
- package/dev-server/app/error.tsx +24 -0
- package/dev-server/app/favicon.ico +0 -0
- package/dev-server/app/globals.css +4 -0
- package/dev-server/app/layout.tsx +38 -0
- package/dev-server/app/not-found.tsx +18 -0
- package/dev-server/app/search/route.ts +17 -0
- package/dev-server/components/dev-reload-script.tsx +86 -0
- package/dev-server/components/providers.tsx +15 -0
- package/dev-server/lib/dev-state.ts +8 -0
- package/dev-server/lib/local-content-source.ts +103 -0
- package/dev-server/lib/local-runtime.tsx +558 -0
- package/dev-server/next-env.d.ts +5 -0
- package/dev-server/next.config.js +46 -0
- package/dev-server/package.json +57 -0
- package/dev-server/postcss.config.mjs +7 -0
- package/dev-server/public/glide-variable.woff2 +0 -0
- package/dev-server/tsconfig.json +50 -0
- package/dist/cli.mjs +311 -86
- package/dist/cli.mjs.map +1 -1
- package/docs/app/globals.css +457 -0
- package/docs/components/api/api-playground.tsx +295 -0
- package/docs/components/api/api-reference.tsx +121 -0
- package/docs/components/content/collection-index.tsx +114 -0
- package/docs/components/docs/contextual-menu.tsx +406 -0
- package/docs/components/docs/copy-page-menu.tsx +255 -0
- package/docs/components/docs/doc-header.tsx +210 -0
- package/docs/components/docs/doc-shell.tsx +313 -0
- package/docs/components/docs/doc-sidebar.tsx +211 -0
- package/docs/components/docs/doc-toc.tsx +45 -0
- package/docs/components/docs/mobile-nav.tsx +205 -0
- package/docs/components/icons/doc-icon.tsx +96 -0
- package/docs/components/mdx/accordion.tsx +83 -0
- package/docs/components/mdx/badge.tsx +79 -0
- package/docs/components/mdx/callout.tsx +88 -0
- package/docs/components/mdx/card.tsx +110 -0
- package/docs/components/mdx/code-block.tsx +75 -0
- package/docs/components/mdx/code-group.tsx +94 -0
- package/docs/components/mdx/color.tsx +87 -0
- package/docs/components/mdx/columns.tsx +25 -0
- package/docs/components/mdx/expandable.tsx +45 -0
- package/docs/components/mdx/field-layout.tsx +77 -0
- package/docs/components/mdx/frame.tsx +23 -0
- package/docs/components/mdx/get-text-content.ts +18 -0
- package/docs/components/mdx/icon.tsx +12 -0
- package/docs/components/mdx/index.tsx +107 -0
- package/docs/components/mdx/installer.tsx +20 -0
- package/docs/components/mdx/panel.tsx +11 -0
- package/docs/components/mdx/param-field.tsx +56 -0
- package/docs/components/mdx/preview.tsx +36 -0
- package/docs/components/mdx/prompt.tsx +63 -0
- package/docs/components/mdx/request-example.tsx +27 -0
- package/docs/components/mdx/response-field.tsx +42 -0
- package/docs/components/mdx/steps.tsx +92 -0
- package/docs/components/mdx/tabs.tsx +88 -0
- package/docs/components/mdx/tile.tsx +43 -0
- package/docs/components/mdx/tooltip.tsx +71 -0
- package/docs/components/mdx/tree.tsx +120 -0
- package/docs/components/mdx/type-table.tsx +71 -0
- package/docs/components/mdx/update.tsx +44 -0
- package/docs/components/mdx/video.tsx +12 -0
- package/docs/components/mdx/view.tsx +66 -0
- package/docs/components/providers.tsx +15 -0
- package/docs/components/ui/breadcrumb.tsx +92 -0
- package/docs/components/ui/button.tsx +90 -0
- package/docs/components/ui/card.tsx +92 -0
- package/docs/components/ui/command.tsx +139 -0
- package/docs/components/ui/dialog.tsx +97 -0
- package/docs/components/ui/field.tsx +237 -0
- package/docs/components/ui/input.tsx +105 -0
- package/docs/components/ui/label.tsx +22 -0
- package/docs/components/ui/popover.tsx +72 -0
- package/docs/components/ui/search.tsx +384 -0
- package/docs/components/ui/separator.tsx +26 -0
- package/docs/components/ui/sheet.tsx +104 -0
- package/docs/components/ui/sidebar.tsx +433 -0
- package/docs/components/ui/theme-toggle.tsx +62 -0
- package/docs/components/ui/tooltip.tsx +53 -0
- package/docs/lib/contextual-options.ts +193 -0
- package/docs/lib/docs-collection.ts +22 -0
- package/docs/lib/mdx.ts +87 -0
- package/docs/lib/navigation.ts +288 -0
- package/docs/lib/openapi.ts +158 -0
- package/docs/lib/routes.ts +44 -0
- package/docs/lib/server-cache.ts +83 -0
- package/docs/lib/shiki.ts +40 -0
- package/docs/lib/theme.ts +29 -0
- package/docs/lib/toc.ts +2 -0
- package/docs/lib/utils.ts +5 -0
- package/package.json +43 -6
- package/packages/@repo/common/dist/index.d.ts +9 -0
- package/packages/@repo/common/dist/index.d.ts.map +1 -0
- package/packages/@repo/common/dist/index.js +42 -0
- package/packages/@repo/common/package.json +34 -0
- package/packages/@repo/common/src/index.ts +51 -0
- package/packages/@repo/contracts/dist/api-key.d.ts +30 -0
- package/packages/@repo/contracts/dist/api-key.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/api-key.js +20 -0
- package/packages/@repo/contracts/dist/dates.d.ts +4 -0
- package/packages/@repo/contracts/dist/dates.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/dates.js +2 -0
- package/packages/@repo/contracts/dist/deployment.d.ts +71 -0
- package/packages/@repo/contracts/dist/deployment.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/deployment.js +46 -0
- package/packages/@repo/contracts/dist/domain.d.ts +94 -0
- package/packages/@repo/contracts/dist/domain.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/domain.js +36 -0
- package/packages/@repo/contracts/dist/ids.d.ts +14 -0
- package/packages/@repo/contracts/dist/ids.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/ids.js +10 -0
- package/packages/@repo/contracts/dist/index.d.ts +10 -0
- package/packages/@repo/contracts/dist/index.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/index.js +11 -0
- package/packages/@repo/contracts/dist/pagination.d.ts +23 -0
- package/packages/@repo/contracts/dist/pagination.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/pagination.js +15 -0
- package/packages/@repo/contracts/dist/project.d.ts +25 -0
- package/packages/@repo/contracts/dist/project.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/project.js +23 -0
- package/packages/@repo/contracts/dist/tenant.d.ts +111 -0
- package/packages/@repo/contracts/dist/tenant.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/tenant.js +56 -0
- package/packages/@repo/contracts/dist/user.d.ts +9 -0
- package/packages/@repo/contracts/dist/user.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/user.js +9 -0
- package/packages/@repo/contracts/package.json +37 -0
- package/packages/@repo/contracts/src/api-key.ts +27 -0
- package/packages/@repo/contracts/src/dates.ts +4 -0
- package/packages/@repo/contracts/src/deployment.ts +73 -0
- package/packages/@repo/contracts/src/domain.ts +51 -0
- package/packages/@repo/contracts/src/ids.ts +22 -0
- package/packages/@repo/contracts/src/index.ts +11 -0
- package/packages/@repo/contracts/src/pagination.ts +21 -0
- package/packages/@repo/contracts/src/project.ts +30 -0
- package/packages/@repo/contracts/src/tenant.ts +92 -0
- package/packages/@repo/contracts/src/user.ts +12 -0
- package/packages/@repo/models/dist/docs-config.d.ts +985 -0
- package/packages/@repo/models/dist/docs-config.d.ts.map +1 -0
- package/packages/@repo/models/dist/docs-config.js +548 -0
- package/packages/@repo/models/dist/index.d.ts +3 -0
- package/packages/@repo/models/dist/index.d.ts.map +1 -0
- package/packages/@repo/models/dist/index.js +3 -0
- package/packages/@repo/models/dist/tenant.d.ts +25 -0
- package/packages/@repo/models/dist/tenant.d.ts.map +1 -0
- package/packages/@repo/models/dist/tenant.js +1 -0
- package/packages/@repo/models/package.json +37 -0
- package/packages/@repo/models/src/docs-config.ts +648 -0
- package/packages/@repo/models/src/index.ts +3 -0
- package/packages/@repo/models/src/tenant.ts +29 -0
- package/packages/@repo/prebuild/dist/index.d.ts +2 -0
- package/packages/@repo/prebuild/dist/index.d.ts.map +1 -0
- package/packages/@repo/prebuild/dist/index.js +2 -0
- package/packages/@repo/prebuild/dist/openapi.d.ts +43 -0
- package/packages/@repo/prebuild/dist/openapi.d.ts.map +1 -0
- package/packages/@repo/prebuild/dist/openapi.js +58 -0
- package/packages/@repo/prebuild/package.json +39 -0
- package/packages/@repo/prebuild/src/index.ts +2 -0
- package/packages/@repo/prebuild/src/openapi.ts +116 -0
- package/packages/@repo/previewing/dist/blob-source.d.ts +16 -0
- package/packages/@repo/previewing/dist/blob-source.d.ts.map +1 -0
- package/packages/@repo/previewing/dist/blob-source.js +110 -0
- package/packages/@repo/previewing/dist/content-source.d.ts +12 -0
- package/packages/@repo/previewing/dist/content-source.d.ts.map +1 -0
- package/packages/@repo/previewing/dist/content-source.js +1 -0
- package/packages/@repo/previewing/dist/fs-source.d.ts +11 -0
- package/packages/@repo/previewing/dist/fs-source.d.ts.map +1 -0
- package/packages/@repo/previewing/dist/fs-source.js +72 -0
- package/packages/@repo/previewing/dist/index.d.ts +120 -0
- package/packages/@repo/previewing/dist/index.d.ts.map +1 -0
- package/packages/@repo/previewing/dist/index.js +984 -0
- package/packages/@repo/previewing/package.json +41 -0
- package/packages/@repo/previewing/src/blob-source.ts +167 -0
- package/packages/@repo/previewing/src/content-source.ts +12 -0
- package/packages/@repo/previewing/src/fs-source.ts +104 -0
- package/packages/@repo/previewing/src/index.ts +1490 -0
- package/packages/@repo/validation/dist/index.d.ts +12 -0
- package/packages/@repo/validation/dist/index.d.ts.map +1 -0
- package/packages/@repo/validation/dist/index.js +30 -0
- package/packages/@repo/validation/package.json +37 -0
- package/packages/@repo/validation/src/index.ts +59 -0
- package/packages/@repo/validation/src/mintlify-docs-schema.json +5016 -0
- package/scripts/prepare-package.mjs +39 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
interface FrameProps {
|
|
4
|
+
caption?: string;
|
|
5
|
+
hint?: string;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const Frame = ({ caption, hint, children }: FrameProps) => (
|
|
10
|
+
<figure className="my-4">
|
|
11
|
+
{hint ? (
|
|
12
|
+
<div className="mb-2 text-sm text-muted-foreground">{hint}</div>
|
|
13
|
+
) : null}
|
|
14
|
+
<div className="overflow-hidden rounded-xl border border-border bg-card">
|
|
15
|
+
{children}
|
|
16
|
+
</div>
|
|
17
|
+
{caption ? (
|
|
18
|
+
<figcaption className="mt-2 text-center text-sm text-muted-foreground">
|
|
19
|
+
{caption}
|
|
20
|
+
</figcaption>
|
|
21
|
+
) : null}
|
|
22
|
+
</figure>
|
|
23
|
+
);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isValidElement } from "react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
export const getTextContent = (node: ReactNode): string => {
|
|
5
|
+
if (typeof node === "string") {
|
|
6
|
+
return node;
|
|
7
|
+
}
|
|
8
|
+
if (typeof node === "number") {
|
|
9
|
+
return String(node);
|
|
10
|
+
}
|
|
11
|
+
if (Array.isArray(node)) {
|
|
12
|
+
return node.map(getTextContent).join("");
|
|
13
|
+
}
|
|
14
|
+
if (isValidElement<{ children?: ReactNode }>(node)) {
|
|
15
|
+
return getTextContent(node.props.children);
|
|
16
|
+
}
|
|
17
|
+
return "";
|
|
18
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DocIcon } from "@/components/icons/doc-icon";
|
|
2
|
+
|
|
3
|
+
interface IconProps {
|
|
4
|
+
icon: string;
|
|
5
|
+
color?: string;
|
|
6
|
+
size?: number;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const Icon = ({ icon, color, size = 16, className }: IconProps) => (
|
|
11
|
+
<DocIcon className={className} color={color} icon={icon} size={size} />
|
|
12
|
+
);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { MDXComponents } from "mdx/types";
|
|
2
|
+
import Link from "next/link";
|
|
3
|
+
import type { ComponentProps } from "react";
|
|
4
|
+
|
|
5
|
+
import { Accordion, AccordionGroup } from "./accordion";
|
|
6
|
+
import { Badge } from "./badge";
|
|
7
|
+
import { Callout, Check, Danger, Info, Note, Tip, Warning } from "./callout";
|
|
8
|
+
import { Card } from "./card";
|
|
9
|
+
import { CodeBlock } from "./code-block";
|
|
10
|
+
import { CodeGroup } from "./code-group";
|
|
11
|
+
import { Color } from "./color";
|
|
12
|
+
import { Column, Columns } from "./columns";
|
|
13
|
+
import { Expandable } from "./expandable";
|
|
14
|
+
import { Frame } from "./frame";
|
|
15
|
+
import { Icon } from "./icon";
|
|
16
|
+
import { Installer } from "./installer";
|
|
17
|
+
import { Panel } from "./panel";
|
|
18
|
+
import { ParamField } from "./param-field";
|
|
19
|
+
import { Preview } from "./preview";
|
|
20
|
+
import { Prompt } from "./prompt";
|
|
21
|
+
import { RequestExample, ResponseExample } from "./request-example";
|
|
22
|
+
import { ResponseField } from "./response-field";
|
|
23
|
+
import { Step, Steps } from "./steps";
|
|
24
|
+
import { Tab, Tabs } from "./tabs";
|
|
25
|
+
import { Tile } from "./tile";
|
|
26
|
+
import { Tooltip } from "./tooltip";
|
|
27
|
+
import { Tree as TreeRoot, TreeFile, TreeFolder } from "./tree";
|
|
28
|
+
import { TypeTable } from "./type-table";
|
|
29
|
+
import { Update } from "./update";
|
|
30
|
+
import { Video } from "./video";
|
|
31
|
+
import { View, ViewGroup } from "./view";
|
|
32
|
+
|
|
33
|
+
// Rebuild dotted MDX exports in the server module so Next's client references
|
|
34
|
+
// still expose `Tree.Folder` and `Tree.File` during MDX evaluation.
|
|
35
|
+
const Tree = Object.assign(
|
|
36
|
+
(props: ComponentProps<typeof TreeRoot>) => <TreeRoot {...props} />,
|
|
37
|
+
{
|
|
38
|
+
File: TreeFile,
|
|
39
|
+
Folder: TreeFolder,
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const MdxLink = ({
|
|
44
|
+
href,
|
|
45
|
+
children,
|
|
46
|
+
...props
|
|
47
|
+
}: React.AnchorHTMLAttributes<HTMLAnchorElement>) => {
|
|
48
|
+
if (!href) {
|
|
49
|
+
return <a {...props}>{children}</a>;
|
|
50
|
+
}
|
|
51
|
+
const isExternal = href.startsWith("http");
|
|
52
|
+
if (isExternal) {
|
|
53
|
+
return (
|
|
54
|
+
<a {...props} href={href} rel="noopener noreferrer" target="_blank">
|
|
55
|
+
{children}
|
|
56
|
+
</a>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return (
|
|
60
|
+
<Link href={href} {...props}>
|
|
61
|
+
{children}
|
|
62
|
+
</Link>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const mdxComponents: MDXComponents = {
|
|
67
|
+
Accordion,
|
|
68
|
+
AccordionGroup,
|
|
69
|
+
Badge,
|
|
70
|
+
Callout,
|
|
71
|
+
Card,
|
|
72
|
+
Check,
|
|
73
|
+
CodeGroup,
|
|
74
|
+
Color,
|
|
75
|
+
Column,
|
|
76
|
+
Columns,
|
|
77
|
+
Danger,
|
|
78
|
+
Expandable,
|
|
79
|
+
Frame,
|
|
80
|
+
Icon,
|
|
81
|
+
Info,
|
|
82
|
+
Installer,
|
|
83
|
+
Note,
|
|
84
|
+
Panel,
|
|
85
|
+
ParamField,
|
|
86
|
+
Preview,
|
|
87
|
+
Prompt,
|
|
88
|
+
RequestExample,
|
|
89
|
+
ResponseExample,
|
|
90
|
+
ResponseField,
|
|
91
|
+
Step,
|
|
92
|
+
Steps,
|
|
93
|
+
Tab,
|
|
94
|
+
Tabs,
|
|
95
|
+
Tile,
|
|
96
|
+
Tip,
|
|
97
|
+
Tooltip,
|
|
98
|
+
Tree,
|
|
99
|
+
TypeTable,
|
|
100
|
+
Update,
|
|
101
|
+
Video,
|
|
102
|
+
View,
|
|
103
|
+
ViewGroup,
|
|
104
|
+
Warning,
|
|
105
|
+
a: MdxLink,
|
|
106
|
+
pre: CodeBlock,
|
|
107
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const Installer = ({
|
|
2
|
+
path,
|
|
3
|
+
command,
|
|
4
|
+
}: {
|
|
5
|
+
path: string;
|
|
6
|
+
command?: string;
|
|
7
|
+
}) => {
|
|
8
|
+
const resolvedCommand =
|
|
9
|
+
command ?? `npx @vercel/platform-elements@latest ${path}`;
|
|
10
|
+
return (
|
|
11
|
+
<div className="my-4 grid gap-2.5 rounded-xl border border-border bg-background/70 p-3.5">
|
|
12
|
+
<div className="text-xs uppercase tracking-widest text-muted-foreground">
|
|
13
|
+
Install
|
|
14
|
+
</div>
|
|
15
|
+
<pre className="m-0 overflow-x-auto rounded-lg bg-code p-3 font-mono text-sm text-code-foreground">
|
|
16
|
+
<code>{resolvedCommand}</code>
|
|
17
|
+
</pre>
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
import { FieldLayout } from "./field-layout";
|
|
4
|
+
|
|
5
|
+
interface ParamFieldProps {
|
|
6
|
+
path?: string;
|
|
7
|
+
query?: string;
|
|
8
|
+
body?: string;
|
|
9
|
+
header?: string;
|
|
10
|
+
type?: string;
|
|
11
|
+
required?: boolean;
|
|
12
|
+
deprecated?: boolean;
|
|
13
|
+
default?: string;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const ParamField = ({
|
|
19
|
+
path,
|
|
20
|
+
query,
|
|
21
|
+
body,
|
|
22
|
+
header,
|
|
23
|
+
type,
|
|
24
|
+
required,
|
|
25
|
+
deprecated,
|
|
26
|
+
default: defaultValue,
|
|
27
|
+
children,
|
|
28
|
+
}: ParamFieldProps) => {
|
|
29
|
+
const name = path ?? query ?? body ?? header ?? "";
|
|
30
|
+
|
|
31
|
+
let location: string | undefined;
|
|
32
|
+
if (path) {
|
|
33
|
+
location = "path";
|
|
34
|
+
} else if (query) {
|
|
35
|
+
location = "query";
|
|
36
|
+
} else if (body) {
|
|
37
|
+
location = "body";
|
|
38
|
+
} else if (header) {
|
|
39
|
+
location = "header";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const badges = location ? [{ label: location }] : undefined;
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<FieldLayout
|
|
46
|
+
badges={badges}
|
|
47
|
+
defaultValue={defaultValue}
|
|
48
|
+
deprecated={deprecated}
|
|
49
|
+
name={name}
|
|
50
|
+
required={required}
|
|
51
|
+
type={type}
|
|
52
|
+
>
|
|
53
|
+
{children}
|
|
54
|
+
</FieldLayout>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export const Preview = ({
|
|
4
|
+
example,
|
|
5
|
+
source,
|
|
6
|
+
title = "Preview",
|
|
7
|
+
children,
|
|
8
|
+
}: {
|
|
9
|
+
example?: string;
|
|
10
|
+
source?: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
}) => (
|
|
14
|
+
<div className="my-4 grid gap-3 rounded-xl border border-border bg-surface p-4">
|
|
15
|
+
<div className="flex flex-wrap items-center gap-2 text-xs uppercase tracking-wider text-muted-foreground">
|
|
16
|
+
<span className="font-semibold">{title}</span>
|
|
17
|
+
{example ? (
|
|
18
|
+
<span className="rounded-full border border-border bg-accent px-2.5 py-1 text-primary">
|
|
19
|
+
{example}
|
|
20
|
+
</span>
|
|
21
|
+
) : null}
|
|
22
|
+
{source ? (
|
|
23
|
+
<span className="rounded-full border border-border bg-accent px-2.5 py-1 text-primary">
|
|
24
|
+
{source}
|
|
25
|
+
</span>
|
|
26
|
+
) : null}
|
|
27
|
+
</div>
|
|
28
|
+
<div className="rounded-xl border border-dashed border-border bg-gradient-to-br from-primary/15 to-primary/5 p-4.5">
|
|
29
|
+
{children ?? (
|
|
30
|
+
<div className="text-sm text-muted-foreground">
|
|
31
|
+
Interactive preview placeholder
|
|
32
|
+
</div>
|
|
33
|
+
)}
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { CheckIcon, ClipboardIcon } from "blode-icons-react";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
5
|
+
import type { ReactNode } from "react";
|
|
6
|
+
|
|
7
|
+
import { getTextContent } from "./get-text-content";
|
|
8
|
+
|
|
9
|
+
interface PromptProps {
|
|
10
|
+
description: string;
|
|
11
|
+
icon?: ReactNode;
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const Prompt = ({ description, icon, children }: PromptProps) => {
|
|
16
|
+
const [copied, setCopied] = useState(false);
|
|
17
|
+
const text = useMemo(() => getTextContent(children), [children]);
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (copied) {
|
|
21
|
+
const timer = setTimeout(() => setCopied(false), 2000);
|
|
22
|
+
return () => clearTimeout(timer);
|
|
23
|
+
}
|
|
24
|
+
}, [copied]);
|
|
25
|
+
|
|
26
|
+
const handleCopy = useCallback(async () => {
|
|
27
|
+
if (!text) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
await navigator.clipboard.writeText(text);
|
|
31
|
+
setCopied(true);
|
|
32
|
+
}, [text]);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<div className="my-4 rounded-xl border border-border bg-card">
|
|
36
|
+
<div className="flex items-start gap-3 border-b border-border p-4">
|
|
37
|
+
{icon ? (
|
|
38
|
+
<span className="mt-0.5 flex size-5 shrink-0 items-center justify-center text-muted-foreground">
|
|
39
|
+
{icon}
|
|
40
|
+
</span>
|
|
41
|
+
) : null}
|
|
42
|
+
<div className="min-w-0 flex-1 text-sm text-foreground">
|
|
43
|
+
{description}
|
|
44
|
+
</div>
|
|
45
|
+
<button
|
|
46
|
+
className="inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
|
|
47
|
+
onClick={handleCopy}
|
|
48
|
+
type="button"
|
|
49
|
+
>
|
|
50
|
+
<span className="sr-only">{copied ? "Copied" : "Copy prompt"}</span>
|
|
51
|
+
{copied ? (
|
|
52
|
+
<CheckIcon aria-hidden className="size-3.5" />
|
|
53
|
+
) : (
|
|
54
|
+
<ClipboardIcon aria-hidden className="size-3.5" />
|
|
55
|
+
)}
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
<div className="p-4 text-sm text-muted-foreground [&>p:first-child]:mt-0 [&>p:last-child]:mb-0">
|
|
59
|
+
{children}
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
interface RequestExampleProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const RequestExample = ({ children }: RequestExampleProps) => (
|
|
8
|
+
<div className="my-4">
|
|
9
|
+
<div className="mb-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
10
|
+
Request
|
|
11
|
+
</div>
|
|
12
|
+
<div className="[&>pre]:mt-0 [&>[data-rehype-pretty-code-figure]]:mt-0">
|
|
13
|
+
{children}
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
export const ResponseExample = ({ children }: RequestExampleProps) => (
|
|
19
|
+
<div className="my-4">
|
|
20
|
+
<div className="mb-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
21
|
+
Response
|
|
22
|
+
</div>
|
|
23
|
+
<div className="[&>pre]:mt-0 [&>[data-rehype-pretty-code-figure]]:mt-0">
|
|
24
|
+
{children}
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
import { FieldLayout } from "./field-layout";
|
|
4
|
+
|
|
5
|
+
interface ResponseFieldProps {
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
default?: string;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
deprecated?: boolean;
|
|
11
|
+
pre?: string[];
|
|
12
|
+
post?: string[];
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const ResponseField = ({
|
|
17
|
+
name,
|
|
18
|
+
type,
|
|
19
|
+
default: defaultValue,
|
|
20
|
+
required,
|
|
21
|
+
deprecated,
|
|
22
|
+
pre,
|
|
23
|
+
post,
|
|
24
|
+
children,
|
|
25
|
+
}: ResponseFieldProps) => {
|
|
26
|
+
const preBadges = pre?.map((label) => ({ label })) ?? [];
|
|
27
|
+
const postBadges = post?.map((label) => ({ label })) ?? [];
|
|
28
|
+
const badges = [...preBadges, ...postBadges];
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<FieldLayout
|
|
32
|
+
badges={badges.length > 0 ? badges : undefined}
|
|
33
|
+
defaultValue={defaultValue}
|
|
34
|
+
deprecated={deprecated}
|
|
35
|
+
name={name}
|
|
36
|
+
required={required}
|
|
37
|
+
type={type}
|
|
38
|
+
>
|
|
39
|
+
{children}
|
|
40
|
+
</FieldLayout>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { isValidElement } from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
interface StepProps {
|
|
7
|
+
title: string;
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
icon?: ReactNode;
|
|
10
|
+
stepNumber?: number;
|
|
11
|
+
titleSize?: "p" | "h2" | "h3" | "h4";
|
|
12
|
+
id?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const Step = ({
|
|
16
|
+
title,
|
|
17
|
+
children,
|
|
18
|
+
icon,
|
|
19
|
+
stepNumber,
|
|
20
|
+
titleSize = "p",
|
|
21
|
+
id,
|
|
22
|
+
}: StepProps) => {
|
|
23
|
+
const TitleTag = titleSize === "p" ? "div" : titleSize;
|
|
24
|
+
const anchorId = id ?? title.toLowerCase().replaceAll(/\s+/g, "-");
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div className="relative pb-8 pl-10 last:pb-0" id={anchorId}>
|
|
28
|
+
<div
|
|
29
|
+
aria-hidden
|
|
30
|
+
className="absolute left-0 flex size-7 items-center justify-center rounded-full border border-border bg-muted font-mono text-xs font-medium"
|
|
31
|
+
>
|
|
32
|
+
{icon ?? stepNumber ?? null}
|
|
33
|
+
</div>
|
|
34
|
+
<TitleTag
|
|
35
|
+
className={cn(
|
|
36
|
+
"font-semibold leading-7",
|
|
37
|
+
titleSize === "h2" && "text-xl",
|
|
38
|
+
titleSize === "h3" && "text-lg",
|
|
39
|
+
titleSize === "h4" && "text-base",
|
|
40
|
+
titleSize === "p" && "text-base"
|
|
41
|
+
)}
|
|
42
|
+
>
|
|
43
|
+
{title}
|
|
44
|
+
</TitleTag>
|
|
45
|
+
{children ? (
|
|
46
|
+
<div className="mt-2 text-sm text-muted-foreground">{children}</div>
|
|
47
|
+
) : null}
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
interface StepsProps {
|
|
53
|
+
children: ReactNode;
|
|
54
|
+
titleSize?: "p" | "h2" | "h3" | "h4";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const Steps = ({ children, titleSize }: StepsProps) => {
|
|
58
|
+
const items = Array.isArray(children) ? children : [children];
|
|
59
|
+
|
|
60
|
+
const hasStepChildren = items.some(
|
|
61
|
+
(child) => isValidElement(child) && child.type === Step
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (!hasStepChildren) {
|
|
65
|
+
return (
|
|
66
|
+
<div className="steps mb-12 [counter-reset:step] md:ml-4 md:border-l md:pl-8 [&>h3]:step">
|
|
67
|
+
{children}
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let counter = 0;
|
|
73
|
+
const numberedChildren = items.map((child) => {
|
|
74
|
+
if (isValidElement<StepProps>(child) && child.type === Step) {
|
|
75
|
+
counter += 1;
|
|
76
|
+
const stepNumber = child.props.stepNumber ?? counter;
|
|
77
|
+
return (
|
|
78
|
+
<Step
|
|
79
|
+
key={child.props.id ?? child.props.title}
|
|
80
|
+
{...child.props}
|
|
81
|
+
stepNumber={stepNumber}
|
|
82
|
+
titleSize={child.props.titleSize ?? titleSize}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
return child;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div className="my-6 border-l border-border pl-2">{numberedChildren}</div>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { isValidElement, useCallback, useMemo, useState } from "react";
|
|
4
|
+
import type { MouseEvent, ReactElement, ReactNode } from "react";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
interface TabProps {
|
|
9
|
+
title?: string;
|
|
10
|
+
label?: string;
|
|
11
|
+
icon?: ReactNode;
|
|
12
|
+
id?: string;
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const Tab = ({ children }: TabProps) => (
|
|
17
|
+
<div className="p-4">{children}</div>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
interface TabsProps {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
defaultTabIndex?: number;
|
|
23
|
+
borderBottom?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const Tabs = ({
|
|
27
|
+
children,
|
|
28
|
+
defaultTabIndex = 0,
|
|
29
|
+
borderBottom,
|
|
30
|
+
}: TabsProps) => {
|
|
31
|
+
const items = useMemo(() => {
|
|
32
|
+
const nodes = Array.isArray(children) ? children : [children];
|
|
33
|
+
return nodes.filter((child): child is ReactElement<TabProps> =>
|
|
34
|
+
isValidElement<TabProps>(child)
|
|
35
|
+
);
|
|
36
|
+
}, [children]);
|
|
37
|
+
|
|
38
|
+
const [active, setActive] = useState(defaultTabIndex);
|
|
39
|
+
const activeItem = items[active];
|
|
40
|
+
const handleTabClick = useCallback((event: MouseEvent<HTMLButtonElement>) => {
|
|
41
|
+
const index = Number(event.currentTarget.dataset.index ?? "0");
|
|
42
|
+
setActive(index);
|
|
43
|
+
}, []);
|
|
44
|
+
|
|
45
|
+
if (!items.length) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
className={cn(
|
|
52
|
+
"overflow-hidden rounded-xl border border-border bg-surface",
|
|
53
|
+
borderBottom && "border-b-2"
|
|
54
|
+
)}
|
|
55
|
+
>
|
|
56
|
+
<div className="flex gap-2 bg-muted p-2" role="tablist">
|
|
57
|
+
{items.map((item, index) => {
|
|
58
|
+
const tabLabel =
|
|
59
|
+
item.props.title ?? item.props.label ?? `Tab ${index + 1}`;
|
|
60
|
+
return (
|
|
61
|
+
<button
|
|
62
|
+
aria-selected={index === active}
|
|
63
|
+
className={cn(
|
|
64
|
+
"inline-flex items-center gap-1.5 rounded-full border-none bg-transparent px-3 py-2 text-sm cursor-pointer transition-colors",
|
|
65
|
+
index === active
|
|
66
|
+
? "bg-primary text-primary-foreground"
|
|
67
|
+
: "text-muted-foreground hover:text-foreground"
|
|
68
|
+
)}
|
|
69
|
+
data-index={index}
|
|
70
|
+
key={String(item.key ?? tabLabel)}
|
|
71
|
+
onClick={handleTabClick}
|
|
72
|
+
role="tab"
|
|
73
|
+
type="button"
|
|
74
|
+
>
|
|
75
|
+
{item.props.icon ? (
|
|
76
|
+
<span className="shrink-0">{item.props.icon}</span>
|
|
77
|
+
) : null}
|
|
78
|
+
{tabLabel}
|
|
79
|
+
</button>
|
|
80
|
+
);
|
|
81
|
+
})}
|
|
82
|
+
</div>
|
|
83
|
+
<div className="p-4" role="tabpanel">
|
|
84
|
+
{activeItem}
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
interface TileProps {
|
|
5
|
+
href: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const Tile = ({ href, title, description, children }: TileProps) => {
|
|
12
|
+
const isExternal = href.startsWith("http");
|
|
13
|
+
|
|
14
|
+
const inner = (
|
|
15
|
+
<div className="group/tile overflow-hidden rounded-xl border border-border bg-card transition-colors hover:border-primary/30 hover:bg-accent/50">
|
|
16
|
+
<div className="flex items-center justify-center bg-muted/50 p-6">
|
|
17
|
+
{children}
|
|
18
|
+
</div>
|
|
19
|
+
{title || description ? (
|
|
20
|
+
<div className="border-t border-border p-3">
|
|
21
|
+
{title ? (
|
|
22
|
+
<div className="text-sm font-medium text-foreground">{title}</div>
|
|
23
|
+
) : null}
|
|
24
|
+
{description ? (
|
|
25
|
+
<div className="mt-0.5 text-xs text-muted-foreground">
|
|
26
|
+
{description}
|
|
27
|
+
</div>
|
|
28
|
+
) : null}
|
|
29
|
+
</div>
|
|
30
|
+
) : null}
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
if (isExternal) {
|
|
35
|
+
return (
|
|
36
|
+
<a href={href} rel="noopener noreferrer" target="_blank">
|
|
37
|
+
{inner}
|
|
38
|
+
</a>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return <Link href={href}>{inner}</Link>;
|
|
43
|
+
};
|