zudoku 0.33.0 → 0.33.2-local.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/config/validators/common.d.ts +226 -8
- package/dist/config/validators/common.js +26 -8
- package/dist/config/validators/common.js.map +1 -1
- package/dist/config/validators/validate.d.ts +89 -2
- package/dist/lib/authentication/hook.d.ts +1 -0
- package/dist/lib/authentication/hook.js +11 -1
- package/dist/lib/authentication/hook.js.map +1 -1
- package/dist/lib/authentication/providers/clerk.js +6 -6
- package/dist/lib/authentication/providers/clerk.js.map +1 -1
- package/dist/lib/authentication/state.js +8 -2
- package/dist/lib/authentication/state.js.map +1 -1
- package/dist/lib/components/Banner.js +1 -1
- package/dist/lib/components/Banner.js.map +1 -1
- package/dist/lib/components/Heading.d.ts +1 -1
- package/dist/lib/components/Layout.js +1 -1
- package/dist/lib/components/Layout.js.map +1 -1
- package/dist/lib/components/index.d.ts +2 -1
- package/dist/lib/core/RouteGuard.d.ts +1 -1
- package/dist/lib/core/RouteGuard.js +24 -18
- package/dist/lib/core/RouteGuard.js.map +1 -1
- package/dist/lib/plugins/api-catalog/Catalog.d.ts +3 -1
- package/dist/lib/plugins/api-catalog/Catalog.js +7 -4
- package/dist/lib/plugins/api-catalog/Catalog.js.map +1 -1
- package/dist/lib/plugins/api-catalog/index.js +1 -1
- package/dist/lib/plugins/api-catalog/index.js.map +1 -1
- package/dist/lib/plugins/markdown/MdxPage.js +1 -1
- package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationList.d.ts +1 -1
- package/dist/lib/plugins/openapi/OperationList.js +2 -1
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js +2 -1
- package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/ParameterList.d.ts +2 -1
- package/dist/lib/plugins/openapi/ParameterList.js +3 -2
- package/dist/lib/plugins/openapi/ParameterList.js.map +1 -1
- package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js +3 -1
- package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/PathParams.d.ts +3 -2
- package/dist/lib/plugins/openapi/playground/PathParams.js +3 -2
- package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.d.ts +4 -1
- package/dist/lib/plugins/openapi/playground/Playground.js +10 -7
- package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
- package/dist/lib/plugins/search-pagefind/PagefindSearch.d.ts +6 -0
- package/dist/lib/plugins/search-pagefind/PagefindSearch.js +66 -0
- package/dist/lib/plugins/search-pagefind/PagefindSearch.js.map +1 -0
- package/dist/lib/plugins/search-pagefind/ResultList.d.ts +8 -0
- package/dist/lib/plugins/search-pagefind/ResultList.js +31 -0
- package/dist/lib/plugins/search-pagefind/ResultList.js.map +1 -0
- package/dist/lib/plugins/search-pagefind/get-results.d.ts +3 -0
- package/dist/lib/plugins/search-pagefind/get-results.js +37 -0
- package/dist/lib/plugins/search-pagefind/get-results.js.map +1 -0
- package/dist/lib/plugins/search-pagefind/index.d.ts +8 -0
- package/dist/lib/plugins/search-pagefind/index.js +9 -0
- package/dist/lib/plugins/search-pagefind/index.js.map +1 -0
- package/dist/lib/plugins/search-pagefind/types.d.ts +85 -0
- package/dist/lib/plugins/search-pagefind/types.js +2 -0
- package/dist/lib/plugins/search-pagefind/types.js.map +1 -0
- package/dist/lib/ui/Command.d.ts +7 -1
- package/dist/lib/ui/Command.js +2 -2
- package/dist/lib/ui/Command.js.map +1 -1
- package/dist/lib/util/useScrollToAnchor.js +6 -8
- package/dist/lib/util/useScrollToAnchor.js.map +1 -1
- package/dist/vite/build.js +4 -0
- package/dist/vite/build.js.map +1 -1
- package/dist/vite/config.js +7 -2
- package/dist/vite/config.js.map +1 -1
- package/dist/vite/dev-server.js +8 -0
- package/dist/vite/dev-server.js.map +1 -1
- package/dist/vite/pagefind.d.ts +4 -0
- package/dist/vite/pagefind.js +15 -0
- package/dist/vite/pagefind.js.map +1 -0
- package/dist/vite/plugin-component.js +4 -0
- package/dist/vite/plugin-component.js.map +1 -1
- package/dist/vite/plugin-search.js +4 -0
- package/dist/vite/plugin-search.js.map +1 -1
- package/dist/vite/prerender/prerender.js +1 -1
- package/dist/vite/prerender/prerender.js.map +1 -1
- package/dist/vite/sitemap.js +2 -1
- package/dist/vite/sitemap.js.map +1 -1
- package/lib/{AuthenticationPlugin-_gUMnGxb.js → AuthenticationPlugin-BCYuduZ9.js} +3 -3
- package/lib/{AuthenticationPlugin-_gUMnGxb.js.map → AuthenticationPlugin-BCYuduZ9.js.map} +1 -1
- package/lib/Command-CrTA1FX0.js +140 -0
- package/lib/Command-CrTA1FX0.js.map +1 -0
- package/lib/Dialog-mi6BrnrM.js +83 -0
- package/lib/Dialog-mi6BrnrM.js.map +1 -0
- package/lib/{Markdown-DePfm7oQ.js → Markdown-DofXBcqg.js} +2 -2
- package/lib/{Markdown-DePfm7oQ.js.map → Markdown-DofXBcqg.js.map} +1 -1
- package/lib/MdxPage-KJcNWIgt.js +200 -0
- package/lib/MdxPage-KJcNWIgt.js.map +1 -0
- package/lib/{OasProvider-Bvu4dDpX.js → OasProvider-HcqBeC4H.js} +4 -4
- package/lib/{OasProvider-Bvu4dDpX.js.map → OasProvider-HcqBeC4H.js.map} +1 -1
- package/lib/{OperationList-DWnNbwVg.js → OperationList-C3wnbFxp.js} +1857 -1816
- package/lib/OperationList-C3wnbFxp.js.map +1 -0
- package/lib/{Select-BmoX1iTH.js → Select-Co6MuS4j.js} +36 -36
- package/lib/{Select-BmoX1iTH.js.map → Select-Co6MuS4j.js.map} +1 -1
- package/lib/{SlotletProvider-DdtIOUi6.js → SlotletProvider-CYFNHuok.js} +4 -4
- package/lib/{SlotletProvider-DdtIOUi6.js.map → SlotletProvider-CYFNHuok.js.map} +1 -1
- package/lib/{chunk-IR6S3I6Y-D_3UmFIn.js → chunk-IR6S3I6Y-CRDBmIgK.js} +3 -3
- package/lib/{chunk-IR6S3I6Y-D_3UmFIn.js.map → chunk-IR6S3I6Y-CRDBmIgK.js.map} +1 -1
- package/lib/hook-LTe5qHSc.js +347 -0
- package/lib/hook-LTe5qHSc.js.map +1 -0
- package/lib/{index-DVBlM15k.js → index-CtkRMvMw.js} +696 -743
- package/lib/index-CtkRMvMw.js.map +1 -0
- package/lib/index-gQD2h1wX.js +447 -0
- package/lib/index-gQD2h1wX.js.map +1 -0
- package/lib/index-vn5bsvmU.js +1399 -0
- package/lib/index-vn5bsvmU.js.map +1 -0
- package/lib/{mutation-DTunCQKB.js → mutation-B81DztCT.js} +2 -2
- package/lib/{mutation-DTunCQKB.js.map → mutation-B81DztCT.js.map} +1 -1
- package/lib/ui/Command.js +105 -78
- package/lib/ui/Command.js.map +1 -1
- package/lib/{useExposedProps-RIvey2Oy.js → useExposedProps-D76yras4.js} +2 -2
- package/lib/{useExposedProps-RIvey2Oy.js.map → useExposedProps-D76yras4.js.map} +1 -1
- package/lib/useQuery-CQUwWR9i.js +1137 -0
- package/lib/useQuery-CQUwWR9i.js.map +1 -0
- package/lib/useScrollToAnchor-DKyrbZoy.js +977 -0
- package/lib/useScrollToAnchor-DKyrbZoy.js.map +1 -0
- package/lib/zudoku.auth-auth0.js +1 -1
- package/lib/zudoku.auth-clerk.js +29 -29
- package/lib/zudoku.auth-clerk.js.map +1 -1
- package/lib/zudoku.auth-openid.js +3 -3
- package/lib/zudoku.components.js +32 -1382
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.hooks.js +1 -1
- package/lib/zudoku.plugin-api-catalog.js +87 -71
- package/lib/zudoku.plugin-api-catalog.js.map +1 -1
- package/lib/zudoku.plugin-api-keys.js +16 -15
- package/lib/zudoku.plugin-api-keys.js.map +1 -1
- package/lib/zudoku.plugin-custom-pages.js +2 -2
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +3 -3
- package/lib/zudoku.plugin-redirect.js +1 -1
- package/lib/zudoku.plugin-search-pagefind.js +274 -0
- package/lib/zudoku.plugin-search-pagefind.js.map +1 -0
- package/package.json +8 -3
- package/src/lib/authentication/hook.ts +12 -1
- package/src/lib/authentication/providers/clerk.tsx +10 -6
- package/src/lib/authentication/state.ts +8 -2
- package/src/lib/components/Banner.tsx +1 -0
- package/src/lib/components/Heading.tsx +1 -1
- package/src/lib/components/Layout.tsx +1 -0
- package/src/lib/core/RouteGuard.tsx +44 -18
- package/src/lib/plugins/api-catalog/Catalog.tsx +23 -7
- package/src/lib/plugins/api-catalog/index.tsx +1 -0
- package/src/lib/plugins/markdown/MdxPage.tsx +5 -1
- package/src/lib/plugins/openapi/OperationList.tsx +15 -3
- package/src/lib/plugins/openapi/OperationListItem.tsx +8 -0
- package/src/lib/plugins/openapi/ParameterList.tsx +4 -0
- package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +7 -0
- package/src/lib/plugins/openapi/Sidecar.tsx +2 -1
- package/src/lib/plugins/openapi/playground/PathParams.tsx +8 -2
- package/src/lib/plugins/openapi/playground/Playground.tsx +61 -5
- package/src/lib/plugins/search-pagefind/PagefindSearch.tsx +135 -0
- package/src/lib/plugins/search-pagefind/ResultList.tsx +104 -0
- package/src/lib/plugins/search-pagefind/get-results.tsx +54 -0
- package/src/lib/plugins/search-pagefind/index.tsx +21 -0
- package/src/lib/plugins/search-pagefind/types.ts +118 -0
- package/src/lib/ui/Command.tsx +25 -3
- package/src/lib/util/useScrollToAnchor.ts +8 -8
- package/README.md +0 -121
- package/lib/MdxPage-DM9mE-G-.js +0 -193
- package/lib/MdxPage-DM9mE-G-.js.map +0 -1
- package/lib/OperationList-DWnNbwVg.js.map +0 -1
- package/lib/hook-4_6pQSo4.js +0 -1460
- package/lib/hook-4_6pQSo4.js.map +0 -1
- package/lib/index-DVBlM15k.js.map +0 -1
- package/lib/index-Du5aNddU.js +0 -509
- package/lib/index-Du5aNddU.js.map +0 -1
- package/lib/index.esm-CQHE3GEU.js +0 -691
- package/lib/index.esm-CQHE3GEU.js.map +0 -1
- package/lib/objectEntries-yMIkr2mI.js +0 -5
- package/lib/objectEntries-yMIkr2mI.js.map +0 -1
- package/lib/useScrollToAnchor-BW8y_cwU.js +0 -290
- package/lib/useScrollToAnchor-BW8y_cwU.js.map +0 -1
|
@@ -15,7 +15,9 @@ export const useAuth = () => {
|
|
|
15
15
|
throw new Error("Authentication is not enabled.");
|
|
16
16
|
}
|
|
17
17
|
// TODO: Should handle errors/state
|
|
18
|
-
await authentication.signIn(
|
|
18
|
+
await authentication.signIn({
|
|
19
|
+
redirectTo: window.location.href,
|
|
20
|
+
});
|
|
19
21
|
},
|
|
20
22
|
|
|
21
23
|
logout: async () => {
|
|
@@ -28,5 +30,14 @@ export const useAuth = () => {
|
|
|
28
30
|
// Redirect to home
|
|
29
31
|
window.location.href = "/";
|
|
30
32
|
},
|
|
33
|
+
|
|
34
|
+
signup: async () => {
|
|
35
|
+
if (!isAuthEnabled) {
|
|
36
|
+
throw new Error("Authentication is not enabled.");
|
|
37
|
+
}
|
|
38
|
+
await authentication.signUp({
|
|
39
|
+
redirectTo: window.location.href,
|
|
40
|
+
});
|
|
41
|
+
},
|
|
31
42
|
};
|
|
32
43
|
};
|
|
@@ -106,18 +106,22 @@ const clerkAuth: AuthenticationProviderInitializer<
|
|
|
106
106
|
providerData: null,
|
|
107
107
|
});
|
|
108
108
|
},
|
|
109
|
-
signIn: async () => {
|
|
109
|
+
signIn: async ({ redirectTo }: { redirectTo?: string }) => {
|
|
110
110
|
await ensureLoaded;
|
|
111
111
|
await clerkApi?.redirectToSignIn({
|
|
112
|
-
signInForceRedirectUrl:
|
|
113
|
-
|
|
112
|
+
signInForceRedirectUrl:
|
|
113
|
+
redirectTo ?? window.location.origin + redirectToAfterSignIn,
|
|
114
|
+
signUpForceRedirectUrl:
|
|
115
|
+
redirectTo ?? window.location.origin + redirectToAfterSignUp,
|
|
114
116
|
});
|
|
115
117
|
},
|
|
116
|
-
signUp: async () => {
|
|
118
|
+
signUp: async ({ redirectTo }: { redirectTo?: string }) => {
|
|
117
119
|
await ensureLoaded;
|
|
118
120
|
await clerkApi?.redirectToSignUp({
|
|
119
|
-
signInForceRedirectUrl:
|
|
120
|
-
|
|
121
|
+
signInForceRedirectUrl:
|
|
122
|
+
redirectTo ?? window.location.origin + redirectToAfterSignIn,
|
|
123
|
+
signUpForceRedirectUrl:
|
|
124
|
+
redirectTo ?? window.location.origin + redirectToAfterSignUp,
|
|
121
125
|
});
|
|
122
126
|
},
|
|
123
127
|
getAuthenticationPlugin() {
|
|
@@ -38,14 +38,20 @@ export const useAuthState = create<AuthState>()(
|
|
|
38
38
|
persist(
|
|
39
39
|
(state) => ({
|
|
40
40
|
isAuthenticated: false,
|
|
41
|
-
isPending:
|
|
41
|
+
isPending: true,
|
|
42
42
|
profile: null,
|
|
43
43
|
providerData: null,
|
|
44
44
|
}),
|
|
45
45
|
{
|
|
46
|
+
merge: (persistedState, currentState) => {
|
|
47
|
+
return {
|
|
48
|
+
...currentState,
|
|
49
|
+
isPending: false,
|
|
50
|
+
...(typeof persistedState === "object" ? persistedState : {}),
|
|
51
|
+
};
|
|
52
|
+
},
|
|
46
53
|
name: "auth-state",
|
|
47
54
|
storage: createJSONStorage(() => localStorage),
|
|
48
|
-
// partialize: (s) => ({ state: s }),
|
|
49
55
|
},
|
|
50
56
|
),
|
|
51
57
|
);
|
|
@@ -38,7 +38,7 @@ const getComponent = (level: number) => {
|
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
export type HeadingProps = React.
|
|
41
|
+
export type HeadingProps = React.HTMLAttributes<HTMLHeadingElement> &
|
|
42
42
|
VariantProps<typeof heading> & {
|
|
43
43
|
children: ReactNode;
|
|
44
44
|
className?: string;
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { matchPath, Outlet, useLocation } from "react-router";
|
|
1
|
+
import { useQuery } from "@tanstack/react-query";
|
|
2
|
+
import { matchPath, Outlet, useLocation, useNavigate } from "react-router";
|
|
3
|
+
import {
|
|
4
|
+
Dialog,
|
|
5
|
+
DialogContent,
|
|
6
|
+
DialogDescription,
|
|
7
|
+
DialogHeader,
|
|
8
|
+
DialogTitle,
|
|
9
|
+
} from "zudoku/ui/Dialog.js";
|
|
3
10
|
import { useAuth } from "../authentication/hook.js";
|
|
4
11
|
import { useZudoku } from "../components/context/ZudokuContext.js";
|
|
5
12
|
import { ZudokuError } from "../util/invariant.js";
|
|
@@ -8,6 +15,7 @@ import { useLatest } from "../util/useLatest.js";
|
|
|
8
15
|
export const RouteGuard = () => {
|
|
9
16
|
const auth = useAuth();
|
|
10
17
|
const zudoku = useZudoku();
|
|
18
|
+
const navigate = useNavigate();
|
|
11
19
|
const location = useLocation();
|
|
12
20
|
const latestPath = useLatest(location.pathname);
|
|
13
21
|
|
|
@@ -15,24 +23,42 @@ export const RouteGuard = () => {
|
|
|
15
23
|
matchPath({ path, end: true }, location.pathname),
|
|
16
24
|
);
|
|
17
25
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
useQuery({
|
|
27
|
+
queryKey: ["login-redirect"],
|
|
28
|
+
queryFn: async () => {
|
|
29
|
+
await new Promise((resolve) => setTimeout(resolve, 1200));
|
|
30
|
+
await zudoku.authentication?.signIn({
|
|
31
|
+
redirectTo: latestPath.current,
|
|
32
|
+
});
|
|
33
|
+
return true;
|
|
34
|
+
},
|
|
35
|
+
enabled:
|
|
36
|
+
typeof window !== "undefined" &&
|
|
37
|
+
isProtected &&
|
|
38
|
+
!auth.isPending &&
|
|
39
|
+
!auth.isAuthenticated,
|
|
40
|
+
});
|
|
33
41
|
|
|
34
42
|
if (isProtected && !auth.isAuthenticated) {
|
|
35
|
-
return
|
|
43
|
+
return (
|
|
44
|
+
<Dialog
|
|
45
|
+
open={true}
|
|
46
|
+
onOpenChange={(open) => {
|
|
47
|
+
if (!open) {
|
|
48
|
+
void navigate(-1);
|
|
49
|
+
}
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
<DialogContent>
|
|
53
|
+
<DialogHeader>
|
|
54
|
+
<DialogTitle>Logging you in...</DialogTitle>
|
|
55
|
+
</DialogHeader>
|
|
56
|
+
<DialogDescription>
|
|
57
|
+
Please wait while we log you in.
|
|
58
|
+
</DialogDescription>
|
|
59
|
+
</DialogContent>
|
|
60
|
+
</Dialog>
|
|
61
|
+
);
|
|
36
62
|
}
|
|
37
63
|
|
|
38
64
|
if (isProtected && !auth.isAuthEnabled) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
2
|
+
import { Helmet } from "@zudoku/react-helmet-async";
|
|
2
3
|
import { useMatch } from "react-router";
|
|
3
|
-
import {
|
|
4
|
+
import { Link } from "zudoku/components";
|
|
4
5
|
import { useAuthState } from "../../authentication/state.js";
|
|
5
6
|
import { Heading } from "../../components/Heading.js";
|
|
6
7
|
import { Markdown } from "../../components/Markdown.js";
|
|
@@ -11,7 +12,10 @@ export const Catalog = ({
|
|
|
11
12
|
items,
|
|
12
13
|
filterCatalogItems = (items) => items,
|
|
13
14
|
label = "API Library",
|
|
14
|
-
|
|
15
|
+
categoryLabel,
|
|
16
|
+
}: Omit<ApiCatalogPluginOptions, "navigationId"> & {
|
|
17
|
+
categoryLabel?: string;
|
|
18
|
+
}) => {
|
|
15
19
|
const auth = useAuthState();
|
|
16
20
|
const match = useMatch({ path: "/catalog/:category" });
|
|
17
21
|
const activeCategory = match?.params.category;
|
|
@@ -21,13 +25,25 @@ export const Catalog = ({
|
|
|
21
25
|
queryKey: ["catalogItems", auth],
|
|
22
26
|
});
|
|
23
27
|
|
|
28
|
+
// Only index the overview page, ignore the rest
|
|
29
|
+
const dataSet = activeCategory ? { "data-pagefind-ignore": "all" } : {};
|
|
30
|
+
|
|
24
31
|
return (
|
|
25
|
-
<section
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
<section
|
|
33
|
+
className="pt-[--padding-content-top] pb-[--padding-content-bottom]"
|
|
34
|
+
{...dataSet}
|
|
35
|
+
>
|
|
36
|
+
<Helmet>
|
|
37
|
+
<title>
|
|
38
|
+
{categoryLabel ? `${categoryLabel} - ` : ""}
|
|
39
|
+
{label}
|
|
40
|
+
</title>
|
|
41
|
+
</Helmet>
|
|
29
42
|
<div className="grid gap-4">
|
|
30
|
-
<Heading level={2}>
|
|
43
|
+
<Heading level={2}>
|
|
44
|
+
{label}
|
|
45
|
+
{categoryLabel && ` - ${categoryLabel}`}
|
|
46
|
+
</Heading>
|
|
31
47
|
|
|
32
48
|
<div className="grid grid-cols-2 gap-4">
|
|
33
49
|
{catalogItems.data
|
|
@@ -90,7 +90,11 @@ export const MdxPage = ({
|
|
|
90
90
|
}, [file]);
|
|
91
91
|
|
|
92
92
|
return (
|
|
93
|
-
<div
|
|
93
|
+
<div
|
|
94
|
+
className="xl:grid grid-cols-[--sidecar-grid-cols] gap-8 justify-between"
|
|
95
|
+
data-pagefind-filter="section:markdown"
|
|
96
|
+
data-pagefind-meta="section:markdown"
|
|
97
|
+
>
|
|
94
98
|
<Helmet>
|
|
95
99
|
<title>{pageTitle}</title>
|
|
96
100
|
{excerpt && <meta name="description" content={excerpt} />}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ResultOf } from "@graphql-typed-document-node/core";
|
|
1
|
+
import { type ResultOf } from "@graphql-typed-document-node/core";
|
|
2
2
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
3
3
|
import { Helmet } from "@zudoku/react-helmet-async";
|
|
4
4
|
import { useNavigate } from "react-router";
|
|
@@ -152,8 +152,14 @@ export const OperationList = ({
|
|
|
152
152
|
? sanitizeMarkdownForMetatag(description)
|
|
153
153
|
: undefined;
|
|
154
154
|
|
|
155
|
+
const showVersions = Object.entries(versions).length > 1;
|
|
156
|
+
|
|
155
157
|
return (
|
|
156
|
-
<div
|
|
158
|
+
<div
|
|
159
|
+
className="pt-[--padding-content-top]"
|
|
160
|
+
data-pagefind-filter="section:openapi"
|
|
161
|
+
data-pagefind-meta="section:openapi"
|
|
162
|
+
>
|
|
157
163
|
<Helmet>
|
|
158
164
|
<title>{title}</title>
|
|
159
165
|
{metaDescription && (
|
|
@@ -168,10 +174,16 @@ export const OperationList = ({
|
|
|
168
174
|
<CategoryHeading>Overview</CategoryHeading>
|
|
169
175
|
<Heading level={1} id="description" registerSidebarAnchor>
|
|
170
176
|
{title}
|
|
177
|
+
{showVersions && (
|
|
178
|
+
<span className="text-xl text-muted-foreground">
|
|
179
|
+
{" "}
|
|
180
|
+
({version})
|
|
181
|
+
</span>
|
|
182
|
+
)}
|
|
171
183
|
</Heading>
|
|
172
184
|
</div>
|
|
173
185
|
<div>
|
|
174
|
-
{
|
|
186
|
+
{showVersions && (
|
|
175
187
|
<Select
|
|
176
188
|
onValueChange={(version) => navigate(versions[version]!)}
|
|
177
189
|
defaultValue={version}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
|
1
2
|
import { useRef, useState } from "react";
|
|
2
3
|
import { Heading } from "../../components/Heading.js";
|
|
3
4
|
import { Markdown, ProseClasses } from "../../components/Markdown.js";
|
|
@@ -84,6 +85,7 @@ export const OperationListItem = ({
|
|
|
84
85
|
groupedParameters[group]?.length ? (
|
|
85
86
|
<ParameterList
|
|
86
87
|
key={group}
|
|
88
|
+
summary={operation.summary ?? undefined}
|
|
87
89
|
id={operation.slug}
|
|
88
90
|
parameters={groupedParameters[group]}
|
|
89
91
|
group={group}
|
|
@@ -101,6 +103,9 @@ export const OperationListItem = ({
|
|
|
101
103
|
className="capitalize"
|
|
102
104
|
id={`${operation.slug}/request-body`}
|
|
103
105
|
>
|
|
106
|
+
{operation.summary && (
|
|
107
|
+
<VisuallyHidden>{operation.summary} › </VisuallyHidden>
|
|
108
|
+
)}
|
|
104
109
|
Request Body
|
|
105
110
|
</Heading>
|
|
106
111
|
<SchemaView schema={schema} />
|
|
@@ -113,6 +118,9 @@ export const OperationListItem = ({
|
|
|
113
118
|
className="capitalize mt-8 pt-8 border-t"
|
|
114
119
|
id={`${operation.slug}/responses`}
|
|
115
120
|
>
|
|
121
|
+
{operation.summary && (
|
|
122
|
+
<VisuallyHidden>{operation.summary} › </VisuallyHidden>
|
|
123
|
+
)}
|
|
116
124
|
Responses
|
|
117
125
|
</Heading>
|
|
118
126
|
<Tabs
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
|
1
2
|
import { Heading } from "../../components/Heading.js";
|
|
2
3
|
import { Card } from "../../ui/Card.js";
|
|
3
4
|
import type { ParameterGroup } from "./OperationListItem.js";
|
|
@@ -7,16 +8,19 @@ import {
|
|
|
7
8
|
} from "./ParameterListItem.js";
|
|
8
9
|
|
|
9
10
|
export const ParameterList = ({
|
|
11
|
+
summary,
|
|
10
12
|
group,
|
|
11
13
|
parameters,
|
|
12
14
|
id,
|
|
13
15
|
}: {
|
|
16
|
+
summary?: string;
|
|
14
17
|
group: ParameterGroup;
|
|
15
18
|
parameters: ParameterListItemResult[];
|
|
16
19
|
id: string;
|
|
17
20
|
}) => (
|
|
18
21
|
<>
|
|
19
22
|
<Heading level={3} id={`${id}/${group}-parameters`} className="capitalize">
|
|
23
|
+
{summary && <VisuallyHidden>{summary} › </VisuallyHidden>}
|
|
20
24
|
{group === "header" ? "Headers" : `${group} Parameters`}
|
|
21
25
|
</Heading>
|
|
22
26
|
<Card>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useAuth } from "zudoku/components";
|
|
1
2
|
import type { OperationListItemResult } from "./OperationList.js";
|
|
2
3
|
import { PlaygroundDialog } from "./playground/PlaygroundDialog.js";
|
|
3
4
|
import { Content } from "./SidecarExamples.js";
|
|
@@ -13,6 +14,9 @@ export const PlaygroundDialogWrapper = ({
|
|
|
13
14
|
operation: OperationListItemResult;
|
|
14
15
|
examples?: Content;
|
|
15
16
|
}) => {
|
|
17
|
+
const { isAuthEnabled, login, signup, isPending, isAuthenticated } =
|
|
18
|
+
useAuth();
|
|
19
|
+
|
|
16
20
|
const headers = operation.parameters
|
|
17
21
|
?.filter((p) => p.in === "header")
|
|
18
22
|
.sort((a, b) => (a.required && !b.required ? -1 : 1))
|
|
@@ -49,6 +53,9 @@ export const PlaygroundDialogWrapper = ({
|
|
|
49
53
|
queryParams={queryParams}
|
|
50
54
|
pathParams={pathParams}
|
|
51
55
|
examples={examples}
|
|
56
|
+
requiresLogin={isAuthEnabled && !isAuthenticated && !isPending}
|
|
57
|
+
onLogin={() => login()}
|
|
58
|
+
onSignUp={() => signup()}
|
|
52
59
|
/>
|
|
53
60
|
);
|
|
54
61
|
};
|
|
@@ -175,10 +175,11 @@ export const Sidecar = ({
|
|
|
175
175
|
<aside
|
|
176
176
|
ref={ref}
|
|
177
177
|
className="flex flex-col overflow-hidden sticky top-[--scroll-padding] gap-4"
|
|
178
|
+
data-pagefind-ignore="all"
|
|
178
179
|
>
|
|
179
180
|
<SidecarBox.Root>
|
|
180
181
|
<SidecarBox.Head className="flex justify-between items-center flex-nowrap py-2.5 gap-2 text-xs">
|
|
181
|
-
<span className="font-mono break-words">
|
|
182
|
+
<span className="font-mono break-words leading-6">
|
|
182
183
|
<span className={cn("font-semibold", methodTextColor)}>
|
|
183
184
|
{operation.method.toLocaleUpperCase()}
|
|
184
185
|
</span>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Control, Controller, useFieldArray } from "react-hook-form";
|
|
1
|
+
import { type Control, Controller, useFieldArray } from "react-hook-form";
|
|
2
2
|
import { Card } from "zudoku/ui/Card.js";
|
|
3
3
|
import { Input } from "../../../ui/Input.js";
|
|
4
4
|
import { ColorizedParam } from "../ColorizedParam.js";
|
|
@@ -7,18 +7,24 @@ import type { PlaygroundForm } from "./Playground.js";
|
|
|
7
7
|
|
|
8
8
|
export const PathParams = ({
|
|
9
9
|
control,
|
|
10
|
+
url,
|
|
10
11
|
}: {
|
|
11
12
|
control: Control<PlaygroundForm>;
|
|
13
|
+
url: string;
|
|
12
14
|
}) => {
|
|
13
15
|
const { fields } = useFieldArray<PlaygroundForm, "pathParams">({
|
|
14
16
|
control,
|
|
15
17
|
name: "pathParams",
|
|
16
18
|
});
|
|
17
19
|
|
|
20
|
+
const sortedFields = [...fields].sort(
|
|
21
|
+
(a, b) => url.indexOf(`{${a.name}}`) - url.indexOf(`{${b.name}}`),
|
|
22
|
+
);
|
|
23
|
+
|
|
18
24
|
return (
|
|
19
25
|
<Card className="rounded-lg">
|
|
20
26
|
<ParamsGrid>
|
|
21
|
-
{
|
|
27
|
+
{sortedFields.map((field, i) => (
|
|
22
28
|
<ParamsGridItem key={field.id}>
|
|
23
29
|
<Controller
|
|
24
30
|
control={control}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { useMutation } from "@tanstack/react-query";
|
|
2
2
|
import { InfoIcon } from "lucide-react";
|
|
3
|
-
import { Fragment, useEffect, useRef, useTransition } from "react";
|
|
3
|
+
import { Fragment, useEffect, useRef, useState, useTransition } from "react";
|
|
4
4
|
import { FormProvider, useForm } from "react-hook-form";
|
|
5
5
|
import { Alert, AlertDescription, AlertTitle } from "zudoku/ui/Alert.js";
|
|
6
6
|
import { PathRenderer } from "../../../components/PathRenderer.js";
|
|
7
7
|
|
|
8
|
+
import { Button } from "zudoku/ui/Button.js";
|
|
8
9
|
import { Label } from "zudoku/ui/Label.js";
|
|
9
10
|
import { RadioGroup, RadioGroupItem } from "zudoku/ui/RadioGroup.js";
|
|
10
11
|
import {
|
|
@@ -97,6 +98,9 @@ export type PlaygroundContentProps = {
|
|
|
97
98
|
pathParams?: PathParam[];
|
|
98
99
|
defaultBody?: string;
|
|
99
100
|
examples?: Content;
|
|
101
|
+
requiresLogin?: boolean;
|
|
102
|
+
onLogin?: () => void;
|
|
103
|
+
onSignUp?: () => void;
|
|
100
104
|
};
|
|
101
105
|
|
|
102
106
|
export const Playground = ({
|
|
@@ -109,11 +113,15 @@ export const Playground = ({
|
|
|
109
113
|
pathParams = [],
|
|
110
114
|
defaultBody = "",
|
|
111
115
|
examples,
|
|
116
|
+
requiresLogin = false,
|
|
117
|
+
onLogin,
|
|
118
|
+
onSignUp,
|
|
112
119
|
}: PlaygroundContentProps) => {
|
|
113
120
|
const { selectedServer, setSelectedServer } = useSelectedServer(
|
|
114
121
|
servers.map((url) => ({ url })),
|
|
115
122
|
);
|
|
116
123
|
const [, startTransition] = useTransition();
|
|
124
|
+
const [skipLogin, setSkipLogin] = useState(false);
|
|
117
125
|
const { register, control, handleSubmit, watch, setValue, ...form } =
|
|
118
126
|
useForm<PlaygroundForm>({
|
|
119
127
|
defaultValues: {
|
|
@@ -262,7 +270,7 @@ export const Playground = ({
|
|
|
262
270
|
));
|
|
263
271
|
|
|
264
272
|
const serverSelect = (
|
|
265
|
-
<div className="inline-block opacity-50 hover:opacity-100 transition">
|
|
273
|
+
<div className="inline-block opacity-50 hover:opacity-100 transition translate-y-[4px]">
|
|
266
274
|
{server ? (
|
|
267
275
|
<span>{server.replace(/^https?:\/\//, "")}</span>
|
|
268
276
|
) : (
|
|
@@ -290,6 +298,8 @@ export const Playground = ({
|
|
|
290
298
|
</div>
|
|
291
299
|
);
|
|
292
300
|
|
|
301
|
+
const showLogin = requiresLogin && !skipLogin;
|
|
302
|
+
|
|
293
303
|
return (
|
|
294
304
|
<FormProvider
|
|
295
305
|
{...{ register, control, handleSubmit, watch, setValue, ...form }}
|
|
@@ -297,15 +307,61 @@ export const Playground = ({
|
|
|
297
307
|
<form
|
|
298
308
|
onSubmit={handleSubmit((data) => queryMutation.mutateAsync(data))}
|
|
299
309
|
ref={formRef}
|
|
310
|
+
className="relative"
|
|
300
311
|
>
|
|
301
|
-
|
|
312
|
+
{showLogin && (
|
|
313
|
+
<div className="absolute top-1/2 right-1/2 -translate-y-1/2 translate-x-1/2 z-50 max-w-md">
|
|
314
|
+
<Alert>
|
|
315
|
+
<AlertTitle className="mb-2">
|
|
316
|
+
Welcome to the Playground!
|
|
317
|
+
</AlertTitle>
|
|
318
|
+
<AlertDescription className="flex flex-col gap-2">
|
|
319
|
+
<div className="mb-2">
|
|
320
|
+
The Playground is a tool for developers to test and explore
|
|
321
|
+
our APIs. To use the Playground, you need to login.
|
|
322
|
+
</div>
|
|
323
|
+
<div className="flex gap-2 justify-between">
|
|
324
|
+
<Button
|
|
325
|
+
type="button"
|
|
326
|
+
variant="ghost"
|
|
327
|
+
onClick={() => setSkipLogin(true)}
|
|
328
|
+
>
|
|
329
|
+
Skip
|
|
330
|
+
</Button>
|
|
331
|
+
<div className="flex gap-2">
|
|
332
|
+
{onSignUp && (
|
|
333
|
+
<Button
|
|
334
|
+
type="button"
|
|
335
|
+
variant="outline"
|
|
336
|
+
onClick={onSignUp}
|
|
337
|
+
>
|
|
338
|
+
Sign Up
|
|
339
|
+
</Button>
|
|
340
|
+
)}
|
|
341
|
+
{onLogin && (
|
|
342
|
+
<Button type="button" variant="default" onClick={onLogin}>
|
|
343
|
+
Login
|
|
344
|
+
</Button>
|
|
345
|
+
)}
|
|
346
|
+
</div>
|
|
347
|
+
</div>
|
|
348
|
+
</AlertDescription>
|
|
349
|
+
</Alert>
|
|
350
|
+
</div>
|
|
351
|
+
)}
|
|
352
|
+
<div
|
|
353
|
+
className={cn(
|
|
354
|
+
"grid grid-cols-2 text-sm h-full",
|
|
355
|
+
showLogin && "opacity-30 pointer-events-none",
|
|
356
|
+
)}
|
|
357
|
+
>
|
|
302
358
|
<div className="flex flex-col gap-4 p-4 after:bg-muted-foreground/20 relative after:absolute after:w-px after:inset-0 after:left-auto">
|
|
303
359
|
<div className="flex gap-2 items-stretch">
|
|
304
360
|
<div className="flex flex-1 items-center w-full border rounded-md">
|
|
305
361
|
<div className="border-r p-2 bg-muted rounded-l-md self-stretch font-semibold font-mono flex items-center">
|
|
306
362
|
{method.toUpperCase()}
|
|
307
363
|
</div>
|
|
308
|
-
<div className="items-center
|
|
364
|
+
<div className="items-center px-2 py-0.5 font-mono text-xs break-all leading-6">
|
|
309
365
|
{serverSelect}
|
|
310
366
|
{path}
|
|
311
367
|
{urlQueryParams.length > 0 ? "?" : ""}
|
|
@@ -351,7 +407,7 @@ export const Playground = ({
|
|
|
351
407
|
{pathParams.length > 0 && (
|
|
352
408
|
<div className="flex flex-col gap-4 my-4">
|
|
353
409
|
<span className="font-semibold">Path Parameters</span>
|
|
354
|
-
<PathParams control={control} />
|
|
410
|
+
<PathParams url={url} control={control} />
|
|
355
411
|
</div>
|
|
356
412
|
)}
|
|
357
413
|
<div className="flex flex-col gap-4 my-4">
|