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,79 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
|
|
5
|
+
const colorStyles: Record<string, string> = {
|
|
6
|
+
blue: "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
|
7
|
+
gray: "bg-muted text-muted-foreground",
|
|
8
|
+
green: "bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300",
|
|
9
|
+
orange:
|
|
10
|
+
"bg-orange-100 text-orange-800 dark:bg-orange-900/40 dark:text-orange-300",
|
|
11
|
+
purple:
|
|
12
|
+
"bg-purple-100 text-purple-800 dark:bg-purple-900/40 dark:text-purple-300",
|
|
13
|
+
red: "bg-red-100 text-red-800 dark:bg-red-900/40 dark:text-red-300",
|
|
14
|
+
surface: "bg-card text-card-foreground",
|
|
15
|
+
white: "bg-white text-foreground dark:bg-white dark:text-black",
|
|
16
|
+
yellow:
|
|
17
|
+
"bg-yellow-100 text-yellow-800 dark:bg-yellow-900/40 dark:text-yellow-300",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const strokeStyles: Record<string, string> = {
|
|
21
|
+
blue: "border-blue-300 text-blue-700 dark:border-blue-700 dark:text-blue-300",
|
|
22
|
+
gray: "border-border text-muted-foreground",
|
|
23
|
+
green:
|
|
24
|
+
"border-green-300 text-green-700 dark:border-green-700 dark:text-green-300",
|
|
25
|
+
orange:
|
|
26
|
+
"border-orange-300 text-orange-700 dark:border-orange-700 dark:text-orange-300",
|
|
27
|
+
purple:
|
|
28
|
+
"border-purple-300 text-purple-700 dark:border-purple-700 dark:text-purple-300",
|
|
29
|
+
red: "border-red-300 text-red-700 dark:border-red-700 dark:text-red-300",
|
|
30
|
+
surface: "border-border text-card-foreground",
|
|
31
|
+
white: "border-border text-foreground",
|
|
32
|
+
yellow:
|
|
33
|
+
"border-yellow-300 text-yellow-700 dark:border-yellow-700 dark:text-yellow-300",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const sizeStyles: Record<string, string> = {
|
|
37
|
+
lg: "px-3 py-1.5 text-sm",
|
|
38
|
+
md: "px-2.5 py-1 text-xs",
|
|
39
|
+
sm: "px-2 py-0.5 text-xs",
|
|
40
|
+
xs: "px-1.5 py-0.5 text-[10px]",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
interface BadgeProps {
|
|
44
|
+
color?: string;
|
|
45
|
+
size?: "xs" | "sm" | "md" | "lg";
|
|
46
|
+
shape?: "rounded" | "pill";
|
|
47
|
+
icon?: ReactNode;
|
|
48
|
+
stroke?: boolean;
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
className?: string;
|
|
51
|
+
children: ReactNode;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const Badge = ({
|
|
55
|
+
color = "gray",
|
|
56
|
+
size = "md",
|
|
57
|
+
shape = "rounded",
|
|
58
|
+
icon,
|
|
59
|
+
stroke = false,
|
|
60
|
+
disabled = false,
|
|
61
|
+
className,
|
|
62
|
+
children,
|
|
63
|
+
}: BadgeProps) => (
|
|
64
|
+
<span
|
|
65
|
+
className={cn(
|
|
66
|
+
"inline-flex items-center gap-1 font-medium",
|
|
67
|
+
shape === "pill" ? "rounded-full" : "rounded-md",
|
|
68
|
+
stroke
|
|
69
|
+
? cn("border bg-transparent", strokeStyles[color] ?? strokeStyles.gray)
|
|
70
|
+
: (colorStyles[color] ?? colorStyles.gray),
|
|
71
|
+
sizeStyles[size] ?? sizeStyles.md,
|
|
72
|
+
disabled && "opacity-50",
|
|
73
|
+
className
|
|
74
|
+
)}
|
|
75
|
+
>
|
|
76
|
+
{icon ? <span className="shrink-0">{icon}</span> : null}
|
|
77
|
+
{children}
|
|
78
|
+
</span>
|
|
79
|
+
);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
|
|
5
|
+
const variantStyles: Record<string, string> = {
|
|
6
|
+
check:
|
|
7
|
+
"border-emerald-600 bg-emerald-100 dark:border-emerald-400 dark:bg-emerald-900",
|
|
8
|
+
danger: "border-red-600 bg-red-100 dark:border-red-400 dark:bg-red-900",
|
|
9
|
+
info: "bg-card border-border",
|
|
10
|
+
note: "bg-card border-border",
|
|
11
|
+
success:
|
|
12
|
+
"border-emerald-600 bg-emerald-100 dark:border-emerald-400 dark:bg-emerald-900",
|
|
13
|
+
tip: "border-blue-600 bg-blue-100 dark:border-blue-400 dark:bg-blue-900",
|
|
14
|
+
warning:
|
|
15
|
+
"border-amber-600 bg-amber-100 dark:border-amber-400 dark:bg-amber-900",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
interface CalloutProps {
|
|
19
|
+
type?: "info" | "success" | "warning" | "danger" | "note" | "tip" | "check";
|
|
20
|
+
title?: string;
|
|
21
|
+
icon?: ReactNode;
|
|
22
|
+
color?: string;
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const Callout = ({
|
|
27
|
+
type = "info",
|
|
28
|
+
title,
|
|
29
|
+
icon,
|
|
30
|
+
color,
|
|
31
|
+
children,
|
|
32
|
+
}: CalloutProps) => (
|
|
33
|
+
<div
|
|
34
|
+
data-slot="alert"
|
|
35
|
+
role="alert"
|
|
36
|
+
data-variant="default"
|
|
37
|
+
className={cn(
|
|
38
|
+
"relative grid grid-cols-[0_1fr] items-start gap-y-0.5 rounded-xl border px-4 py-3 text-sm text-surface-foreground",
|
|
39
|
+
"has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3",
|
|
40
|
+
"[&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
|
|
41
|
+
"**:[code]:border md:-mx-1",
|
|
42
|
+
variantStyles[type]
|
|
43
|
+
)}
|
|
44
|
+
style={
|
|
45
|
+
color
|
|
46
|
+
? {
|
|
47
|
+
backgroundColor: `${color}10`,
|
|
48
|
+
borderColor: color,
|
|
49
|
+
}
|
|
50
|
+
: undefined
|
|
51
|
+
}
|
|
52
|
+
>
|
|
53
|
+
{icon}
|
|
54
|
+
<div
|
|
55
|
+
data-slot="alert-description"
|
|
56
|
+
className="col-start-2 grid justify-items-start gap-1 text-sm text-foreground [&_p]:leading-relaxed"
|
|
57
|
+
>
|
|
58
|
+
{title ? <strong className="font-medium">{title}</strong> : null}
|
|
59
|
+
<div className="text-sm [&>p:first-child]:mt-0 [&>p:last-child]:mb-0 [&_p]:leading-relaxed [&_p:not(:first-child)]:mt-6">
|
|
60
|
+
{children}
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
export const Note = ({ children }: { children: ReactNode }) => (
|
|
67
|
+
<Callout type="note">{children}</Callout>
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
export const Warning = ({ children }: { children: ReactNode }) => (
|
|
71
|
+
<Callout type="warning">{children}</Callout>
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
export const Info = ({ children }: { children: ReactNode }) => (
|
|
75
|
+
<Callout type="info">{children}</Callout>
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
export const Tip = ({ children }: { children: ReactNode }) => (
|
|
79
|
+
<Callout type="tip">{children}</Callout>
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
export const Check = ({ children }: { children: ReactNode }) => (
|
|
83
|
+
<Callout type="check">{children}</Callout>
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
export const Danger = ({ children }: { children: ReactNode }) => (
|
|
87
|
+
<Callout type="danger">{children}</Callout>
|
|
88
|
+
);
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import Image from "next/image";
|
|
2
|
+
import Link from "next/link";
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
import { DocIcon } from "@/components/icons/doc-icon";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
interface CardProps {
|
|
9
|
+
title?: string;
|
|
10
|
+
icon?: ReactNode;
|
|
11
|
+
color?: string;
|
|
12
|
+
href?: string;
|
|
13
|
+
horizontal?: boolean;
|
|
14
|
+
img?: string;
|
|
15
|
+
cta?: string;
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const CardInner = ({
|
|
20
|
+
title,
|
|
21
|
+
icon,
|
|
22
|
+
color,
|
|
23
|
+
horizontal,
|
|
24
|
+
img,
|
|
25
|
+
cta,
|
|
26
|
+
href,
|
|
27
|
+
children,
|
|
28
|
+
}: CardProps) => {
|
|
29
|
+
const resolvedIcon =
|
|
30
|
+
typeof icon === "string" ? <DocIcon icon={icon} size={18} /> : icon;
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div
|
|
34
|
+
className={cn(
|
|
35
|
+
"group/card rounded-xl border border-border bg-card p-4 transition-colors",
|
|
36
|
+
href && "hover:border-primary/30 hover:bg-accent/50",
|
|
37
|
+
horizontal && "flex items-start gap-4"
|
|
38
|
+
)}
|
|
39
|
+
>
|
|
40
|
+
{img && !horizontal ? (
|
|
41
|
+
<div className="relative mb-3 aspect-video overflow-hidden rounded-lg">
|
|
42
|
+
<Image
|
|
43
|
+
alt={title ?? ""}
|
|
44
|
+
className="object-cover"
|
|
45
|
+
fill
|
|
46
|
+
sizes="(max-width: 768px) 100vw, 50vw"
|
|
47
|
+
src={img}
|
|
48
|
+
unoptimized
|
|
49
|
+
/>
|
|
50
|
+
</div>
|
|
51
|
+
) : null}
|
|
52
|
+
{resolvedIcon ? (
|
|
53
|
+
<div
|
|
54
|
+
className="mb-3 flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground"
|
|
55
|
+
style={color ? { color } : undefined}
|
|
56
|
+
>
|
|
57
|
+
{resolvedIcon}
|
|
58
|
+
</div>
|
|
59
|
+
) : null}
|
|
60
|
+
<div className="min-w-0 flex-1">
|
|
61
|
+
{title ? (
|
|
62
|
+
<div className="mb-1 font-medium text-foreground">{title}</div>
|
|
63
|
+
) : null}
|
|
64
|
+
{children ? (
|
|
65
|
+
<div className="text-sm text-muted-foreground [&>p:first-child]:mt-0 [&>p:last-child]:mb-0">
|
|
66
|
+
{children}
|
|
67
|
+
</div>
|
|
68
|
+
) : null}
|
|
69
|
+
{cta ? (
|
|
70
|
+
<div className="mt-2 text-sm font-medium text-primary">{cta}</div>
|
|
71
|
+
) : null}
|
|
72
|
+
</div>
|
|
73
|
+
{href ? (
|
|
74
|
+
<svg
|
|
75
|
+
aria-hidden
|
|
76
|
+
className="mt-0.5 size-4 shrink-0 text-muted-foreground transition-transform group-hover/card:translate-x-0.5"
|
|
77
|
+
fill="none"
|
|
78
|
+
stroke="currentColor"
|
|
79
|
+
strokeWidth={2}
|
|
80
|
+
viewBox="0 0 24 24"
|
|
81
|
+
>
|
|
82
|
+
<path
|
|
83
|
+
d="M5 12h14M12 5l7 7-7 7"
|
|
84
|
+
strokeLinecap="round"
|
|
85
|
+
strokeLinejoin="round"
|
|
86
|
+
/>
|
|
87
|
+
</svg>
|
|
88
|
+
) : null}
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const Card = (props: CardProps) => {
|
|
94
|
+
if (props.href) {
|
|
95
|
+
const isExternal = props.href.startsWith("http");
|
|
96
|
+
if (isExternal) {
|
|
97
|
+
return (
|
|
98
|
+
<a href={props.href} rel="noopener noreferrer" target="_blank">
|
|
99
|
+
<CardInner {...props} />
|
|
100
|
+
</a>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
return (
|
|
104
|
+
<Link href={props.href}>
|
|
105
|
+
<CardInner {...props} />
|
|
106
|
+
</Link>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return <CardInner {...props} />;
|
|
110
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { CheckIcon, ClipboardIcon } from "blode-icons-react";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
5
|
+
import type { ComponentPropsWithoutRef, ReactNode } from "react";
|
|
6
|
+
|
|
7
|
+
import { Button } from "@/components/ui/button";
|
|
8
|
+
import { cn } from "@/lib/utils";
|
|
9
|
+
|
|
10
|
+
import { getTextContent } from "./get-text-content";
|
|
11
|
+
|
|
12
|
+
export const CodeBlock = ({
|
|
13
|
+
children,
|
|
14
|
+
className,
|
|
15
|
+
style,
|
|
16
|
+
tabIndex,
|
|
17
|
+
...props
|
|
18
|
+
}: ComponentPropsWithoutRef<"pre"> & {
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
}) => {
|
|
21
|
+
const [copied, setCopied] = useState(false);
|
|
22
|
+
const code = useMemo(() => getTextContent(children), [children]);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (copied) {
|
|
26
|
+
const timer = setTimeout(() => setCopied(false), 2000);
|
|
27
|
+
return () => clearTimeout(timer);
|
|
28
|
+
}
|
|
29
|
+
}, [copied]);
|
|
30
|
+
|
|
31
|
+
const handleCopy = useCallback(async () => {
|
|
32
|
+
if (!code) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
await navigator.clipboard.writeText(code);
|
|
36
|
+
setCopied(true);
|
|
37
|
+
}, [code]);
|
|
38
|
+
|
|
39
|
+
const preStyle = style ? { ...style } : undefined;
|
|
40
|
+
if (preStyle) {
|
|
41
|
+
delete preStyle.backgroundColor;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<figure data-rehype-pretty-code-figure="">
|
|
46
|
+
<pre
|
|
47
|
+
className={cn(
|
|
48
|
+
"no-scrollbar min-w-0 overflow-x-auto overflow-y-auto overscroll-y-auto overscroll-x-contain px-4 py-3.5 outline-none has-[[data-slot=tabs]]:p-0 has-[[data-highlighted-line]]:px-0 has-[[data-line-numbers]]:px-0",
|
|
49
|
+
className
|
|
50
|
+
)}
|
|
51
|
+
style={preStyle}
|
|
52
|
+
tabIndex={tabIndex ?? 0}
|
|
53
|
+
{...props}
|
|
54
|
+
>
|
|
55
|
+
<Button
|
|
56
|
+
className="absolute top-3 right-2 z-10 size-7 bg-code hover:opacity-100 focus-visible:opacity-100"
|
|
57
|
+
data-copied={copied}
|
|
58
|
+
data-slot="copy-button"
|
|
59
|
+
onClick={handleCopy}
|
|
60
|
+
size="icon"
|
|
61
|
+
type="button"
|
|
62
|
+
variant="ghost"
|
|
63
|
+
>
|
|
64
|
+
<span className="sr-only">{copied ? "Copied" : "Copy"}</span>
|
|
65
|
+
{copied ? (
|
|
66
|
+
<CheckIcon aria-hidden="true" />
|
|
67
|
+
) : (
|
|
68
|
+
<ClipboardIcon aria-hidden="true" />
|
|
69
|
+
)}
|
|
70
|
+
</Button>
|
|
71
|
+
{children}
|
|
72
|
+
</pre>
|
|
73
|
+
</figure>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
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 CodeGroupProps {
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const CodeGroup = ({ children }: CodeGroupProps) => {
|
|
13
|
+
const items = useMemo(() => {
|
|
14
|
+
const nodes = Array.isArray(children) ? children : [children];
|
|
15
|
+
return nodes.filter((child): child is ReactElement =>
|
|
16
|
+
isValidElement(child)
|
|
17
|
+
);
|
|
18
|
+
}, [children]);
|
|
19
|
+
|
|
20
|
+
const [active, setActive] = useState(0);
|
|
21
|
+
|
|
22
|
+
const labels = useMemo(
|
|
23
|
+
() =>
|
|
24
|
+
items.map((item) => {
|
|
25
|
+
if (
|
|
26
|
+
!isValidElement<{
|
|
27
|
+
"data-rehype-pretty-code-title"?: string;
|
|
28
|
+
children?: ReactNode;
|
|
29
|
+
}>(item)
|
|
30
|
+
) {
|
|
31
|
+
return "Code";
|
|
32
|
+
}
|
|
33
|
+
const title = item.props["data-rehype-pretty-code-title"];
|
|
34
|
+
if (title) {
|
|
35
|
+
return title;
|
|
36
|
+
}
|
|
37
|
+
const itemChildren = Array.isArray(item.props.children)
|
|
38
|
+
? item.props.children
|
|
39
|
+
: [item.props.children];
|
|
40
|
+
const pre = itemChildren.find(
|
|
41
|
+
(c: unknown) => isValidElement(c) && c.type === "pre"
|
|
42
|
+
);
|
|
43
|
+
if (isValidElement<{ className?: string }>(pre)) {
|
|
44
|
+
const lang = pre.props.className
|
|
45
|
+
?.split(" ")
|
|
46
|
+
.find((c: string) => c.startsWith("language-"))
|
|
47
|
+
?.replace("language-", "");
|
|
48
|
+
if (lang) {
|
|
49
|
+
return lang;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return `Tab ${items.indexOf(item) + 1}`;
|
|
53
|
+
}),
|
|
54
|
+
[items]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const handleTabClick = useCallback((event: MouseEvent<HTMLButtonElement>) => {
|
|
58
|
+
const index = Number(event.currentTarget.dataset.index ?? "0");
|
|
59
|
+
setActive(index);
|
|
60
|
+
}, []);
|
|
61
|
+
|
|
62
|
+
if (items.length <= 1) {
|
|
63
|
+
return children as ReactElement;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div className="my-4 overflow-hidden rounded-xl border border-border bg-code">
|
|
68
|
+
<div
|
|
69
|
+
className="flex gap-1 border-b border-border bg-muted/50 px-2 pt-2"
|
|
70
|
+
role="tablist"
|
|
71
|
+
>
|
|
72
|
+
{labels.map((label, index) => (
|
|
73
|
+
<button
|
|
74
|
+
aria-selected={index === active}
|
|
75
|
+
className={cn(
|
|
76
|
+
"rounded-t-md border-b-2 px-3 py-1.5 font-mono text-xs transition-colors",
|
|
77
|
+
index === active
|
|
78
|
+
? "border-primary text-foreground"
|
|
79
|
+
: "border-transparent text-muted-foreground hover:text-foreground"
|
|
80
|
+
)}
|
|
81
|
+
data-index={index}
|
|
82
|
+
key={label}
|
|
83
|
+
onClick={handleTabClick}
|
|
84
|
+
role="tab"
|
|
85
|
+
type="button"
|
|
86
|
+
>
|
|
87
|
+
{label}
|
|
88
|
+
</button>
|
|
89
|
+
))}
|
|
90
|
+
</div>
|
|
91
|
+
<div role="tabpanel">{items[active]}</div>
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
|
|
5
|
+
interface ColorItemProps {
|
|
6
|
+
name?: string;
|
|
7
|
+
value: string | { light: string; dark: string };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const ColorItem = ({ name, value }: ColorItemProps) => {
|
|
11
|
+
const lightValue = typeof value === "string" ? value : value.light;
|
|
12
|
+
const darkValue = typeof value === "string" ? value : value.dark;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div className="flex items-center gap-3">
|
|
16
|
+
<div
|
|
17
|
+
className="size-8 shrink-0 rounded-md border border-border"
|
|
18
|
+
style={{ backgroundColor: lightValue }}
|
|
19
|
+
>
|
|
20
|
+
{typeof value === "string" ? null : (
|
|
21
|
+
<div
|
|
22
|
+
className="hidden size-full rounded-md dark:block"
|
|
23
|
+
style={{ backgroundColor: darkValue }}
|
|
24
|
+
/>
|
|
25
|
+
)}
|
|
26
|
+
</div>
|
|
27
|
+
<div className="min-w-0">
|
|
28
|
+
{name ? (
|
|
29
|
+
<div className="text-sm font-medium text-foreground">{name}</div>
|
|
30
|
+
) : null}
|
|
31
|
+
<div className="font-mono text-xs text-muted-foreground">
|
|
32
|
+
{lightValue}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
interface ColorRowProps {
|
|
40
|
+
title?: string;
|
|
41
|
+
children: ReactNode;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const ColorRow = ({ title, children }: ColorRowProps) => (
|
|
45
|
+
<>
|
|
46
|
+
{title ? (
|
|
47
|
+
<tr>
|
|
48
|
+
<td
|
|
49
|
+
className="border-b border-border bg-muted/50 px-4 py-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground"
|
|
50
|
+
colSpan={2}
|
|
51
|
+
>
|
|
52
|
+
{title}
|
|
53
|
+
</td>
|
|
54
|
+
</tr>
|
|
55
|
+
) : null}
|
|
56
|
+
{children}
|
|
57
|
+
</>
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
interface ColorProps {
|
|
61
|
+
variant?: "compact" | "table";
|
|
62
|
+
children: ReactNode;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const Color = ({ variant = "compact", children }: ColorProps) => (
|
|
66
|
+
<div
|
|
67
|
+
className={cn(
|
|
68
|
+
"my-4",
|
|
69
|
+
variant === "compact" &&
|
|
70
|
+
"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4",
|
|
71
|
+
variant === "table" && "overflow-hidden rounded-xl border border-border"
|
|
72
|
+
)}
|
|
73
|
+
>
|
|
74
|
+
{variant === "table" ? (
|
|
75
|
+
<table className="w-full text-sm">
|
|
76
|
+
<tbody>{children}</tbody>
|
|
77
|
+
</table>
|
|
78
|
+
) : (
|
|
79
|
+
children
|
|
80
|
+
)}
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
Color.Item = ColorItem;
|
|
85
|
+
Color.Row = ColorRow;
|
|
86
|
+
|
|
87
|
+
export { Color };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
|
|
5
|
+
interface ColumnsProps {
|
|
6
|
+
cols?: 1 | 2 | 3 | 4;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const colStyles: Record<number, string> = {
|
|
11
|
+
1: "grid-cols-1",
|
|
12
|
+
2: "grid-cols-1 sm:grid-cols-2",
|
|
13
|
+
3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
|
|
14
|
+
4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const Columns = ({ cols = 2, children }: ColumnsProps) => (
|
|
18
|
+
<div className={cn("my-4 grid gap-4", colStyles[cols] ?? colStyles[2])}>
|
|
19
|
+
{children}
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export const Column = ({ children }: { children: ReactNode }) => (
|
|
24
|
+
<div className="min-w-0">{children}</div>
|
|
25
|
+
);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import type { ReactNode } from "react";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
interface ExpandableProps {
|
|
9
|
+
title?: string;
|
|
10
|
+
defaultOpen?: boolean;
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const Expandable = ({
|
|
15
|
+
title = "properties",
|
|
16
|
+
defaultOpen = false,
|
|
17
|
+
children,
|
|
18
|
+
}: ExpandableProps) => {
|
|
19
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
20
|
+
const toggle = useCallback(() => setOpen((prev) => !prev), []);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div className="mt-2 ml-4 border-l border-border pl-4">
|
|
24
|
+
<button
|
|
25
|
+
className="inline-flex items-center gap-1.5 text-xs font-medium text-muted-foreground hover:text-foreground"
|
|
26
|
+
onClick={toggle}
|
|
27
|
+
type="button"
|
|
28
|
+
>
|
|
29
|
+
<svg
|
|
30
|
+
aria-hidden
|
|
31
|
+
className={cn(
|
|
32
|
+
"size-3 transition-transform duration-150",
|
|
33
|
+
open && "rotate-90"
|
|
34
|
+
)}
|
|
35
|
+
fill="currentColor"
|
|
36
|
+
viewBox="0 0 24 24"
|
|
37
|
+
>
|
|
38
|
+
<path d="m9 18 6-6-6-6" />
|
|
39
|
+
</svg>
|
|
40
|
+
{open ? "Hide" : "Show"} {title}
|
|
41
|
+
</button>
|
|
42
|
+
{open ? <div className="mt-2">{children}</div> : null}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
|
|
5
|
+
interface FieldBadge {
|
|
6
|
+
label: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface FieldLayoutProps {
|
|
11
|
+
name: string;
|
|
12
|
+
type?: string;
|
|
13
|
+
required?: boolean;
|
|
14
|
+
deprecated?: boolean;
|
|
15
|
+
defaultValue?: string;
|
|
16
|
+
badges?: FieldBadge[];
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const FieldLayout = ({
|
|
21
|
+
name,
|
|
22
|
+
type,
|
|
23
|
+
required,
|
|
24
|
+
deprecated,
|
|
25
|
+
defaultValue,
|
|
26
|
+
badges,
|
|
27
|
+
children,
|
|
28
|
+
}: FieldLayoutProps) => (
|
|
29
|
+
<div className="border-b border-border py-4 first:pt-0 last:border-b-0">
|
|
30
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
31
|
+
{badges
|
|
32
|
+
?.filter((b) => b.label)
|
|
33
|
+
.map((badge) => (
|
|
34
|
+
<span
|
|
35
|
+
className={cn(
|
|
36
|
+
"rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground",
|
|
37
|
+
badge.className
|
|
38
|
+
)}
|
|
39
|
+
key={badge.label}
|
|
40
|
+
>
|
|
41
|
+
{badge.label}
|
|
42
|
+
</span>
|
|
43
|
+
))}
|
|
44
|
+
<code className="rounded-md bg-muted px-1.5 py-0.5 font-mono text-sm font-medium">
|
|
45
|
+
{name}
|
|
46
|
+
</code>
|
|
47
|
+
{type ? (
|
|
48
|
+
<span className="text-xs text-muted-foreground">{type}</span>
|
|
49
|
+
) : null}
|
|
50
|
+
{required ? (
|
|
51
|
+
<span className="text-xs font-medium text-red-600 dark:text-red-400">
|
|
52
|
+
required
|
|
53
|
+
</span>
|
|
54
|
+
) : null}
|
|
55
|
+
{deprecated ? (
|
|
56
|
+
<span
|
|
57
|
+
className={cn(
|
|
58
|
+
"rounded-full bg-amber-100 px-2 py-0.5 text-xs text-amber-700",
|
|
59
|
+
"dark:bg-amber-900/40 dark:text-amber-300"
|
|
60
|
+
)}
|
|
61
|
+
>
|
|
62
|
+
deprecated
|
|
63
|
+
</span>
|
|
64
|
+
) : null}
|
|
65
|
+
{defaultValue ? (
|
|
66
|
+
<span className="text-xs text-muted-foreground">
|
|
67
|
+
Default: <code className="font-mono">{defaultValue}</code>
|
|
68
|
+
</span>
|
|
69
|
+
) : null}
|
|
70
|
+
</div>
|
|
71
|
+
{children ? (
|
|
72
|
+
<div className="mt-2 text-sm text-muted-foreground [&>p:first-child]:mt-0 [&>p:last-child]:mb-0">
|
|
73
|
+
{children}
|
|
74
|
+
</div>
|
|
75
|
+
) : null}
|
|
76
|
+
</div>
|
|
77
|
+
);
|