zudoku 0.0.0-e3f7e48 → 0.0.0-e4d0ea8

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 (297) hide show
  1. package/cli.js +2 -2
  2. package/dist/app/entry.client.js +2 -2
  3. package/dist/app/entry.client.js.map +1 -1
  4. package/dist/app/entry.server.js +3 -0
  5. package/dist/app/entry.server.js.map +1 -1
  6. package/dist/app/main.d.ts +1 -0
  7. package/dist/app/main.js +9 -24
  8. package/dist/app/main.js.map +1 -1
  9. package/dist/app/standalone.js.map +1 -1
  10. package/dist/cli/common/machine-id/lib.js.map +1 -1
  11. package/dist/cli/common/outdated.js.map +1 -1
  12. package/dist/cli/common/utils/box.js.map +1 -1
  13. package/dist/cli/dev/handler.js +2 -2
  14. package/dist/cli/dev/handler.js.map +1 -1
  15. package/dist/config/validators/InputSidebarSchema.d.ts +2 -2
  16. package/dist/config/validators/SidebarSchema.d.ts +1 -1
  17. package/dist/config/validators/SidebarSchema.js +5 -9
  18. package/dist/config/validators/SidebarSchema.js.map +1 -1
  19. package/dist/config/validators/validate.d.ts +97 -30
  20. package/dist/config/validators/validate.js +10 -7
  21. package/dist/config/validators/validate.js.map +1 -1
  22. package/dist/index.d.ts +5 -1
  23. package/dist/index.js +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/lib/authentication/state.d.ts +16 -0
  26. package/dist/lib/authentication/state.js +5 -0
  27. package/dist/lib/authentication/state.js.map +1 -1
  28. package/dist/lib/components/Banner.js +7 -1
  29. package/dist/lib/components/Banner.js.map +1 -1
  30. package/dist/lib/components/ErrorPage.js +1 -2
  31. package/dist/lib/components/ErrorPage.js.map +1 -1
  32. package/dist/lib/components/Header.js +5 -1
  33. package/dist/lib/components/Header.js.map +1 -1
  34. package/dist/lib/components/InlineCode.d.ts +2 -1
  35. package/dist/lib/components/InlineCode.js +9 -1
  36. package/dist/lib/components/InlineCode.js.map +1 -1
  37. package/dist/lib/components/Layout.js +1 -1
  38. package/dist/lib/components/Layout.js.map +1 -1
  39. package/dist/lib/components/MobileTopNavigation.js +2 -1
  40. package/dist/lib/components/MobileTopNavigation.js.map +1 -1
  41. package/dist/lib/components/SlotletProvider.d.ts +5 -2
  42. package/dist/lib/components/SlotletProvider.js +6 -2
  43. package/dist/lib/components/SlotletProvider.js.map +1 -1
  44. package/dist/lib/components/TopNavigation.js +30 -5
  45. package/dist/lib/components/TopNavigation.js.map +1 -1
  46. package/dist/lib/components/context/ZudokuContext.d.ts +4 -9
  47. package/dist/lib/components/context/ZudokuContext.js +26 -20
  48. package/dist/lib/components/context/ZudokuContext.js.map +1 -1
  49. package/dist/lib/components/index.d.ts +2 -1
  50. package/dist/lib/components/index.js.map +1 -1
  51. package/dist/lib/components/navigation/Sidebar.js +3 -3
  52. package/dist/lib/components/navigation/Sidebar.js.map +1 -1
  53. package/dist/lib/components/navigation/SidebarCategory.js +1 -3
  54. package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
  55. package/dist/lib/components/navigation/SidebarItem.js +1 -3
  56. package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
  57. package/dist/lib/components/navigation/utils.js +10 -14
  58. package/dist/lib/components/navigation/utils.js.map +1 -1
  59. package/dist/lib/core/DevPortalContext.d.ts +4 -7
  60. package/dist/lib/core/DevPortalContext.js.map +1 -1
  61. package/dist/lib/core/plugins.d.ts +1 -0
  62. package/dist/lib/core/plugins.js.map +1 -1
  63. package/dist/lib/oas/graphql/index.js +12 -6
  64. package/dist/lib/oas/graphql/index.js.map +1 -1
  65. package/dist/lib/oas/parser/index.d.ts +1 -0
  66. package/dist/lib/oas/parser/index.js.map +1 -1
  67. package/dist/lib/plugins/{custom-page → custom-pages}/index.d.ts +2 -2
  68. package/dist/lib/plugins/{custom-page → custom-pages}/index.js +1 -1
  69. package/dist/lib/plugins/custom-pages/index.js.map +1 -0
  70. package/dist/lib/plugins/markdown/index.d.ts +5 -6
  71. package/dist/lib/plugins/markdown/index.js +31 -3
  72. package/dist/lib/plugins/markdown/index.js.map +1 -1
  73. package/dist/lib/plugins/markdown/resolver.d.ts +38 -0
  74. package/dist/lib/plugins/markdown/resolver.js +75 -0
  75. package/dist/lib/plugins/markdown/resolver.js.map +1 -0
  76. package/dist/lib/plugins/openapi/Endpoint.d.ts +1 -3
  77. package/dist/lib/plugins/openapi/Endpoint.js +46 -8
  78. package/dist/lib/plugins/openapi/Endpoint.js.map +1 -1
  79. package/dist/lib/plugins/openapi/OperationList.js +2 -2
  80. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  81. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.d.ts +2 -1
  82. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js +2 -2
  83. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js.map +1 -1
  84. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
  85. package/dist/lib/plugins/openapi/Route.d.ts +1 -1
  86. package/dist/lib/plugins/openapi/Route.js +1 -1
  87. package/dist/lib/plugins/openapi/Route.js.map +1 -1
  88. package/dist/lib/plugins/openapi/Sidecar.js +15 -4
  89. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  90. package/dist/lib/plugins/openapi/SimpleSelect.d.ts +2 -1
  91. package/dist/lib/plugins/openapi/SimpleSelect.js +1 -1
  92. package/dist/lib/plugins/openapi/SimpleSelect.js.map +1 -1
  93. package/dist/lib/plugins/openapi/client/createMemoryClient.js +1 -1
  94. package/dist/lib/plugins/openapi/client/createMemoryClient.js.map +1 -1
  95. package/dist/lib/plugins/openapi/client/createWorkerClient.js +1 -1
  96. package/dist/lib/plugins/openapi/client/createWorkerClient.js.map +1 -1
  97. package/dist/lib/plugins/openapi/client/worker.js.map +1 -1
  98. package/dist/lib/plugins/openapi/graphql/gql.d.ts +10 -2
  99. package/dist/lib/plugins/openapi/graphql/gql.js +2 -1
  100. package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
  101. package/dist/lib/plugins/openapi/graphql/graphql.d.ts +26 -0
  102. package/dist/lib/plugins/openapi/graphql/graphql.js +87 -0
  103. package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
  104. package/dist/lib/plugins/openapi/index.js +1 -1
  105. package/dist/lib/plugins/openapi/index.js.map +1 -1
  106. package/dist/lib/plugins/openapi/playground/Playground.d.ts +2 -1
  107. package/dist/lib/plugins/openapi/playground/Playground.js +13 -5
  108. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  109. package/dist/lib/plugins/openapi/playground/ResponseTab.js +1 -1
  110. package/dist/lib/plugins/openapi/playground/ResponseTab.js.map +1 -1
  111. package/dist/lib/ui/Callout.d.ts +36 -35
  112. package/dist/lib/ui/Callout.js.map +1 -1
  113. package/dist/lib/ui/Drawer.d.ts +8 -10
  114. package/dist/lib/ui/Drawer.js.map +1 -1
  115. package/dist/lib/util/useScrollToAnchor.js.map +1 -1
  116. package/dist/vite/build.js +7 -2
  117. package/dist/vite/build.js.map +1 -1
  118. package/dist/vite/config.js +15 -13
  119. package/dist/vite/config.js.map +1 -1
  120. package/dist/vite/debug.d.ts +1 -0
  121. package/dist/vite/debug.js +10 -0
  122. package/dist/vite/debug.js.map +1 -0
  123. package/dist/vite/dev-server.d.ts +6 -1
  124. package/dist/vite/dev-server.js +13 -3
  125. package/dist/vite/dev-server.js.map +1 -1
  126. package/dist/vite/plugin-component.js +0 -1
  127. package/dist/vite/plugin-component.js.map +1 -1
  128. package/dist/vite/plugin-config-reload.js.map +1 -1
  129. package/dist/vite/plugin-custom-pages.d.ts +4 -0
  130. package/dist/vite/plugin-custom-pages.js +30 -0
  131. package/dist/vite/plugin-custom-pages.js.map +1 -0
  132. package/dist/vite/plugin-docs.js +20 -15
  133. package/dist/vite/plugin-docs.js.map +1 -1
  134. package/dist/vite/plugin-sidebar.js +5 -2
  135. package/dist/vite/plugin-sidebar.js.map +1 -1
  136. package/dist/vite/plugin.js +2 -0
  137. package/dist/vite/plugin.js.map +1 -1
  138. package/dist/vite/prerender.d.ts +5 -1
  139. package/dist/vite/prerender.js +6 -5
  140. package/dist/vite/prerender.js.map +1 -1
  141. package/lib/{utils-ByIc_KIM.js → AnchorLink-DovtSBJk.js} +231 -275
  142. package/lib/AnchorLink-DovtSBJk.js.map +1 -0
  143. package/lib/{AuthenticationPlugin-Bx9FK124.js → AuthenticationPlugin-Cnqy9csQ.js} +3 -3
  144. package/lib/{AuthenticationPlugin-Bx9FK124.js.map → AuthenticationPlugin-Cnqy9csQ.js.map} +1 -1
  145. package/lib/{CategoryHeading-EN3W3xEN.js → CategoryHeading-C7VfgpFZ.js} +2 -2
  146. package/lib/{CategoryHeading-EN3W3xEN.js.map → CategoryHeading-C7VfgpFZ.js.map} +1 -1
  147. package/lib/{DeveloperHint-CZ4VwuKw.js → DeveloperHint-CNyuFROc.js} +2 -2
  148. package/lib/{DeveloperHint-CZ4VwuKw.js.map → DeveloperHint-CNyuFROc.js.map} +1 -1
  149. package/lib/ErrorPage-CUz-Zzmx.js +16 -0
  150. package/lib/ErrorPage-CUz-Zzmx.js.map +1 -0
  151. package/lib/Input-x-t53FyR.js +2229 -0
  152. package/lib/Input-x-t53FyR.js.map +1 -0
  153. package/lib/{Markdown-BUUIyZbc.js → Markdown-C-0TaxoY.js} +721 -555
  154. package/lib/Markdown-C-0TaxoY.js.map +1 -0
  155. package/lib/{MdxPage-COBmXj_4.js → MdxPage-C5I9c7R1.js} +27 -26
  156. package/lib/{MdxPage-COBmXj_4.js.map → MdxPage-C5I9c7R1.js.map} +1 -1
  157. package/lib/{OperationList-BwJXexkA.js → OperationList-qsBOguHS.js} +149 -108
  158. package/lib/OperationList-qsBOguHS.js.map +1 -0
  159. package/lib/{Route-CX_-Q1HO.js → Route-DlKvXPAO.js} +3 -4
  160. package/lib/Route-DlKvXPAO.js.map +1 -0
  161. package/lib/SidebarBadge-DaA0-bFW.js +503 -0
  162. package/lib/SidebarBadge-DaA0-bFW.js.map +1 -0
  163. package/lib/{SlotletProvider-CULK8zmk.js → SlotletProvider-BGEs7yyu.js} +28 -26
  164. package/lib/{SlotletProvider-CULK8zmk.js.map → SlotletProvider-BGEs7yyu.js.map} +1 -1
  165. package/lib/ZudokuContext-DSipF8sq.js +1222 -0
  166. package/lib/ZudokuContext-DSipF8sq.js.map +1 -0
  167. package/lib/__vite-browser-external-BYRIRx8p.js +9 -0
  168. package/lib/__vite-browser-external-BYRIRx8p.js.map +1 -0
  169. package/lib/assets/{index-B9EWVYfo.js → index-B_Jk_Yzp.js} +968 -938
  170. package/lib/assets/index-B_Jk_Yzp.js.map +1 -0
  171. package/lib/assets/{worker-DgVH8VJc.js → worker-DaFlmuyf.js} +4371 -4169
  172. package/lib/assets/worker-DaFlmuyf.js.map +1 -0
  173. package/lib/{index-BuA1OA5H.js → index-BIl-R3aH.js} +1939 -1675
  174. package/lib/index-BIl-R3aH.js.map +1 -0
  175. package/lib/{index-Q0TPJvr8.js → index-CKmSo0py.js} +3 -3
  176. package/lib/{index-Q0TPJvr8.js.map → index-CKmSo0py.js.map} +1 -1
  177. package/lib/{index-CLd8ycZz.js → index-CkwDvuPt.js} +947 -917
  178. package/lib/index-CkwDvuPt.js.map +1 -0
  179. package/lib/{index-LNp6rxyU.js → index-D06ATMgg.js} +2 -2
  180. package/lib/{index-LNp6rxyU.js.map → index-D06ATMgg.js.map} +1 -1
  181. package/lib/index-DJqnphbT.js +35 -0
  182. package/lib/{index-Bn6Lc9tq.js.map → index-DJqnphbT.js.map} +1 -1
  183. package/lib/{index-BfA1oLPP.js → index-Dssw7Gff.js} +597 -544
  184. package/lib/index-Dssw7Gff.js.map +1 -0
  185. package/lib/{index-BG0g4WW0.js → index-SrtqdZ3j.js} +746 -736
  186. package/lib/index-SrtqdZ3j.js.map +1 -0
  187. package/lib/router-Oe6YmY6B.js +3024 -0
  188. package/lib/router-Oe6YmY6B.js.map +1 -0
  189. package/lib/state-CsuHT8ZO.js +183 -0
  190. package/lib/state-CsuHT8ZO.js.map +1 -0
  191. package/lib/urql-core-KJnLL26g.js +1455 -0
  192. package/lib/urql-core-KJnLL26g.js.map +1 -0
  193. package/lib/zudoku.auth-auth0.js +1 -1
  194. package/lib/zudoku.auth-clerk.js +2 -2
  195. package/lib/zudoku.auth-openid.js +363 -350
  196. package/lib/zudoku.auth-openid.js.map +1 -1
  197. package/lib/zudoku.components.js +1717 -1634
  198. package/lib/zudoku.components.js.map +1 -1
  199. package/lib/zudoku.openapi-worker.js +4463 -4260
  200. package/lib/zudoku.openapi-worker.js.map +1 -1
  201. package/lib/zudoku.plugin-api-keys.js +7 -7
  202. package/lib/{zudoku.plugin-custom-page.js → zudoku.plugin-custom-pages.js} +3 -3
  203. package/lib/zudoku.plugin-custom-pages.js.map +1 -0
  204. package/lib/zudoku.plugin-markdown.js +93 -27
  205. package/lib/zudoku.plugin-markdown.js.map +1 -1
  206. package/lib/zudoku.plugin-openapi.js +9 -10
  207. package/lib/zudoku.plugin-openapi.js.map +1 -1
  208. package/lib/zudoku.plugin-redirect.js +1 -1
  209. package/package.json +70 -68
  210. package/src/app/entry.client.tsx +4 -2
  211. package/src/app/entry.server.tsx +4 -0
  212. package/src/app/main.css +4 -0
  213. package/src/app/main.tsx +12 -28
  214. package/src/app/standalone.tsx +1 -1
  215. package/src/lib/authentication/state.ts +17 -0
  216. package/src/lib/components/Banner.tsx +12 -2
  217. package/src/lib/components/ErrorPage.tsx +0 -2
  218. package/src/lib/components/Header.tsx +13 -3
  219. package/src/lib/components/InlineCode.tsx +10 -0
  220. package/src/lib/components/Layout.tsx +2 -1
  221. package/src/lib/components/MobileTopNavigation.tsx +2 -0
  222. package/src/lib/components/SlotletProvider.tsx +20 -4
  223. package/src/lib/components/TopNavigation.tsx +58 -24
  224. package/src/lib/components/context/ZudokuContext.ts +28 -20
  225. package/src/lib/components/index.ts +1 -1
  226. package/src/lib/components/navigation/Sidebar.tsx +5 -5
  227. package/src/lib/components/navigation/SidebarCategory.tsx +1 -3
  228. package/src/lib/components/navigation/SidebarItem.tsx +1 -3
  229. package/src/lib/components/navigation/utils.ts +11 -16
  230. package/src/lib/core/DevPortalContext.ts +4 -3
  231. package/src/lib/core/plugins.ts +2 -0
  232. package/src/lib/oas/graphql/index.ts +15 -11
  233. package/src/lib/oas/parser/index.ts +1 -0
  234. package/src/lib/plugins/{custom-page → custom-pages}/index.tsx +3 -3
  235. package/src/lib/plugins/markdown/index.tsx +49 -12
  236. package/src/lib/plugins/markdown/resolver.ts +92 -0
  237. package/src/lib/plugins/openapi/Endpoint.tsx +86 -22
  238. package/src/lib/plugins/openapi/OperationList.tsx +4 -2
  239. package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +3 -0
  240. package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +1 -1
  241. package/src/lib/plugins/openapi/Route.tsx +1 -2
  242. package/src/lib/plugins/openapi/Sidecar.tsx +19 -4
  243. package/src/lib/plugins/openapi/SimpleSelect.tsx +10 -2
  244. package/src/lib/plugins/openapi/client/createMemoryClient.ts +1 -6
  245. package/src/lib/plugins/openapi/client/createWorkerClient.ts +1 -6
  246. package/src/lib/plugins/openapi/client/worker.ts +2 -2
  247. package/src/lib/plugins/openapi/graphql/gql.ts +11 -3
  248. package/src/lib/plugins/openapi/graphql/graphql.ts +113 -1
  249. package/src/lib/plugins/openapi/index.tsx +2 -6
  250. package/src/lib/plugins/openapi/playground/Playground.tsx +39 -5
  251. package/src/lib/plugins/openapi/playground/ResponseTab.tsx +0 -1
  252. package/src/lib/ui/Callout.tsx +7 -6
  253. package/src/lib/ui/Drawer.tsx +38 -36
  254. package/src/lib/util/useScrollToAnchor.ts +1 -1
  255. package/dist/lib/plugins/custom-page/index.js.map +0 -1
  256. package/dist/lib/plugins/markdown/generateRoutes.d.ts +0 -3
  257. package/dist/lib/plugins/markdown/generateRoutes.js +0 -21
  258. package/dist/lib/plugins/markdown/generateRoutes.js.map +0 -1
  259. package/dist/lib/plugins/openapi/playground/Editor.d.ts +0 -1
  260. package/dist/lib/plugins/openapi/playground/Editor.js +0 -5
  261. package/dist/lib/plugins/openapi/playground/Editor.js.map +0 -1
  262. package/dist/lib/plugins/openapi/util/urql.d.ts +0 -7
  263. package/dist/lib/plugins/openapi/util/urql.js +0 -8
  264. package/dist/lib/plugins/openapi/util/urql.js.map +0 -1
  265. package/lib/ErrorPage-C5Pnyfbg.js +0 -18
  266. package/lib/ErrorPage-C5Pnyfbg.js.map +0 -1
  267. package/lib/Input-DulGxZh-.js +0 -2198
  268. package/lib/Input-DulGxZh-.js.map +0 -1
  269. package/lib/Markdown-BUUIyZbc.js.map +0 -1
  270. package/lib/OperationList-BwJXexkA.js.map +0 -1
  271. package/lib/Route-CX_-Q1HO.js.map +0 -1
  272. package/lib/SidebarBadge-gvlvsv3E.js +0 -498
  273. package/lib/SidebarBadge-gvlvsv3E.js.map +0 -1
  274. package/lib/ZudokuContext-cr-pTRY1.js +0 -1084
  275. package/lib/ZudokuContext-cr-pTRY1.js.map +0 -1
  276. package/lib/_commonjsHelpers-BkfeUUK-.js +0 -29
  277. package/lib/_commonjsHelpers-BkfeUUK-.js.map +0 -1
  278. package/lib/assets/index-B9EWVYfo.js.map +0 -1
  279. package/lib/assets/worker-DgVH8VJc.js.map +0 -1
  280. package/lib/index-BG0g4WW0.js.map +0 -1
  281. package/lib/index-BfA1oLPP.js.map +0 -1
  282. package/lib/index-Bn6Lc9tq.js +0 -9
  283. package/lib/index-BuA1OA5H.js.map +0 -1
  284. package/lib/index-CLd8ycZz.js.map +0 -1
  285. package/lib/joinPath-B7kNnUX4.js +0 -8
  286. package/lib/joinPath-B7kNnUX4.js.map +0 -1
  287. package/lib/router-D2p7Olpn.js +0 -2971
  288. package/lib/router-D2p7Olpn.js.map +0 -1
  289. package/lib/state-BUM4jc0J.js +0 -288
  290. package/lib/state-BUM4jc0J.js.map +0 -1
  291. package/lib/urql-YhcsXYy8.js +0 -1591
  292. package/lib/urql-YhcsXYy8.js.map +0 -1
  293. package/lib/utils-ByIc_KIM.js.map +0 -1
  294. package/lib/zudoku.plugin-custom-page.js.map +0 -1
  295. package/src/lib/plugins/markdown/generateRoutes.tsx +0 -38
  296. package/src/lib/plugins/openapi/playground/Editor.tsx +0 -4
  297. package/src/lib/plugins/openapi/util/urql.ts +0 -8
