zudoku 0.1.1-dev.18 → 0.1.1-dev.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/plugins/openapi/worker/createSharedWorkerClient.js +2 -3
- package/dist/lib/plugins/openapi/worker/createSharedWorkerClient.js.map +1 -1
- package/dist/lib/plugins/openapi/worker/shared-worker.d.ts +1 -0
- package/dist/lib/plugins/openapi/worker/shared-worker.js +6 -0
- package/dist/lib/plugins/openapi/worker/shared-worker.js.map +1 -0
- package/dist/vite/config.d.ts +1 -1
- package/dist/vite/config.js +13 -13
- package/dist/vite/config.js.map +1 -1
- package/dist/vite/dev-server.js +1 -1
- package/dist/vite/dev-server.js.map +1 -1
- package/lib/zudoku.openapi-worker.js +12 -0
- package/lib/zudoku.plugins.js +1318 -1323
- package/package.json +5 -2
- package/src/cli/build/handler.ts +14 -0
- package/src/cli/cli.ts +77 -0
- package/src/cli/cmds/build.ts +24 -0
- package/src/cli/cmds/dev.ts +29 -0
- package/src/cli/common/analytics/lib.ts +89 -0
- package/src/cli/common/constants.ts +10 -0
- package/src/cli/common/logger.ts +5 -0
- package/src/cli/common/machine-id/lib.ts +85 -0
- package/src/cli/common/outdated.ts +102 -0
- package/src/cli/common/output.ts +86 -0
- package/src/cli/common/utils/box.license.txt +202 -0
- package/src/cli/common/utils/box.ts +116 -0
- package/src/cli/common/utils/ports.ts +21 -0
- package/src/cli/common/validators/lib.ts +43 -0
- package/src/cli/common/xdg/lib.ts +36 -0
- package/src/cli/dev/handler.ts +42 -0
- package/src/config/config.ts +56 -0
- package/src/index.ts +8 -0
- package/src/lib/DevPortal.tsx +93 -0
- package/src/lib/Heading.tsx +60 -0
- package/src/lib/Router.tsx +28 -0
- package/src/lib/auth.ts +1 -0
- package/src/lib/authentication/authentication.ts +18 -0
- package/src/lib/authentication/clerk.ts +45 -0
- package/src/lib/authentication/openid.ts +192 -0
- package/src/lib/components/AnchorLink.tsx +19 -0
- package/src/lib/components/CategoryHeading.tsx +16 -0
- package/src/lib/components/Dialog.tsx +119 -0
- package/src/lib/components/DynamicIcon.tsx +60 -0
- package/src/lib/components/Header.tsx +69 -0
- package/src/lib/components/Input.tsx +24 -0
- package/src/lib/components/Layout.tsx +56 -0
- package/src/lib/components/Markdown.tsx +37 -0
- package/src/lib/components/SyntaxHighlight.tsx +94 -0
- package/src/lib/components/TopNavigation.tsx +32 -0
- package/src/lib/components/context/ComponentsContext.tsx +24 -0
- package/src/lib/components/context/DevPortalProvider.ts +54 -0
- package/src/lib/components/context/PluginSystem.ts +0 -0
- package/src/lib/components/context/ThemeContext.tsx +46 -0
- package/src/lib/components/context/ViewportAnchorContext.tsx +139 -0
- package/src/lib/components/navigation/SideNavigation.tsx +18 -0
- package/src/lib/components/navigation/SideNavigationCategory.tsx +74 -0
- package/src/lib/components/navigation/SideNavigationItem.tsx +143 -0
- package/src/lib/components/navigation/SideNavigationWrapper.tsx +15 -0
- package/src/lib/components/navigation/useNavigationCollapsibleState.ts +27 -0
- package/src/lib/components/navigation/util.ts +38 -0
- package/src/lib/components.ts +3 -0
- package/src/lib/core/DevPortalContext.ts +164 -0
- package/src/lib/core/helmet.ts +5 -0
- package/src/lib/core/icons.tsx +1 -0
- package/src/lib/core/plugins.ts +43 -0
- package/src/lib/core/router.tsx +1 -0
- package/src/lib/core/types/combine.ts +16 -0
- package/src/lib/oas/graphql/index.ts +422 -0
- package/src/lib/oas/graphql/server.ts +10 -0
- package/src/lib/oas/parser/dereference/index.ts +59 -0
- package/src/lib/oas/parser/dereference/resolveRef.ts +32 -0
- package/src/lib/oas/parser/index.ts +94 -0
- package/src/lib/oas/parser/schemas/v3.0.json +1489 -0
- package/src/lib/oas/parser/schemas/v3.1.json +1298 -0
- package/src/lib/oas/parser/upgrade/index.ts +108 -0
- package/src/lib/plugins/api-key/SettingsApiKeys.tsx +22 -0
- package/src/lib/plugins/api-key/index.tsx +123 -0
- package/src/lib/plugins/markdown/MdxPage.tsx +128 -0
- package/src/lib/plugins/markdown/Toc.tsx +122 -0
- package/src/lib/plugins/markdown/generateRoutes.tsx +72 -0
- package/src/lib/plugins/markdown/index.tsx +31 -0
- package/src/lib/plugins/openapi/ColorizedParam.tsx +82 -0
- package/src/lib/plugins/openapi/MakeRequest.tsx +49 -0
- package/src/lib/plugins/openapi/MethodBadge.tsx +36 -0
- package/src/lib/plugins/openapi/OperationList.tsx +117 -0
- package/src/lib/plugins/openapi/OperationListItem.tsx +55 -0
- package/src/lib/plugins/openapi/ParameterList.tsx +32 -0
- package/src/lib/plugins/openapi/ParameterListItem.tsx +60 -0
- package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +51 -0
- package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +60 -0
- package/src/lib/plugins/openapi/Select.tsx +35 -0
- package/src/lib/plugins/openapi/Sidecar.tsx +160 -0
- package/src/lib/plugins/openapi/SidecarBox.tsx +36 -0
- package/src/lib/plugins/openapi/graphql/fragment-masking.ts +111 -0
- package/src/lib/plugins/openapi/graphql/gql.ts +70 -0
- package/src/lib/plugins/openapi/graphql/graphql.ts +795 -0
- package/src/lib/plugins/openapi/graphql/index.ts +2 -0
- package/src/lib/plugins/openapi/index.tsx +142 -0
- package/src/lib/plugins/openapi/playground/Playground.tsx +309 -0
- package/src/lib/plugins/openapi/queries.graphql +6 -0
- package/src/lib/plugins/openapi/util/generateSchemaExample.ts +59 -0
- package/src/lib/plugins/openapi/util/urql.ts +8 -0
- package/src/lib/plugins/openapi/worker/createSharedWorkerClient.ts +60 -0
- package/src/lib/plugins/openapi/worker/shared-worker.ts +5 -0
- package/src/lib/plugins/openapi/worker/worker.ts +30 -0
- package/src/lib/plugins/redirect/index.tsx +20 -0
- package/src/lib/plugins.ts +5 -0
- package/src/lib/ui/Button.tsx +56 -0
- package/src/lib/ui/Callout.tsx +87 -0
- package/src/lib/ui/Card.tsx +82 -0
- package/src/lib/ui/Note.tsx +58 -0
- package/src/lib/ui/Tabs.tsx +52 -0
- package/src/lib/util/MdxComponents.tsx +70 -0
- package/src/lib/util/cn.ts +6 -0
- package/src/lib/util/createVariantComponent.tsx +30 -0
- package/src/lib/util/createWaitForNotify.ts +18 -0
- package/src/lib/util/groupBy.ts +24 -0
- package/src/lib/util/joinPath.tsx +10 -0
- package/src/lib/util/pastellize.ts +25 -0
- package/src/lib/util/slugify.ts +3 -0
- package/src/lib/util/traverseNavigation.ts +55 -0
- package/src/lib/util/useScrollToAnchor.ts +38 -0
- package/src/lib/util/useScrollToTop.ts +13 -0
- package/src/ts.ts +94 -0
- package/src/types.d.ts +24 -0
- package/src/vite/build.ts +33 -0
- package/src/vite/config.test.ts +10 -0
- package/src/vite/config.ts +183 -0
- package/src/vite/dev-server.ts +64 -0
- package/src/vite/html.ts +37 -0
- package/src/vite/plugin-api.ts +57 -0
- package/src/vite/plugin-auth.ts +32 -0
- package/src/vite/plugin-component.ts +26 -0
- package/src/vite/plugin-config.ts +31 -0
- package/src/vite/plugin-docs.test.ts +32 -0
- package/src/vite/plugin-docs.ts +52 -0
- package/src/vite/plugin-html.ts +50 -0
- package/src/vite/plugin-mdx.ts +74 -0
- package/src/vite/plugin-metadata.ts +30 -0
- package/src/vite/plugin.ts +23 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
|
+
import { cn } from "../util/cn.js";
|
|
5
|
+
|
|
6
|
+
const buttonVariants = cva(
|
|
7
|
+
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default:
|
|
12
|
+
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
13
|
+
destructive:
|
|
14
|
+
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
15
|
+
outline:
|
|
16
|
+
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
17
|
+
secondary:
|
|
18
|
+
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
19
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
20
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
21
|
+
},
|
|
22
|
+
size: {
|
|
23
|
+
default: "h-9 px-4 py-2",
|
|
24
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
25
|
+
lg: "h-10 rounded-md px-8",
|
|
26
|
+
icon: "h-9 w-9",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: {
|
|
30
|
+
variant: "default",
|
|
31
|
+
size: "default",
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
export interface ButtonProps
|
|
37
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
38
|
+
VariantProps<typeof buttonVariants> {
|
|
39
|
+
asChild?: boolean
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
43
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
44
|
+
const Comp = asChild ? Slot : "button"
|
|
45
|
+
return (
|
|
46
|
+
<Comp
|
|
47
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
48
|
+
ref={ref}
|
|
49
|
+
{...props}
|
|
50
|
+
/>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
Button.displayName = "Button"
|
|
55
|
+
|
|
56
|
+
export { Button, buttonVariants }
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import {
|
|
3
|
+
AlertTriangleIcon,
|
|
4
|
+
InfoIcon,
|
|
5
|
+
LightbulbIcon,
|
|
6
|
+
ShieldAlertIcon,
|
|
7
|
+
} from "../core/icons.js";
|
|
8
|
+
import { cn } from "../util/cn.js";
|
|
9
|
+
|
|
10
|
+
const stylesMap = {
|
|
11
|
+
note: {
|
|
12
|
+
border: "border-gray-300 dark:border-zinc-800",
|
|
13
|
+
bg: "bg-gray-100 dark:bg-zinc-800/50",
|
|
14
|
+
iconColor: "text-gray-600 dark:text-zinc-300",
|
|
15
|
+
titleColor: "text-gray-600 dark:text-zinc-300",
|
|
16
|
+
textColor: "text-gray-600 dark:text-zinc-300",
|
|
17
|
+
Icon: InfoIcon,
|
|
18
|
+
},
|
|
19
|
+
tip: {
|
|
20
|
+
border: "border-green-500 dark:border-green-800",
|
|
21
|
+
bg: "bg-green-200/25 dark:bg-green-950/70",
|
|
22
|
+
iconColor: "text-green-600 dark:text-green-200",
|
|
23
|
+
titleColor: "text-green-700 dark:text-green-200",
|
|
24
|
+
textColor: "text-green-600 dark:text-green-50",
|
|
25
|
+
Icon: LightbulbIcon,
|
|
26
|
+
},
|
|
27
|
+
info: {
|
|
28
|
+
border: "border-blue-400 dark:border-blue-900/60",
|
|
29
|
+
bg: "bg-blue-50 dark:bg-blue-950/40",
|
|
30
|
+
iconColor: "text-blue-400 dark:text-blue-200",
|
|
31
|
+
titleColor: "text-blue-700 dark:text-blue-200",
|
|
32
|
+
textColor: "text-blue-600 dark:text-blue-100",
|
|
33
|
+
Icon: InfoIcon,
|
|
34
|
+
},
|
|
35
|
+
caution: {
|
|
36
|
+
border: "border-yellow-400 dark:border-yellow-400/25",
|
|
37
|
+
bg: "bg-yellow-100/60 dark:bg-yellow-400/10",
|
|
38
|
+
iconColor: "text-yellow-500 dark:text-yellow-300",
|
|
39
|
+
titleColor: "text-yellow-600 dark:text-yellow-300",
|
|
40
|
+
textColor: "text-yellow-700 dark:text-yellow-200",
|
|
41
|
+
Icon: AlertTriangleIcon,
|
|
42
|
+
},
|
|
43
|
+
danger: {
|
|
44
|
+
border: "border-rose-400 dark:border-rose-800",
|
|
45
|
+
bg: "bg-rose-50 dark:bg-rose-950/40",
|
|
46
|
+
iconColor: "text-rose-400 dark:text-rose-300",
|
|
47
|
+
titleColor: "text-rose-800 dark:text-rose-300",
|
|
48
|
+
textColor: "text-rose-700 dark:text-rose-100",
|
|
49
|
+
Icon: ShieldAlertIcon,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
type CalloutProps = {
|
|
54
|
+
type: keyof typeof stylesMap;
|
|
55
|
+
title?: string;
|
|
56
|
+
children: ReactNode;
|
|
57
|
+
className?: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const Callout = ({ type, children, title, className }: CalloutProps) => {
|
|
61
|
+
const { border, bg, iconColor, titleColor, textColor, Icon } =
|
|
62
|
+
stylesMap[type];
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<div
|
|
66
|
+
className={cn(
|
|
67
|
+
"not-prose grid grid-cols-[fit-content_1fr] grid-rows-[fit-content_1fr] gap-x-4 gap-y-2 text-md rounded-md border p-4",
|
|
68
|
+
"[&_a]:underline [&_a]:decoration-current [&_a]:decoration-from-font [&_a]:underline-offset-4 hover:[&_a]:decoration-1",
|
|
69
|
+
"[&_code]:!bg-transparent [&_code]:!border-none",
|
|
70
|
+
title && "items-center",
|
|
71
|
+
border,
|
|
72
|
+
bg,
|
|
73
|
+
className,
|
|
74
|
+
)}
|
|
75
|
+
>
|
|
76
|
+
<Icon
|
|
77
|
+
className={cn(!title && "mt-1 translate-y-px", iconColor)}
|
|
78
|
+
size={20}
|
|
79
|
+
aria-hidden="true"
|
|
80
|
+
/>
|
|
81
|
+
{title && <h3 className={cn("font-medium", titleColor)}>{title}</h3>}
|
|
82
|
+
<div className={cn("col-start-2", !title && "row-start-1", textColor)}>
|
|
83
|
+
{children}
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "../util/cn.js";
|
|
3
|
+
|
|
4
|
+
const Card = React.forwardRef<
|
|
5
|
+
HTMLDivElement,
|
|
6
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
7
|
+
>(({ className, ...props }, ref) => (
|
|
8
|
+
<div
|
|
9
|
+
ref={ref}
|
|
10
|
+
className={cn(
|
|
11
|
+
"rounded-xl border border-border bg-card text-card-foreground shadow",
|
|
12
|
+
className,
|
|
13
|
+
)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
));
|
|
17
|
+
Card.displayName = "Card";
|
|
18
|
+
|
|
19
|
+
const CardHeader = React.forwardRef<
|
|
20
|
+
HTMLDivElement,
|
|
21
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
22
|
+
>(({ className, ...props }, ref) => (
|
|
23
|
+
<div
|
|
24
|
+
ref={ref}
|
|
25
|
+
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
));
|
|
29
|
+
CardHeader.displayName = "CardHeader";
|
|
30
|
+
|
|
31
|
+
const CardTitle = React.forwardRef<
|
|
32
|
+
HTMLParagraphElement,
|
|
33
|
+
React.HTMLAttributes<HTMLHeadingElement>
|
|
34
|
+
>(({ className, ...props }, ref) => (
|
|
35
|
+
<h3
|
|
36
|
+
ref={ref}
|
|
37
|
+
className={cn("font-semibold leading-none tracking-tight", className)}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
));
|
|
41
|
+
CardTitle.displayName = "CardTitle";
|
|
42
|
+
|
|
43
|
+
const CardDescription = React.forwardRef<
|
|
44
|
+
HTMLParagraphElement,
|
|
45
|
+
React.HTMLAttributes<HTMLParagraphElement>
|
|
46
|
+
>(({ className, ...props }, ref) => (
|
|
47
|
+
<p
|
|
48
|
+
ref={ref}
|
|
49
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
));
|
|
53
|
+
CardDescription.displayName = "CardDescription";
|
|
54
|
+
|
|
55
|
+
const CardContent = React.forwardRef<
|
|
56
|
+
HTMLDivElement,
|
|
57
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
58
|
+
>(({ className, ...props }, ref) => (
|
|
59
|
+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
|
60
|
+
));
|
|
61
|
+
CardContent.displayName = "CardContent";
|
|
62
|
+
|
|
63
|
+
const CardFooter = React.forwardRef<
|
|
64
|
+
HTMLDivElement,
|
|
65
|
+
React.HTMLAttributes<HTMLDivElement>
|
|
66
|
+
>(({ className, ...props }, ref) => (
|
|
67
|
+
<div
|
|
68
|
+
ref={ref}
|
|
69
|
+
className={cn("flex items-center p-6 pt-0", className)}
|
|
70
|
+
{...props}
|
|
71
|
+
/>
|
|
72
|
+
));
|
|
73
|
+
CardFooter.displayName = "CardFooter";
|
|
74
|
+
|
|
75
|
+
export {
|
|
76
|
+
Card,
|
|
77
|
+
CardContent,
|
|
78
|
+
CardDescription,
|
|
79
|
+
CardFooter,
|
|
80
|
+
CardHeader,
|
|
81
|
+
CardTitle,
|
|
82
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../util/cn.js";
|
|
4
|
+
|
|
5
|
+
const noteVariants = cva(
|
|
6
|
+
"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
|
|
7
|
+
{
|
|
8
|
+
variants: {
|
|
9
|
+
variant: {
|
|
10
|
+
default: "bg-background text-foreground",
|
|
11
|
+
destructive:
|
|
12
|
+
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
variant: "default",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const Note = React.forwardRef<
|
|
22
|
+
HTMLDivElement,
|
|
23
|
+
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof noteVariants>
|
|
24
|
+
>(({ className, variant, ...props }, ref) => (
|
|
25
|
+
<div
|
|
26
|
+
ref={ref}
|
|
27
|
+
role="alert"
|
|
28
|
+
className={cn(noteVariants({ variant }), className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
));
|
|
32
|
+
Note.displayName = "Alert";
|
|
33
|
+
|
|
34
|
+
const NoteTitle = React.forwardRef<
|
|
35
|
+
HTMLParagraphElement,
|
|
36
|
+
React.HTMLAttributes<HTMLHeadingElement>
|
|
37
|
+
>(({ className, ...props }, ref) => (
|
|
38
|
+
<h5
|
|
39
|
+
ref={ref}
|
|
40
|
+
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
));
|
|
44
|
+
NoteTitle.displayName = "AlertTitle";
|
|
45
|
+
|
|
46
|
+
const NoteDescription = React.forwardRef<
|
|
47
|
+
HTMLParagraphElement,
|
|
48
|
+
React.HTMLAttributes<HTMLParagraphElement>
|
|
49
|
+
>(({ className, ...props }, ref) => (
|
|
50
|
+
<div
|
|
51
|
+
ref={ref}
|
|
52
|
+
className={cn("text-sm [&_p]:leading-relaxed", className)}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
));
|
|
56
|
+
NoteDescription.displayName = "AlertDescription";
|
|
57
|
+
|
|
58
|
+
export { Note, NoteDescription, NoteTitle };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
3
|
+
import { cn } from "../util/cn.js";
|
|
4
|
+
|
|
5
|
+
const Tabs = TabsPrimitive.Root;
|
|
6
|
+
|
|
7
|
+
const TabsList = React.forwardRef<
|
|
8
|
+
React.ElementRef<typeof TabsPrimitive.List>,
|
|
9
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
|
10
|
+
>(({ className, ...props }, ref) => (
|
|
11
|
+
<TabsPrimitive.List
|
|
12
|
+
ref={ref}
|
|
13
|
+
className={cn(
|
|
14
|
+
"inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
|
|
15
|
+
className,
|
|
16
|
+
)}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
));
|
|
20
|
+
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
21
|
+
|
|
22
|
+
const TabsTrigger = React.forwardRef<
|
|
23
|
+
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
24
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
|
25
|
+
>(({ className, ...props }, ref) => (
|
|
26
|
+
<TabsPrimitive.Trigger
|
|
27
|
+
ref={ref}
|
|
28
|
+
className={cn(
|
|
29
|
+
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
|
|
30
|
+
className,
|
|
31
|
+
)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
));
|
|
35
|
+
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
36
|
+
|
|
37
|
+
const TabsContent = React.forwardRef<
|
|
38
|
+
React.ElementRef<typeof TabsPrimitive.Content>,
|
|
39
|
+
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
|
40
|
+
>(({ className, ...props }, ref) => (
|
|
41
|
+
<TabsPrimitive.Content
|
|
42
|
+
ref={ref}
|
|
43
|
+
className={cn(
|
|
44
|
+
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
45
|
+
className,
|
|
46
|
+
)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
));
|
|
50
|
+
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
51
|
+
|
|
52
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { MDXProvider } from "@mdx-js/react";
|
|
2
|
+
import type { ComponentProps } from "react";
|
|
3
|
+
|
|
4
|
+
import { Link } from "react-router-dom";
|
|
5
|
+
import { Heading } from "../Heading.js";
|
|
6
|
+
import { SyntaxHighlight } from "../components/SyntaxHighlight.js";
|
|
7
|
+
import { Callout } from "../ui/Callout.js";
|
|
8
|
+
import { cn } from "./cn.js";
|
|
9
|
+
|
|
10
|
+
export type MdxComponentsType = ComponentProps<
|
|
11
|
+
typeof MDXProvider
|
|
12
|
+
>["components"];
|
|
13
|
+
|
|
14
|
+
export const MdxComponents = {
|
|
15
|
+
img: (props) => {
|
|
16
|
+
if (/\.(mp4|webm|mov|avi)$/.test(props.src ?? "")) {
|
|
17
|
+
return <video src={props.src} controls playsInline autoPlay loop />;
|
|
18
|
+
}
|
|
19
|
+
return <img {...props} className="rounded-md" />;
|
|
20
|
+
},
|
|
21
|
+
h1: ({ children, id }) => <Heading level={1} id={id} children={children} />,
|
|
22
|
+
h2: ({ children, id }) => <Heading level={2} id={id} children={children} />,
|
|
23
|
+
h3: ({ children, id }) => <Heading level={3} id={id} children={children} />,
|
|
24
|
+
h4: ({ children, id }) => <Heading level={4} id={id} children={children} />,
|
|
25
|
+
h5: ({ children, id }) => <Heading level={5} id={id} children={children} />,
|
|
26
|
+
h6: ({ children, id }) => <Heading level={6} id={id} children={children} />,
|
|
27
|
+
a: ({ href, ...props }) =>
|
|
28
|
+
href && !href.startsWith("http") ? (
|
|
29
|
+
<Link to={href} relative="path" {...props} />
|
|
30
|
+
) : (
|
|
31
|
+
<a href={href} target="_blank" {...props} />
|
|
32
|
+
),
|
|
33
|
+
Callout,
|
|
34
|
+
tip: (props) => <Callout type="tip" {...props} />,
|
|
35
|
+
info: (props) => <Callout type="info" {...props} />,
|
|
36
|
+
note: (props) => <Callout type="note" {...props} />,
|
|
37
|
+
caution: (props) => <Callout type="caution" {...props} />,
|
|
38
|
+
warning: (props) => <Callout type="caution" {...props} />,
|
|
39
|
+
danger: (props) => <Callout type="danger" {...props} />,
|
|
40
|
+
|
|
41
|
+
pre: ({ children }) => <>{children}</>,
|
|
42
|
+
code: ({ className, children, ...props }) => {
|
|
43
|
+
// `inline` provided by the rehype plugin, as react-markdown removed support for that
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
const inline = (props as any).inline;
|
|
46
|
+
|
|
47
|
+
if (!inline) {
|
|
48
|
+
const match = className?.match(/language?-(\w+)/);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<SyntaxHighlight
|
|
52
|
+
language={match?.[1] ?? "markup"}
|
|
53
|
+
className="rounded-xl overflow-x-auto p-4 border border-border dark:!bg-foreground/10 dark:border-transparent"
|
|
54
|
+
code={String(children).trim()}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<code
|
|
61
|
+
className={cn(
|
|
62
|
+
className,
|
|
63
|
+
"font-mono border border-border p-1 py-0.5 rounded bg-border/50 dark:bg-border/70",
|
|
64
|
+
)}
|
|
65
|
+
>
|
|
66
|
+
{children}
|
|
67
|
+
</code>
|
|
68
|
+
);
|
|
69
|
+
},
|
|
70
|
+
} satisfies MdxComponentsType;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
|
+
import { ClassValue } from "clsx";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { JSX } from "react/jsx-runtime";
|
|
5
|
+
import { cn } from "./cn.js";
|
|
6
|
+
|
|
7
|
+
const createVariantComponent = <
|
|
8
|
+
E extends keyof React.ReactHTML,
|
|
9
|
+
C extends ReturnType<typeof cva>,
|
|
10
|
+
>(
|
|
11
|
+
tag: E,
|
|
12
|
+
cvx: ClassValue | C,
|
|
13
|
+
// variantProps: Array<keyof VariantProps<C>> = [],
|
|
14
|
+
) => {
|
|
15
|
+
const MyVariant = ({
|
|
16
|
+
className,
|
|
17
|
+
...props
|
|
18
|
+
}: JSX.IntrinsicElements[E] & { className?: ClassValue }) =>
|
|
19
|
+
React.createElement(tag, {
|
|
20
|
+
...props,
|
|
21
|
+
className:
|
|
22
|
+
typeof cvx === "function" ? cvx({ className }) : cn(cvx, className),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
MyVariant.displayName = `VariantComponent(${tag})`;
|
|
26
|
+
|
|
27
|
+
return MyVariant;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default createVariantComponent;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const createWaitForNotify = <T extends NonNullable<unknown>>() => {
|
|
2
|
+
const resolveMap = new Map<string, (value: T | PromiseLike<T>) => void>();
|
|
3
|
+
|
|
4
|
+
const waitFor = (id: string) =>
|
|
5
|
+
new Promise<T>((resolve) => {
|
|
6
|
+
resolveMap.set(id, resolve);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const notify = (id: string, data: T) => {
|
|
10
|
+
const resolveFn = resolveMap.get(id);
|
|
11
|
+
if (resolveFn) {
|
|
12
|
+
resolveFn(data);
|
|
13
|
+
resolveMap.delete(id);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
return [waitFor, notify] as const;
|
|
18
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type MapValuesToKeysIfAllowed<T> = {
|
|
2
|
+
[K in keyof T]: T[K] extends PropertyKey ? K : never;
|
|
3
|
+
};
|
|
4
|
+
type Filter<T> = MapValuesToKeysIfAllowed<T>[keyof T];
|
|
5
|
+
|
|
6
|
+
export const groupBy = <
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
+
T extends Record<PropertyKey, any>,
|
|
9
|
+
Key extends Filter<T>,
|
|
10
|
+
>(
|
|
11
|
+
arr: T[],
|
|
12
|
+
key: Key,
|
|
13
|
+
): Record<T[Key], T[]> =>
|
|
14
|
+
arr.reduce(
|
|
15
|
+
(accumulator, val) => {
|
|
16
|
+
const groupedKey = val[key];
|
|
17
|
+
if (!accumulator[groupedKey]) {
|
|
18
|
+
accumulator[groupedKey] = [];
|
|
19
|
+
}
|
|
20
|
+
accumulator[groupedKey].push(val);
|
|
21
|
+
return accumulator;
|
|
22
|
+
},
|
|
23
|
+
{} as Record<T[Key], T[]>,
|
|
24
|
+
);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const joinPath = (
|
|
2
|
+
...parts: Array<string | null | undefined | boolean>
|
|
3
|
+
) => {
|
|
4
|
+
const cleanPath = parts
|
|
5
|
+
.filter((part): part is string => Boolean(part))
|
|
6
|
+
.map((part) => part.replace(/(^\/+|\/+$)/g, "")) // Strip leading and trailing slashes
|
|
7
|
+
.join("/");
|
|
8
|
+
|
|
9
|
+
return cleanPath ? `/${cleanPath}` : "";
|
|
10
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const c2n = (c: string) =>
|
|
2
|
+
Math.abs(
|
|
3
|
+
isNaN(parseInt(c))
|
|
4
|
+
? c.toLowerCase().charCodeAt(0) - 96
|
|
5
|
+
: isNaN(parseInt(c))
|
|
6
|
+
? 0
|
|
7
|
+
: parseInt(c),
|
|
8
|
+
);
|
|
9
|
+
const s2n = (s: string) =>
|
|
10
|
+
s.length > 1
|
|
11
|
+
? parseInt(s.split("").reduce((a, c) => `${c2n(a) + c2n(c)}`))
|
|
12
|
+
: c2n(s);
|
|
13
|
+
|
|
14
|
+
export const pastellize = (
|
|
15
|
+
s: string,
|
|
16
|
+
options: {
|
|
17
|
+
saturation?: number;
|
|
18
|
+
lightness?: number;
|
|
19
|
+
} = {},
|
|
20
|
+
) => {
|
|
21
|
+
const hue = (3 * s2n(s) + 2 * s2n(s) + s2n(s)) % 360;
|
|
22
|
+
const { saturation = 75, lightness = 60 } = options;
|
|
23
|
+
|
|
24
|
+
return `${hue}deg ${saturation}% ${lightness}%`;
|
|
25
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { isPathItem } from "../components/navigation/util.js";
|
|
2
|
+
import type {
|
|
3
|
+
NavigationCategory,
|
|
4
|
+
NavigationCategoryItem,
|
|
5
|
+
NavigationItem,
|
|
6
|
+
} from "../core/DevPortalContext.js";
|
|
7
|
+
import { joinPath } from "./joinPath.js";
|
|
8
|
+
|
|
9
|
+
export type NavigationNode = NavigationCategoryItem | NavigationCategory;
|
|
10
|
+
type Callback<T> = (
|
|
11
|
+
node: NavigationNode,
|
|
12
|
+
fullPath: string,
|
|
13
|
+
parentNodes: NavigationNode[],
|
|
14
|
+
) => T | undefined;
|
|
15
|
+
|
|
16
|
+
export const traverseNavigationNode = <T>(
|
|
17
|
+
node: NavigationNode,
|
|
18
|
+
callback: Callback<T>,
|
|
19
|
+
parentPath: string,
|
|
20
|
+
parentNodes: NavigationNode[] = [],
|
|
21
|
+
): T | undefined => {
|
|
22
|
+
const newPath = isPathItem(node)
|
|
23
|
+
? joinPath(parentPath, node.path)
|
|
24
|
+
: parentPath;
|
|
25
|
+
const result = callback(node, newPath, parentNodes);
|
|
26
|
+
|
|
27
|
+
if (result !== undefined) return result;
|
|
28
|
+
|
|
29
|
+
if ("children" in node && node.children) {
|
|
30
|
+
const newParentNodes = [...parentNodes, node];
|
|
31
|
+
for (const child of node.children) {
|
|
32
|
+
const childResult = traverseNavigationNode(
|
|
33
|
+
child,
|
|
34
|
+
callback,
|
|
35
|
+
newPath,
|
|
36
|
+
newParentNodes,
|
|
37
|
+
);
|
|
38
|
+
if (childResult !== undefined) return childResult;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const traverseNavigation = <T>(
|
|
45
|
+
navItem: NavigationItem,
|
|
46
|
+
callback: Callback<T>,
|
|
47
|
+
): T | undefined => {
|
|
48
|
+
if (navItem.categories) {
|
|
49
|
+
for (const category of navItem.categories) {
|
|
50
|
+
const result = traverseNavigationNode(category, callback, navItem.path);
|
|
51
|
+
if (result !== undefined) return result;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { useLocation } from "react-router-dom";
|
|
3
|
+
import { useViewportAnchor } from "../components/context/ViewportAnchorContext.js";
|
|
4
|
+
|
|
5
|
+
export const useScrollToAnchor = () => {
|
|
6
|
+
const location = useLocation();
|
|
7
|
+
const { setActiveAnchor } = useViewportAnchor();
|
|
8
|
+
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (!location.hash) return;
|
|
11
|
+
|
|
12
|
+
const hash = location.hash.split("/")[0].slice(1);
|
|
13
|
+
|
|
14
|
+
const element = document.getElementById(decodeURIComponent(hash));
|
|
15
|
+
if (element) {
|
|
16
|
+
// on page navigation element might be in DOM but not yet scrollable, so wait for a frame
|
|
17
|
+
requestAnimationFrame(() => {
|
|
18
|
+
element.scrollIntoView();
|
|
19
|
+
requestIdleCallback(() => setActiveAnchor(hash));
|
|
20
|
+
});
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// on page load, the element might not be available yet
|
|
25
|
+
const observer = new MutationObserver((_mutations, obs) => {
|
|
26
|
+
const element = document.getElementById(decodeURIComponent(hash));
|
|
27
|
+
if (!element) return;
|
|
28
|
+
|
|
29
|
+
element.scrollIntoView();
|
|
30
|
+
requestIdleCallback(() => setActiveAnchor(hash));
|
|
31
|
+
obs.disconnect();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
35
|
+
|
|
36
|
+
return () => observer.disconnect();
|
|
37
|
+
}, [location.hash, setActiveAnchor]);
|
|
38
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
import { useLocation } from "react-router-dom";
|
|
3
|
+
|
|
4
|
+
export const useScrollToTop = () => {
|
|
5
|
+
const location = useLocation();
|
|
6
|
+
const previousPath = useRef(location.pathname);
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (previousPath.current === location.pathname) return;
|
|
10
|
+
window.scrollTo(0, 0);
|
|
11
|
+
previousPath.current = location.pathname;
|
|
12
|
+
}, [location.pathname]);
|
|
13
|
+
};
|