zudoku 0.25.3 → 0.26.1

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 (278) hide show
  1. package/dist/cli/dev/handler.js +2 -2
  2. package/dist/cli/dev/handler.js.map +1 -1
  3. package/dist/config/config.d.ts +1 -0
  4. package/dist/config/loader.js +1 -1
  5. package/dist/config/loader.js.map +1 -1
  6. package/dist/config/validators/common.d.ts +39 -28
  7. package/dist/config/validators/common.js +1 -0
  8. package/dist/config/validators/common.js.map +1 -1
  9. package/dist/config/validators/icon-types.d.ts +1 -1
  10. package/dist/config/validators/validate.d.ts +17 -12
  11. package/dist/lib/authentication/providers/auth0.js +1 -1
  12. package/dist/lib/authentication/providers/auth0.js.map +1 -1
  13. package/dist/lib/authentication/providers/openid.d.ts +1 -1
  14. package/dist/lib/authentication/providers/openid.js +10 -6
  15. package/dist/lib/authentication/providers/openid.js.map +1 -1
  16. package/dist/lib/components/Autocomplete.d.ts +12 -0
  17. package/dist/lib/components/Autocomplete.js +47 -0
  18. package/dist/lib/components/Autocomplete.js.map +1 -0
  19. package/dist/lib/components/Header.js +3 -3
  20. package/dist/lib/components/Header.js.map +1 -1
  21. package/dist/lib/components/index.js +2 -2
  22. package/dist/lib/components/index.js.map +1 -1
  23. package/dist/lib/components/navigation/SidebarCategory.js +1 -1
  24. package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
  25. package/dist/lib/plugins/markdown/MdxPage.js +8 -2
  26. package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
  27. package/dist/lib/plugins/openapi/OperationList.js +3 -0
  28. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  29. package/dist/lib/plugins/openapi/ParameterListItem.js +1 -1
  30. package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
  31. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.d.ts +3 -1
  32. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js +3 -2
  33. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js.map +1 -1
  34. package/dist/lib/plugins/openapi/RequestBodySidecarBox.d.ts +2 -1
  35. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js +2 -2
  36. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
  37. package/dist/lib/plugins/openapi/Sidecar.js +9 -6
  38. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  39. package/dist/lib/plugins/openapi/SidecarBox.js +1 -1
  40. package/dist/lib/plugins/openapi/SidecarBox.js.map +1 -1
  41. package/dist/lib/plugins/openapi/SidecarExamples.d.ts +2 -1
  42. package/dist/lib/plugins/openapi/SidecarExamples.js +7 -4
  43. package/dist/lib/plugins/openapi/SidecarExamples.js.map +1 -1
  44. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.d.ts +6 -0
  45. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.js +12 -0
  46. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.js.map +1 -0
  47. package/dist/lib/plugins/openapi/playground/Headers.js +66 -4
  48. package/dist/lib/plugins/openapi/playground/Headers.js.map +1 -1
  49. package/dist/lib/plugins/openapi/playground/Playground.d.ts +5 -1
  50. package/dist/lib/plugins/openapi/playground/Playground.js +36 -11
  51. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  52. package/dist/lib/plugins/openapi/playground/QueryParams.js +20 -30
  53. package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
  54. package/dist/lib/plugins/openapi/post-processors/removeExtensions.d.ts +2 -1
  55. package/dist/lib/plugins/openapi/post-processors/removeExtensions.js +5 -3
  56. package/dist/lib/plugins/openapi/post-processors/removeExtensions.js.map +1 -1
  57. package/dist/lib/plugins/openapi/post-processors/removeExtensions.test.js +49 -0
  58. package/dist/lib/plugins/openapi/post-processors/removeExtensions.test.js.map +1 -1
  59. package/dist/lib/plugins/openapi/post-processors/removeParameters.d.ts +10 -0
  60. package/dist/lib/plugins/openapi/post-processors/removeParameters.js +66 -0
  61. package/dist/lib/plugins/openapi/post-processors/removeParameters.js.map +1 -0
  62. package/dist/lib/plugins/openapi/post-processors/removeParameters.test.d.ts +1 -0
  63. package/dist/lib/plugins/openapi/post-processors/removeParameters.test.js +131 -0
  64. package/dist/lib/plugins/openapi/post-processors/removeParameters.test.js.map +1 -0
  65. package/dist/lib/plugins/openapi/schema/SchemaComponents.js +1 -1
  66. package/dist/lib/plugins/openapi/schema/SchemaComponents.js.map +1 -1
  67. package/dist/lib/ui/Badge.d.ts +1 -1
  68. package/dist/lib/ui/Badge.js +1 -0
  69. package/dist/lib/ui/Badge.js.map +1 -1
  70. package/dist/lib/ui/Command.d.ts +9 -1
  71. package/dist/lib/ui/Command.js +5 -1
  72. package/dist/lib/ui/Command.js.map +1 -1
  73. package/dist/lib/util/joinUrl.d.ts +1 -0
  74. package/dist/lib/util/joinUrl.js +40 -0
  75. package/dist/lib/util/joinUrl.js.map +1 -0
  76. package/dist/vite/build.js +10 -10
  77. package/dist/vite/build.js.map +1 -1
  78. package/dist/vite/config.js +4 -1
  79. package/dist/vite/config.js.map +1 -1
  80. package/dist/vite/config.test.js +5 -1
  81. package/dist/vite/config.test.js.map +1 -1
  82. package/dist/vite/dev-server.js +4 -1
  83. package/dist/vite/dev-server.js.map +1 -1
  84. package/dist/vite/plugin-api.d.ts +1 -1
  85. package/dist/vite/plugin-api.js +23 -5
  86. package/dist/vite/plugin-api.js.map +1 -1
  87. package/dist/vite/plugin-auth.js +4 -1
  88. package/dist/vite/plugin-auth.js.map +1 -1
  89. package/dist/vite/plugin-mdx.js +9 -4
  90. package/dist/vite/plugin-mdx.js.map +1 -1
  91. package/dist/vite/prerender.d.ts +2 -2
  92. package/dist/vite/prerender.js +4 -4
  93. package/dist/vite/prerender.js.map +1 -1
  94. package/dist/zuplo/enrich-with-zuplo.d.ts +5 -0
  95. package/dist/zuplo/enrich-with-zuplo.js +184 -0
  96. package/dist/zuplo/enrich-with-zuplo.js.map +1 -0
  97. package/dist/zuplo/env.d.ts +1 -0
  98. package/dist/zuplo/env.js +3 -0
  99. package/dist/zuplo/env.js.map +1 -1
  100. package/dist/zuplo/policy-types.d.ts +33 -0
  101. package/dist/zuplo/policy-types.js +8 -0
  102. package/dist/zuplo/policy-types.js.map +1 -0
  103. package/dist/zuplo/with-zuplo-processors.d.ts +3 -0
  104. package/dist/zuplo/with-zuplo-processors.js +26 -0
  105. package/dist/zuplo/with-zuplo-processors.js.map +1 -0
  106. package/dist/zuplo/with-zuplo.d.ts +1 -2
  107. package/dist/zuplo/with-zuplo.js +6 -27
  108. package/dist/zuplo/with-zuplo.js.map +1 -1
  109. package/lib/{AnchorLink-DFZZbmvr.js → AnchorLink-bObQitZv.js} +3 -3
  110. package/lib/{AnchorLink-DFZZbmvr.js.map → AnchorLink-bObQitZv.js.map} +1 -1
  111. package/lib/{AuthenticationPlugin-D7G3me8L.js → AuthenticationPlugin-C9SwOxkc.js} +4 -4
  112. package/lib/{AuthenticationPlugin-D7G3me8L.js.map → AuthenticationPlugin-C9SwOxkc.js.map} +1 -1
  113. package/lib/{CategoryHeading-CBconmtI.js → CategoryHeading-MYL1u_6K.js} +3 -3
  114. package/lib/{CategoryHeading-CBconmtI.js.map → CategoryHeading-MYL1u_6K.js.map} +1 -1
  115. package/lib/{Markdown-CZDLNOFc.js → Markdown-DFN6p0J-.js} +1041 -1041
  116. package/lib/{Markdown-CZDLNOFc.js.map → Markdown-DFN6p0J-.js.map} +1 -1
  117. package/lib/{MdxPage-DKMbBROv.js → MdxPage-D9c4z09Q.js} +61 -56
  118. package/lib/MdxPage-D9c4z09Q.js.map +1 -0
  119. package/lib/{OperationList-B8bHMKme.js → OperationList-DGJWDx1G.js} +1264 -1244
  120. package/lib/OperationList-DGJWDx1G.js.map +1 -0
  121. package/lib/{Route-DYwKZ_c_.js → Route-VdmEyOD0.js} +5 -5
  122. package/lib/{Route-DYwKZ_c_.js.map → Route-VdmEyOD0.js.map} +1 -1
  123. package/lib/{Select-B_IxRUUC.js → Select-D3O7wISy.js} +36 -36
  124. package/lib/{Select-B_IxRUUC.js.map → Select-D3O7wISy.js.map} +1 -1
  125. package/lib/{SlotletProvider-pfc9oejW.js → SlotletProvider-_3zzX_g_.js} +53 -53
  126. package/lib/{SlotletProvider-pfc9oejW.js.map → SlotletProvider-_3zzX_g_.js.map} +1 -1
  127. package/lib/{Button-DeAoTouo.js → Spinner-BlzrEEk1.js} +16 -13
  128. package/lib/Spinner-BlzrEEk1.js.map +1 -0
  129. package/lib/{SyntaxHighlight-Bz-lOJtH.js → SyntaxHighlight-CJCSPG1F.js} +297 -301
  130. package/lib/{SyntaxHighlight-Bz-lOJtH.js.map → SyntaxHighlight-CJCSPG1F.js.map} +1 -1
  131. package/lib/{ZudokuContext-hmLMUdf2.js → ZudokuContext-DeQZEp-x.js} +357 -356
  132. package/lib/ZudokuContext-DeQZEp-x.js.map +1 -0
  133. package/lib/{chunk-D52XG6IA-Dl7HLe6j.js → chunk-SYFQ2XB5-BF5IDYrB.js} +410 -412
  134. package/lib/chunk-SYFQ2XB5-BF5IDYrB.js.map +1 -0
  135. package/lib/context-rwLGh-6_.js +22 -0
  136. package/lib/{context-h_UkBLvr.js.map → context-rwLGh-6_.js.map} +1 -1
  137. package/lib/{createServer-BznDkeSA.js → createServer-BcaswoFO.js} +1274 -1286
  138. package/lib/createServer-BcaswoFO.js.map +1 -0
  139. package/lib/{hook-CHq7pFyz.js → hook-BRQEDRbn.js} +17 -17
  140. package/lib/{hook-CHq7pFyz.js.map → hook-BRQEDRbn.js.map} +1 -1
  141. package/lib/index-B7mqiOei.js +509 -0
  142. package/lib/index-B7mqiOei.js.map +1 -0
  143. package/lib/index-CXRrqOIl.js +1750 -0
  144. package/lib/index-CXRrqOIl.js.map +1 -0
  145. package/lib/index-Djenk2Hj.js +36 -0
  146. package/lib/{index-CPNSgwSb.js.map → index-Djenk2Hj.js.map} +1 -1
  147. package/lib/{index-CBXSgjaE.js → index-Dl3Yl0yb.js} +65 -69
  148. package/lib/index-Dl3Yl0yb.js.map +1 -0
  149. package/lib/{index.esm-BSV1C092.js → index.esm-9-TF9KQB.js} +52 -52
  150. package/lib/{index.esm-BSV1C092.js.map → index.esm-9-TF9KQB.js.map} +1 -1
  151. package/lib/index.esm-CrSoEshU.js +1207 -0
  152. package/lib/index.esm-CrSoEshU.js.map +1 -0
  153. package/lib/joinUrl-BTy9bvoK.js +20 -0
  154. package/lib/joinUrl-BTy9bvoK.js.map +1 -0
  155. package/lib/{jsx-runtime-Dx-03ztt.js → jsx-runtime-Bdg6XQ1m.js} +135 -135
  156. package/lib/{jsx-runtime-Dx-03ztt.js.map → jsx-runtime-Bdg6XQ1m.js.map} +1 -1
  157. package/lib/post-processors/removeExtensions.js +7 -7
  158. package/lib/post-processors/removeExtensions.js.map +1 -1
  159. package/lib/post-processors/removeParameters.js +48 -0
  160. package/lib/post-processors/removeParameters.js.map +1 -0
  161. package/lib/{prism-bash.min-DadFsM4Z.js → prism-bash.min-HHIMdNJ_.js} +4 -4
  162. package/lib/{prism-bash.min-DadFsM4Z.js.map → prism-bash.min-HHIMdNJ_.js.map} +1 -1
  163. package/lib/{prism-csharp.min-DUwvItt4.js → prism-csharp.min-bQAo2pmx.js} +33 -33
  164. package/lib/{prism-csharp.min-DUwvItt4.js.map → prism-csharp.min-bQAo2pmx.js.map} +1 -1
  165. package/lib/{prism-java.min-BtgBR4yd.js → prism-java.min-BpvsOuIa.js} +12 -12
  166. package/lib/{prism-java.min-BtgBR4yd.js.map → prism-java.min-BpvsOuIa.js.map} +1 -1
  167. package/lib/{prism-markdown.min-F3U-vPBi.js → prism-markdown.min-C0Qn0m-5.js} +30 -30
  168. package/lib/{prism-markdown.min-F3U-vPBi.js.map → prism-markdown.min-C0Qn0m-5.js.map} +1 -1
  169. package/lib/{prism-ruby.min-DeDXCp1r.js → prism-ruby.min-Dx9KO9ds.js} +16 -16
  170. package/lib/{prism-ruby.min-DeDXCp1r.js.map → prism-ruby.min-Dx9KO9ds.js.map} +1 -1
  171. package/lib/prism-typescript.min-CD7H2IYQ.js.map +1 -1
  172. package/lib/state-mM7uaXTW.js +202 -0
  173. package/lib/state-mM7uaXTW.js.map +1 -0
  174. package/lib/ui/Accordion.js +1 -1
  175. package/lib/ui/ActionButton.js +10 -11
  176. package/lib/ui/ActionButton.js.map +1 -1
  177. package/lib/ui/Alert.js +2 -2
  178. package/lib/ui/AlertDialog.js +1 -1
  179. package/lib/ui/Badge.js +3 -2
  180. package/lib/ui/Badge.js.map +1 -1
  181. package/lib/ui/Breadcrumb.js +1 -1
  182. package/lib/ui/Button.js +2 -2
  183. package/lib/ui/Callout.js +1 -1
  184. package/lib/ui/Card.js +1 -1
  185. package/lib/ui/Carousel.js +3 -3
  186. package/lib/ui/Carousel.js.map +1 -1
  187. package/lib/ui/Checkbox.js +2 -2
  188. package/lib/ui/Command.js +125 -13
  189. package/lib/ui/Command.js.map +1 -1
  190. package/lib/ui/Dialog.js +1 -1
  191. package/lib/ui/Drawer.js +520 -519
  192. package/lib/ui/Drawer.js.map +1 -1
  193. package/lib/ui/DropdownMenu.js +1 -1
  194. package/lib/ui/Form.js +2 -2
  195. package/lib/ui/HoverCard.js +1 -1
  196. package/lib/ui/Input.js +1 -1
  197. package/lib/ui/Label.js +2 -2
  198. package/lib/ui/Pagination.js +7 -7
  199. package/lib/ui/Popover.js +1 -1
  200. package/lib/ui/Progress.js +1 -1
  201. package/lib/ui/RadioGroup.js +1 -1
  202. package/lib/ui/ScrollArea.js +1 -1
  203. package/lib/ui/Select.js +1 -1
  204. package/lib/ui/Skeleton.js +1 -1
  205. package/lib/ui/Slider.js +1 -1
  206. package/lib/ui/Switch.js +1 -1
  207. package/lib/ui/Tabs.js +1 -1
  208. package/lib/ui/Textarea.js +1 -1
  209. package/lib/ui/Toggle.js +2 -2
  210. package/lib/ui/ToggleGroup.js +1 -1
  211. package/lib/ui/Tooltip.js +1 -1
  212. package/lib/{useExposedProps-DE9lR6MF.js → useExposedProps-CetwhZpP.js} +2 -2
  213. package/lib/{useExposedProps-DE9lR6MF.js.map → useExposedProps-CetwhZpP.js.map} +1 -1
  214. package/lib/zudoku.auth-auth0.js +8 -10
  215. package/lib/zudoku.auth-auth0.js.map +1 -1
  216. package/lib/zudoku.auth-clerk.js +18 -18
  217. package/lib/zudoku.auth-openid.js +225 -221
  218. package/lib/zudoku.auth-openid.js.map +1 -1
  219. package/lib/zudoku.components.js +476 -461
  220. package/lib/zudoku.components.js.map +1 -1
  221. package/lib/zudoku.plugin-api-catalog.js +5 -5
  222. package/lib/zudoku.plugin-api-keys.js +7 -7
  223. package/lib/zudoku.plugin-custom-pages.js +3 -3
  224. package/lib/zudoku.plugin-markdown.js +2 -2
  225. package/lib/zudoku.plugin-openapi.js +5 -5
  226. package/lib/zudoku.plugin-redirect.js +1 -1
  227. package/lib/zudoku.plugin-search-inkeep.js +9 -9
  228. package/package.json +48 -48
  229. package/src/app/main.css +50 -50
  230. package/src/lib/authentication/providers/auth0.tsx +1 -4
  231. package/src/lib/authentication/providers/openid.tsx +12 -5
  232. package/src/lib/components/Autocomplete.tsx +111 -0
  233. package/src/lib/components/Header.tsx +3 -3
  234. package/src/lib/components/index.ts +2 -2
  235. package/src/lib/components/navigation/SidebarCategory.tsx +2 -2
  236. package/src/lib/plugins/markdown/MdxPage.tsx +9 -1
  237. package/src/lib/plugins/openapi/OperationList.tsx +4 -0
  238. package/src/lib/plugins/openapi/ParameterListItem.tsx +1 -5
  239. package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +5 -0
  240. package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +8 -2
  241. package/src/lib/plugins/openapi/Sidecar.tsx +15 -7
  242. package/src/lib/plugins/openapi/SidecarBox.tsx +1 -1
  243. package/src/lib/plugins/openapi/SidecarExamples.tsx +14 -6
  244. package/src/lib/plugins/openapi/playground/ExamplesDropdown.tsx +51 -0
  245. package/src/lib/plugins/openapi/playground/Headers.tsx +138 -41
  246. package/src/lib/plugins/openapi/playground/Playground.tsx +156 -62
  247. package/src/lib/plugins/openapi/playground/QueryParams.tsx +89 -122
  248. package/src/lib/plugins/openapi/post-processors/removeExtensions.test.ts +58 -0
  249. package/src/lib/plugins/openapi/post-processors/removeExtensions.ts +7 -4
  250. package/src/lib/plugins/openapi/post-processors/removeParameters.test.ts +148 -0
  251. package/src/lib/plugins/openapi/post-processors/removeParameters.ts +101 -0
  252. package/src/lib/plugins/openapi/schema/SchemaComponents.tsx +1 -1
  253. package/src/lib/ui/Badge.tsx +1 -0
  254. package/src/lib/ui/Command.tsx +20 -0
  255. package/src/lib/util/joinUrl.ts +57 -0
  256. package/dist/lib/plugins/openapi/playground/EnumSelector.d.ts +0 -8
  257. package/dist/lib/plugins/openapi/playground/EnumSelector.js +0 -21
  258. package/dist/lib/plugins/openapi/playground/EnumSelector.js.map +0 -1
  259. package/lib/Button-DeAoTouo.js.map +0 -1
  260. package/lib/Command-9x_kZHr4.js +0 -611
  261. package/lib/Command-9x_kZHr4.js.map +0 -1
  262. package/lib/MdxPage-DKMbBROv.js.map +0 -1
  263. package/lib/OperationList-B8bHMKme.js.map +0 -1
  264. package/lib/Spinner-DuxJLLNE.js +0 -7
  265. package/lib/Spinner-DuxJLLNE.js.map +0 -1
  266. package/lib/ZudokuContext-hmLMUdf2.js.map +0 -1
  267. package/lib/chunk-D52XG6IA-Dl7HLe6j.js.map +0 -1
  268. package/lib/context-h_UkBLvr.js +0 -22
  269. package/lib/createServer-BznDkeSA.js.map +0 -1
  270. package/lib/index-CBXSgjaE.js.map +0 -1
  271. package/lib/index-CPNSgwSb.js +0 -36
  272. package/lib/index-sD8L1_Dl.js +0 -1292
  273. package/lib/index-sD8L1_Dl.js.map +0 -1
  274. package/lib/index.esm-BnnBRKJX.js +0 -1214
  275. package/lib/index.esm-BnnBRKJX.js.map +0 -1
  276. package/lib/state-CFQsUZUP.js +0 -202
  277. package/lib/state-CFQsUZUP.js.map +0 -1
  278. package/src/lib/plugins/openapi/playground/EnumSelector.tsx +0 -86