@@ -1,5 +1,4 @@
1
1
  import type { ReactNode } from "react";
2
- import { Link } from "react-router-dom";
3
2
  import { CategoryHeading } from "./CategoryHeading.js";
4
3
  import { Heading } from "./Heading.js";
5
4
  import { ProseClasses } from "./Markdown.js";
@@ -22,7 +21,6 @@ export const ErrorPage = ({
22
21
  </Heading>
23
22
  )}
24
23
  <p>{message}</p>
25
- <Link to="/">Go back home</Link>
26
24
  </div>
27
25
  );
28
26
  };
@@ -70,14 +70,22 @@ export const Header = memo(function HeaderInner() {
70
70
  {page?.logo && (
71
71
  <>
72
72
  <img
73
- src={page.logo.src.light}
73
+ src={
74
+ /https?:\/\//.test(page.logo.src.light)
75
+ ? page.logo.src.light
76
+ : import.meta.env.BASE_URL + page.logo.src.light
77
+ }
74
78
  alt={page.logo.alt ?? page.pageTitle}
75
79
  style={{ width: page.logo.width }}
76
80
  className={cn("h-10", isDark && "hidden")}
77
81
  loading="lazy"
78
82
  />
79
83
  <img
80
- src={page.logo.src.dark}
84
+ src={
85
+ /https?:\/\//.test(page.logo.src.dark)
86
+ ? page.logo.src.dark
87
+ : import.meta.env.BASE_URL + page.logo.src.dark
88
+ }
81
89
  alt={page.logo.alt ?? page.pageTitle}
82
90
  style={{ width: page.logo.width }}
83
91
  className={cn("h-10", !isDark && "hidden")}
@@ -92,7 +100,7 @@ export const Header = memo(function HeaderInner() {
92
100
  </Link>
93
101
  </div>
94
102
  <div className="grid grid-cols-2 md:grid-cols-[--sidecar-grid-cols] items-center gap-8">
95
- <div className="w-full justify-center flex">
103
+ <div className="w-full justify-center hidden md:flex ">
96
104
  <Search />
97
105
  </div>
98
106
 
@@ -133,7 +141,9 @@ export const Header = memo(function HeaderInner() {
133
141
  </div>
134
142
  </div>
135
143
  </div>
144
+ <Slotlet name="top-navigation-before" />
136
145
  <TopNavigation />
146
+ <Slotlet name="top-navigation-after" />
137
147
  </div>
138
148
  </header>
139
149
  );
@@ -4,11 +4,21 @@ import { cn } from "../util/cn.js";
4
4
  export const InlineCode = ({
5
5
  className,
6
6
  children,
7
+ selectOnClick,
7
8
  }: {
8
9
  className?: string;
9
10
  children: ReactNode;
11
+ selectOnClick?: boolean;
10
12
  }) => (
11
13
  <code
14
+ onClick={(e) => {
15
+ if (!selectOnClick) return;
16
+ const selection = window.getSelection();
17
+ const range = document.createRange();
18
+ range.selectNodeContents(e.currentTarget);
19
+ selection?.removeAllRanges();
20
+ selection?.addRange(range);
21
+ }}
12
22
  className={cn(
13
23
  "font-mono border p-1 py-0.5 rounded bg-border/50 dark:bg-border/70 whitespace-nowrap",
14
24
  className,
@@ -49,11 +49,12 @@ export const Layout = ({ children }: { children?: ReactNode }) => {
49
49
  </Helmet>
50
50
  <Slotlet name="layout-before-head" />
51
51
  <Header />
52
+ <Slotlet name="layout-after-head" />
52
53
 
53
54
  <div className="w-full max-w-screen-2xl mx-auto px-10 lg:px-12">
54
55
  <Suspense
55
56
  fallback={
56
- <main className="grid h-full place-items-center">
57
+ <main className="grid h-[calc(100vh-var(--header-height))] place-items-center">
57
58
  <Spinner />
58
59
  </main>
59
60
  }
@@ -10,6 +10,7 @@ import {
10
10
  DrawerTrigger,
11
11
  } from "../ui/Drawer.js";
12
12
  import { useZudoku } from "./context/ZudokuContext.js";
13
+ import { Search } from "./Search.js";
13
14
 
14
15
  export const MobileTopNavigation = () => {
15
16
  const { topNavigation } = useZudoku();
@@ -27,6 +28,7 @@ export const MobileTopNavigation = () => {
27
28
  <VisuallyHidden>
28
29
  <DrawerTitle>Navigation</DrawerTitle>
29
30
  </VisuallyHidden>
31
+ <Search />
30
32
  <ul className="flex flex-col items-center gap-4 p-4">
31
33
  {topNavigation.map((item) => (
32
34
  <li key={item.label}>
@@ -1,6 +1,15 @@
1
- import React, { type ReactElement, ReactNode, useContext } from "react";
1
+ import React, {
2
+ type ComponentType,
3
+ type ReactElement,
4
+ ReactNode,
5
+ useContext,
6
+ } from "react";
2
7
  import { isValidElementType } from "react-is";
3
- export type Slotlets = Record<string, ReactNode | ReactElement>;
8
+ import { useLocation } from "react-router-dom";
9
+ export type Slotlets = Record<
10
+ string,
11
+ ReactNode | ReactElement | ComponentType<SlotletComponentProps>
12
+ >;
4
13
 
5
14
  const SlotletContext = React.createContext<Slotlets | undefined>({});
6
15
 
@@ -18,13 +27,20 @@ export const SlotletProvider = ({
18
27
  );
19
28
  };
20
29
 
30
+ export type SlotletComponentProps = {
31
+ location: Location;
32
+ };
33
+
21
34
  export const Slotlet = ({ name }: { name: string }) => {
22
35
  const context = useContext(SlotletContext);
23
36
  const componentOrElement = context?.[name];
37
+ const location = useLocation();
24
38
 
25
39
  if (isValidElementType(componentOrElement)) {
26
- return React.createElement(componentOrElement);
40
+ return React.createElement(componentOrElement, {
41
+ location,
42
+ });
27
43
  }
28
44
 
29
- return componentOrElement;
45
+ return componentOrElement as ReactNode;
30
46
  };
@@ -1,7 +1,10 @@
1
1
  import { cx } from "class-variance-authority";
2
- import { NavLink } from "react-router-dom";
3
-
4
- import { useZudoku } from "./context/ZudokuContext.js";
2
+ import { Suspense } from "react";
3
+ import { Link } from "react-router-dom";
4
+ import { TopNavigationItem } from "../../config/validators/validate.js";
5
+ import { joinPath } from "../util/joinPath.js";
6
+ import { useCurrentNavigation, useZudoku } from "./context/ZudokuContext.js";
7
+ import { traverseSidebar } from "./navigation/utils.js";
5
8
 
6
9
  export const TopNavigation = () => {
7
10
  const { topNavigation } = useZudoku();
@@ -12,26 +15,57 @@ export const TopNavigation = () => {
12
15
  }
13
16
 
14
17
  return (
15
- <nav className="hidden lg:block border-b text-sm px-12 h-[--top-nav-height]">
16
- <ul className="flex flex-row items-center gap-8">
17
- {topNavigation.map((item) => (
18
- <li key={item.label}>
19
- <NavLink
20
- className={({ isActive }) =>
21
- cx(
22
- "block py-3.5 font-medium -mb-px border-b-2",
23
- isActive
24
- ? "border-primary text-foreground"
25
- : "border-transparent text-foreground/75 hover:text-foreground hover:border-accent-foreground/25",
26
- )
27
- }
28
- to={item.id}
29
- >
30
- {item.label}
31
- </NavLink>
32
- </li>
33
- ))}
34
- </ul>
35
- </nav>
18
+ <Suspense>
19
+ <nav className="hidden lg:block border-b text-sm px-12 h-[--top-nav-height]">
20
+ <ul className="flex flex-row items-center gap-8">
21
+ {topNavigation.map((item) => (
22
+ <li key={item.id}>
23
+ <TopNavItem {...item} />
24
+ </li>
25
+ ))}
26
+ </ul>
27
+ </nav>
28
+ </Suspense>
29
+ );
30
+ };
31
+
32
+ const TopNavItem = ({ id, label, default: defaultLink }: TopNavigationItem) => {
33
+ const { sidebars } = useZudoku();
34
+ const nav = useCurrentNavigation();
35
+ const currentSidebar = sidebars[id];
36
+
37
+ // TODO: This is a bit of a hack to get the first link in the sidebar
38
+ // We should really process this when we load the config so we can validate
39
+ // that the sidebar is actually set. In this case we just fall back to linking
40
+ // to the id if we can't resolve a sidebar.
41
+ const first =
42
+ defaultLink ??
43
+ (currentSidebar
44
+ ? traverseSidebar(currentSidebar, (item) => {
45
+ if (item.type === "doc") return joinPath(item.id);
46
+ })
47
+ : joinPath(id));
48
+
49
+ if (!first) {
50
+ throw new Error(
51
+ `No links found in top navigation for top navigation '${id}'. Check that the sidebar isn't empty or that a default link set.`,
52
+ );
53
+ }
54
+
55
+ // Manually set the active sidebar based on our logic of what is active
56
+ const isActive = nav.data.topNavItem?.id === id;
57
+
58
+ return (
59
+ <Link
60
+ className={cx(
61
+ "block py-3.5 font-medium -mb-px border-b-2",
62
+ isActive
63
+ ? "border-primary text-foreground"
64
+ : "border-transparent text-foreground/75 hover:text-foreground hover:border-accent-foreground/25",
65
+ )}
66
+ to={first}
67
+ >
68
+ {label}
69
+ </Link>
36
70
  );
37
71
  };
@@ -1,7 +1,9 @@
1
1
  import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
2
2
  import { createContext, useContext } from "react";
3
- import { useLocation } from "react-router-dom";
3
+ import { matchPath, useLocation } from "react-router-dom";
4
4
  import { DevPortalContext } from "../../core/DevPortalContext.js";
5
+ import { joinPath } from "../../util/joinPath.js";
6
+ import { traverseSidebar } from "../navigation/utils.js";
5
7
 
6
8
  export const ZudokuReactContext = createContext<DevPortalContext | undefined>(
7
9
  undefined,
@@ -25,34 +27,40 @@ export const useApiIdentities = () => {
25
27
  });
26
28
  };
27
29
 
28
- export const useTopNavigationItem = () => {
29
- const { topNavigation } = useZudoku();
30
+ export const useCurrentNavigation = () => {
31
+ const { getPluginSidebar, sidebars, topNavigation } = useZudoku();
30
32
  const location = useLocation();
31
33
 
32
- const firstPart = location.pathname.split("/").at(1);
33
- if (!firstPart) return;
34
+ const currentSidebarItem = Object.entries(sidebars).find(([, sidebar]) => {
35
+ return traverseSidebar(sidebar, (item) => {
36
+ const itemId =
37
+ item.type === "doc"
38
+ ? joinPath(item.id)
39
+ : item.type === "category" && item.link
40
+ ? joinPath(item.link.id)
41
+ : undefined;
34
42
 
35
- return topNavigation.find((item) => item.id === firstPart);
36
- };
37
-
38
- export const useNavigation = () => {
39
- const { getPluginSidebar, sidebars } = useZudoku();
40
- const navItem = useTopNavigationItem();
41
- const path = navItem?.id;
42
- const currentSidebar = path ? (sidebars[path] ?? []) : [];
43
- const location = useLocation();
43
+ if (itemId === location.pathname) {
44
+ return item;
45
+ }
46
+ });
47
+ });
48
+ const currentTopNavItem =
49
+ topNavigation.find((t) => t.id === currentSidebarItem?.[0]) ??
50
+ topNavigation.find((item) => matchPath(item.id, location.pathname));
44
51
 
45
52
  return useSuspenseQuery({
46
53
  queryFn: async () => {
47
- const pluginSidebar = path
48
- ? await getPluginSidebar(path)
49
- : await getPluginSidebar(location.pathname);
54
+ const pluginSidebar = await getPluginSidebar(location.pathname);
50
55
 
51
56
  return {
52
- items: [...currentSidebar, ...pluginSidebar],
53
- currentTopNavItem: navItem,
57
+ sidebar: [
58
+ ...(currentSidebarItem ? currentSidebarItem[1] : []),
59
+ ...pluginSidebar,
60
+ ],
61
+ topNavItem: currentTopNavItem,
54
62
  };
55
63
  },
56
- queryKey: ["navigation", path],
64
+ queryKey: ["navigation", location.pathname],
57
65
  });
58
66
  };
@@ -16,7 +16,7 @@ export const useMDXComponents = /*@__PURE__*/ useMDXComponentsImport;
16
16
  export const Callout = /*@__PURE__*/ CalloutImport;
17
17
  export const DevPortal = /*@__PURE__*/ DevPortalImport;
18
18
  export const Layout = /*@__PURE__*/ LayoutImport;
19
- export const Link = /*@__PURE__*/ LinkImport;
19
+ export const Link: typeof LinkImport = /*@__PURE__*/ LinkImport;
20
20
  export const RouterError = /*@__PURE__*/ RouterErrorImport;
21
21
  export const ServerError = /*@__PURE__*/ ServerErrorImport;
22
22
  export const Bootstrap = /*@__PURE__*/ BootstrapImport;
@@ -2,23 +2,23 @@ import { useRef } from "react";
2
2
 
3
3
  import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
4
4
  import { DrawerContent, DrawerTitle } from "../../ui/Drawer.js";
5
- import { useNavigation } from "../context/ZudokuContext.js";
5
+ import { useCurrentNavigation } from "../context/ZudokuContext.js";
6
6
  import { Slotlet } from "../SlotletProvider.js";
7
7
  import { SidebarItem } from "./SidebarItem.js";
8
8
  import { SidebarWrapper } from "./SidebarWrapper.js";
9
9
 
10
10
  export const Sidebar = () => {
11
11
  const navRef = useRef<HTMLDivElement | null>(null);
12
- const navigation = useNavigation();
12
+ const navigation = useCurrentNavigation();
13
13
 
14
14
  return (
15
15
  <>
16
16
  <SidebarWrapper
17
17
  ref={navRef}
18
- pushMainContent={navigation.data.items.length > 0}
18
+ pushMainContent={navigation.data.sidebar.length > 0}
19
19
  >
20
20
  <Slotlet name="zudoku-before-navigation" />
21
- {navigation.data.items.map((item) => (
21
+ {navigation.data.sidebar.map((item) => (
22
22
  <SidebarItem key={item.label} item={item} />
23
23
  ))}
24
24
  <Slotlet name="zudoku-after-navigation" />
@@ -30,7 +30,7 @@ export const Sidebar = () => {
30
30
  <VisuallyHidden>
31
31
  <DrawerTitle>Sidebar</DrawerTitle>
32
32
  </VisuallyHidden>
33
- {navigation.data.items.map((item) => (
33
+ {navigation.data.sidebar.map((item) => (
34
34
  <SidebarItem key={item.label} item={item} />
35
35
  ))}
36
36
  </DrawerContent>
@@ -5,7 +5,6 @@ import { NavLink } from "react-router-dom";
5
5
  import type { SidebarItemCategory } from "../../../config/validators/SidebarSchema.js";
6
6
  import { cn } from "../../util/cn.js";
7
7
  import { joinPath } from "../../util/joinPath.js";
8
- import { useTopNavigationItem } from "../context/ZudokuContext.js";
9
8
  import { navigationListItem, SidebarItem } from "./SidebarItem.js";
10
9
  import { useIsCategoryOpen } from "./utils.js";
11
10
 
@@ -16,7 +15,6 @@ export const SidebarCategory = ({
16
15
  category: SidebarItemCategory;
17
16
  level: number;
18
17
  }) => {
19
- const topNavItem = useTopNavigationItem();
20
18
  const isCategoryOpen = useIsCategoryOpen(category);
21
19
  const [hasInteracted, setHasInteracted] = useState(false);
22
20
 
@@ -79,7 +77,7 @@ export const SidebarCategory = ({
79
77
  )}
80
78
  {category.link?.type === "doc" ? (
81
79
  <NavLink
82
- to={joinPath(topNavItem?.id, category.link.id)}
80
+ to={joinPath(category.link.id)}
83
81
  className="flex-1"
84
82
  onClick={() => setHasInteracted(true)}
85
83
  >
@@ -7,7 +7,6 @@ import { cn } from "../../util/cn.js";
7
7
  import { joinPath } from "../../util/joinPath.js";
8
8
  import { AnchorLink } from "../AnchorLink.js";
9
9
  import { useViewportAnchor } from "../context/ViewportAnchorContext.js";
10
- import { useTopNavigationItem } from "../context/ZudokuContext.js";
11
10
  import { SidebarBadge } from "./SidebarBadge.js";
12
11
  import { SidebarCategory } from "./SidebarCategory.js";
13
12
 
@@ -40,7 +39,6 @@ export const SidebarItem = ({
40
39
  basePath?: string;
41
40
  level?: number;
42
41
  }) => {
43
- const topNavItem = useTopNavigationItem();
44
42
  const { activeAnchor } = useViewportAnchor();
45
43
  const [searchParams] = useSearchParams();
46
44
 
@@ -53,7 +51,7 @@ export const SidebarItem = ({
53
51
  className={({ isActive }) =>
54
52
  navigationListItem({ isActive, isTopLevel: level === 0 })
55
53
  }
56
- to={joinPath(topNavItem?.id, item.id)}
54
+ to={joinPath(item.id)}
57
55
  >
58
56
  {item.icon && <item.icon size={16} className="align-[-0.125em]" />}
59
57
  {item.badge ? (
@@ -4,7 +4,7 @@ import type {
4
4
  SidebarItemCategory,
5
5
  } from "../../../config/validators/SidebarSchema.js";
6
6
  import { joinPath } from "../../util/joinPath.js";
7
- import { useTopNavigationItem, useZudoku } from "../context/ZudokuContext.js";
7
+ import { useCurrentNavigation } from "../context/ZudokuContext.js";
8
8
 
9
9
  export type TraverseCallback<T> = (
10
10
  item: SidebarItem,
@@ -42,15 +42,12 @@ export const traverseSidebarItem = <T>(
42
42
 
43
43
  export const useCurrentItem = () => {
44
44
  const location = useLocation();
45
- const topNavItem = useTopNavigationItem();
46
- const { sidebars } = useZudoku();
47
- const currentSidebar = topNavItem?.id ? sidebars[topNavItem.id] : [];
45
+ const nav = useCurrentNavigation();
46
+
47
+ const currentSidebar = nav.data.sidebar;
48
48
 
49
49
  return traverseSidebar(currentSidebar, (item) => {
50
- if (
51
- item.type === "doc" &&
52
- joinPath(topNavItem?.id, item.id) === location.pathname
53
- ) {
50
+ if (item.type === "doc" && joinPath(item.id) === location.pathname) {
54
51
  return item;
55
52
  }
56
53
  });
@@ -58,18 +55,17 @@ export const useCurrentItem = () => {
58
55
 
59
56
  export const useIsCategoryOpen = (category: SidebarItemCategory) => {
60
57
  const location = useLocation();
61
- const topNavItem = useTopNavigationItem();
62
58
 
63
59
  return traverseSidebarItem(category, (item) => {
64
60
  if (item.type === "category" && item.link) {
65
- const categoryLinkPath = joinPath(topNavItem?.id, item.link.id);
61
+ const categoryLinkPath = joinPath(item.link.id);
66
62
  if (categoryLinkPath === location.pathname) {
67
63
  return true;
68
64
  }
69
65
  }
70
66
 
71
67
  if (item.type === "doc") {
72
- const docPath = joinPath(topNavItem?.id, item.id);
68
+ const docPath = joinPath(item.id);
73
69
  if (docPath === location.pathname) {
74
70
  return true;
75
71
  }
@@ -82,9 +78,8 @@ export const usePrevNext = (): {
82
78
  next?: { label: string; id: string };
83
79
  } => {
84
80
  const currentId = useLocation().pathname;
85
- const { sidebars } = useZudoku();
86
- const topNavItem = useTopNavigationItem();
87
- const currentSidebar = topNavItem?.id ? sidebars[topNavItem.id] : [];
81
+ const nav = useCurrentNavigation();
82
+ const currentSidebar = nav.data.sidebar;
88
83
 
89
84
  let prev;
90
85
  let next;
@@ -94,9 +89,9 @@ export const usePrevNext = (): {
94
89
  traverseSidebar(currentSidebar, (item) => {
95
90
  const itemId =
96
91
  item.type === "doc"
97
- ? joinPath(topNavItem?.id, item.id)
92
+ ? joinPath(item.id)
98
93
  : item.type === "category" && item.link
99
- ? joinPath(topNavItem?.id, item.link.id)
94
+ ? joinPath(item.link.id)
100
95
  : undefined;
101
96
 
102
97
  if (!itemId) return;
@@ -1,6 +1,7 @@
1
1
  import { QueryClient } from "@tanstack/react-query";
2
2
  import { ReactNode } from "react";
3
3
  import type { SidebarConfig } from "../../config/validators/SidebarSchema.js";
4
+ import { TopNavigationItem } from "../../config/validators/validate.js";
4
5
  import { type AuthenticationProvider } from "../authentication/authentication.js";
5
6
  import type { ComponentsContextType } from "../components/context/ComponentsContext.js";
6
7
  import { Slotlets } from "../components/SlotletProvider.js";
@@ -51,7 +52,7 @@ type Page = Partial<{
51
52
  };
52
53
  banner?: {
53
54
  message: ReactNode;
54
- color?: "note" | "tip" | "info" | "caution" | "danger";
55
+ color?: "note" | "tip" | "info" | "caution" | "danger" | (string & {});
55
56
  dismissible?: boolean;
56
57
  };
57
58
  }>;
@@ -60,7 +61,7 @@ export type ZudokuContextOptions = {
60
61
  metadata?: Metadata;
61
62
  page?: Page;
62
63
  authentication?: AuthenticationProvider;
63
- topNavigation?: Array<{ id: string; label: string; default?: string }>;
64
+ topNavigation?: TopNavigationItem[];
64
65
  sidebars?: SidebarConfig;
65
66
  plugins?: DevPortalPlugin[];
66
67
  slotlets?: Slotlets;
@@ -72,7 +73,7 @@ export type ZudokuContextOptions = {
72
73
 
73
74
  export class DevPortalContext {
74
75
  public plugins: NonNullable<ZudokuContextOptions["plugins"]>;
75
- public sidebars: NonNullable<ZudokuContextOptions["sidebars"]>;
76
+ public sidebars: SidebarConfig;
76
77
  public topNavigation: NonNullable<ZudokuContextOptions["topNavigation"]>;
77
78
  public meta: ZudokuContextOptions["metadata"];
78
79
  public page: ZudokuContextOptions["page"];
@@ -11,6 +11,8 @@ export type DevPortalPlugin =
11
11
  | ApiIdentityPlugin
12
12
  | SearchProviderPlugin;
13
13
 
14
+ export type { RouteObject };
15
+
14
16
  export interface NavigationPlugin {
15
17
  getRoutes: () => RouteObject[];
16
18
  getSidebar?: (path: string) => Promise<Sidebar>;
@@ -18,6 +18,7 @@ import {
18
18
  type ParameterObject,
19
19
  type PathsObject,
20
20
  type SchemaObject,
21
+ type ServerObject,
21
22
  type TagObject,
22
23
  } from "../parser/index.js";
23
24
 
@@ -57,9 +58,10 @@ export const createOperationSlug = (
57
58
  );
58
59
  };
59
60
 
60
- const cache = new LRUCache<string, Promise<OpenAPIDocument>>({
61
+ const cache = new LRUCache<string, OpenAPIDocument>({
61
62
  ttl: 60 * 10 * 1000,
62
63
  ttlAutopurge: true,
64
+ fetchMethod: (_key, _oldValue, { context }) => validate(context as string),
63
65
  });
64
66
 
65
67
  const builder = new SchemaBuilder<{
@@ -158,6 +160,13 @@ const SchemaTag = builder.objectRef<TagObject>("SchemaTag").implement({
158
160
  }),
159
161
  });
160
162
 
163
+ const ServerItem = builder.objectRef<ServerObject>("Server").implement({
164
+ fields: (t) => ({
165
+ url: t.exposeString("url"),
166
+ description: t.exposeString("description", { nullable: true }),
167
+ }),
168
+ });
169
+
161
170
  const PathItem = builder
162
171
  .objectRef<{
163
172
  path: string;
@@ -371,6 +380,10 @@ const Schema = builder.objectRef<OpenAPIDocument>("Schema").implement({
371
380
  fields: (t) => ({
372
381
  openapi: t.string({ resolve: (root) => root.openapi }),
373
382
  url: t.string({ resolve: (root) => root.servers?.at(0)?.url ?? "/" }),
383
+ servers: t.field({
384
+ type: [ServerItem],
385
+ resolve: (root) => root.servers ?? [],
386
+ }),
374
387
  title: t.string({ resolve: (root) => root.info.title }),
375
388
  version: t.string({ resolve: (root) => root.info.version }),
376
389
  description: t.string({
@@ -417,16 +430,7 @@ const Schema = builder.objectRef<OpenAPIDocument>("Schema").implement({
417
430
 
418
431
  const loadOpenAPISchema = async (input: NonNullable<unknown>) => {
419
432
  const hash = hashit(input);
420
-
421
- if (cache.has(hash)) {
422
- return cache.get(hash)!;
423
- }
424
-
425
- const schema = validate(input);
426
-
427
- cache.set(hash, schema);
428
-
429
- return schema;
433
+ return await cache.forceFetch(hash, { context: input });
430
434
  };
431
435
 
432
436
  const SchemaSource = builder.enumType("SchemaType", {
@@ -20,6 +20,7 @@ export type TagObject = DeepOmitReference<OpenAPIV3_1.TagObject>;
20
20
  export type ExampleObject = DeepOmitReference<OpenAPIV3_1.ExampleObject>;
21
21
  export type EncodingObject = DeepOmitReference<OpenAPIV3_1.EncodingObject>;
22
22
  export type SchemaObject = DeepOmitReference<OpenAPIV3_1.SchemaObject>;
23
+ export type ServerObject = DeepOmitReference<OpenAPIV3_1.ServerObject>;
23
24
 
24
25
  export const HttpMethods = Object.values(OpenAPIV3.HttpMethods);
25
26
 
@@ -3,13 +3,13 @@ import type { RouteObject } from "react-router-dom";
3
3
  import { ProseClasses } from "../../components/Markdown.js";
4
4
  import type { DevPortalPlugin, NavigationPlugin } from "../../core/plugins.js";
5
5
 
6
- type CustomPageConfig = Array<{
6
+ type CustomPagesConfig = Array<{
7
7
  path: string;
8
8
  element: ReactNode;
9
9
  }>;
10
10
 
11
- export const customPagePlugin = (
12
- config: CustomPageConfig,
11
+ export const customPagesPlugin = (
12
+ config: CustomPagesConfig,
13
13
  ): DevPortalPlugin & NavigationPlugin => {
14
14
  return {
15
15
  getRoutes: (): RouteObject[] =>