zudoku 0.47.2 → 0.48.0

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.
Files changed (264) hide show
  1. package/dist/app/ZuploBuildConfig.d.ts +4 -114
  2. package/dist/app/ZuploBuildConfig.js +1 -1
  3. package/dist/app/ZuploBuildConfig.js.map +1 -1
  4. package/dist/app/demo.js +4 -3
  5. package/dist/app/demo.js.map +1 -1
  6. package/dist/app/main.js +5 -5
  7. package/dist/app/main.js.map +1 -1
  8. package/dist/app/standalone.js +4 -3
  9. package/dist/app/standalone.js.map +1 -1
  10. package/dist/config/loader.js +1 -2
  11. package/dist/config/loader.js.map +1 -1
  12. package/dist/config/validators/BuildSchema.d.ts +20 -44
  13. package/dist/config/validators/BuildSchema.js +3 -14
  14. package/dist/config/validators/BuildSchema.js.map +1 -1
  15. package/dist/config/validators/InputNavigationSchema.d.ts +7217 -0
  16. package/dist/config/validators/InputNavigationSchema.js +74 -0
  17. package/dist/config/validators/InputNavigationSchema.js.map +1 -0
  18. package/dist/config/validators/InputNavigationSchema.test-d.d.ts +1 -0
  19. package/dist/config/validators/InputNavigationSchema.test-d.js +146 -0
  20. package/dist/config/validators/InputNavigationSchema.test-d.js.map +1 -0
  21. package/dist/config/validators/NavigationSchema.d.ts +44 -0
  22. package/dist/config/validators/NavigationSchema.js +95 -0
  23. package/dist/config/validators/NavigationSchema.js.map +1 -0
  24. package/dist/config/validators/icon-types.d.ts +2 -1
  25. package/dist/config/validators/icon-types.js +1775 -1
  26. package/dist/config/validators/icon-types.js.map +1 -1
  27. package/dist/config/validators/validate.d.ts +442 -5780
  28. package/dist/config/validators/validate.js +37 -55
  29. package/dist/config/validators/validate.js.map +1 -1
  30. package/dist/config/validators/validate.test.js +0 -2
  31. package/dist/config/validators/validate.test.js.map +1 -1
  32. package/dist/index.d.ts +1 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/lib/components/BuildCheck.js +1 -1
  35. package/dist/lib/components/BuildCheck.js.map +1 -1
  36. package/dist/lib/components/Header.js +10 -9
  37. package/dist/lib/components/Header.js.map +1 -1
  38. package/dist/lib/components/Heading.d.ts +6 -2
  39. package/dist/lib/components/Heading.js +2 -2
  40. package/dist/lib/components/Heading.js.map +1 -1
  41. package/dist/lib/components/Main.js +4 -4
  42. package/dist/lib/components/Main.js.map +1 -1
  43. package/dist/lib/components/MobileTopNavigation.js +5 -5
  44. package/dist/lib/components/MobileTopNavigation.js.map +1 -1
  45. package/dist/lib/components/PageProgress.d.ts +1 -0
  46. package/dist/lib/components/PageProgress.js +20 -0
  47. package/dist/lib/components/PageProgress.js.map +1 -0
  48. package/dist/lib/components/TopNavigation.d.ts +2 -3
  49. package/dist/lib/components/TopNavigation.js +45 -44
  50. package/dist/lib/components/TopNavigation.js.map +1 -1
  51. package/dist/lib/components/context/ZudokuContext.d.ts +3 -7
  52. package/dist/lib/components/context/ZudokuContext.js +44 -26
  53. package/dist/lib/components/context/ZudokuContext.js.map +1 -1
  54. package/dist/lib/components/navigation/Navigation.d.ts +5 -0
  55. package/dist/lib/components/navigation/Navigation.js +12 -0
  56. package/dist/lib/components/navigation/Navigation.js.map +1 -0
  57. package/dist/lib/components/navigation/{SidebarBadge.d.ts → NavigationBadge.d.ts} +1 -1
  58. package/dist/lib/components/navigation/{SidebarBadge.js → NavigationBadge.js} +2 -2
  59. package/dist/lib/components/navigation/NavigationBadge.js.map +1 -0
  60. package/dist/lib/components/navigation/NavigationCategory.d.ts +5 -0
  61. package/dist/lib/components/navigation/{SidebarCategory.js → NavigationCategory.js} +14 -12
  62. package/dist/lib/components/navigation/NavigationCategory.js.map +1 -0
  63. package/dist/lib/components/navigation/NavigationItem.d.ts +6 -0
  64. package/dist/lib/components/navigation/NavigationItem.js +47 -0
  65. package/dist/lib/components/navigation/NavigationItem.js.map +1 -0
  66. package/dist/lib/components/navigation/{SidebarWrapper.d.ts → NavigationWrapper.d.ts} +1 -1
  67. package/dist/lib/components/navigation/{SidebarWrapper.js → NavigationWrapper.js} +3 -3
  68. package/dist/lib/components/navigation/NavigationWrapper.js.map +1 -0
  69. package/dist/lib/components/navigation/utils.d.ts +7 -9
  70. package/dist/lib/components/navigation/utils.js +17 -17
  71. package/dist/lib/components/navigation/utils.js.map +1 -1
  72. package/dist/lib/core/ZudokuContext.d.ts +6 -8
  73. package/dist/lib/core/ZudokuContext.js +5 -7
  74. package/dist/lib/core/ZudokuContext.js.map +1 -1
  75. package/dist/lib/core/plugins.d.ts +2 -2
  76. package/dist/lib/hooks/useEvent.test.js +5 -3
  77. package/dist/lib/hooks/useEvent.test.js.map +1 -1
  78. package/dist/lib/plugins/api-catalog/Catalog.d.ts +1 -1
  79. package/dist/lib/plugins/api-catalog/index.d.ts +6 -6
  80. package/dist/lib/plugins/api-catalog/index.js +10 -10
  81. package/dist/lib/plugins/api-catalog/index.js.map +1 -1
  82. package/dist/lib/plugins/api-keys/SettingsApiKeys.js +4 -4
  83. package/dist/lib/plugins/api-keys/SettingsApiKeys.js.map +1 -1
  84. package/dist/lib/plugins/custom-pages/index.d.ts +3 -2
  85. package/dist/lib/plugins/custom-pages/index.js +15 -8
  86. package/dist/lib/plugins/custom-pages/index.js.map +1 -1
  87. package/dist/lib/plugins/markdown/MdxPage.js +6 -3
  88. package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
  89. package/dist/lib/plugins/markdown/index.d.ts +2 -1
  90. package/dist/lib/plugins/markdown/index.js +9 -26
  91. package/dist/lib/plugins/markdown/index.js.map +1 -1
  92. package/dist/lib/plugins/openapi/OperationList.js +1 -1
  93. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  94. package/dist/lib/plugins/openapi/OperationListItem.js +1 -1
  95. package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
  96. package/dist/lib/plugins/openapi/SchemaList.js +1 -1
  97. package/dist/lib/plugins/openapi/SchemaList.js.map +1 -1
  98. package/dist/lib/plugins/openapi/graphql/gql.d.ts +1 -1
  99. package/dist/lib/plugins/openapi/graphql/gql.js +1 -1
  100. package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
  101. package/dist/lib/plugins/openapi/graphql/graphql.d.ts +3 -3
  102. package/dist/lib/plugins/openapi/graphql/graphql.js +2 -2
  103. package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
  104. package/dist/lib/plugins/openapi/index.d.ts +3 -3
  105. package/dist/lib/plugins/openapi/index.js +9 -9
  106. package/dist/lib/plugins/openapi/index.js.map +1 -1
  107. package/dist/lib/plugins/openapi/interfaces.d.ts +3 -3
  108. package/dist/lib/plugins/openapi/util/createNavigationCategory.d.ts +9 -0
  109. package/dist/lib/plugins/openapi/util/{createSidebarCategory.js → createNavigationCategory.js} +5 -4
  110. package/dist/lib/plugins/openapi/util/createNavigationCategory.js.map +1 -0
  111. package/dist/lib/plugins/openapi/util/getRoutes.js +2 -2
  112. package/dist/lib/plugins/openapi/util/getRoutes.js.map +1 -1
  113. package/dist/lib/plugins/openapi/util/methodColorMap.d.ts +1 -1
  114. package/dist/lib/util/useScrollToAnchor.js +3 -3
  115. package/dist/lib/util/useScrollToAnchor.js.map +1 -1
  116. package/dist/vite/api/SchemaManager.d.ts +4 -4
  117. package/dist/vite/api/SchemaManager.js +19 -19
  118. package/dist/vite/api/SchemaManager.js.map +1 -1
  119. package/dist/vite/api/SchemaManager.test.js +4 -4
  120. package/dist/vite/api/SchemaManager.test.js.map +1 -1
  121. package/dist/vite/config.js +1 -0
  122. package/dist/vite/config.js.map +1 -1
  123. package/dist/vite/plugin-api.js +8 -8
  124. package/dist/vite/plugin-api.js.map +1 -1
  125. package/dist/vite/plugin-config-reload.js +2 -0
  126. package/dist/vite/plugin-config-reload.js.map +1 -1
  127. package/dist/vite/plugin-custom-pages.js +2 -2
  128. package/dist/vite/plugin-custom-pages.js.map +1 -1
  129. package/dist/vite/plugin-docs.js +61 -59
  130. package/dist/vite/plugin-docs.js.map +1 -1
  131. package/dist/vite/{plugin-sidebar.d.ts → plugin-navigation.d.ts} +1 -1
  132. package/dist/vite/{plugin-sidebar.js → plugin-navigation.js} +20 -19
  133. package/dist/vite/plugin-navigation.js.map +1 -0
  134. package/dist/vite/plugin.js +2 -2
  135. package/dist/vite/plugin.js.map +1 -1
  136. package/dist/vite/shadcn-registry.d.ts +4 -4
  137. package/lib/{Markdown-C5j8kKSX.js → Markdown-DCAIYXF5.js} +480 -475
  138. package/lib/Markdown-DCAIYXF5.js.map +1 -0
  139. package/lib/{MdxPage-CKTMf1cR.js → MdxPage-Cf9YXWoC.js} +30 -30
  140. package/lib/MdxPage-Cf9YXWoC.js.map +1 -0
  141. package/lib/OasProvider-JMVTfG6_.js +35 -0
  142. package/lib/OasProvider-JMVTfG6_.js.map +1 -0
  143. package/lib/{OperationList-BJAKaG5p.js → OperationList-m4tFCI4S.js} +8 -8
  144. package/lib/{OperationList-BJAKaG5p.js.map → OperationList-m4tFCI4S.js.map} +1 -1
  145. package/lib/{RouteGuard-B7GVW4oL.js → RouteGuard-gV7nvzi7.js} +2 -2
  146. package/lib/{RouteGuard-B7GVW4oL.js.map → RouteGuard-gV7nvzi7.js.map} +1 -1
  147. package/lib/{SchemaList-Dgc0A8x5.js → SchemaList-_wRy4aQ0.js} +20 -20
  148. package/lib/SchemaList-_wRy4aQ0.js.map +1 -0
  149. package/lib/{SchemaView-DVx-jFN4.js → SchemaView-CRl_cQYH.js} +3 -3
  150. package/lib/{SchemaView-DVx-jFN4.js.map → SchemaView-CRl_cQYH.js.map} +1 -1
  151. package/lib/{SignUp-CRIKdWt9.js → SignUp-B6w5AwHM.js} +2 -2
  152. package/lib/{SignUp-CRIKdWt9.js.map → SignUp-B6w5AwHM.js.map} +1 -1
  153. package/lib/{Slot-ITby_hMb.js → Slot-BkYrj_uC.js} +4 -4
  154. package/lib/{Slot-ITby_hMb.js.map → Slot-BkYrj_uC.js.map} +1 -1
  155. package/lib/{SyntaxHighlight-CqKHkyEy.js → SyntaxHighlight-CH9OUJre.js} +2 -2
  156. package/lib/{SyntaxHighlight-CqKHkyEy.js.map → SyntaxHighlight-CH9OUJre.js.map} +1 -1
  157. package/lib/{Toc-Csq3UNtW.js → Toc-DRxqEsFc.js} +2 -2
  158. package/lib/{Toc-Csq3UNtW.js.map → Toc-DRxqEsFc.js.map} +1 -1
  159. package/lib/{circular-BP4OrHFK.js → circular-wJaV4vh_.js} +2 -2
  160. package/lib/{circular-BP4OrHFK.js.map → circular-wJaV4vh_.js.map} +1 -1
  161. package/lib/{createServer-zu4cDiPe.js → createServer-DN5AJLcN.js} +3 -3
  162. package/lib/{createServer-zu4cDiPe.js.map → createServer-DN5AJLcN.js.map} +1 -1
  163. package/lib/{errors-CPPSp5F4.js → errors-D_5vKvUq.js} +3 -3
  164. package/lib/{errors-CPPSp5F4.js.map → errors-D_5vKvUq.js.map} +1 -1
  165. package/lib/hook-CHXroBFt.js +1503 -0
  166. package/lib/hook-CHXroBFt.js.map +1 -0
  167. package/lib/{index-jWXxqkni.js → index-DJVaRmzI.js} +63 -62
  168. package/lib/index-DJVaRmzI.js.map +1 -0
  169. package/lib/{mutation-C1XCQTQL.js → mutation-BpcyTgWI.js} +2 -2
  170. package/lib/{mutation-C1XCQTQL.js.map → mutation-BpcyTgWI.js.map} +1 -1
  171. package/lib/ui/SyntaxHighlight.js +2 -2
  172. package/lib/{useMutation-BKvPttRn.js → useMutation-N4ockVKi.js} +3 -3
  173. package/lib/{useMutation-BKvPttRn.js.map → useMutation-N4ockVKi.js.map} +1 -1
  174. package/lib/zudoku.auth-auth0.js +1 -1
  175. package/lib/zudoku.auth-azureb2c.js +2 -2
  176. package/lib/zudoku.auth-clerk.js +2 -2
  177. package/lib/zudoku.auth-openid.js +2 -2
  178. package/lib/zudoku.components.js +2756 -3424
  179. package/lib/zudoku.components.js.map +1 -1
  180. package/lib/zudoku.hooks.js +2 -2
  181. package/lib/zudoku.plugin-api-catalog.js +44 -44
  182. package/lib/zudoku.plugin-api-catalog.js.map +1 -1
  183. package/lib/zudoku.plugin-api-keys.js +42 -39
  184. package/lib/zudoku.plugin-api-keys.js.map +1 -1
  185. package/lib/zudoku.plugin-custom-pages.js +22 -16
  186. package/lib/zudoku.plugin-custom-pages.js.map +1 -1
  187. package/lib/zudoku.plugin-markdown.js +20 -69
  188. package/lib/zudoku.plugin-markdown.js.map +1 -1
  189. package/lib/zudoku.plugin-openapi.js +5 -5
  190. package/lib/zudoku.plugin-search-pagefind.js +2 -2
  191. package/lib/zudoku.plugins.js.map +1 -1
  192. package/package.json +12 -9
  193. package/src/app/ZuploBuildConfig.ts +1 -1
  194. package/src/app/demo.tsx +4 -3
  195. package/src/app/main.css +5 -0
  196. package/src/app/main.tsx +6 -5
  197. package/src/app/standalone.tsx +4 -3
  198. package/src/lib/components/BuildCheck.tsx +1 -1
  199. package/src/lib/components/Header.tsx +5 -3
  200. package/src/lib/components/Heading.tsx +7 -3
  201. package/src/lib/components/Main.tsx +8 -8
  202. package/src/lib/components/MobileTopNavigation.tsx +12 -11
  203. package/src/lib/components/PageProgress.tsx +28 -0
  204. package/src/lib/components/TopNavigation.tsx +57 -66
  205. package/src/lib/components/context/ZudokuContext.ts +50 -32
  206. package/src/lib/components/navigation/{Sidebar.tsx → Navigation.tsx} +18 -16
  207. package/src/lib/components/navigation/{SidebarBadge.tsx → NavigationBadge.tsx} +1 -1
  208. package/src/lib/components/navigation/{SidebarCategory.tsx → NavigationCategory.tsx} +16 -14
  209. package/src/lib/components/navigation/{SidebarItem.tsx → NavigationItem.tsx} +23 -17
  210. package/src/lib/components/navigation/{SidebarWrapper.tsx → NavigationWrapper.tsx} +2 -2
  211. package/src/lib/components/navigation/utils.ts +27 -28
  212. package/src/lib/core/ZudokuContext.ts +9 -15
  213. package/src/lib/core/plugins.ts +2 -2
  214. package/src/lib/hooks/useEvent.test.tsx +7 -5
  215. package/src/lib/plugins/api-catalog/Catalog.tsx +1 -1
  216. package/src/lib/plugins/api-catalog/index.tsx +19 -19
  217. package/src/lib/plugins/api-keys/SettingsApiKeys.tsx +6 -5
  218. package/src/lib/plugins/custom-pages/index.tsx +20 -11
  219. package/src/lib/plugins/markdown/MdxPage.tsx +6 -3
  220. package/src/lib/plugins/markdown/index.tsx +19 -40
  221. package/src/lib/plugins/openapi/OperationList.tsx +1 -1
  222. package/src/lib/plugins/openapi/OperationListItem.tsx +1 -1
  223. package/src/lib/plugins/openapi/SchemaList.tsx +2 -2
  224. package/src/lib/plugins/openapi/graphql/gql.ts +5 -5
  225. package/src/lib/plugins/openapi/graphql/graphql.ts +6 -6
  226. package/src/lib/plugins/openapi/index.tsx +11 -11
  227. package/src/lib/plugins/openapi/interfaces.ts +3 -3
  228. package/src/lib/plugins/openapi/util/{createSidebarCategory.tsx → createNavigationCategory.tsx} +6 -5
  229. package/src/lib/plugins/openapi/util/getRoutes.tsx +2 -2
  230. package/src/lib/plugins/openapi/util/methodColorMap.tsx +1 -1
  231. package/src/lib/util/useScrollToAnchor.ts +3 -3
  232. package/dist/config/validators/InputSidebarSchema.d.ts +0 -220
  233. package/dist/config/validators/InputSidebarSchema.js +0 -63
  234. package/dist/config/validators/InputSidebarSchema.js.map +0 -1
  235. package/dist/config/validators/SidebarSchema.d.ts +0 -46
  236. package/dist/config/validators/SidebarSchema.js +0 -118
  237. package/dist/config/validators/SidebarSchema.js.map +0 -1
  238. package/dist/lib/components/navigation/Sidebar.d.ts +0 -5
  239. package/dist/lib/components/navigation/Sidebar.js +0 -10
  240. package/dist/lib/components/navigation/Sidebar.js.map +0 -1
  241. package/dist/lib/components/navigation/SidebarBadge.js.map +0 -1
  242. package/dist/lib/components/navigation/SidebarCategory.d.ts +0 -5
  243. package/dist/lib/components/navigation/SidebarCategory.js.map +0 -1
  244. package/dist/lib/components/navigation/SidebarItem.d.ts +0 -6
  245. package/dist/lib/components/navigation/SidebarItem.js +0 -44
  246. package/dist/lib/components/navigation/SidebarItem.js.map +0 -1
  247. package/dist/lib/components/navigation/SidebarWrapper.js.map +0 -1
  248. package/dist/lib/plugins/markdown/resolver.d.ts +0 -32
  249. package/dist/lib/plugins/markdown/resolver.js +0 -46
  250. package/dist/lib/plugins/markdown/resolver.js.map +0 -1
  251. package/dist/lib/plugins/openapi/util/createSidebarCategory.d.ts +0 -9
  252. package/dist/lib/plugins/openapi/util/createSidebarCategory.js.map +0 -1
  253. package/dist/vite/plugin-sidebar.js.map +0 -1
  254. package/lib/Markdown-C5j8kKSX.js.map +0 -1
  255. package/lib/MdxPage-CKTMf1cR.js.map +0 -1
  256. package/lib/OasProvider-_GzmsbMg.js +0 -33
  257. package/lib/OasProvider-_GzmsbMg.js.map +0 -1
  258. package/lib/SchemaList-Dgc0A8x5.js.map +0 -1
  259. package/lib/hook-7wZANGJP.js +0 -1483
  260. package/lib/hook-7wZANGJP.js.map +0 -1
  261. package/lib/index-jWXxqkni.js.map +0 -1
  262. package/lib/joinPath-B7kNnUX4.js +0 -8
  263. package/lib/joinPath-B7kNnUX4.js.map +0 -1
  264. package/src/lib/plugins/markdown/resolver.ts +0 -59