@@ -2,7 +2,7 @@ import { useMDXComponents } from "@mdx-js/react";
2
2
  import slugify from "@sindresorhus/slugify";
3
3
  import { Helmet } from "@zudoku/react-helmet-async";
4
4
  import { type PropsWithChildren, useEffect } from "react";
5
- import { Link } from "react-router";
5
+ import { Link, useHref } from "react-router";
6
6
  import { CategoryHeading } from "../../components/CategoryHeading.js";
7
7
  import { Heading } from "../../components/Heading.js";
8
8
  import { ProseClasses } from "../../components/Markdown.js";
@@ -51,6 +51,13 @@ export const MdxPage = ({
51
51
  }
52
52
  >) => {
53
53
  const categoryTitle = useCurrentItem()?.categoryLabel;
54
+ let canonicalUrl = null;
55
+ const path = useHref("");
56
+ if (typeof window !== "undefined") {
57
+ const domain = window.location.origin;
58
+ canonicalUrl = `${domain}${path}`;
59
+ }
60
+
54
61
  const title = frontmatter.title;
55
62
  const category = frontmatter.category ?? categoryTitle;
56
63
  const hideToc = frontmatter.toc === false || defaultOptions?.toc === false;
@@ -87,6 +94,7 @@ export const MdxPage = ({
87
94
  <Helmet>
88
95
  <title>{pageTitle}</title>
89
96
  {excerpt && <meta name="description" content={excerpt} />}
97
+ {canonicalUrl && <link rel="canonical" href={canonicalUrl} />}
90
98
  </Helmet>
91
99
  <div
92
100
  className={cn(
@@ -13,6 +13,7 @@ import { useSelectedServerStore } from "../../authentication/state.js";
13
13
  import { CategoryHeading } from "../../components/CategoryHeading.js";
14
14
  import { Heading } from "../../components/Heading.js";
15
15
  import { Markdown, ProseClasses } from "../../components/Markdown.js";
16
+ import { useApiIdentities } from "../../components/context/ZudokuContext.js";
16
17
  import { cn } from "../../util/cn.js";
17
18
  import { Endpoint } from "./Endpoint.js";
18
19
  import { OperationListItem } from "./OperationListItem.js";
@@ -118,6 +119,9 @@ export const OperationList = () => {
118
119
  const description = result.data.schema.description;
119
120
  const navigate = useNavigate();
120
121
 
122
+ // Prefetch for Playground
123
+ useApiIdentities();
124
+
121
125
  // The summary property is preferable here as it is a short description of
122
126
  // the API, whereas the description property is typically longer and supports
123
127
  // commonmark formatting, making it ill-suited for use in the meta description
@@ -47,17 +47,13 @@ export const ParameterListItem = ({
47
47
  )}
48
48
  </code>
49
49
  {paramSchema.type && (
50
- <Badge variant="secondary">
50
+ <Badge variant="muted">
51
51
  {paramSchema.type === "array"
52
52
  ? `${paramSchema.items.type}[]`
53
53
  : paramSchema.type}
54
54
  </Badge>
55
55
  )}
56
56
  {parameter.required && <Badge variant="outline">required</Badge>}
57
- {/* <span className="py-px px-1.5 font-medium bg-primary/75 text-primary-foreground rounded-lg">
58
- required
59
- </span>
60
- )} */}
61
57
  </div>
62
58
  {parameter.description && (
63
59
  <Markdown
@@ -1,20 +1,24 @@
1
1
  import type { OperationListItemResult } from "./OperationList.js";
2
2
  import { PlaygroundDialog } from "./playground/PlaygroundDialog.js";
3
+ import { Content } from "./SidecarExamples.js";
3
4
 
4
5
  export const PlaygroundDialogWrapper = ({
5
6
  server,
6
7
  servers,
7
8
  operation,
9
+ examples,
8
10
  }: {
9
11
  server: string;
10
12
  servers?: string[];
11
13
  operation: OperationListItemResult;
14
+ examples?: Content;
12
15
  }) => {
13
16
  const headers = operation.parameters
14
17
  ?.filter((p) => p.in === "header")
15
18
  .map((p) => ({
16
19
  name: p.name,
17
20
  defaultValue: p.examples?.find((x) => x.value)?.value ?? "",
21
+ defaultActive: false,
18
22
  }));
19
23
  const queryParams = operation.parameters
20
24
  ?.filter((p) => p.in === "query")
@@ -39,6 +43,7 @@ export const PlaygroundDialogWrapper = ({
39
43
  headers={headers}
40
44
  queryParams={queryParams}
41
45
  pathParams={pathParams}
46
+ examples={examples}
42
47
  />
43
48
  );
44
49
  };
@@ -1,13 +1,19 @@
1
1
  import * as SidecarBox from "./SidecarBox.js";
2
2
  import { type Content, SidecarExamples } from "./SidecarExamples.js";
3
3
 
4
- export const RequestBodySidecarBox = ({ content }: { content: Content }) => {
4
+ export const RequestBodySidecarBox = ({
5
+ content,
6
+ onExampleChange,
7
+ }: {
8
+ content: Content;
9
+ onExampleChange?: (example: unknown) => void;
10
+ }) => {
5
11
  return (
6
12
  <SidecarBox.Root>
7
13
  <SidecarBox.Head className="text-xs flex justify-between items-center">
8
14
  <span className="font-mono">Request Body Example</span>
9
15
  </SidecarBox.Head>
10
- <SidecarExamples content={content} />
16
+ <SidecarExamples content={content} onExampleChange={onExampleChange} />
11
17
  </SidecarBox.Root>
12
18
  );
13
19
  };
@@ -1,6 +1,6 @@
1
1
  import { useSuspenseQuery } from "@tanstack/react-query";
2
2
  import { HTTPSnippet } from "@zudoku/httpsnippet";
3
- import { Fragment, useMemo, useTransition } from "react";
3
+ import { Fragment, useMemo, useState, useTransition } from "react";
4
4
  import { useSearchParams } from "react-router";
5
5
  import { useSelectedServerStore } from "../../authentication/state.js";
6
6
  import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
@@ -107,6 +107,7 @@ export const Sidecar = ({
107
107
 
108
108
  const [searchParams, setSearchParams] = useSearchParams();
109
109
  const [, startTransition] = useTransition();
110
+ const [selectedExample, setSelectedExample] = useState<unknown>();
110
111
 
111
112
  const selectedLang = searchParams.get("lang") ?? "shell";
112
113
 
@@ -141,9 +142,11 @@ export const Sidecar = ({
141
142
  const { selectedServer } = useSelectedServerStore();
142
143
 
143
144
  const code = useMemo(() => {
144
- const example = requestBodyContent?.[0]?.schema
145
- ? generateSchemaExample(requestBodyContent[0].schema as SchemaObject)
146
- : undefined;
145
+ const example =
146
+ selectedExample ??
147
+ (requestBodyContent?.[0]?.schema
148
+ ? generateSchemaExample(requestBodyContent[0].schema as SchemaObject)
149
+ : undefined);
147
150
 
148
151
  const snippet = new HTTPSnippet({
149
152
  method: operation.method.toLocaleUpperCase(),
@@ -166,6 +169,7 @@ export const Sidecar = ({
166
169
 
167
170
  return getConverted(snippet, selectedLang);
168
171
  }, [
172
+ selectedExample,
169
173
  requestBodyContent,
170
174
  operation.method,
171
175
  operation.path,
@@ -181,7 +185,7 @@ export const Sidecar = ({
181
185
  className="flex flex-col overflow-hidden sticky top-[--scroll-padding] gap-4"
182
186
  >
183
187
  <SidecarBox.Root>
184
- <SidecarBox.Head className="flex justify-between items-center flex-nowrap py-4 gap-2 text-xs">
188
+ <SidecarBox.Head className="flex justify-between items-center flex-nowrap py-2.5 gap-2 text-xs">
185
189
  <span className="font-mono break-words">
186
190
  <span className={cn("font-semibold", methodTextColor)}>
187
191
  {operation.method.toLocaleUpperCase()}
@@ -194,6 +198,7 @@ export const Sidecar = ({
194
198
  server={result.data.schema.url}
195
199
  servers={result.data.schema.servers.map((server) => server.url)}
196
200
  operation={operation}
201
+ examples={requestBodyContent ?? undefined}
197
202
  />
198
203
  )}
199
204
  </SidecarBox.Head>
@@ -209,7 +214,7 @@ export const Sidecar = ({
209
214
  />
210
215
  </CollapsibleCode>
211
216
  </SidecarBox.Body>
212
- <SidecarBox.Footer className="flex items-center text-xs gap-2 justify-end py-3">
217
+ <SidecarBox.Footer className="flex items-center text-xs gap-2 justify-end py-2.5">
213
218
  <span>Show example in</span>
214
219
  <SimpleSelect
215
220
  className="self-start max-w-[150px]"
@@ -229,7 +234,10 @@ export const Sidecar = ({
229
234
  )}
230
235
  </SidecarBox.Root>
231
236
  {isOnScreen && requestBodyContent && (
232
- <RequestBodySidecarBox content={requestBodyContent} />
237
+ <RequestBodySidecarBox
238
+ content={requestBodyContent}
239
+ onExampleChange={setSelectedExample}
240
+ />
233
241
  )}
234
242
  {isOnScreen && operation.responses.length > 0 && (
235
243
  <ResponsesSidecarBox
@@ -16,7 +16,7 @@ export const Root = ({ children, className }: BaseComponentProps) => (
16
16
  export const Head = ({ children, className }: BaseComponentProps) => (
17
17
  <div
18
18
  className={cn(
19
- "border-b bg-muted dark:bg-transparent text-card-foreground p-3",
19
+ "border-b bg-muted dark:bg-transparent text-card-foreground p-3 py-2.5",
20
20
  className,
21
21
  )}
22
22
  >
@@ -1,4 +1,4 @@
1
- import { useState } from "react";
1
+ import { useEffect, useState } from "react";
2
2
  import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
3
3
  import { type SchemaObject } from "../../oas/graphql/index.js";
4
4
  import { CollapsibleCode } from "./CollapsibleCode.js";
@@ -36,11 +36,13 @@ const getLanguage = (mediaType?: string): string => {
36
36
  export type SidecarExamplesProps = {
37
37
  content: Content;
38
38
  description?: string;
39
+ onExampleChange?: (example: unknown) => void;
39
40
  };
40
41
 
41
42
  export const SidecarExamples = ({
42
43
  content,
43
44
  description,
45
+ onExampleChange,
44
46
  }: SidecarExamplesProps) => {
45
47
  const [selectedContentTypeIndex, setSelectedContentTypeIndex] = useState(0);
46
48
  const [selectedExampleIndex, setSelectedExampleIndex] = useState(0);
@@ -67,6 +69,10 @@ export const SidecarExamples = ({
67
69
  );
68
70
  }
69
71
 
72
+ useEffect(() => {
73
+ onExampleChange?.(exampleValue);
74
+ }, [exampleValue, onExampleChange]);
75
+
70
76
  const formattedExample = formatForDisplay(exampleValue);
71
77
  const language = getLanguage(effectiveContent?.mediaType);
72
78
 
@@ -104,8 +110,13 @@ export const SidecarExamples = ({
104
110
  )}
105
111
  </SidecarBox.Body>
106
112
  {hasContent && (
107
- <SidecarBox.Footer className="flex flex-col gap-2 text-xs py-1">
108
- <div className="flex items-center gap-2 justify-between min-w-0">
113
+ <SidecarBox.Footer className="text-xs p-0">
114
+ {description && (
115
+ <div className="text-muted-foreground text-xs border-b px-3 py-2">
116
+ {description}
117
+ </div>
118
+ )}
119
+ <div className="flex items-center gap-2 justify-between min-w-0 px-3 py-2">
109
120
  <div className="flex items-center gap-2 min-w-0">
110
121
  {content.length > 1 ? (
111
122
  <SimpleSelect
@@ -145,9 +156,6 @@ export const SidecarExamples = ({
145
156
  </div>
146
157
  )}
147
158
  </div>
148
- {description && (
149
- <div className="text-muted-foreground text-xs">{description}</div>
150
- )}
151
159
  </SidecarBox.Footer>
152
160
  )}
153
161
  </>
@@ -0,0 +1,51 @@
1
+ import { Button } from "zudoku/ui/Button.js";
2
+ import {
3
+ DropdownMenu,
4
+ DropdownMenuContent,
5
+ DropdownMenuGroup,
6
+ DropdownMenuItem,
7
+ DropdownMenuLabel,
8
+ DropdownMenuSeparator,
9
+ DropdownMenuTrigger,
10
+ } from "zudoku/ui/DropdownMenu.js";
11
+ import { Content, Example } from "../SidecarExamples.js";
12
+
13
+ const ExamplesDropdown = ({
14
+ examples,
15
+ onSelect,
16
+ }: {
17
+ examples: Content;
18
+ onSelect: (example: Example) => void;
19
+ }) => {
20
+ return (
21
+ <DropdownMenu>
22
+ <DropdownMenuTrigger asChild>
23
+ <Button variant="outline">Use Example</Button>
24
+ </DropdownMenuTrigger>
25
+ <DropdownMenuContent className="w-56">
26
+ {examples.map((example) => {
27
+ return (
28
+ <div key={example.mediaType}>
29
+ <DropdownMenuLabel>{example.mediaType}</DropdownMenuLabel>
30
+ <DropdownMenuSeparator />
31
+ <DropdownMenuGroup>
32
+ {example.examples?.map((example) => {
33
+ return (
34
+ <DropdownMenuItem
35
+ key={example.name}
36
+ onSelect={() => onSelect(example)}
37
+ >
38
+ {example.name}
39
+ </DropdownMenuItem>
40
+ );
41
+ })}
42
+ </DropdownMenuGroup>
43
+ </div>
44
+ );
45
+ })}
46
+ </DropdownMenuContent>
47
+ </DropdownMenu>
48
+ );
49
+ };
50
+
51
+ export default ExamplesDropdown;
@@ -1,9 +1,48 @@
1
1
  import { XIcon } from "lucide-react";
2
- import { Control, useFieldArray, UseFormRegister } from "react-hook-form";
2
+ import { useRef } from "react";
3
+ import {
4
+ Control,
5
+ Controller,
6
+ useFieldArray,
7
+ useFormContext,
8
+ UseFormRegister,
9
+ } from "react-hook-form";
10
+ import { Card } from "zudoku/ui/Card.js";
11
+ import { Checkbox } from "zudoku/ui/Checkbox.js";
12
+ import { Autocomplete } from "../../../components/Autocomplete.js";
3
13
  import { Button } from "../../../ui/Button.js";
4
14
  import { Input } from "../../../ui/Input.js";
5
15
  import { type PlaygroundForm } from "./Playground.js";
6
16
 
17
+ const headerOptions = Object.freeze([
18
+ "Accept",
19
+ "Accept-Encoding",
20
+ "Accept-Language",
21
+ "Authorization",
22
+ "Cache-Control",
23
+ "Connection",
24
+ "Content-Disposition",
25
+ "Content-Encoding",
26
+ "Content-Language",
27
+ "Content-Length",
28
+ "Content-Range",
29
+ "Content-Security-Policy",
30
+ "Content-Type",
31
+ "Cookie",
32
+ "Date",
33
+ "ETag",
34
+ "Expires",
35
+ "Host",
36
+ "If-Modified-Since",
37
+ "Location",
38
+ "Origin",
39
+ "Pragma",
40
+ "Referer",
41
+ "Set-Cookie",
42
+ "User-Agent",
43
+ "X-Requested-With",
44
+ ]);
45
+
7
46
  export const Headers = ({
8
47
  control,
9
48
  register,
@@ -15,53 +54,111 @@ export const Headers = ({
15
54
  control,
16
55
  name: "headers",
17
56
  });
57
+ const { setValue } = useFormContext<PlaygroundForm>();
58
+ const valueRefs = useRef<Array<HTMLInputElement | null>>([]);
59
+ const nameRefs = useRef<Array<HTMLInputElement | null>>([]);
60
+
61
+ const addNewHeader = () => {
62
+ append({
63
+ name: "",
64
+ value: "",
65
+ active: false,
66
+ } as PlaygroundForm["headers"][number]);
67
+ };
68
+
69
+ const handleHeaderEnter = (index: number) => {
70
+ valueRefs.current[index]?.focus();
71
+ };
72
+
73
+ const handleValueEnter = (index: number) => {
74
+ addNewHeader();
75
+ requestAnimationFrame(() => nameRefs.current[index + 1]?.focus());
76
+ };
18
77
 
19
78
  return (
20
79
  <div className="flex flex-col gap-2">
21
- <table className="w-full [&_td]:border [&_td]:p-1.5 [&_td]:px-2">
22
- <tbody>
23
- {fields.map((header, i) => (
24
- <tr
25
- key={header.id}
26
- className="group has-[:focus]:bg-muted/50 hover:bg-muted/50"
27
- >
28
- <td className="flex gap-2 items-center">
29
- <Input
30
- {...register(`headers.${i}.name`)}
31
- placeholder="Name"
32
- className="border-0 shadow-none text-xs font-mono"
33
- autoComplete="off"
34
- />
35
- </td>
36
- <td>
37
- <div className="flex items-center gap-2">
38
- <Input
39
- placeholder={"Value"}
40
- className="border-0 shadow-none text-xs font-mono"
41
- {...register(`headers.${i}.value`)}
42
- autoComplete="off"
80
+ <Card className="flex flex-col gap-2 overflow-hidden">
81
+ <table className="w-full">
82
+ <tbody>
83
+ {fields.map((header, i) => (
84
+ <tr
85
+ key={header.id}
86
+ className="group has-[:focus]:bg-muted/50 hover:bg-muted/50"
87
+ >
88
+ <td className="flex gap-2 items-center pl-3">
89
+ <Controller
90
+ control={control}
91
+ name={`headers.${i}.active`}
92
+ render={({ field }) => (
93
+ <Checkbox
94
+ variant="outline"
95
+ id={`headers.${i}.active`}
96
+ checked={field.value}
97
+ onCheckedChange={(checked) => {
98
+ field.onChange(checked);
99
+ }}
100
+ />
101
+ )}
102
+ />
103
+ <Controller
104
+ control={control}
105
+ name={`headers.${i}.name`}
106
+ render={({ field }) => (
107
+ <Autocomplete
108
+ {...field}
109
+ placeholder="Name"
110
+ className="border-0 shadow-none bg-transparent text-xs font-mono"
111
+ options={headerOptions}
112
+ onEnterPress={() => handleHeaderEnter(i)}
113
+ onChange={(e) => {
114
+ field.onChange(e);
115
+ setValue(`headers.${i}.active`, true);
116
+ }}
117
+ ref={(el) => {
118
+ nameRefs.current[i] = el;
119
+ }}
120
+ />
121
+ )}
43
122
  />
44
- <Button
45
- size="icon"
46
- variant="ghost"
47
- className="text-muted-foreground opacity-0 group-hover:opacity-100"
48
- onClick={() => {
49
- remove(i);
50
- }}
51
- type="button"
52
- >
53
- <XIcon size={16} />
54
- </Button>
55
- </div>
56
- </td>
57
- </tr>
58
- ))}
59
- </tbody>
60
- </table>
123
+ </td>
124
+ <td>
125
+ <div className="flex items-center gap-2">
126
+ <Input
127
+ placeholder="Value"
128
+ className="w-full border-0 shadow-none text-xs font-mono"
129
+ {...register(`headers.${i}.value`)}
130
+ ref={(el) => {
131
+ valueRefs.current[i] = el;
132
+ }}
133
+ onKeyDown={(e) => {
134
+ if (e.key === "Enter" && e.currentTarget.value.trim()) {
135
+ handleValueEnter(i);
136
+ }
137
+ }}
138
+ autoComplete="off"
139
+ />
140
+ <Button
141
+ size="icon"
142
+ variant="ghost"
143
+ className="text-muted-foreground opacity-0 group-hover:opacity-100"
144
+ onClick={() => {
145
+ remove(i);
146
+ }}
147
+ type="button"
148
+ >
149
+ <XIcon size={16} />
150
+ </Button>
151
+ </div>
152
+ </td>
153
+ </tr>
154
+ ))}
155
+ </tbody>
156
+ </table>
157
+ </Card>
61
158
  <div className="text-end">
62
159
  <Button
63
160
  className=""
64
- onClick={() => append({ name: "", value: "" })}
161
+ onClick={addNewHeader}
65
162
  type="button"
66
163
  variant="secondary"
67
164
  >