zudoku 0.35.2 → 0.35.4
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/components/InlineCode.js +2 -9
- package/dist/lib/components/InlineCode.js.map +1 -1
- package/dist/lib/components/Layout.js +2 -2
- package/dist/lib/components/Layout.js.map +1 -1
- package/dist/lib/errors/ErrorAlert.js +6 -1
- package/dist/lib/errors/ErrorAlert.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js +3 -11
- package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/ParamInfos.d.ts +6 -0
- package/dist/lib/plugins/openapi/ParamInfos.js +34 -0
- package/dist/lib/plugins/openapi/ParamInfos.js.map +1 -0
- package/dist/lib/plugins/openapi/ParameterListItem.js +6 -4
- package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/components/EnumValues.d.ts +5 -0
- package/dist/lib/plugins/openapi/components/EnumValues.js +15 -0
- package/dist/lib/plugins/openapi/components/EnumValues.js.map +1 -0
- package/dist/lib/plugins/openapi/components/SelectOnClick.d.ts +5 -0
- package/dist/lib/plugins/openapi/components/SelectOnClick.js +16 -0
- package/dist/lib/plugins/openapi/components/SelectOnClick.js.map +1 -0
- package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js +7 -8
- package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js.map +1 -1
- package/dist/lib/ui/Button.d.ts +2 -2
- package/dist/lib/ui/Button.js +1 -0
- package/dist/lib/ui/Button.js.map +1 -1
- package/dist/lib/ui/SyntaxHighlight.js +2 -0
- package/dist/lib/ui/SyntaxHighlight.js.map +1 -1
- package/lib/{Markdown-D1Y3cd9l.js → Markdown-hBN9vkm5.js} +1045 -1026
- package/lib/Markdown-hBN9vkm5.js.map +1 -0
- package/lib/{MdxPage-CUL_SQzW.js → MdxPage-UCWwxhzC.js} +2 -2
- package/lib/{MdxPage-CUL_SQzW.js.map → MdxPage-UCWwxhzC.js.map} +1 -1
- package/lib/{OasProvider-_ye9MUAd.js → OasProvider-BbSqUQka.js} +2 -2
- package/lib/{OasProvider-_ye9MUAd.js.map → OasProvider-BbSqUQka.js.map} +1 -1
- package/lib/{OperationList-Br5x22KD.js → OperationList-CENzwqY8.js} +1992 -1935
- package/lib/OperationList-CENzwqY8.js.map +1 -0
- package/lib/SlotletProvider-D-XPr1Wg.js +338 -0
- package/lib/SlotletProvider-D-XPr1Wg.js.map +1 -0
- package/lib/{Spinner-1KrEmx1V.js → Spinner-C6n4eOvh.js} +13 -12
- package/lib/Spinner-C6n4eOvh.js.map +1 -0
- package/lib/SyntaxHighlight-BEoSoPEo.js +2890 -0
- package/lib/SyntaxHighlight-BEoSoPEo.js.map +1 -0
- package/lib/{index-C7TIhpXK.js → index-BVhQWA89.js} +5 -5
- package/lib/{index-C7TIhpXK.js.map → index-BVhQWA89.js.map} +1 -1
- package/lib/prism-jsstacktrace.min-BfobCF2F.js +2 -0
- package/lib/prism-jsstacktrace.min-BfobCF2F.js.map +1 -0
- package/lib/ui/ActionButton.js +1 -1
- package/lib/ui/Button.js +12 -11
- package/lib/ui/Button.js.map +1 -1
- package/lib/ui/SyntaxHighlight.js +8 -2883
- package/lib/ui/SyntaxHighlight.js.map +1 -1
- package/lib/zudoku.components.js +40 -40
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.plugin-api-catalog.js +1 -1
- package/lib/zudoku.plugin-api-keys.js +1 -1
- package/lib/zudoku.plugin-custom-pages.js +1 -1
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +1 -1
- package/package.json +1 -1
- package/src/lib/components/InlineCode.tsx +11 -16
- package/src/lib/components/Layout.tsx +2 -2
- package/src/lib/errors/ErrorAlert.tsx +24 -17
- package/src/lib/plugins/openapi/OperationListItem.tsx +4 -16
- package/src/lib/plugins/openapi/ParamInfos.tsx +64 -0
- package/src/lib/plugins/openapi/ParameterListItem.tsx +12 -12
- package/src/lib/plugins/openapi/components/EnumValues.tsx +58 -0
- package/src/lib/plugins/openapi/components/SelectOnClick.tsx +29 -0
- package/src/lib/plugins/openapi/schema/SchemaPropertyItem.tsx +19 -28
- package/src/lib/ui/Button.tsx +3 -1
- package/src/lib/ui/SyntaxHighlight.tsx +2 -0
- package/lib/Markdown-D1Y3cd9l.js.map +0 -1
- package/lib/OperationList-Br5x22KD.js.map +0 -1
- package/lib/SlotletProvider-iDmNlxD5.js +0 -221
- package/lib/SlotletProvider-iDmNlxD5.js.map +0 -1
- package/lib/Spinner-1KrEmx1V.js.map +0 -1
|
@@ -5,7 +5,7 @@ import { j as d } from "./joinUrl-10po2Jdj.js";
|
|
|
5
5
|
import { u as j, b as y } from "./hook-CfCFKZ-2.js";
|
|
6
6
|
import { H as v } from "./index.esm-CltAN0Tf.js";
|
|
7
7
|
import { Link as N } from "./zudoku.components.js";
|
|
8
|
-
import { H as S, M as w } from "./Markdown-
|
|
8
|
+
import { H as S, M as w } from "./Markdown-hBN9vkm5.js";
|
|
9
9
|
const H = ({
|
|
10
10
|
items: s,
|
|
11
11
|
filterCatalogItems: l = (n) => n,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-CYK1ROHF.js";
|
|
2
2
|
import { RotateCwIcon as j, TrashIcon as v, EyeOffIcon as w, EyeIcon as K, CheckIcon as b, CopyIcon as k, FileKey2Icon as N } from "lucide-react";
|
|
3
|
-
import { D as I, S as x, R as S } from "./SlotletProvider-
|
|
3
|
+
import { D as I, S as x, R as S } from "./SlotletProvider-D-XPr1Wg.js";
|
|
4
4
|
import { i as c } from "./invariant-Caa8-XvF.js";
|
|
5
5
|
import { u as h } from "./useQuery-CQUwWR9i.js";
|
|
6
6
|
import { u as d, S as A, a as C, b as E, c as P, d as D, e as p } from "./Select-FAYHOYTy.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { j as o } from "./jsx-runtime-CYK1ROHF.js";
|
|
2
2
|
import a from "react";
|
|
3
|
-
import { P as n } from "./Markdown-
|
|
3
|
+
import { P as n } from "./Markdown-hBN9vkm5.js";
|
|
4
4
|
import { c } from "./cn-qaFjX9_3.js";
|
|
5
5
|
import { u as p } from "./useExposedProps-BslIn-FE.js";
|
|
6
6
|
const u = ({
|
|
@@ -53,7 +53,7 @@ const P = (e) => ({
|
|
|
53
53
|
const u = {
|
|
54
54
|
path: r,
|
|
55
55
|
lazy: async () => {
|
|
56
|
-
const { MdxPage: p } = await import("./MdxPage-
|
|
56
|
+
const { MdxPage: p } = await import("./MdxPage-UCWwxhzC.js"), { default: f, ...l } = await i();
|
|
57
57
|
return {
|
|
58
58
|
element: /* @__PURE__ */ d.jsx(
|
|
59
59
|
p,
|
|
@@ -5,7 +5,7 @@ import "./chunk-HA7DTUK3-ZGg2W6yV.js";
|
|
|
5
5
|
import "./hook-CfCFKZ-2.js";
|
|
6
6
|
import "./ui/Button.js";
|
|
7
7
|
import "./joinUrl-10po2Jdj.js";
|
|
8
|
-
import { U as n, o as s } from "./index-
|
|
8
|
+
import { U as n, o as s } from "./index-BVhQWA89.js";
|
|
9
9
|
export {
|
|
10
10
|
n as UNTAGGED_PATH,
|
|
11
11
|
s as openApiPlugin
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
+
import { SelectOnClick } from "../plugins/openapi/components/SelectOnClick.js";
|
|
2
3
|
import { cn } from "../util/cn.js";
|
|
3
4
|
|
|
4
5
|
export const InlineCode = ({
|
|
@@ -10,20 +11,14 @@ export const InlineCode = ({
|
|
|
10
11
|
children: ReactNode;
|
|
11
12
|
selectOnClick?: boolean;
|
|
12
13
|
}) => (
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"font-mono border p-1 py-0.5 rounded bg-border/50 dark:bg-border/70 [overflow-wrap:anywhere]",
|
|
24
|
-
className,
|
|
25
|
-
)}
|
|
26
|
-
>
|
|
27
|
-
{children}
|
|
28
|
-
</code>
|
|
14
|
+
<SelectOnClick asChild enabled={selectOnClick}>
|
|
15
|
+
<code
|
|
16
|
+
className={cn(
|
|
17
|
+
"font-mono border p-1 py-0.5 rounded bg-border/50 dark:bg-border/70 [overflow-wrap:anywhere]",
|
|
18
|
+
className,
|
|
19
|
+
)}
|
|
20
|
+
>
|
|
21
|
+
{children}
|
|
22
|
+
</code>
|
|
23
|
+
</SelectOnClick>
|
|
29
24
|
);
|
|
@@ -12,7 +12,7 @@ import { Slotlet } from "./SlotletProvider.js";
|
|
|
12
12
|
import { Spinner } from "./Spinner.js";
|
|
13
13
|
|
|
14
14
|
const LoadingFallback = () => (
|
|
15
|
-
<main className="col-span-full grid place-items-center">
|
|
15
|
+
<main className="col-span-full row-span-full grid place-items-center">
|
|
16
16
|
<Spinner />
|
|
17
17
|
</main>
|
|
18
18
|
);
|
|
@@ -62,7 +62,7 @@ export const Layout = ({ children }: { children?: ReactNode }) => {
|
|
|
62
62
|
<Header />
|
|
63
63
|
<Slotlet name="layout-after-head" />
|
|
64
64
|
|
|
65
|
-
<div className="grid lg:grid-cols-[var(--side-nav-width)_1fr] max-w-screen-2xl w-full lg:mx-auto px-4 lg:px-8 2xl:border-x">
|
|
65
|
+
<div className="grid grid-cols-1 grid-rows-[min-content_1fr] lg:grid-cols-[var(--side-nav-width)_1fr] max-w-screen-2xl w-full lg:mx-auto px-4 lg:px-8 2xl:border-x">
|
|
66
66
|
{showSpinner ? (
|
|
67
67
|
<LoadingFallback />
|
|
68
68
|
) : (
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
+
import { SyntaxHighlight } from "zudoku/ui/SyntaxHighlight.js";
|
|
2
3
|
import { DeveloperHint } from "../components/DeveloperHint.js";
|
|
4
|
+
import { Heading } from "../components/Heading.js";
|
|
5
|
+
import { ProseClasses } from "../components/Markdown.js";
|
|
6
|
+
import { cn } from "../util/cn.js";
|
|
3
7
|
import { ZudokuError } from "../util/invariant.js";
|
|
4
8
|
|
|
5
9
|
export function ErrorAlert({ error }: { error: unknown }) {
|
|
@@ -12,24 +16,27 @@ export function ErrorAlert({ error }: { error: unknown }) {
|
|
|
12
16
|
const stack = error instanceof Error ? error.stack : undefined;
|
|
13
17
|
const cause = error instanceof Error ? error.cause : undefined;
|
|
14
18
|
|
|
19
|
+
const stringError = cause instanceof Error ? String(cause.stack) : stack;
|
|
20
|
+
|
|
15
21
|
return (
|
|
16
|
-
<div
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
<div
|
|
23
|
+
className={cn(
|
|
24
|
+
ProseClasses,
|
|
25
|
+
"grid grid-cols-1 !max-w-none pt-[--padding-content-top]",
|
|
26
|
+
)}
|
|
27
|
+
>
|
|
28
|
+
<Heading level={1}>{title}</Heading>
|
|
29
|
+
Error: {message}
|
|
30
|
+
{hint && <DeveloperHint className="mb-4">{hint}</DeveloperHint>}
|
|
31
|
+
{stringError && (
|
|
32
|
+
<div>
|
|
33
|
+
<SyntaxHighlight
|
|
34
|
+
className="max-h-[400px] border mt-2"
|
|
35
|
+
language="jsstacktrace"
|
|
36
|
+
code={stringError}
|
|
37
|
+
/>
|
|
38
|
+
</div>
|
|
39
|
+
)}
|
|
33
40
|
</div>
|
|
34
41
|
);
|
|
35
42
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
|
2
|
-
import {
|
|
2
|
+
import { useState } from "react";
|
|
3
3
|
import { Badge } from "zudoku/ui/Badge.js";
|
|
4
4
|
import { Heading } from "../../components/Heading.js";
|
|
5
5
|
import { Markdown, ProseClasses } from "../../components/Markdown.js";
|
|
@@ -10,6 +10,7 @@ import { renderIf } from "../../util/renderIf.js";
|
|
|
10
10
|
import { OperationsFragment } from "./OperationList.js";
|
|
11
11
|
import { ParameterList } from "./ParameterList.js";
|
|
12
12
|
import { Sidecar } from "./Sidecar.js";
|
|
13
|
+
import { SelectOnClick } from "./components/SelectOnClick.js";
|
|
13
14
|
import { type FragmentType, useFragment } from "./graphql/index.js";
|
|
14
15
|
import { SchemaView } from "./schema/SchemaView.js";
|
|
15
16
|
import { methodForColor } from "./util/methodToColor.js";
|
|
@@ -29,7 +30,6 @@ export const OperationListItem = ({
|
|
|
29
30
|
operation.parameters ?? [],
|
|
30
31
|
(param) => param.in,
|
|
31
32
|
);
|
|
32
|
-
const parentRef = useRef<HTMLDivElement>(null);
|
|
33
33
|
|
|
34
34
|
const first = operation.responses.at(0);
|
|
35
35
|
const [selectedResponse, setSelectedResponse] = useState(first?.statusCode);
|
|
@@ -60,19 +60,7 @@ export const OperationListItem = ({
|
|
|
60
60
|
<span className={methodForColor(operation.method)}>
|
|
61
61
|
{operation.method.toUpperCase()}
|
|
62
62
|
</span>
|
|
63
|
-
<
|
|
64
|
-
ref={parentRef}
|
|
65
|
-
className="max-w-full truncate flex cursor-pointer"
|
|
66
|
-
onClick={() => {
|
|
67
|
-
if (parentRef.current) {
|
|
68
|
-
const range = document.createRange();
|
|
69
|
-
range.selectNodeContents(parentRef.current);
|
|
70
|
-
const selection = window.getSelection();
|
|
71
|
-
selection?.removeAllRanges();
|
|
72
|
-
selection?.addRange(range);
|
|
73
|
-
}
|
|
74
|
-
}}
|
|
75
|
-
>
|
|
63
|
+
<SelectOnClick className="max-w-full truncate flex cursor-pointer">
|
|
76
64
|
{serverUrl && (
|
|
77
65
|
<div className="text-neutral-400 dark:text-neutral-500 truncate">
|
|
78
66
|
{serverUrl}
|
|
@@ -81,7 +69,7 @@ export const OperationListItem = ({
|
|
|
81
69
|
<div className="text-neutral-900 dark:text-neutral-200">
|
|
82
70
|
{operation.path}
|
|
83
71
|
</div>
|
|
84
|
-
</
|
|
72
|
+
</SelectOnClick>
|
|
85
73
|
</div>
|
|
86
74
|
|
|
87
75
|
<div className="flex flex-col gap-4">
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { isValidElement } from "react";
|
|
2
|
+
import { InlineCode } from "../../components/InlineCode.js";
|
|
3
|
+
import { type SchemaObject } from "../../oas/parser/index.js";
|
|
4
|
+
|
|
5
|
+
const getSchemaInfos = (schema?: SchemaObject) => {
|
|
6
|
+
if (!schema) return [];
|
|
7
|
+
|
|
8
|
+
return [
|
|
9
|
+
schema.type === "array" && schema.items.type
|
|
10
|
+
? `${schema.items.type}[]`
|
|
11
|
+
: Array.isArray(schema.type)
|
|
12
|
+
? schema.type.join(" | ")
|
|
13
|
+
: schema.type,
|
|
14
|
+
|
|
15
|
+
schema.enum && "enum",
|
|
16
|
+
schema.format,
|
|
17
|
+
schema.minimum && `min: ${schema.minimum}`,
|
|
18
|
+
schema.maximum && `max: ${schema.maximum}`,
|
|
19
|
+
schema.minLength && `minLength: ${schema.minLength}`,
|
|
20
|
+
schema.maxLength && `maxLength: ${schema.maxLength}`,
|
|
21
|
+
schema.minItems && `minItems: ${schema.minItems}`,
|
|
22
|
+
schema.maxItems && `maxItems: ${schema.maxItems}`,
|
|
23
|
+
schema.uniqueItems && "unique",
|
|
24
|
+
schema.minProperties && `minProps: ${schema.minProperties}`,
|
|
25
|
+
schema.maxProperties && `maxProps: ${schema.maxProperties}`,
|
|
26
|
+
schema.readOnly && "readOnly",
|
|
27
|
+
schema.writeOnly && "writeOnly",
|
|
28
|
+
schema.deprecated && "deprecated",
|
|
29
|
+
schema.pattern && (
|
|
30
|
+
<>
|
|
31
|
+
pattern: <InlineCode className="text-xs">{schema.pattern}</InlineCode>
|
|
32
|
+
</>
|
|
33
|
+
),
|
|
34
|
+
];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const ParamInfos = ({
|
|
38
|
+
schema,
|
|
39
|
+
extraItems = [],
|
|
40
|
+
className,
|
|
41
|
+
}: {
|
|
42
|
+
schema?: SchemaObject;
|
|
43
|
+
extraItems?: unknown[];
|
|
44
|
+
className?: string;
|
|
45
|
+
}) => {
|
|
46
|
+
const filteredItems = [...extraItems, ...getSchemaInfos(schema)].flatMap(
|
|
47
|
+
(item) => (typeof item === "string" || isValidElement(item) ? item : []),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div className={className}>
|
|
52
|
+
{filteredItems.map((item, index) => (
|
|
53
|
+
<span className="text-muted-foreground" key={index}>
|
|
54
|
+
{item}
|
|
55
|
+
{index < filteredItems.length - 1 && (
|
|
56
|
+
<span className="text-muted-foreground/50">
|
|
57
|
+
·
|
|
58
|
+
</span>
|
|
59
|
+
)}
|
|
60
|
+
</span>
|
|
61
|
+
))}
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Badge } from "zudoku/ui/Badge.js";
|
|
2
1
|
import { Markdown } from "../../components/Markdown.js";
|
|
3
2
|
import { type SchemaObject } from "../../oas/graphql/index.js";
|
|
4
3
|
import { ColorizedParam } from "./ColorizedParam.js";
|
|
5
4
|
import type { OperationListItemResult } from "./OperationList.js";
|
|
6
5
|
import type { ParameterGroup } from "./OperationListItem.js";
|
|
6
|
+
import { ParamInfos } from "./ParamInfos.js";
|
|
7
|
+
import { EnumValues } from "./components/EnumValues.js";
|
|
7
8
|
|
|
8
9
|
const getParameterSchema = (
|
|
9
10
|
parameter: ParameterListItemResult,
|
|
@@ -32,29 +33,27 @@ export const ParameterListItem = ({
|
|
|
32
33
|
const paramSchema = getParameterSchema(parameter);
|
|
33
34
|
|
|
34
35
|
return (
|
|
35
|
-
<li className="p-4 bg-border/20 text-sm flex flex-col gap-1">
|
|
36
|
+
<li className="p-4 bg-border/20 text-sm flex flex-col gap-1.5">
|
|
36
37
|
<div className="flex items-center gap-2">
|
|
37
38
|
<code>
|
|
38
39
|
{group === "path" ? (
|
|
39
40
|
<ColorizedParam
|
|
40
41
|
name={parameter.name}
|
|
41
42
|
backgroundOpacity="15%"
|
|
42
|
-
className="px-
|
|
43
|
+
className="px-2"
|
|
43
44
|
slug={`${id}-${parameter.name}`}
|
|
44
45
|
/>
|
|
45
46
|
) : (
|
|
46
47
|
parameter.name
|
|
47
48
|
)}
|
|
48
49
|
</code>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
{parameter.required && <Badge variant="outline">required</Badge>}
|
|
57
|
-
{parameter.style === "form" && <Badge variant="secondary">form</Badge>}
|
|
50
|
+
<ParamInfos
|
|
51
|
+
schema={paramSchema}
|
|
52
|
+
extraItems={[
|
|
53
|
+
parameter.required && "required",
|
|
54
|
+
parameter.style === "form" && "form",
|
|
55
|
+
]}
|
|
56
|
+
/>
|
|
58
57
|
</div>
|
|
59
58
|
{parameter.description && (
|
|
60
59
|
<Markdown
|
|
@@ -62,6 +61,7 @@ export const ParameterListItem = ({
|
|
|
62
61
|
className="text-sm prose-p:my-1 prose-code:whitespace-pre-line"
|
|
63
62
|
/>
|
|
64
63
|
)}
|
|
64
|
+
{paramSchema.enum && <EnumValues values={paramSchema.enum} />}
|
|
65
65
|
</li>
|
|
66
66
|
);
|
|
67
67
|
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Button } from "zudoku/ui/Button.js";
|
|
4
|
+
import { cn } from "../../../util/cn.js";
|
|
5
|
+
import { SelectOnClick } from "./SelectOnClick.js";
|
|
6
|
+
|
|
7
|
+
export const EnumValues = ({
|
|
8
|
+
values,
|
|
9
|
+
className,
|
|
10
|
+
maxVisibleValues = 8,
|
|
11
|
+
}: {
|
|
12
|
+
values: Array<string | number>;
|
|
13
|
+
className?: string;
|
|
14
|
+
maxVisibleValues?: number;
|
|
15
|
+
}) => {
|
|
16
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
17
|
+
|
|
18
|
+
if (!values.length) return null;
|
|
19
|
+
|
|
20
|
+
const shouldCollapse = values.length > maxVisibleValues;
|
|
21
|
+
const visibleValues =
|
|
22
|
+
shouldCollapse && !isOpen ? values.slice(0, maxVisibleValues) : values;
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className={cn("flex flex-wrap gap-1.5 text-xs", className)}>
|
|
26
|
+
<span className="text-muted-foreground">Enum values: </span>
|
|
27
|
+
{visibleValues.map((value) => (
|
|
28
|
+
<div key={value}>
|
|
29
|
+
<SelectOnClick className="border rounded px-1 font-mono cursor-pointer">
|
|
30
|
+
{value}
|
|
31
|
+
</SelectOnClick>
|
|
32
|
+
</div>
|
|
33
|
+
))}
|
|
34
|
+
{shouldCollapse && (
|
|
35
|
+
<Button
|
|
36
|
+
variant="ghost"
|
|
37
|
+
size="sm"
|
|
38
|
+
className="h-fit px-0"
|
|
39
|
+
onClick={() => setIsOpen(!isOpen)}
|
|
40
|
+
>
|
|
41
|
+
{isOpen ? (
|
|
42
|
+
<div className="flex items-center gap-1">
|
|
43
|
+
<ChevronUpIcon size={12} />
|
|
44
|
+
<span className="text-muted-foreground">show less</span>
|
|
45
|
+
</div>
|
|
46
|
+
) : (
|
|
47
|
+
<div className="flex items-center gap-1">
|
|
48
|
+
<ChevronDownIcon size={12} />
|
|
49
|
+
<span className="text-muted-foreground">
|
|
50
|
+
show {values.length - maxVisibleValues} more
|
|
51
|
+
</span>
|
|
52
|
+
</div>
|
|
53
|
+
)}
|
|
54
|
+
</Button>
|
|
55
|
+
)}
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Slot, type SlotProps } from "@radix-ui/react-slot";
|
|
2
|
+
|
|
3
|
+
export const SelectOnClick = ({
|
|
4
|
+
asChild,
|
|
5
|
+
onClick,
|
|
6
|
+
enabled = true,
|
|
7
|
+
...props
|
|
8
|
+
}: {
|
|
9
|
+
asChild?: boolean;
|
|
10
|
+
enabled?: boolean;
|
|
11
|
+
} & SlotProps) => {
|
|
12
|
+
const Component = asChild ? Slot : "span";
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Component
|
|
16
|
+
onClick={(e) => {
|
|
17
|
+
if (enabled) {
|
|
18
|
+
const range = document.createRange();
|
|
19
|
+
range.selectNodeContents(e.currentTarget);
|
|
20
|
+
const selection = window.getSelection();
|
|
21
|
+
selection?.removeAllRanges();
|
|
22
|
+
selection?.addRange(range);
|
|
23
|
+
}
|
|
24
|
+
onClick?.(e);
|
|
25
|
+
}}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import * as Collapsible from "@radix-ui/react-collapsible";
|
|
2
|
-
import {
|
|
2
|
+
import { MinusIcon, PlusIcon, RefreshCcwDotIcon } from "lucide-react";
|
|
3
3
|
import { useCallback, useState } from "react";
|
|
4
|
-
import { Badge } from "zudoku/ui/Badge.js";
|
|
5
4
|
import { Markdown, ProseClasses } from "../../../components/Markdown.js";
|
|
6
5
|
import type { SchemaObject } from "../../../oas/parser/index.js";
|
|
7
6
|
import { Button } from "../../../ui/Button.js";
|
|
8
7
|
import { cn } from "../../../util/cn.js";
|
|
9
8
|
import { objectEntries } from "../../../util/objectEntries.js";
|
|
9
|
+
import { EnumValues } from "../components/EnumValues.js";
|
|
10
|
+
import { ParamInfos } from "../ParamInfos.js";
|
|
10
11
|
import { LogicalGroup } from "./LogicalGroup/LogicalGroup.js";
|
|
11
12
|
import { SchemaView } from "./SchemaView.js";
|
|
12
13
|
import {
|
|
@@ -42,8 +43,8 @@ export const SchemaLogicalGroup = ({
|
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
const RecursiveIndicator = () => (
|
|
45
|
-
<div className="flex items-center gap-
|
|
46
|
-
<RefreshCcwDotIcon size={
|
|
46
|
+
<div className="flex items-center gap-1.5 italic text-xs text-muted-foreground font-mono bg-muted px-2 py-0.5 rounded-md">
|
|
47
|
+
<RefreshCcwDotIcon size={13} />
|
|
47
48
|
<span>circular</span>
|
|
48
49
|
</div>
|
|
49
50
|
);
|
|
@@ -68,11 +69,13 @@ export const SchemaPropertyItem = ({
|
|
|
68
69
|
if (isCircularRef(schema)) {
|
|
69
70
|
return (
|
|
70
71
|
<li className="p-4 bg-border/20 hover:bg-border/30">
|
|
71
|
-
<div className="flex flex-col gap-
|
|
72
|
+
<div className="flex flex-col gap-2.5 justify-between text-sm">
|
|
72
73
|
<div className="flex gap-2 items-center">
|
|
73
74
|
<code>{name}</code>
|
|
74
|
-
<
|
|
75
|
-
|
|
75
|
+
<ParamInfos
|
|
76
|
+
schema={schema}
|
|
77
|
+
extraItems={[group === "optional" && "optional"]}
|
|
78
|
+
/>
|
|
76
79
|
<RecursiveIndicator />
|
|
77
80
|
</div>
|
|
78
81
|
</div>
|
|
@@ -82,30 +85,24 @@ export const SchemaPropertyItem = ({
|
|
|
82
85
|
|
|
83
86
|
return (
|
|
84
87
|
<li className="p-4 bg-border/20 hover:bg-border/30">
|
|
85
|
-
<div className="flex flex-col gap-
|
|
88
|
+
<div className="flex flex-col gap-2.5 justify-between text-sm">
|
|
86
89
|
<div className="flex gap-2 items-center">
|
|
87
90
|
<code>{name}</code>
|
|
88
|
-
<
|
|
89
|
-
{schema
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
<span>{schema.type.join(" | ")}</span>
|
|
93
|
-
) : (
|
|
94
|
-
<span>{schema.type}</span>
|
|
95
|
-
)}
|
|
96
|
-
</Badge>
|
|
97
|
-
{group === "optional" && <Badge variant="outline">optional</Badge>}
|
|
91
|
+
<ParamInfos
|
|
92
|
+
schema={schema}
|
|
93
|
+
extraItems={[group === "optional" && "optional"]}
|
|
94
|
+
/>
|
|
98
95
|
{schema.type === "array" &&
|
|
99
96
|
"items" in schema &&
|
|
100
97
|
isCircularRef(schema.items) && <RecursiveIndicator />}
|
|
101
98
|
</div>
|
|
102
|
-
|
|
103
99
|
{schema.description && (
|
|
104
100
|
<Markdown
|
|
105
101
|
className={cn(ProseClasses, "text-sm leading-normal line-clamp-4")}
|
|
106
102
|
content={schema.description}
|
|
107
103
|
/>
|
|
108
104
|
)}
|
|
105
|
+
{schema.enum && <EnumValues values={schema.enum} />}
|
|
109
106
|
|
|
110
107
|
{(hasLogicalGroupings(schema) || isComplexType(schema)) && (
|
|
111
108
|
<Collapsible.Root
|
|
@@ -115,15 +112,9 @@ export const SchemaPropertyItem = ({
|
|
|
115
112
|
>
|
|
116
113
|
{showCollapseButton && (
|
|
117
114
|
<Collapsible.Trigger asChild>
|
|
118
|
-
<Button
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
className="mt-2 flex gap-1.5"
|
|
122
|
-
>
|
|
123
|
-
<ListPlusIcon size={18} />
|
|
124
|
-
{!isOpen
|
|
125
|
-
? "Show nested properties"
|
|
126
|
-
: "Hide nested properties"}
|
|
115
|
+
<Button variant="expand" size="sm" className="h-7">
|
|
116
|
+
{isOpen ? <MinusIcon size={12} /> : <PlusIcon size={12} />}
|
|
117
|
+
{!isOpen ? "Show properties" : "Hide properties"}
|
|
127
118
|
</Button>
|
|
128
119
|
</Collapsible.Trigger>
|
|
129
120
|
)}
|
package/src/lib/ui/Button.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Slot } from "@radix-ui/react-slot";
|
|
2
|
-
import { cva, VariantProps } from "class-variance-authority";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { cn } from "../util/cn.js";
|
|
5
5
|
|
|
@@ -18,6 +18,8 @@ export const buttonVariants = cva(
|
|
|
18
18
|
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
19
19
|
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
20
20
|
link: "text-primary underline-offset-4 hover:underline",
|
|
21
|
+
expand:
|
|
22
|
+
"flex gap-1.5 border bg-transparent rounded-xl text-muted-foreground hover:text-foreground",
|
|
21
23
|
},
|
|
22
24
|
size: {
|
|
23
25
|
default: "h-9 px-4 py-2",
|
|
@@ -28,6 +28,8 @@ void import("prismjs/components/prism-markdown.min.js");
|
|
|
28
28
|
void import("prismjs/components/prism-javascript.min.js");
|
|
29
29
|
// @ts-expect-error This is untyped
|
|
30
30
|
void import("prismjs/components/prism-typescript.min.js");
|
|
31
|
+
// @ts-expect-error This is untyped
|
|
32
|
+
void import("prismjs/components/prism-jsstacktrace.min.js");
|
|
31
33
|
|
|
32
34
|
import { useTheme } from "next-themes";
|
|
33
35
|
import { memo, useState } from "react";
|