@@ -1,42 +1,44 @@
1
1
  import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
2
- import type { SidebarItem as SidebarItemType } from "../../../config/validators/SidebarSchema.js";
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 { SidebarItem } from "./SidebarItem.js";
6
- import { SidebarWrapper } from "./SidebarWrapper.js";
5
+ import { NavigationItem } from "./NavigationItem.js";
6
+ import { NavigationWrapper } from "./NavigationWrapper.js";
7
7
 
8
- export const Sidebar = ({
8
+ export const Navigation = ({
9
9
  onRequestClose,
10
- sidebar,
10
+ navigation,
11
11
  }: {
12
12
  onRequestClose?: () => void;
13
- sidebar: SidebarItemType[];
13
+ navigation: NavigationItemType[];
14
14
  }) => (
15
15
  <>
16
- <SidebarWrapper>
16
+ <NavigationWrapper>
17
17
  <Slot.Target name="navigation-before" />
18
- {sidebar.map((item) => (
19
- <SidebarItem
18
+ {navigation.map((item) => (
19
+ <NavigationItem
20
20
  key={
21
- ("id" in item ? item.id : "") +
22
- ("href" in item ? item.href : "") +
23
- item.label
21
+ item.type +
22
+ (item.label ?? "") +
23
+ ("path" in item ? item.path : "") +
24
+ ("file" in item ? item.file : "") +
25
+ ("to" in item ? item.to : "")
24
26
  }
25
27
  item={item}
26
28
  />
27
29
  ))}
28
30
  <Slot.Target name="navigation-after" />
29
- </SidebarWrapper>
31
+ </NavigationWrapper>
30
32
  <DrawerContent
31
33
  className="lg:hidden h-[100dvh] start-0 w-[320px] rounded-none"
32
34
  aria-describedby={undefined}
33
35
  >
34
36
  <div className="p-4 overflow-y-auto overscroll-none">
35
37
  <VisuallyHidden>
36
- <DrawerTitle>Sidebar</DrawerTitle>
38
+ <DrawerTitle>Navigation</DrawerTitle>
37
39
  </VisuallyHidden>
38
- {sidebar.map((item) => (
39
- <SidebarItem
40
+ {navigation.map((item) => (
41
+ <NavigationItem
40
42
  key={item.label}
41
43
  item={item}
42
44
  onRequestClose={onRequestClose}
@@ -22,7 +22,7 @@ export const ColorMapInvert = {
22
22
  outline: "",
23
23
  };
24
24
 
25
- export const SidebarBadge = ({
25
+ export const NavigationBadge = ({
26
26
  color,
27
27
  label,
28
28
  className,
@@ -4,17 +4,17 @@ import { ChevronRightIcon } from "lucide-react";
4
4
  import { memo, useEffect, useState } from "react";
5
5
  import { NavLink, useLocation, useMatch } from "react-router";
6
6
  import { Button } from "zudoku/ui/Button.js";
7
- import type { SidebarItemCategory } from "../../../config/validators/SidebarSchema.js";
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 { SidebarItem } from "./SidebarItem.js";
10
+ import { NavigationItem } from "./NavigationItem.js";
11
11
  import { navigationListItem, useIsCategoryOpen } from "./utils.js";
12
12
 
13
- const SidebarCategoryInner = ({
13
+ const NavigationCategoryInner = ({
14
14
  category,
15
15
  onRequestClose,
16
16
  }: {
17
- category: SidebarItemCategory;
17
+ category: NavigationCategoryType;
18
18
  onRequestClose?: () => void;
19
19
  }) => {
20
20
  const isCategoryOpen = useIsCategoryOpen(category);
@@ -27,11 +27,11 @@ const SidebarCategoryInner = ({
27
27
  !isCollapsible || !isCollapsed || isCategoryOpen,
28
28
  );
29
29
  const [open, setOpen] = useState(isDefaultOpen);
30
- const isActive = useMatch(category.link?.id ?? "");
30
+ const isActive = useMatch(category.link?.path ?? "");
31
31
 
32
32
  useEffect(() => {
33
- // this is triggered when an item from the sidebar is clicked
34
- // and the sidebar, enclosing this item, is not opened
33
+ // this is triggered when an item from the navigation is clicked
34
+ // and the navigation, enclosing this item, is not opened
35
35
  if (isCategoryOpen) {
36
36
  setOpen(true);
37
37
  }
@@ -85,7 +85,7 @@ const SidebarCategoryInner = ({
85
85
  {category.link?.type === "doc" ? (
86
86
  <NavLink
87
87
  to={{
88
- pathname: joinUrl(category.link.id),
88
+ pathname: joinUrl(category.link.path),
89
89
  search: location.search,
90
90
  }}
91
91
  className={styles}
@@ -123,11 +123,13 @@ const SidebarCategoryInner = ({
123
123
  >
124
124
  <ul className="relative after:absolute after:-start-(--padding-nav-item) after:translate-x-[1.5px] after:top-0 after:bottom-0 after:w-px after:bg-border">
125
125
  {category.items.map((item) => (
126
- <SidebarItem
126
+ <NavigationItem
127
127
  key={
128
- ("id" in item ? item.id : "") +
129
- ("href" in item ? item.href : "") +
130
- item.label
128
+ item.type +
129
+ (item.label ?? "") +
130
+ ("path" in item ? item.path : "") +
131
+ ("file" in item ? item.file : "") +
132
+ ("to" in item ? item.to : "")
131
133
  }
132
134
  onRequestClose={onRequestClose}
133
135
  item={item}
@@ -139,6 +141,6 @@ const SidebarCategoryInner = ({
139
141
  );
140
142
  };
141
143
 
142
- export const SidebarCategory = memo(SidebarCategoryInner, deepEqual);
144
+ export const NavigationCategory = memo(NavigationCategoryInner, deepEqual);
143
145
 
144
- SidebarCategory.displayName = "SidebarCategory";
146
+ NavigationCategory.displayName = "NavigationCategory";
@@ -8,13 +8,13 @@ import {
8
8
  TooltipProvider,
9
9
  TooltipTrigger,
10
10
  } from "zudoku/ui/Tooltip.js";
11
- import type { SidebarItem as SidebarItemType } from "../../../config/validators/SidebarSchema.js";
11
+ import type { NavigationItem as NavigationItemType } from "../../../config/validators/NavigationSchema.js";
12
12
  import { cn } from "../../util/cn.js";
13
13
  import { joinUrl } from "../../util/joinUrl.js";
14
14
  import { AnchorLink } from "../AnchorLink.js";
15
15
  import { useViewportAnchor } from "../context/ViewportAnchorContext.js";
16
- import { SidebarBadge } from "./SidebarBadge.js";
17
- import { SidebarCategory } from "./SidebarCategory.js";
16
+ import { NavigationBadge } from "./NavigationBadge.js";
17
+ import { NavigationCategory } from "./NavigationCategory.js";
18
18
  import { navigationListItem } from "./utils.js";
19
19
 
20
20
  const TruncatedLabel = ({
@@ -65,11 +65,11 @@ const TruncatedLabel = ({
65
65
 
66
66
  export const DATA_ANCHOR_ATTR = "data-anchor";
67
67
 
68
- export const SidebarItem = ({
68
+ export const NavigationItem = ({
69
69
  item,
70
70
  onRequestClose,
71
71
  }: {
72
- item: SidebarItemType;
72
+ item: NavigationItemType;
73
73
  onRequestClose?: () => void;
74
74
  }) => {
75
75
  const location = useLocation();
@@ -78,23 +78,26 @@ export const SidebarItem = ({
78
78
  switch (item.type) {
79
79
  case "category":
80
80
  return (
81
- <SidebarCategory category={item} onRequestClose={onRequestClose} />
81
+ <NavigationCategory category={item} onRequestClose={onRequestClose} />
82
82
  );
83
83
  case "doc":
84
84
  return (
85
85
  <NavLink
86
+ viewTransition
86
87
  className={({ isActive, isPending }) =>
87
88
  navigationListItem({ isActive, isPending })
88
89
  }
89
- to={joinUrl(item.id)}
90
+ to={joinUrl(item.path)}
90
91
  onClick={onRequestClose}
91
92
  end
92
93
  >
93
94
  {item.icon && <item.icon size={16} className="align-[-0.125em]" />}
94
95
  {item.badge ? (
95
96
  <>
96
- <TruncatedLabel label={item.label} className="flex-1" />
97
- <SidebarBadge {...item.badge} />
97
+ {item.label && (
98
+ <TruncatedLabel label={item.label} className="flex-1" />
99
+ )}
100
+ <NavigationBadge {...item.badge} />
98
101
  </>
99
102
  ) : (
100
103
  item.label
@@ -102,24 +105,26 @@ export const SidebarItem = ({
102
105
  </NavLink>
103
106
  );
104
107
  case "link":
105
- return !item.href.startsWith("http") ? (
108
+ case "custom-page": {
109
+ const href = item.type === "link" ? item.to : item.path;
110
+ return !href.startsWith("http") ? (
106
111
  <AnchorLink
107
112
  to={{
108
- pathname: item.href.split("#")[0],
109
- hash: item.href.split("#")[1],
113
+ pathname: href.split("#")[0],
114
+ hash: href.split("#")[1],
110
115
  search: location.search,
111
116
  }}
112
- {...{ [DATA_ANCHOR_ATTR]: item.href.split("#")[1] }}
117
+ {...{ [DATA_ANCHOR_ATTR]: href.split("#")[1] }}
113
118
  className={navigationListItem({
114
- isActive: item.href === [location.pathname, activeAnchor].join("#"),
119
+ isActive: href === [location.pathname, activeAnchor].join("#"),
115
120
  })}
116
121
  onClick={onRequestClose}
117
122
  >
118
123
  {item.icon && <item.icon size={16} className="align-[-0.125em]" />}
119
124
  {item.badge ? (
120
125
  <>
121
- <TruncatedLabel label={item.label} />
122
- <SidebarBadge {...item.badge} />
126
+ {item.label && <TruncatedLabel label={item.label} />}
127
+ <NavigationBadge {...item.badge} />
123
128
  </>
124
129
  ) : (
125
130
  <span className="break-all">{item.label}</span>
@@ -128,7 +133,7 @@ export const SidebarItem = ({
128
133
  ) : (
129
134
  <a
130
135
  className={navigationListItem()}
131
- href={item.href}
136
+ href={href}
132
137
  target="_blank"
133
138
  rel="noopener noreferrer"
134
139
  onClick={onRequestClose}
@@ -141,5 +146,6 @@ export const SidebarItem = ({
141
146
  </span>
142
147
  </a>
143
148
  );
149
+ }
144
150
  }
145
151
  };
@@ -4,7 +4,7 @@ import { scrollIntoViewIfNeeded } from "../../util/scrollIntoViewIfNeeded.js";
4
4
  import { useZudoku } from "../context/ZudokuContext.js";
5
5
  import { PoweredByZudoku } from "./PoweredByZudoku.js";
6
6
 
7
- export const SidebarWrapper = ({
7
+ export const NavigationWrapper = ({
8
8
  children,
9
9
  className,
10
10
  }: PropsWithChildren<{
@@ -43,4 +43,4 @@ export const SidebarWrapper = ({
43
43
  );
44
44
  };
45
45
 
46
- SidebarWrapper.displayName = "SidebarWrapper";
46
+ NavigationWrapper.displayName = "NavigationWrapper";
@@ -1,38 +1,38 @@
1
1
  import { cva } from "class-variance-authority";
2
2
  import { useLocation } from "react-router";
3
3
  import type {
4
- SidebarItem,
5
- SidebarItemCategory,
6
- } from "../../../config/validators/SidebarSchema.js";
4
+ NavigationCategory,
5
+ NavigationItem,
6
+ } from "../../../config/validators/NavigationSchema.js";
7
7
  import { joinUrl } from "../../util/joinUrl.js";
8
8
  import { useCurrentNavigation } from "../context/ZudokuContext.js";
9
9
 
10
10
  export type TraverseCallback<T> = (
11
- item: SidebarItem,
12
- parentCategories: SidebarItem[],
11
+ item: NavigationItem,
12
+ parentCategories: NavigationItem[],
13
13
  ) => T | void;
14
14
 
15
- export const traverseSidebar = <T>(
16
- sidebar: SidebarItem[],
15
+ export const traverseNavigation = <T>(
16
+ navigation: NavigationItem[],
17
17
  callback: TraverseCallback<T>,
18
18
  ): T | undefined => {
19
- for (const item of sidebar) {
20
- const result = traverseSidebarItem(item, callback);
19
+ for (const item of navigation) {
20
+ const result = traverseNavigationItem(item, callback);
21
21
  if (result !== undefined) return result;
22
22
  }
23
23
  };
24
24
 
25
- export const traverseSidebarItem = <T>(
26
- item: SidebarItem,
25
+ export const traverseNavigationItem = <T>(
26
+ item: NavigationItem,
27
27
  callback: TraverseCallback<T>,
28
- parentCategories: SidebarItem[] = [],
28
+ parentCategories: NavigationItem[] = [],
29
29
  ): T | undefined => {
30
30
  const result = callback(item, parentCategories);
31
31
  if (result !== undefined) return result;
32
32
 
33
33
  if (item.type === "category") {
34
34
  for (const child of item.items) {
35
- const childResult = traverseSidebarItem(child, callback, [
35
+ const childResult = traverseNavigationItem(child, callback, [
36
36
  ...parentCategories,
37
37
  item,
38
38
  ]);
@@ -43,30 +43,28 @@ export const traverseSidebarItem = <T>(
43
43
 
44
44
  export const useCurrentItem = () => {
45
45
  const location = useLocation();
46
- const nav = useCurrentNavigation();
46
+ const { navigation } = useCurrentNavigation();
47
47
 
48
- const currentSidebar = nav.sidebar;
49
-
50
- return traverseSidebar(currentSidebar, (item) => {
51
- if (item.type === "doc" && joinUrl(item.id) === location.pathname) {
48
+ return traverseNavigation(navigation, (item) => {
49
+ if (item.type === "doc" && joinUrl(item.path) === location.pathname) {
52
50
  return item;
53
51
  }
54
52
  });
55
53
  };
56
54
 
57
- export const useIsCategoryOpen = (category: SidebarItemCategory) => {
55
+ export const useIsCategoryOpen = (category: NavigationCategory) => {
58
56
  const location = useLocation();
59
57
 
60
- return traverseSidebarItem(category, (item) => {
58
+ return traverseNavigationItem(category, (item) => {
61
59
  if (item.type === "category" && item.link) {
62
- const categoryLinkPath = joinUrl(item.link.id);
60
+ const categoryLinkPath = joinUrl(item.link.path);
63
61
  if (categoryLinkPath === location.pathname) {
64
62
  return true;
65
63
  }
66
64
  }
67
65
 
68
66
  if (item.type === "doc") {
69
- const docPath = joinUrl(item.id);
67
+ const docPath = joinUrl(item.path);
70
68
  if (docPath === location.pathname) {
71
69
  return true;
72
70
  }
@@ -79,20 +77,19 @@ export const usePrevNext = (): {
79
77
  next?: { label: string; id: string };
80
78
  } => {
81
79
  const currentId = useLocation().pathname;
82
- const nav = useCurrentNavigation();
83
- const currentSidebar = nav.sidebar;
80
+ const { navigation } = useCurrentNavigation();
84
81
 
85
82
  let prev;
86
83
  let next;
87
84
 
88
85
  let foundCurrent = false;
89
86
 
90
- traverseSidebar(currentSidebar, (item) => {
87
+ traverseNavigation(navigation, (item) => {
91
88
  const itemId =
92
89
  item.type === "doc"
93
- ? joinUrl(item.id)
90
+ ? joinUrl(item.path)
94
91
  : item.type === "category" && item.link
95
- ? joinUrl(item.link.id)
92
+ ? joinUrl(item.link.path)
96
93
  : undefined;
97
94
 
98
95
  if (!itemId) return;
@@ -137,8 +134,10 @@ export const navigationListItem = cva(
137
134
 
138
135
  export const isHiddenItem =
139
136
  (isAuthenticated?: boolean) =>
140
- (item: { display?: "auth" | "anon" | "always" | "hide" }): boolean => {
137
+ (item: NavigationItem): boolean => {
141
138
  if (item.display === "hide") return false;
139
+ if (!item.label) return false;
140
+
142
141
  return (
143
142
  (item.display === "auth" && isAuthenticated) ||
144
143
  (item.display === "anon" && !isAuthenticated) ||
@@ -3,17 +3,14 @@ import { createNanoEvents } from "nanoevents";
3
3
  import type { ReactNode } from "react";
4
4
  import type { Location } from "react-router";
5
5
  import type { BundledTheme, HighlighterCore } from "shiki";
6
- import type { z } from "zod";
7
- import type { SidebarConfig } from "../../config/validators/SidebarSchema.js";
8
- import type {
9
- FooterSchema,
10
- TopNavigationItem,
11
- } from "../../config/validators/validate.js";
6
+ import type { z } from "zod/v4";
7
+ import type { Navigation } from "../../config/validators/NavigationSchema.js";
8
+ import type { FooterSchema } from "../../config/validators/validate.js";
12
9
  import type { AuthenticationPlugin } from "../authentication/authentication.js";
13
10
  import { type AuthState, useAuthState } from "../authentication/state.js";
14
11
  import type { ComponentsContextType } from "../components/context/ComponentsContext.js";
15
12
  import type { SlotType } from "../components/context/SlotProvider.js";
16
- import { joinPath } from "../util/joinPath.js";
13
+ import { joinUrl } from "../util/joinUrl.js";
17
14
  import type { MdxComponentsType } from "../util/MdxComponents.js";
18
15
  import { objectEntries } from "../util/objectEntries.js";
19
16
  import {
@@ -83,8 +80,7 @@ export type ZudokuContextOptions = {
83
80
  metadata?: Metadata;
84
81
  page?: Page;
85
82
  authentication?: AuthenticationPlugin;
86
- topNavigation?: TopNavigationItem[];
87
- sidebars?: SidebarConfig;
83
+ navigation?: Navigation;
88
84
  plugins?: ZudokuPlugin[];
89
85
  slots?: Record<string, SlotType>;
90
86
  /**
@@ -104,8 +100,7 @@ export type ZudokuContextOptions = {
104
100
 
105
101
  export class ZudokuContext {
106
102
  public plugins: NonNullable<ZudokuContextOptions["plugins"]>;
107
- public sidebars: SidebarConfig;
108
- public topNavigation: NonNullable<ZudokuContextOptions["topNavigation"]>;
103
+ public navigation: Navigation;
109
104
  public meta: ZudokuContextOptions["metadata"];
110
105
  public page: ZudokuContextOptions["page"];
111
106
  public readonly authentication?: ZudokuContextOptions["authentication"];
@@ -124,8 +119,7 @@ export class ZudokuContext {
124
119
  this.queryClient = queryClient;
125
120
  this.options = { ...options, protectedRoutes };
126
121
  this.plugins = options.plugins ?? [];
127
- this.topNavigation = options.topNavigation ?? [];
128
- this.sidebars = options.sidebars ?? {};
122
+ this.navigation = options.navigation ?? [];
129
123
  this.navigationPlugins = this.plugins.filter(isNavigationPlugin);
130
124
  this.authentication = this.plugins.find(isAuthenticationPlugin);
131
125
  this.meta = options.metadata;
@@ -178,10 +172,10 @@ export class ZudokuContext {
178
172
  return this.emitter.emit(event, ...data);
179
173
  };
180
174
 
181
- getPluginSidebar = async (path: string) => {
175
+ getPluginNavigation = async (path: string) => {
182
176
  const navigations = await Promise.all(
183
177
  this.navigationPlugins.map((plugin) =>
184
- plugin.getSidebar?.(joinPath(path), this),
178
+ plugin.getNavigation?.(joinUrl(path), this),
185
179
  ),
186
180
  );
187
181
 
@@ -1,7 +1,7 @@
1
1
  import type { LucideIcon } from "lucide-react";
2
2
  import type { ReactElement } from "react";
3
3
  import type { Location, RouteObject } from "react-router";
4
- import type { Sidebar } from "../../config/validators/SidebarSchema.js";
4
+ import type { Navigation } from "../../config/validators/NavigationSchema.js";
5
5
  import type { AuthenticationPlugin } from "../authentication/authentication.js";
6
6
  import type { MdxComponentsType } from "../util/MdxComponents.js";
7
7
  import type {
@@ -23,7 +23,7 @@ export type { AuthenticationPlugin, RouteObject };
23
23
 
24
24
  export interface NavigationPlugin {
25
25
  getRoutes: () => RouteObject[];
26
- getSidebar?: (path: string, context: ZudokuContext) => Promise<Sidebar>;
26
+ getNavigation?: (path: string, context: ZudokuContext) => Promise<Navigation>;
27
27
  getProtectedRoutes?: () => string[];
28
28
  }
29
29
 
@@ -116,11 +116,13 @@ describe("useEvent", () => {
116
116
  describe("types", () => {
117
117
  const { wrapper } = createTestContext();
118
118
 
119
- it("infers event type when no callback is provided", () => {
120
- const hook = renderHook(() => useEvent("location"), { wrapper });
121
- assertType<Parameters<ZudokuEvents["location"]> | undefined>(
122
- hook.result.current,
123
- );
119
+ it("infers event type when no callback is provided", async () => {
120
+ await act(async () => {
121
+ const hook = renderHook(() => useEvent("location"), { wrapper });
122
+ assertType<Parameters<ZudokuEvents["location"]> | undefined>(
123
+ hook.result.current,
124
+ );
125
+ });
124
126
  });
125
127
 
126
128
  it("infers string type from pathname callback", () => {
@@ -13,7 +13,7 @@ export const Catalog = ({
13
13
  filterCatalogItems = (items) => items,
14
14
  label = "API Library",
15
15
  categoryLabel,
16
- }: Omit<ApiCatalogPluginOptions, "navigationId"> & {
16
+ }: Omit<ApiCatalogPluginOptions, "path"> & {
17
17
  categoryLabel?: string;
18
18
  }) => {
19
19
  const auth = useAuthState();
@@ -1,6 +1,6 @@
1
1
  import slugify from "@sindresorhus/slugify";
2
2
  import { matchPath } from "react-router";
3
- import type { SidebarItem } from "../../../config/validators/SidebarSchema.js";
3
+ import type { NavigationItem } from "../../../config/validators/NavigationSchema.js";
4
4
  import type { AuthState } from "../../authentication/state.js";
5
5
  import type { ZudokuPlugin } from "../../core/plugins.js";
6
6
  import { joinUrl } from "../../util/joinUrl.js";
@@ -22,46 +22,46 @@ export type CatalogCategory = {
22
22
  };
23
23
 
24
24
  export type ApiCatalogPluginOptions = {
25
- navigationId: string;
25
+ path: string;
26
26
  label: string;
27
27
  categories?: CatalogCategory[];
28
28
  items: ApiCatalogItem[];
29
- filterCatalogItems?: filterCatalogItems;
29
+ filterCatalogItems?: FilterCatalogItemsFn;
30
30
  };
31
31
 
32
32
  export type CatalogContext<ProviderData = unknown> = {
33
33
  auth: AuthState<ProviderData>;
34
34
  };
35
35
 
36
- export type filterCatalogItems<ProviderData = unknown> = (
36
+ export type FilterCatalogItemsFn<ProviderData = unknown> = (
37
37
  items: ApiCatalogItem[],
38
38
  { auth }: CatalogContext<ProviderData>,
39
39
  ) => ApiCatalogItem[];
40
40
 
41
41
  export const apiCatalogPlugin = ({
42
- navigationId,
42
+ path,
43
43
  items,
44
44
  label,
45
45
  categories = [],
46
46
  filterCatalogItems,
47
47
  }: {
48
- navigationId: string;
48
+ path: string;
49
49
  label: string;
50
50
  categories?: CatalogCategory[];
51
51
  items: ApiCatalogItem[];
52
- filterCatalogItems?: filterCatalogItems;
52
+ filterCatalogItems?: FilterCatalogItemsFn;
53
53
  }): ZudokuPlugin => {
54
54
  const paths = Object.fromEntries(
55
55
  categories.flatMap((category) =>
56
56
  [undefined, ...category.tags].map((tag) => [
57
- joinUrl(navigationId, tag ? getKey(category.label, tag) : undefined),
57
+ joinUrl(path, tag ? getKey(category.label, tag) : undefined),
58
58
  tag,
59
59
  ]),
60
60
  ),
61
61
  );
62
62
 
63
63
  return {
64
- getSidebar: async (currentPath) => {
64
+ getNavigation: async (currentPath) => {
65
65
  const matches = Object.keys(paths).some((path) =>
66
66
  matchPath(path, currentPath),
67
67
  );
@@ -70,13 +70,13 @@ export const apiCatalogPlugin = ({
70
70
  return [];
71
71
  }
72
72
 
73
- const sidebar: SidebarItem[] = categories.map((category) => ({
74
- type: "category" as const,
73
+ const navigation: NavigationItem[] = categories.map((category) => ({
74
+ type: "category",
75
75
  label: category.label,
76
76
  collapsible: false,
77
77
  items: category.tags.map((tag) => ({
78
- type: "doc" as const,
79
- id: joinUrl(navigationId, getKey(category.label, tag)),
78
+ type: "link",
79
+ to: joinUrl(path, getKey(category.label, tag)),
80
80
  label: tag,
81
81
  badge: {
82
82
  label: String(
@@ -84,19 +84,19 @@ export const apiCatalogPlugin = ({
84
84
  api.categories.find((c) => c.tags.includes(tag)),
85
85
  ).length,
86
86
  ),
87
- color: "outline" as const,
87
+ color: "outline",
88
88
  },
89
89
  })),
90
90
  }));
91
91
 
92
- sidebar.unshift({
93
- type: "doc" as const,
94
- id: joinUrl(navigationId),
92
+ navigation.unshift({
93
+ type: "link",
94
+ to: joinUrl(path),
95
95
  label: "Overview",
96
- badge: { label: String(items.length), color: "outline" as const },
96
+ badge: { label: String(items.length), color: "outline" },
97
97
  });
98
98
 
99
- return sidebar;
99
+ return navigation;
100
100
  },
101
101
  getRoutes: () =>
102
102
  Object.entries(paths).map(([path, tag]) => ({