zudoku 0.0.0-z6bcd96da → 0.0.0-z6e949a6d
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/loader.js +3 -1
- package/dist/config/loader.js.map +1 -1
- package/dist/config/validators/InputNavigationSchema.d.ts +170 -120
- package/dist/config/validators/InputNavigationSchema.js +17 -0
- package/dist/config/validators/InputNavigationSchema.js.map +1 -1
- package/dist/config/validators/NavigationSchema.d.ts +10 -2
- package/dist/config/validators/NavigationSchema.js +6 -0
- package/dist/config/validators/NavigationSchema.js.map +1 -1
- package/dist/config/validators/ProtectedRoutesSchema.d.ts +1 -1
- package/dist/config/validators/validate.d.ts +7 -7
- package/dist/flat-config.d.ts +35 -24
- package/dist/lib/components/Heading.d.ts +1 -1
- package/dist/lib/components/MobileTopNavigation.js +2 -1
- package/dist/lib/components/MobileTopNavigation.js.map +1 -1
- package/dist/lib/components/TopNavigation.d.ts +7 -1
- package/dist/lib/components/TopNavigation.js +7 -2
- package/dist/lib/components/TopNavigation.js.map +1 -1
- package/dist/lib/components/context/ZudokuContext.d.ts +8 -1
- package/dist/lib/components/context/ZudokuContext.js +2 -0
- package/dist/lib/components/context/ZudokuContext.js.map +1 -1
- package/dist/lib/components/index.d.ts +18 -74
- package/dist/lib/components/index.js +19 -36
- package/dist/lib/components/index.js.map +1 -1
- package/dist/lib/components/navigation/Navigation.js +4 -3
- package/dist/lib/components/navigation/Navigation.js.map +1 -1
- package/dist/lib/components/navigation/NavigationCategory.js +8 -0
- package/dist/lib/components/navigation/NavigationCategory.js.map +1 -1
- package/dist/lib/components/navigation/NavigationFilterContext.d.ts +8 -0
- package/dist/lib/components/navigation/NavigationFilterContext.js +12 -0
- package/dist/lib/components/navigation/NavigationFilterContext.js.map +1 -0
- package/dist/lib/components/navigation/NavigationFilterInput.d.ts +3 -0
- package/dist/lib/components/navigation/NavigationFilterInput.js +9 -0
- package/dist/lib/components/navigation/NavigationFilterInput.js.map +1 -0
- package/dist/lib/components/navigation/NavigationItem.js +11 -1
- package/dist/lib/components/navigation/NavigationItem.js.map +1 -1
- package/dist/lib/components/navigation/utils.d.ts +2 -1
- package/dist/lib/components/navigation/utils.js +22 -1
- package/dist/lib/components/navigation/utils.js.map +1 -1
- package/dist/lib/core/plugins.d.ts +11 -1
- package/dist/lib/core/plugins.js +1 -0
- package/dist/lib/core/plugins.js.map +1 -1
- package/dist/lib/core/transform-config.d.ts +2 -0
- package/dist/lib/core/transform-config.js +22 -0
- package/dist/lib/core/transform-config.js.map +1 -0
- package/dist/lib/hooks/index.d.ts +7 -30
- package/dist/lib/hooks/index.js +7 -15
- package/dist/lib/hooks/index.js.map +1 -1
- package/dist/lib/oas/graphql/circular.d.ts +1 -1
- package/dist/lib/oas/graphql/circular.js +18 -35
- package/dist/lib/oas/graphql/circular.js.map +1 -1
- package/dist/lib/oas/graphql/circular.test.js +33 -2
- package/dist/lib/oas/graphql/circular.test.js.map +1 -1
- package/dist/lib/oas/parser/index.js +14 -5
- package/dist/lib/oas/parser/index.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/fileUtils.d.ts +1 -0
- package/dist/lib/plugins/openapi/playground/fileUtils.js +3 -0
- package/dist/lib/plugins/openapi/playground/fileUtils.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/result-panel/AudioPlayer.d.ts +6 -0
- package/dist/lib/plugins/openapi/playground/result-panel/AudioPlayer.js +20 -0
- package/dist/lib/plugins/openapi/playground/result-panel/AudioPlayer.js.map +1 -0
- package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js +7 -2
- package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js.map +1 -1
- package/dist/lib/ui/Command.d.ts +3 -3
- package/dist/lib/ui/InputGroup.d.ts +16 -0
- package/dist/lib/ui/InputGroup.js +65 -0
- package/dist/lib/ui/InputGroup.js.map +1 -0
- package/dist/lib/util/flattenAllOf.d.ts +0 -2
- package/dist/lib/util/flattenAllOf.js +0 -46
- package/dist/lib/util/flattenAllOf.js.map +1 -1
- package/dist/lib/util/flattenAllOf.test.js +2 -1
- package/dist/lib/util/flattenAllOf.test.js.map +1 -1
- package/dist/lib/util/flattenAllOfProcessor.d.ts +2 -0
- package/dist/lib/util/flattenAllOfProcessor.js +48 -0
- package/dist/lib/util/flattenAllOfProcessor.js.map +1 -0
- package/dist/lib/util/readFrontmatter.js +2 -1
- package/dist/lib/util/readFrontmatter.js.map +1 -1
- package/dist/vite/api/SchemaManager.js +1 -1
- package/dist/vite/api/SchemaManager.js.map +1 -1
- package/dist/vite/api/SchemaManager.test.js +1 -1
- package/dist/vite/api/SchemaManager.test.js.map +1 -1
- package/dist/vite/build.js +91 -73
- package/dist/vite/build.js.map +1 -1
- package/dist/vite/mdx/remark-inject-filepath.js +5 -1
- package/dist/vite/mdx/remark-inject-filepath.js.map +1 -1
- package/dist/vite/mdx/remark-link-rewrite.js +3 -2
- package/dist/vite/mdx/remark-link-rewrite.js.map +1 -1
- package/dist/vite/plugin-docs.js +9 -7
- package/dist/vite/plugin-docs.js.map +1 -1
- package/dist/vite/plugin-markdown-export.js +4 -2
- package/dist/vite/plugin-markdown-export.js.map +1 -1
- package/lib/{ClaudeLogo-DJ9bU-sO.js → ClaudeLogo-OpUSMQJe.js} +26 -22
- package/lib/{ClaudeLogo-DJ9bU-sO.js.map → ClaudeLogo-OpUSMQJe.js.map} +1 -1
- package/lib/{MdxPage-stpAoBtx.js → MdxPage-dzCPGdvD.js} +8 -8
- package/lib/{MdxPage-stpAoBtx.js.map → MdxPage-dzCPGdvD.js.map} +1 -1
- package/lib/{Mermaid-Koc3z8mU.js → Mermaid-JEnWyK0s.js} +3 -2
- package/lib/{Mermaid-Koc3z8mU.js.map → Mermaid-JEnWyK0s.js.map} +1 -1
- package/lib/{OAuthErrorPage-DJ811Bn_.js → OAuthErrorPage-D7n-_cqN.js} +20 -18
- package/lib/{OAuthErrorPage-DJ811Bn_.js.map → OAuthErrorPage-D7n-_cqN.js.map} +1 -1
- package/lib/{OasProvider-CS_ASmBB.js → OasProvider-DPPdikt_.js} +3 -3
- package/lib/{OasProvider-CS_ASmBB.js.map → OasProvider-DPPdikt_.js.map} +1 -1
- package/lib/{OperationList-Dq_AB4W9.js → OperationList-cEveQ_l5.js} +948 -946
- package/lib/OperationList-cEveQ_l5.js.map +1 -0
- package/lib/{RouteGuard--A04ESy8.js → RouteGuard-BMbu_Yb7.js} +5 -5
- package/lib/{RouteGuard--A04ESy8.js.map → RouteGuard-BMbu_Yb7.js.map} +1 -1
- package/lib/{SchemaList-BJZJv1gD.js → SchemaList-CRC8n5co.js} +7 -7
- package/lib/{SchemaList-BJZJv1gD.js.map → SchemaList-CRC8n5co.js.map} +1 -1
- package/lib/{SchemaView-U4JMYB3N.js → SchemaView-BR6dtnPg.js} +3 -3
- package/lib/{SchemaView-U4JMYB3N.js.map → SchemaView-BR6dtnPg.js.map} +1 -1
- package/lib/{SignUp-DCBViNUi.js → SignUp-ChqXj9vd.js} +31 -26
- package/lib/{SignUp-DCBViNUi.js.map → SignUp-ChqXj9vd.js.map} +1 -1
- package/lib/{SyntaxHighlight-Dshjn3Zf.js → SyntaxHighlight-O-IZOPLg.js} +3 -3
- package/lib/{SyntaxHighlight-Dshjn3Zf.js.map → SyntaxHighlight-O-IZOPLg.js.map} +1 -1
- package/lib/{Toc-Cgz6CPiE.js → Toc-DQF7trHT.js} +2 -2
- package/lib/{Toc-Cgz6CPiE.js.map → Toc-DQF7trHT.js.map} +1 -1
- package/lib/{index-CL8eDnQW.js → Zudoku-DA1yA-te.js} +2609 -2452
- package/lib/Zudoku-DA1yA-te.js.map +1 -0
- package/lib/{ZudokuContext-BZB1TWdT.js → ZudokuContext-C6wlLMUH.js} +137 -135
- package/lib/{ZudokuContext-BZB1TWdT.js.map → ZudokuContext-C6wlLMUH.js.map} +1 -1
- package/lib/{circular-BmMJjG1v.js → circular-C4l1Kj1N.js} +1327 -1346
- package/lib/{circular-BmMJjG1v.js.map → circular-C4l1Kj1N.js.map} +1 -1
- package/lib/createServer-DoRZ6tMa.js +13036 -0
- package/lib/createServer-DoRZ6tMa.js.map +1 -0
- package/lib/{errors-b9I-fAOY.js → errors-CYLN8SNc.js} +3 -3
- package/lib/{errors-b9I-fAOY.js.map → errors-CYLN8SNc.js.map} +1 -1
- package/lib/{firebase-BCXX7Qv5.js → firebase-DF-VVKB7.js} +14 -14
- package/lib/firebase-DF-VVKB7.js.map +1 -0
- package/lib/{hook-BGlHBdET.js → hook-C35h0YhF.js} +2 -2
- package/lib/{hook-BGlHBdET.js.map → hook-C35h0YhF.js.map} +1 -1
- package/lib/{index-O9RHI87z.js → index-Ck4TmzTO.js} +574 -538
- package/lib/index-Ck4TmzTO.js.map +1 -0
- package/lib/index-DAWHN3cH.js +86 -0
- package/lib/index-DAWHN3cH.js.map +1 -0
- package/lib/{index-UOLtazB8.js → index-DrAVvbXa.js} +2 -2
- package/lib/{index-UOLtazB8.js.map → index-DrAVvbXa.js.map} +1 -1
- package/lib/{index.esm-C5CBsVzN.js → index.esm-B2cLXwjS.js} +2 -2
- package/lib/index.esm-B2cLXwjS.js.map +1 -0
- package/lib/{index.esm-B_0dvNjB.js → index.esm-Ca5zvoff.js} +20 -20
- package/lib/{index.esm-B_0dvNjB.js.map → index.esm-Ca5zvoff.js.map} +1 -1
- package/lib/{invariant-BJAl77rw.js → invariant-B_t_F2s_.js} +3 -3
- package/lib/{invariant-BJAl77rw.js.map → invariant-B_t_F2s_.js.map} +1 -1
- package/lib/ui/InputGroup.js +155 -0
- package/lib/ui/InputGroup.js.map +1 -0
- package/lib/ui/SyntaxHighlight.js +3 -3
- package/lib/useExposedProps-CzTDfXfq.js +30 -0
- package/lib/useExposedProps-CzTDfXfq.js.map +1 -0
- package/lib/zudoku.__internal.js +1493 -1031
- package/lib/zudoku.__internal.js.map +1 -1
- package/lib/zudoku.auth-auth0.js +1 -1
- package/lib/zudoku.auth-azureb2c.js +4 -4
- package/lib/zudoku.auth-clerk.js +2 -2
- package/lib/zudoku.auth-firebase.js +5 -5
- package/lib/zudoku.auth-openid.js +5 -5
- package/lib/zudoku.auth-supabase.js +4 -4
- package/lib/zudoku.components.js +31 -29
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.hooks.js +24 -11
- package/lib/zudoku.hooks.js.map +1 -1
- package/lib/zudoku.mermaid.js +4 -3
- package/lib/zudoku.mermaid.js.map +1 -1
- package/lib/zudoku.plugin-api-catalog.js +36 -32
- package/lib/zudoku.plugin-api-catalog.js.map +1 -1
- package/lib/zudoku.plugin-api-keys.js +131 -130
- package/lib/zudoku.plugin-api-keys.js.map +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 +2 -2
- package/lib/zudoku.plugin-search-pagefind.js +2 -2
- package/lib/zudoku.plugins.js +9 -8
- package/lib/zudoku.plugins.js.map +1 -1
- package/package.json +6 -4
- package/src/lib/components/MobileTopNavigation.tsx +13 -8
- package/src/lib/components/TopNavigation.tsx +25 -7
- package/src/lib/components/context/ZudokuContext.ts +1 -0
- package/src/lib/components/index.ts +19 -39
- package/src/lib/components/navigation/Navigation.tsx +4 -3
- package/src/lib/components/navigation/NavigationCategory.tsx +9 -0
- package/src/lib/components/navigation/NavigationFilterContext.tsx +28 -0
- package/src/lib/components/navigation/NavigationFilterInput.tsx +35 -0
- package/src/lib/components/navigation/NavigationItem.tsx +17 -1
- package/src/lib/components/navigation/utils.ts +32 -1
- package/src/lib/core/plugins.ts +21 -1
- package/src/lib/core/transform-config.ts +29 -0
- package/src/lib/hooks/index.ts +7 -16
- package/src/lib/oas/graphql/circular.test.ts +37 -2
- package/src/lib/oas/graphql/circular.ts +25 -51
- package/src/lib/oas/parser/index.ts +17 -6
- package/src/lib/plugins/openapi/playground/fileUtils.ts +4 -0
- package/src/lib/plugins/openapi/playground/result-panel/AudioPlayer.tsx +50 -0
- package/src/lib/plugins/openapi/playground/result-panel/ResponseTab.tsx +33 -17
- package/src/lib/ui/InputGroup.tsx +168 -0
- package/src/lib/util/flattenAllOf.test.ts +2 -1
- package/src/lib/util/flattenAllOf.ts +0 -57
- package/src/lib/util/flattenAllOfProcessor.ts +58 -0
- package/src/lib/util/readFrontmatter.ts +2 -1
- package/src/zuplo/enrich-with-zuplo-mcp.ts +168 -0
- package/src/zuplo/enrich-with-zuplo.ts +254 -0
- package/src/zuplo/policy-types.ts +46 -0
- package/src/zuplo/with-zuplo-processors.ts +35 -0
- package/src/zuplo/with-zuplo.ts +14 -0
- package/lib/OperationList-Dq_AB4W9.js.map +0 -1
- package/lib/Separator-BXt1LYnm.js +0 -27
- package/lib/Separator-BXt1LYnm.js.map +0 -1
- package/lib/___vite-browser-external_commonjs-proxy-BttVsNON.js +0 -9
- package/lib/___vite-browser-external_commonjs-proxy-BttVsNON.js.map +0 -1
- package/lib/createServer-CLSZ7hWJ.js +0 -16693
- package/lib/createServer-CLSZ7hWJ.js.map +0 -1
- package/lib/firebase-BCXX7Qv5.js.map +0 -1
- package/lib/index-CL8eDnQW.js.map +0 -1
- package/lib/index-DBjOT2H1.js +0 -133
- package/lib/index-DBjOT2H1.js.map +0 -1
- package/lib/index-O9RHI87z.js.map +0 -1
- package/lib/index.esm-C5CBsVzN.js.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
|
2
2
|
import { MenuIcon } from "lucide-react";
|
|
3
3
|
import { useState } from "react";
|
|
4
|
+
import { Separator } from "zudoku/ui/Separator.js";
|
|
4
5
|
import { Skeleton } from "zudoku/ui/Skeleton.js";
|
|
5
6
|
import { useAuth } from "../authentication/hook.js";
|
|
6
7
|
import {
|
|
@@ -43,7 +44,7 @@ export const MobileTopNavigation = () => {
|
|
|
43
44
|
<PageProgress />
|
|
44
45
|
</div>
|
|
45
46
|
<DrawerContent
|
|
46
|
-
className="lg:hidden h-
|
|
47
|
+
className="lg:hidden h-dvh end-0 start-auto w-[320px] rounded-none"
|
|
47
48
|
aria-describedby={undefined}
|
|
48
49
|
>
|
|
49
50
|
<div className="p-4 overflow-y-auto overscroll-none h-full flex flex-col justify-between">
|
|
@@ -84,13 +85,17 @@ export const MobileTopNavigation = () => {
|
|
|
84
85
|
)}
|
|
85
86
|
</ClientOnly>
|
|
86
87
|
)}
|
|
87
|
-
{filteredItems.map((item) =>
|
|
88
|
-
|
|
89
|
-
<
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
{filteredItems.map((item) =>
|
|
89
|
+
item.type === "separator" ? (
|
|
90
|
+
<Separator className="w-full" key={item.label} />
|
|
91
|
+
) : item.type !== "section" && item.type !== "filter" ? (
|
|
92
|
+
<li key={item.label}>
|
|
93
|
+
<button type="button" onClick={() => setDrawerOpen(false)}>
|
|
94
|
+
<TopNavItem {...item} />
|
|
95
|
+
</button>
|
|
96
|
+
</li>
|
|
97
|
+
) : null,
|
|
98
|
+
)}
|
|
94
99
|
{isAuthEnabled && isAuthenticated && accountItems.length > 0 && (
|
|
95
100
|
<ClientOnly
|
|
96
101
|
fallback={<Skeleton className="rounded-sm h-5 w-24 mr-4" />}
|
|
@@ -2,6 +2,7 @@ import { cx } from "class-variance-authority";
|
|
|
2
2
|
import { deepEqual } from "fast-equals";
|
|
3
3
|
import { Suspense } from "react";
|
|
4
4
|
import { NavLink, type NavLinkProps } from "react-router";
|
|
5
|
+
import { Separator } from "zudoku/ui/Separator.js";
|
|
5
6
|
import type { NavigationItem } from "../../config/validators/NavigationSchema.js";
|
|
6
7
|
import { useAuth } from "../authentication/hook.js";
|
|
7
8
|
import { joinUrl } from "../util/joinUrl.js";
|
|
@@ -24,11 +25,17 @@ export const TopNavigation = () => {
|
|
|
24
25
|
<div className="items-center justify-between px-8 h-(--top-nav-height) hidden lg:flex text-sm relative">
|
|
25
26
|
<nav className="text-sm">
|
|
26
27
|
<ul className="flex flex-row items-center gap-8">
|
|
27
|
-
{filteredItems.map((item) =>
|
|
28
|
-
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
{filteredItems.map((item) =>
|
|
29
|
+
item.type === "separator" ? (
|
|
30
|
+
<li key={item.label} className="-mx-4 h-7">
|
|
31
|
+
<Separator orientation="vertical" />
|
|
32
|
+
</li>
|
|
33
|
+
) : item.type !== "section" && item.type !== "filter" ? (
|
|
34
|
+
<li key={item.label + item.type}>
|
|
35
|
+
<TopNavItem {...item} />
|
|
36
|
+
</li>
|
|
37
|
+
) : null,
|
|
38
|
+
)}
|
|
32
39
|
</ul>
|
|
33
40
|
</nav>
|
|
34
41
|
<Slot.Target name="top-navigation-side" />
|
|
@@ -51,7 +58,11 @@ const getPathForItem = (item: NavigationItem): string => {
|
|
|
51
58
|
|
|
52
59
|
return (
|
|
53
60
|
traverseNavigationItem(item, (child) => {
|
|
54
|
-
if (
|
|
61
|
+
if (
|
|
62
|
+
child.type !== "category" &&
|
|
63
|
+
child.type !== "separator" &&
|
|
64
|
+
child.type !== "section"
|
|
65
|
+
) {
|
|
55
66
|
return getPathForItem(child);
|
|
56
67
|
}
|
|
57
68
|
}) ?? ""
|
|
@@ -59,6 +70,8 @@ const getPathForItem = (item: NavigationItem): string => {
|
|
|
59
70
|
}
|
|
60
71
|
case "custom-page":
|
|
61
72
|
return item.path;
|
|
73
|
+
default:
|
|
74
|
+
return "";
|
|
62
75
|
}
|
|
63
76
|
};
|
|
64
77
|
|
|
@@ -97,7 +110,12 @@ export const TopNavLink = ({
|
|
|
97
110
|
);
|
|
98
111
|
};
|
|
99
112
|
|
|
100
|
-
export const TopNavItem = (
|
|
113
|
+
export const TopNavItem = (
|
|
114
|
+
item: Exclude<
|
|
115
|
+
NavigationItem,
|
|
116
|
+
{ type: "separator" } | { type: "section" } | { type: "filter" }
|
|
117
|
+
>,
|
|
118
|
+
) => {
|
|
101
119
|
const currentNav = useCurrentNavigation();
|
|
102
120
|
const isActiveTopNavItem = deepEqual(currentNav.topNavItem, item);
|
|
103
121
|
|
|
@@ -77,6 +77,7 @@ export const useCurrentNavigation = () => {
|
|
|
77
77
|
const location = useLocation();
|
|
78
78
|
|
|
79
79
|
const navItem = traverseNavigation(navigation, (item, parentCategories) => {
|
|
80
|
+
if (item.type === "link") return;
|
|
80
81
|
if (getItemPath(item) === location.pathname) {
|
|
81
82
|
return parentCategories.at(0) ?? item;
|
|
82
83
|
}
|
|
@@ -1,46 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "./
|
|
14
|
-
import { useZudoku as useZudokuImport } from "./context/ZudokuContext.js";
|
|
15
|
-
import { Heading as HeadingImport } from "./Heading.js";
|
|
16
|
-
import { Markdown as MarkdownImport } from "./Markdown.js";
|
|
17
|
-
import { Slot as SlotImport } from "./Slot.js";
|
|
18
|
-
import { Spinner as SpinnerImport } from "./Spinner.js";
|
|
19
|
-
import { Typography as TypographyImport } from "./Typography.js";
|
|
20
|
-
import { Zudoku as ZudokuImport } from "./Zudoku.js";
|
|
1
|
+
export { Helmet as Head } from "@zudoku/react-helmet-async";
|
|
2
|
+
export { Link } from "react-router";
|
|
3
|
+
export { Button } from "../ui/Button.js";
|
|
4
|
+
export { Callout } from "../ui/Callout.js";
|
|
5
|
+
export { ZudokuError } from "../util/invariant.js";
|
|
6
|
+
export { ClientOnly } from "./ClientOnly.js";
|
|
7
|
+
export { Heading } from "./Heading.js";
|
|
8
|
+
export { Markdown } from "./Markdown.js";
|
|
9
|
+
export { Search } from "./Search.js";
|
|
10
|
+
export { Slot } from "./Slot.js";
|
|
11
|
+
export { Spinner } from "./Spinner.js";
|
|
12
|
+
export { Typography } from "./Typography.js";
|
|
13
|
+
export { Zudoku } from "./Zudoku.js";
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
export const Heading = /*@__PURE__*/ HeadingImport;
|
|
24
|
-
export const Callout = /*@__PURE__*/ CalloutImport;
|
|
25
|
-
export const Markdown = /*@__PURE__*/ MarkdownImport;
|
|
26
|
-
export const Spinner = /*@__PURE__*/ SpinnerImport;
|
|
27
|
-
export const ClientOnly = /*@__PURE__*/ ClientOnlyImport;
|
|
28
|
-
export const Button = /*@__PURE__*/ ButtonImport;
|
|
29
|
-
export const Link = /*@__PURE__*/ LinkImport;
|
|
30
|
-
export const Zudoku = /*@__PURE__*/ ZudokuImport;
|
|
31
|
-
export const Typography = /*@__PURE__*/ TypographyImport;
|
|
32
|
-
export const Slot = /*@__PURE__*/ SlotImport;
|
|
33
|
-
export const ZudokuError = /*@__PURE__*/ ZudokuErrorImport;
|
|
15
|
+
//
|
|
34
16
|
|
|
35
17
|
/** @deprecated Import from `zudoku/hooks` instead */
|
|
36
|
-
export
|
|
18
|
+
export { useMDXComponents } from "@mdx-js/react";
|
|
37
19
|
/** @deprecated Import from `zudoku/hooks` instead */
|
|
38
|
-
export
|
|
20
|
+
export { useTheme } from "next-themes";
|
|
39
21
|
/** @deprecated Import from `zudoku/hooks` instead */
|
|
40
|
-
export
|
|
22
|
+
export { useAuth } from "../authentication/hook.js";
|
|
41
23
|
/** @deprecated Import from `zudoku/hooks` instead */
|
|
42
|
-
export
|
|
24
|
+
export { CACHE_KEYS, useCache } from "./cache.js";
|
|
43
25
|
/** @deprecated Import from `zudoku/hooks` instead */
|
|
44
|
-
export
|
|
45
|
-
/** @deprecated Import from `zudoku/hooks` instead */
|
|
46
|
-
export const useTheme = /*@__PURE__*/ useThemeImport;
|
|
26
|
+
export { useZudoku } from "./context/ZudokuContext.js";
|
|
@@ -2,6 +2,7 @@ import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
|
|
2
2
|
import type { NavigationItem as NavigationItemType } from "../../../config/validators/NavigationSchema.js";
|
|
3
3
|
import { DrawerContent, DrawerTitle } from "../../ui/Drawer.js";
|
|
4
4
|
import { Slot } from "../Slot.js";
|
|
5
|
+
import { NavigationFilterProvider } from "./NavigationFilterContext.js";
|
|
5
6
|
import { NavigationItem } from "./NavigationItem.js";
|
|
6
7
|
import { NavigationWrapper } from "./NavigationWrapper.js";
|
|
7
8
|
|
|
@@ -12,7 +13,7 @@ export const Navigation = ({
|
|
|
12
13
|
onRequestClose?: () => void;
|
|
13
14
|
navigation: NavigationItemType[];
|
|
14
15
|
}) => (
|
|
15
|
-
|
|
16
|
+
<NavigationFilterProvider>
|
|
16
17
|
<NavigationWrapper>
|
|
17
18
|
<Slot.Target name="navigation-before" />
|
|
18
19
|
{navigation.map((item) => (
|
|
@@ -30,7 +31,7 @@ export const Navigation = ({
|
|
|
30
31
|
<Slot.Target name="navigation-after" />
|
|
31
32
|
</NavigationWrapper>
|
|
32
33
|
<DrawerContent
|
|
33
|
-
className="lg:hidden h-
|
|
34
|
+
className="lg:hidden h-dvh start-0 w-[320px] rounded-none"
|
|
34
35
|
aria-describedby={undefined}
|
|
35
36
|
>
|
|
36
37
|
<div className="p-4 overflow-y-auto overscroll-none">
|
|
@@ -46,5 +47,5 @@ export const Navigation = ({
|
|
|
46
47
|
))}
|
|
47
48
|
</div>
|
|
48
49
|
</DrawerContent>
|
|
49
|
-
|
|
50
|
+
</NavigationFilterProvider>
|
|
50
51
|
);
|
|
@@ -7,6 +7,7 @@ import { Button } from "zudoku/ui/Button.js";
|
|
|
7
7
|
import type { NavigationCategory as NavigationCategoryType } from "../../../config/validators/NavigationSchema.js";
|
|
8
8
|
import { cn } from "../../util/cn.js";
|
|
9
9
|
import { joinUrl } from "../../util/joinUrl.js";
|
|
10
|
+
import { useNavigationFilter } from "./NavigationFilterContext.js";
|
|
10
11
|
import { NavigationItem } from "./NavigationItem.js";
|
|
11
12
|
import { navigationListItem, useIsCategoryOpen } from "./utils.js";
|
|
12
13
|
|
|
@@ -20,6 +21,7 @@ const NavigationCategoryInner = ({
|
|
|
20
21
|
const isCategoryOpen = useIsCategoryOpen(category);
|
|
21
22
|
const [hasInteracted, setHasInteracted] = useState(false);
|
|
22
23
|
const location = useLocation();
|
|
24
|
+
const { query: filterQuery } = useNavigationFilter();
|
|
23
25
|
|
|
24
26
|
const isCollapsible = category.collapsible ?? true;
|
|
25
27
|
const isCollapsed = category.collapsed ?? true;
|
|
@@ -37,6 +39,13 @@ const NavigationCategoryInner = ({
|
|
|
37
39
|
}
|
|
38
40
|
}, [isCategoryOpen]);
|
|
39
41
|
|
|
42
|
+
// Auto-expand when there's an active filter query
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (filterQuery.trim()) {
|
|
45
|
+
setOpen(true);
|
|
46
|
+
}
|
|
47
|
+
}, [filterQuery]);
|
|
48
|
+
|
|
40
49
|
const ToggleButton = isCollapsible && (
|
|
41
50
|
<Button
|
|
42
51
|
onClick={(e) => {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
type PropsWithChildren,
|
|
4
|
+
useContext,
|
|
5
|
+
useState,
|
|
6
|
+
} from "react";
|
|
7
|
+
|
|
8
|
+
type NavigationFilterContextType = {
|
|
9
|
+
query: string;
|
|
10
|
+
setQuery: (query: string) => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const NavigationFilterContext = createContext<NavigationFilterContextType>({
|
|
14
|
+
query: "",
|
|
15
|
+
setQuery: () => {},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const NavigationFilterProvider = ({ children }: PropsWithChildren) => {
|
|
19
|
+
const [query, setQuery] = useState("");
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<NavigationFilterContext.Provider value={{ query, setQuery }}>
|
|
23
|
+
{children}
|
|
24
|
+
</NavigationFilterContext.Provider>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const useNavigationFilter = () => useContext(NavigationFilterContext);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SearchIcon, XIcon } from "lucide-react";
|
|
2
|
+
import {
|
|
3
|
+
InputGroup,
|
|
4
|
+
InputGroupAddon,
|
|
5
|
+
InputGroupButton,
|
|
6
|
+
InputGroupInput,
|
|
7
|
+
} from "zudoku/ui/InputGroup.js";
|
|
8
|
+
import { useNavigationFilter } from "./NavigationFilterContext.js";
|
|
9
|
+
|
|
10
|
+
export const NavigationFilterInput = ({
|
|
11
|
+
placeholder,
|
|
12
|
+
}: {
|
|
13
|
+
placeholder?: string;
|
|
14
|
+
}) => {
|
|
15
|
+
const { query, setQuery } = useNavigationFilter();
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<InputGroup className="my-2">
|
|
19
|
+
<InputGroupAddon>
|
|
20
|
+
<SearchIcon className="size-3.5" />
|
|
21
|
+
</InputGroupAddon>
|
|
22
|
+
<InputGroupInput
|
|
23
|
+
type="text"
|
|
24
|
+
placeholder={placeholder}
|
|
25
|
+
value={query}
|
|
26
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
27
|
+
/>
|
|
28
|
+
{query && (
|
|
29
|
+
<InputGroupButton onClick={() => setQuery("")}>
|
|
30
|
+
<XIcon className="size-3" />
|
|
31
|
+
</InputGroupButton>
|
|
32
|
+
)}
|
|
33
|
+
</InputGroup>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ExternalLinkIcon } from "lucide-react";
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
import { NavLink, useLocation } from "react-router";
|
|
4
|
+
import { Separator } from "zudoku/ui/Separator.js";
|
|
4
5
|
import { Tooltip, TooltipContent, TooltipTrigger } from "zudoku/ui/Tooltip.js";
|
|
5
6
|
import type { NavigationItem as NavigationItemType } from "../../../config/validators/NavigationSchema.js";
|
|
6
7
|
import { useAuth } from "../../authentication/hook.js";
|
|
@@ -11,6 +12,8 @@ import { useViewportAnchor } from "../context/ViewportAnchorContext.js";
|
|
|
11
12
|
import { useZudoku } from "../context/ZudokuContext.js";
|
|
12
13
|
import { NavigationBadge } from "./NavigationBadge.js";
|
|
13
14
|
import { NavigationCategory } from "./NavigationCategory.js";
|
|
15
|
+
import { useNavigationFilter } from "./NavigationFilterContext.js";
|
|
16
|
+
import { NavigationFilterInput } from "./NavigationFilterInput.js";
|
|
14
17
|
import { navigationListItem, shouldShowItem } from "./utils.js";
|
|
15
18
|
|
|
16
19
|
const TruncatedLabel = ({
|
|
@@ -65,8 +68,9 @@ export const NavigationItem = ({
|
|
|
65
68
|
const { activeAnchor } = useViewportAnchor();
|
|
66
69
|
const auth = useAuth();
|
|
67
70
|
const context = useZudoku();
|
|
71
|
+
const { query } = useNavigationFilter();
|
|
68
72
|
|
|
69
|
-
if (!shouldShowItem(auth, context)(item)) {
|
|
73
|
+
if (!shouldShowItem(auth, context, query)(item)) {
|
|
70
74
|
return null;
|
|
71
75
|
}
|
|
72
76
|
|
|
@@ -75,6 +79,18 @@ export const NavigationItem = ({
|
|
|
75
79
|
return (
|
|
76
80
|
<NavigationCategory category={item} onRequestClose={onRequestClose} />
|
|
77
81
|
);
|
|
82
|
+
case "separator":
|
|
83
|
+
return (
|
|
84
|
+
<Separator className="my-1 mx-auto w-[calc(100%-var(--padding-nav-item)*2)]!" />
|
|
85
|
+
);
|
|
86
|
+
case "section":
|
|
87
|
+
return (
|
|
88
|
+
<div className="mt-4 px-(--padding-nav-item) text-xs font-semibold text-muted-foreground uppercase tracking-wider">
|
|
89
|
+
{item.label}
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
case "filter":
|
|
93
|
+
return <NavigationFilterInput placeholder={item.placeholder} />;
|
|
78
94
|
case "doc":
|
|
79
95
|
return (
|
|
80
96
|
<NavLink
|
|
@@ -86,6 +86,13 @@ export const usePrevNext = (): {
|
|
|
86
86
|
let foundCurrent = false;
|
|
87
87
|
|
|
88
88
|
traverseNavigation(navigation, (item) => {
|
|
89
|
+
if (
|
|
90
|
+
item.type === "separator" ||
|
|
91
|
+
item.type === "section" ||
|
|
92
|
+
item.type === "filter"
|
|
93
|
+
)
|
|
94
|
+
return;
|
|
95
|
+
|
|
89
96
|
const itemId =
|
|
90
97
|
item.type === "doc"
|
|
91
98
|
? joinUrl(item.path)
|
|
@@ -133,9 +140,33 @@ export const navigationListItem = cva(
|
|
|
133
140
|
},
|
|
134
141
|
);
|
|
135
142
|
|
|
143
|
+
export const itemMatchesFilter = (
|
|
144
|
+
item: NavigationItem,
|
|
145
|
+
query: string,
|
|
146
|
+
): boolean => {
|
|
147
|
+
if (["separator", "section", "filter"].includes(item.type)) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
if (item.label?.toLowerCase().includes(query.toLowerCase())) {
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (item.type === "category") {
|
|
155
|
+
return item.items.some((child) => itemMatchesFilter(child, query));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return false;
|
|
159
|
+
};
|
|
160
|
+
|
|
136
161
|
export const shouldShowItem =
|
|
137
|
-
(auth: UseAuthReturn, context: ZudokuContext) =>
|
|
162
|
+
(auth: UseAuthReturn, context: ZudokuContext, filterQuery?: string) =>
|
|
138
163
|
(item: NavigationItem): boolean => {
|
|
164
|
+
if (item.type === "filter") return true;
|
|
165
|
+
|
|
166
|
+
if (filterQuery?.trim() && !itemMatchesFilter(item, filterQuery)) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
|
|
139
170
|
if (typeof item.display === "function") {
|
|
140
171
|
return item.display({ context, auth });
|
|
141
172
|
}
|
package/src/lib/core/plugins.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { ReactNode } from "react";
|
|
|
3
3
|
import type { Location, RouteObject } from "react-router";
|
|
4
4
|
import type { Navigation } from "../../config/validators/NavigationSchema.js";
|
|
5
5
|
import type { ProtectedRoutesInput } from "../../config/validators/ProtectedRoutesSchema.js";
|
|
6
|
+
import type { ZudokuConfig } from "../../config/validators/validate.js";
|
|
6
7
|
import type { AuthenticationPlugin } from "../authentication/authentication.js";
|
|
7
8
|
import type { MdxComponentsType } from "../util/MdxComponents.js";
|
|
8
9
|
import type {
|
|
@@ -18,7 +19,8 @@ export type ZudokuPlugin =
|
|
|
18
19
|
| ApiIdentityPlugin
|
|
19
20
|
| SearchProviderPlugin
|
|
20
21
|
| EventConsumerPlugin
|
|
21
|
-
| AuthenticationPlugin
|
|
22
|
+
| AuthenticationPlugin
|
|
23
|
+
| TransformConfigPlugin;
|
|
22
24
|
|
|
23
25
|
export type { AuthenticationPlugin, RouteObject };
|
|
24
26
|
|
|
@@ -60,6 +62,19 @@ export type ProfileNavigationItem = {
|
|
|
60
62
|
icon?: LucideIcon;
|
|
61
63
|
};
|
|
62
64
|
|
|
65
|
+
export interface ConfigHookContext {
|
|
66
|
+
mode: typeof process.env.ZUDOKU_ENV;
|
|
67
|
+
rootDir: string;
|
|
68
|
+
configPath: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface TransformConfigPlugin {
|
|
72
|
+
transformConfig?: (
|
|
73
|
+
config: ZudokuConfig,
|
|
74
|
+
ctx: ConfigHookContext,
|
|
75
|
+
) => Partial<ZudokuConfig> | void | Promise<Partial<ZudokuConfig> | void>;
|
|
76
|
+
}
|
|
77
|
+
|
|
63
78
|
export interface CommonPlugin {
|
|
64
79
|
initialize?: (
|
|
65
80
|
context: ZudokuContext,
|
|
@@ -110,3 +125,8 @@ export const isApiIdentityPlugin = (
|
|
|
110
125
|
obj: ZudokuPlugin,
|
|
111
126
|
): obj is ApiIdentityPlugin =>
|
|
112
127
|
"getIdentities" in obj && typeof obj.getIdentities === "function";
|
|
128
|
+
|
|
129
|
+
export const isTransformConfigPlugin = (
|
|
130
|
+
obj: ZudokuPlugin,
|
|
131
|
+
): obj is TransformConfigPlugin =>
|
|
132
|
+
"transformConfig" in obj && typeof obj.transformConfig === "function";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import createDeepmerge from "@fastify/deepmerge";
|
|
2
|
+
import type { ConfigWithMeta } from "../../config/loader.js";
|
|
3
|
+
import { type ConfigHookContext, isTransformConfigPlugin } from "./plugins.js";
|
|
4
|
+
|
|
5
|
+
const mergeConfig = createDeepmerge({
|
|
6
|
+
mergeArray: (opt) => (_, source) => opt.clone(source),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export const runTransformConfigHooks = async (
|
|
10
|
+
config: ConfigWithMeta,
|
|
11
|
+
): Promise<ConfigWithMeta> => {
|
|
12
|
+
const ctx = {
|
|
13
|
+
mode: config.__meta.mode,
|
|
14
|
+
rootDir: config.__meta.rootDir,
|
|
15
|
+
configPath: config.__meta.configPath,
|
|
16
|
+
} satisfies ConfigHookContext;
|
|
17
|
+
const plugins = config.plugins ?? [];
|
|
18
|
+
|
|
19
|
+
let result = config;
|
|
20
|
+
|
|
21
|
+
for (const plugin of plugins.filter(isTransformConfigPlugin)) {
|
|
22
|
+
const partial = await plugin.transformConfig?.(result, ctx);
|
|
23
|
+
if (!partial) continue;
|
|
24
|
+
|
|
25
|
+
result = mergeConfig(result, partial) as ConfigWithMeta;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return result;
|
|
29
|
+
};
|
package/src/lib/hooks/index.ts
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export const useEvent = /*@__PURE__*/ useEventImport;
|
|
10
|
-
export const useTheme = /*@__PURE__*/ useThemeImport;
|
|
11
|
-
export const useExposedProps = /*@__PURE__*/ useExposedPropsImport;
|
|
12
|
-
export const useMDXComponents = /*@__PURE__*/ useMDXComponentsImport;
|
|
13
|
-
export const useAuth = /*@__PURE__*/ useAuthImport;
|
|
14
|
-
export const useZudoku = /*@__PURE__*/ useZudokuImport;
|
|
15
|
-
export const useCache = /*@__PURE__*/ useCacheImport;
|
|
16
|
-
export { CACHE_KEYS };
|
|
1
|
+
export { useMDXComponents } from "@mdx-js/react";
|
|
2
|
+
export { useTheme } from "next-themes";
|
|
3
|
+
export { useAuth } from "../authentication/hook.js";
|
|
4
|
+
export { CACHE_KEYS, useCache } from "../components/cache.js";
|
|
5
|
+
export { useZudoku } from "../components/context/ZudokuContext.js";
|
|
6
|
+
export { useExposedProps } from "../util/useExposedProps.js";
|
|
7
|
+
export { useEvent } from "./useEvent.js";
|
|
@@ -156,16 +156,20 @@ describe("handleCircularRefs", () => {
|
|
|
156
156
|
});
|
|
157
157
|
});
|
|
158
158
|
|
|
159
|
-
it("should
|
|
159
|
+
it("should handle shared object instances with __$ref without marking circular", () => {
|
|
160
160
|
const shared = { __$ref: "#/components/schemas/Foo", type: "string" };
|
|
161
161
|
const obj = { a: shared, b: shared };
|
|
162
162
|
const result = handleCircularRefs(obj);
|
|
163
163
|
|
|
164
|
+
// Both should return the cached result, not mark as circular
|
|
164
165
|
expect(result.a).toEqual({
|
|
165
166
|
__$ref: "#/components/schemas/Foo",
|
|
166
167
|
type: "string",
|
|
167
168
|
});
|
|
168
|
-
expect(result.b).
|
|
169
|
+
expect(result.b).toEqual({
|
|
170
|
+
__$ref: "#/components/schemas/Foo",
|
|
171
|
+
type: "string",
|
|
172
|
+
});
|
|
169
173
|
});
|
|
170
174
|
|
|
171
175
|
it("should mark circular ref with property name from path", () => {
|
|
@@ -183,4 +187,35 @@ describe("handleCircularRefs", () => {
|
|
|
183
187
|
|
|
184
188
|
expect(result.properties.child.properties.back).toContain(CIRCULAR_REF);
|
|
185
189
|
});
|
|
190
|
+
|
|
191
|
+
// Exact reproduction of #1869 - shared object instances with __$ref
|
|
192
|
+
it("should NOT mark shared object instances with __$ref as circular (issue #1869)", () => {
|
|
193
|
+
// When dereferencing, the SAME object instance is returned for all refs to the same schema
|
|
194
|
+
const timestampSchema = {
|
|
195
|
+
__$ref: "#/components/schemas/timestamp",
|
|
196
|
+
type: "string",
|
|
197
|
+
format: "date-time",
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// Both created_at and updated_at point to the SAME object instance
|
|
201
|
+
const obj = {
|
|
202
|
+
type: "object",
|
|
203
|
+
properties: {
|
|
204
|
+
created_at: timestampSchema,
|
|
205
|
+
updated_at: timestampSchema,
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const result = handleCircularRefs(obj);
|
|
210
|
+
|
|
211
|
+
// The first one should be fully expanded
|
|
212
|
+
expect(result.properties.created_at).toEqual({
|
|
213
|
+
__$ref: "#/components/schemas/timestamp",
|
|
214
|
+
type: "string",
|
|
215
|
+
format: "date-time",
|
|
216
|
+
});
|
|
217
|
+
// The second one should ALSO be fully expanded (not marked as circular)
|
|
218
|
+
expect(typeof result.properties.updated_at).toBe("object");
|
|
219
|
+
expect(result.properties.updated_at).not.toContain(CIRCULAR_REF);
|
|
220
|
+
});
|
|
186
221
|
});
|