zudoku 0.26.0 → 0.27.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 (300) hide show
  1. package/dist/app/main.d.ts +1 -1
  2. package/dist/app/main.js +19 -7
  3. package/dist/app/main.js.map +1 -1
  4. package/dist/config/config.d.ts +1 -0
  5. package/dist/config/validators/InputSidebarSchema.d.ts +2 -2
  6. package/dist/config/validators/common.d.ts +78 -0
  7. package/dist/config/validators/common.js +6 -0
  8. package/dist/config/validators/common.js.map +1 -1
  9. package/dist/config/validators/validate.d.ts +34 -0
  10. package/dist/lib/authentication/providers/auth0.js +1 -1
  11. package/dist/lib/authentication/providers/auth0.js.map +1 -1
  12. package/dist/lib/authentication/providers/openid.d.ts +1 -1
  13. package/dist/lib/authentication/providers/openid.js +10 -6
  14. package/dist/lib/authentication/providers/openid.js.map +1 -1
  15. package/dist/lib/components/AnchorLink.js +5 -2
  16. package/dist/lib/components/AnchorLink.js.map +1 -1
  17. package/dist/lib/components/Autocomplete.d.ts +12 -0
  18. package/dist/lib/components/Autocomplete.js +47 -0
  19. package/dist/lib/components/Autocomplete.js.map +1 -0
  20. package/dist/lib/components/Header.js +4 -4
  21. package/dist/lib/components/Header.js.map +1 -1
  22. package/dist/lib/components/Heading.d.ts +1 -1
  23. package/dist/lib/components/Markdown.d.ts +2 -2
  24. package/dist/lib/components/Markdown.js +3 -1
  25. package/dist/lib/components/Markdown.js.map +1 -1
  26. package/dist/lib/components/StatusPage.d.ts +7 -0
  27. package/dist/lib/components/StatusPage.js +71 -0
  28. package/dist/lib/components/StatusPage.js.map +1 -0
  29. package/dist/lib/components/SyntaxHighlight.d.ts +2 -1
  30. package/dist/lib/components/SyntaxHighlight.js +2 -2
  31. package/dist/lib/components/SyntaxHighlight.js.map +1 -1
  32. package/dist/lib/components/ThemeSwitch.js +4 -4
  33. package/dist/lib/components/ThemeSwitch.js.map +1 -1
  34. package/dist/lib/components/cache.d.ts +6 -0
  35. package/dist/lib/components/cache.js +13 -0
  36. package/dist/lib/components/cache.js.map +1 -0
  37. package/dist/lib/components/context/ViewportAnchorContext.js +16 -4
  38. package/dist/lib/components/context/ViewportAnchorContext.js.map +1 -1
  39. package/dist/lib/components/context/ZudokuContext.js +2 -1
  40. package/dist/lib/components/context/ZudokuContext.js.map +1 -1
  41. package/dist/lib/components/index.d.ts +9 -2
  42. package/dist/lib/components/index.js +5 -2
  43. package/dist/lib/components/index.js.map +1 -1
  44. package/dist/lib/core/RouteGuard.d.ts +1 -0
  45. package/dist/lib/core/RouteGuard.js +28 -0
  46. package/dist/lib/core/RouteGuard.js.map +1 -0
  47. package/dist/lib/core/ZudokuContext.d.ts +4 -2
  48. package/dist/lib/core/ZudokuContext.js +9 -7
  49. package/dist/lib/core/ZudokuContext.js.map +1 -1
  50. package/dist/lib/oas/graphql/circular.d.ts +3 -0
  51. package/dist/lib/oas/graphql/circular.js +27 -0
  52. package/dist/lib/oas/graphql/circular.js.map +1 -0
  53. package/dist/lib/oas/graphql/index.js +5 -6
  54. package/dist/lib/oas/graphql/index.js.map +1 -1
  55. package/dist/lib/oas/parser/dereference/index.d.ts +0 -1
  56. package/dist/lib/oas/parser/dereference/index.js +1 -1
  57. package/dist/lib/oas/parser/dereference/index.js.map +1 -1
  58. package/dist/lib/plugins/markdown/MdxPage.js +8 -2
  59. package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
  60. package/dist/lib/plugins/openapi/OperationListItem.js +1 -1
  61. package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
  62. package/dist/lib/plugins/openapi/ParameterListItem.js +1 -1
  63. package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
  64. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.d.ts +3 -1
  65. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js +3 -2
  66. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js.map +1 -1
  67. package/dist/lib/plugins/openapi/Sidecar.js +3 -3
  68. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  69. package/dist/lib/plugins/openapi/index.js +4 -11
  70. package/dist/lib/plugins/openapi/index.js.map +1 -1
  71. package/dist/lib/plugins/openapi/interfaces.d.ts +7 -2
  72. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.d.ts +6 -0
  73. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.js +12 -0
  74. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.js.map +1 -0
  75. package/dist/lib/plugins/openapi/playground/Headers.js +67 -4
  76. package/dist/lib/plugins/openapi/playground/Headers.js.map +1 -1
  77. package/dist/lib/plugins/openapi/playground/ParamsGrid.d.ts +5 -0
  78. package/dist/lib/plugins/openapi/playground/ParamsGrid.js +4 -0
  79. package/dist/lib/plugins/openapi/playground/ParamsGrid.js.map +1 -0
  80. package/dist/lib/plugins/openapi/playground/PathParams.js +4 -12
  81. package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
  82. package/dist/lib/plugins/openapi/playground/Playground.d.ts +18 -1
  83. package/dist/lib/plugins/openapi/playground/Playground.js +53 -40
  84. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  85. package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js +1 -1
  86. package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js.map +1 -1
  87. package/dist/lib/plugins/openapi/playground/QueryParams.js +21 -30
  88. package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
  89. package/dist/lib/plugins/openapi/playground/SubmitButton.d.ts +7 -0
  90. package/dist/lib/plugins/openapi/playground/SubmitButton.js +22 -0
  91. package/dist/lib/plugins/openapi/playground/SubmitButton.js.map +1 -0
  92. package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.d.ts +7 -0
  93. package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.js +11 -0
  94. package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.js.map +1 -0
  95. package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.d.ts +8 -0
  96. package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js +95 -0
  97. package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js.map +1 -0
  98. package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.d.ts +7 -0
  99. package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js +16 -0
  100. package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js.map +1 -0
  101. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.d.ts +10 -0
  102. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.js +32 -0
  103. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.js.map +1 -0
  104. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.test.d.ts +1 -0
  105. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.test.js +56 -0
  106. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.test.js.map +1 -0
  107. package/dist/lib/plugins/openapi/post-processors/removeExtensions.d.ts +2 -1
  108. package/dist/lib/plugins/openapi/post-processors/removeExtensions.js +5 -3
  109. package/dist/lib/plugins/openapi/post-processors/removeExtensions.js.map +1 -1
  110. package/dist/lib/plugins/openapi/post-processors/removeExtensions.test.js +49 -0
  111. package/dist/lib/plugins/openapi/post-processors/removeExtensions.test.js.map +1 -1
  112. package/dist/lib/plugins/openapi/post-processors/removeParameters.d.ts +10 -0
  113. package/dist/lib/plugins/openapi/post-processors/removeParameters.js +66 -0
  114. package/dist/lib/plugins/openapi/post-processors/removeParameters.js.map +1 -0
  115. package/dist/lib/plugins/openapi/post-processors/removeParameters.test.d.ts +1 -0
  116. package/dist/lib/plugins/openapi/post-processors/removeParameters.test.js +131 -0
  117. package/dist/lib/plugins/openapi/post-processors/removeParameters.test.js.map +1 -0
  118. package/dist/lib/plugins/openapi/schema/SchemaComponents.js +1 -1
  119. package/dist/lib/plugins/openapi/schema/SchemaComponents.js.map +1 -1
  120. package/dist/lib/ui/Command.d.ts +9 -1
  121. package/dist/lib/ui/Command.js +5 -1
  122. package/dist/lib/ui/Command.js.map +1 -1
  123. package/dist/lib/ui/Select.js +2 -2
  124. package/dist/lib/ui/Select.js.map +1 -1
  125. package/dist/lib/util/MdxComponents.js +2 -2
  126. package/dist/lib/util/MdxComponents.js.map +1 -1
  127. package/dist/lib/util/joinUrl.d.ts +1 -0
  128. package/dist/lib/util/joinUrl.js +40 -0
  129. package/dist/lib/util/joinUrl.js.map +1 -0
  130. package/dist/lib/util/useScrollToAnchor.d.ts +1 -0
  131. package/dist/lib/util/useScrollToAnchor.js +26 -15
  132. package/dist/lib/util/useScrollToAnchor.js.map +1 -1
  133. package/dist/vite/build.js +10 -10
  134. package/dist/vite/build.js.map +1 -1
  135. package/dist/vite/config.js +4 -1
  136. package/dist/vite/config.js.map +1 -1
  137. package/dist/vite/dev-server.js +4 -1
  138. package/dist/vite/dev-server.js.map +1 -1
  139. package/dist/vite/plugin-api.d.ts +1 -1
  140. package/dist/vite/plugin-api.js +31 -7
  141. package/dist/vite/plugin-api.js.map +1 -1
  142. package/dist/vite/plugin-auth.js +4 -1
  143. package/dist/vite/plugin-auth.js.map +1 -1
  144. package/dist/vite/plugin-mdx.js +9 -4
  145. package/dist/vite/plugin-mdx.js.map +1 -1
  146. package/dist/vite/prerender.d.ts +2 -2
  147. package/dist/vite/prerender.js +5 -4
  148. package/dist/vite/prerender.js.map +1 -1
  149. package/dist/zuplo/enrich-with-zuplo.d.ts +5 -0
  150. package/dist/zuplo/enrich-with-zuplo.js +184 -0
  151. package/dist/zuplo/enrich-with-zuplo.js.map +1 -0
  152. package/dist/zuplo/env.d.ts +1 -0
  153. package/dist/zuplo/env.js +3 -0
  154. package/dist/zuplo/env.js.map +1 -1
  155. package/dist/zuplo/policy-types.d.ts +33 -0
  156. package/dist/zuplo/policy-types.js +8 -0
  157. package/dist/zuplo/policy-types.js.map +1 -0
  158. package/dist/zuplo/with-zuplo-processors.d.ts +3 -0
  159. package/dist/zuplo/with-zuplo-processors.js +26 -0
  160. package/dist/zuplo/with-zuplo-processors.js.map +1 -0
  161. package/dist/zuplo/with-zuplo.d.ts +1 -1
  162. package/dist/zuplo/with-zuplo.js +7 -26
  163. package/dist/zuplo/with-zuplo.js.map +1 -1
  164. package/lib/{AuthenticationPlugin-DNXBcsVN.js → AuthenticationPlugin-CO_YCd2x.js} +3 -3
  165. package/lib/{AuthenticationPlugin-DNXBcsVN.js.map → AuthenticationPlugin-CO_YCd2x.js.map} +1 -1
  166. package/lib/{Markdown-BrfrjEk_.js → Markdown-B8o9Qz4q.js} +1197 -1186
  167. package/lib/{Markdown-BrfrjEk_.js.map → Markdown-B8o9Qz4q.js.map} +1 -1
  168. package/lib/{MdxPage-LNZLj_A5.js → MdxPage-BxRt3Ly7.js} +63 -58
  169. package/lib/MdxPage-BxRt3Ly7.js.map +1 -0
  170. package/lib/OperationList-DH-zIgtq.js +5160 -0
  171. package/lib/OperationList-DH-zIgtq.js.map +1 -0
  172. package/lib/{Route-Pzk6qwIk.js → Route-DJ0ZlVq1.js} +3 -3
  173. package/lib/{Route-Pzk6qwIk.js.map → Route-DJ0ZlVq1.js.map} +1 -1
  174. package/lib/{Select-DkOpAG0c.js → Select-B7UXR0SB.js} +61 -61
  175. package/lib/Select-B7UXR0SB.js.map +1 -0
  176. package/lib/{SlotletProvider-DPbx9KdU.js → SlotletProvider-CtIp8rP3.js} +4 -4
  177. package/lib/{SlotletProvider-DPbx9KdU.js.map → SlotletProvider-CtIp8rP3.js.map} +1 -1
  178. package/lib/{Button-oroWHXAy.js → Spinner-BlzrEEk1.js} +15 -12
  179. package/lib/Spinner-BlzrEEk1.js.map +1 -0
  180. package/lib/{SyntaxHighlight-CJCSPG1F.js → SyntaxHighlight-C1w1QPdY.js} +300 -295
  181. package/lib/{SyntaxHighlight-CJCSPG1F.js.map → SyntaxHighlight-C1w1QPdY.js.map} +1 -1
  182. package/lib/{ZudokuContext-D3ayHjP-.js → ZudokuContext-8jts0fF3.js} +259 -248
  183. package/lib/ZudokuContext-8jts0fF3.js.map +1 -0
  184. package/lib/{chunk-SYFQ2XB5-KWlHsT7t.js → chunk-SYFQ2XB5-BPvC-soB.js} +6 -5
  185. package/lib/{chunk-SYFQ2XB5-KWlHsT7t.js.map → chunk-SYFQ2XB5-BPvC-soB.js.map} +1 -1
  186. package/lib/circular-Dgpd6AN-.js +15397 -0
  187. package/lib/circular-Dgpd6AN-.js.map +1 -0
  188. package/lib/{createServer-BcaswoFO.js → createServer-BV0tHzLK.js} +3450 -5577
  189. package/lib/createServer-BV0tHzLK.js.map +1 -0
  190. package/lib/{hook-DUyACbIK.js → hook-BG02esyv.js} +2 -2
  191. package/lib/{hook-DUyACbIK.js.map → hook-BG02esyv.js.map} +1 -1
  192. package/lib/index-B7mqiOei.js +509 -0
  193. package/lib/index-B7mqiOei.js.map +1 -0
  194. package/lib/index-DmqsUPcm.js +1915 -0
  195. package/lib/index-DmqsUPcm.js.map +1 -0
  196. package/lib/joinUrl-BTy9bvoK.js +20 -0
  197. package/lib/joinUrl-BTy9bvoK.js.map +1 -0
  198. package/lib/post-processors/removeExtensions.js +7 -7
  199. package/lib/post-processors/removeExtensions.js.map +1 -1
  200. package/lib/post-processors/removeParameters.js +48 -0
  201. package/lib/post-processors/removeParameters.js.map +1 -0
  202. package/lib/ui/ActionButton.js +10 -11
  203. package/lib/ui/ActionButton.js.map +1 -1
  204. package/lib/ui/Command.js +125 -13
  205. package/lib/ui/Command.js.map +1 -1
  206. package/lib/ui/Select.js +2 -2
  207. package/lib/ui/Select.js.map +1 -1
  208. package/lib/{useExposedProps-BBHR7aLM.js → useExposedProps-BLKFBylA.js} +2 -2
  209. package/lib/{useExposedProps-BBHR7aLM.js.map → useExposedProps-BLKFBylA.js.map} +1 -1
  210. package/lib/useScrollToAnchor-Bl6mz9_x.js +288 -0
  211. package/lib/useScrollToAnchor-Bl6mz9_x.js.map +1 -0
  212. package/lib/zudoku.auth-auth0.js +7 -9
  213. package/lib/zudoku.auth-auth0.js.map +1 -1
  214. package/lib/zudoku.auth-clerk.js +1 -1
  215. package/lib/zudoku.auth-openid.js +223 -219
  216. package/lib/zudoku.auth-openid.js.map +1 -1
  217. package/lib/zudoku.components.js +754 -992
  218. package/lib/zudoku.components.js.map +1 -1
  219. package/lib/zudoku.plugin-api-catalog.js +3 -3
  220. package/lib/zudoku.plugin-api-keys.js +5 -5
  221. package/lib/zudoku.plugin-custom-pages.js +2 -2
  222. package/lib/zudoku.plugin-markdown.js +1 -1
  223. package/lib/zudoku.plugin-openapi.js +4 -4
  224. package/lib/zudoku.plugin-redirect.js +1 -1
  225. package/package.json +2 -2
  226. package/src/app/main.css +50 -50
  227. package/src/app/main.tsx +26 -7
  228. package/src/lib/authentication/providers/auth0.tsx +1 -4
  229. package/src/lib/authentication/providers/openid.tsx +12 -5
  230. package/src/lib/components/AnchorLink.tsx +5 -2
  231. package/src/lib/components/Autocomplete.tsx +111 -0
  232. package/src/lib/components/Header.tsx +4 -4
  233. package/src/lib/components/Markdown.tsx +14 -15
  234. package/src/lib/components/StatusPage.tsx +91 -0
  235. package/src/lib/components/SyntaxHighlight.tsx +14 -0
  236. package/src/lib/components/ThemeSwitch.tsx +14 -15
  237. package/src/lib/components/cache.ts +15 -0
  238. package/src/lib/components/context/ViewportAnchorContext.tsx +20 -6
  239. package/src/lib/components/context/ZudokuContext.ts +3 -1
  240. package/src/lib/components/index.ts +9 -2
  241. package/src/lib/core/RouteGuard.tsx +35 -0
  242. package/src/lib/core/ZudokuContext.ts +9 -8
  243. package/src/lib/oas/graphql/circular.ts +29 -0
  244. package/src/lib/oas/graphql/index.ts +9 -9
  245. package/src/lib/oas/parser/dereference/index.ts +1 -2
  246. package/src/lib/plugins/markdown/MdxPage.tsx +9 -1
  247. package/src/lib/plugins/openapi/OperationListItem.tsx +0 -2
  248. package/src/lib/plugins/openapi/ParameterListItem.tsx +1 -0
  249. package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +5 -0
  250. package/src/lib/plugins/openapi/Sidecar.tsx +4 -2
  251. package/src/lib/plugins/openapi/index.tsx +9 -15
  252. package/src/lib/plugins/openapi/interfaces.ts +10 -2
  253. package/src/lib/plugins/openapi/playground/ExamplesDropdown.tsx +54 -0
  254. package/src/lib/plugins/openapi/playground/Headers.tsx +136 -39
  255. package/src/lib/plugins/openapi/playground/ParamsGrid.tsx +8 -0
  256. package/src/lib/plugins/openapi/playground/PathParams.tsx +34 -74
  257. package/src/lib/plugins/openapi/playground/Playground.tsx +219 -177
  258. package/src/lib/plugins/openapi/playground/PlaygroundDialog.tsx +1 -1
  259. package/src/lib/plugins/openapi/playground/QueryParams.tsx +90 -122
  260. package/src/lib/plugins/openapi/playground/SubmitButton.tsx +75 -0
  261. package/src/lib/plugins/openapi/playground/result-panel/RequestTab.tsx +73 -0
  262. package/src/lib/plugins/openapi/playground/result-panel/ResponseTab.tsx +210 -0
  263. package/src/lib/plugins/openapi/playground/result-panel/ResultPanel.tsx +101 -0
  264. package/src/lib/plugins/openapi/playground/result-panel/convertToTypes.test.ts +64 -0
  265. package/src/lib/plugins/openapi/playground/result-panel/convertToTypes.ts +36 -0
  266. package/src/lib/plugins/openapi/post-processors/removeExtensions.test.ts +58 -0
  267. package/src/lib/plugins/openapi/post-processors/removeExtensions.ts +7 -4
  268. package/src/lib/plugins/openapi/post-processors/removeParameters.test.ts +148 -0
  269. package/src/lib/plugins/openapi/post-processors/removeParameters.ts +101 -0
  270. package/src/lib/plugins/openapi/schema/SchemaComponents.tsx +1 -1
  271. package/src/lib/ui/Command.tsx +20 -0
  272. package/src/lib/ui/Select.tsx +1 -1
  273. package/src/lib/util/MdxComponents.tsx +2 -1
  274. package/src/lib/util/joinUrl.ts +57 -0
  275. package/src/lib/util/useScrollToAnchor.ts +32 -15
  276. package/dist/lib/plugins/openapi/playground/EnumSelector.d.ts +0 -8
  277. package/dist/lib/plugins/openapi/playground/EnumSelector.js +0 -21
  278. package/dist/lib/plugins/openapi/playground/EnumSelector.js.map +0 -1
  279. package/dist/lib/plugins/openapi/playground/ResponseTab.d.ts +0 -4
  280. package/dist/lib/plugins/openapi/playground/ResponseTab.js +0 -42
  281. package/dist/lib/plugins/openapi/playground/ResponseTab.js.map +0 -1
  282. package/lib/AnchorLink-_Vu02ceN.js +0 -34
  283. package/lib/AnchorLink-_Vu02ceN.js.map +0 -1
  284. package/lib/Button-oroWHXAy.js.map +0 -1
  285. package/lib/Command-D5DE0DD7.js +0 -611
  286. package/lib/Command-D5DE0DD7.js.map +0 -1
  287. package/lib/MdxPage-LNZLj_A5.js.map +0 -1
  288. package/lib/OperationList-PCwzTp1r.js +0 -5144
  289. package/lib/OperationList-PCwzTp1r.js.map +0 -1
  290. package/lib/Select-DkOpAG0c.js.map +0 -1
  291. package/lib/Spinner-C5gHXrVz.js +0 -7
  292. package/lib/Spinner-C5gHXrVz.js.map +0 -1
  293. package/lib/ZudokuContext-D3ayHjP-.js.map +0 -1
  294. package/lib/createServer-BcaswoFO.js.map +0 -1
  295. package/lib/index-CaILD1AV.js +0 -1292
  296. package/lib/index-CaILD1AV.js.map +0 -1
  297. package/lib/index-TaRXY2w1.js +0 -43
  298. package/lib/index-TaRXY2w1.js.map +0 -1
  299. package/src/lib/plugins/openapi/playground/EnumSelector.tsx +0 -86
  300. package/src/lib/plugins/openapi/playground/ResponseTab.tsx +0 -76
@@ -1,4 +1,3 @@
1
- import { EraserIcon } from "lucide-react";
2
1
  import {
3
2
  Control,
4
3
  Controller,
@@ -7,16 +6,11 @@ import {
7
6
  } from "react-hook-form";
8
7
  import { Card } from "zudoku/ui/Card.js";
9
8
  import { Checkbox } from "zudoku/ui/Checkbox.js";
10
- import { Button } from "../../../ui/Button.js";
9
+ import { Autocomplete } from "../../../components/Autocomplete.js";
11
10
  import { Input } from "../../../ui/Input.js";
12
- import { cn } from "../../../util/cn.js";
13
- import { EnumSelector } from "./EnumSelector.js";
14
11
  import { InlineInput } from "./InlineInput.js";
15
- import {
16
- NO_IDENTITY,
17
- type PlaygroundForm,
18
- type QueryParam,
19
- } from "./Playground.js";
12
+ import ParamsGrid from "./ParamsGrid.js";
13
+ import { type PlaygroundForm, type QueryParam } from "./Playground.js";
20
14
 
21
15
  export const QueryParams = ({
22
16
  control,
@@ -33,127 +27,101 @@ export const QueryParams = ({
33
27
 
34
28
  const requiredFields = queryParams.map((param) => Boolean(param.isRequired));
35
29
 
36
- const selectedIdentity = form.watch("identity");
37
- const hasSelectedIdentity = selectedIdentity !== NO_IDENTITY;
38
-
39
30
  return (
40
31
  <Card className="rounded-lg">
41
- <table className="w-full">
42
- <tbody>
43
- {fields
44
- .filter(
45
- // TODO remove this hack for Accu or make it more generic
46
- (field) => !(hasSelectedIdentity && field.name === "apikey"),
47
- )
48
- .map((field, i) => {
49
- const currentParam = queryParams.find(
50
- (param) => param.name === field.name,
51
- );
52
- return (
53
- <tr key={field.id} className="hover:bg-accent/40">
54
- <td className="w-5/12 flex items-center ps-3">
55
- <Controller
56
- control={control}
57
- name={`queryParams.${i}.active`}
58
- render={({ field }) => (
59
- <Checkbox
60
- variant="outline"
61
- id={`queryParams.${i}.active`}
62
- checked={field.value}
63
- onCheckedChange={field.onChange}
64
- />
65
- )}
32
+ <div className="w-full ">
33
+ {fields.map((field, i) => {
34
+ const currentParam = queryParams.find(
35
+ (param) => param.name === field.name,
36
+ );
37
+ return (
38
+ <ParamsGrid key={field.id}>
39
+ <div className="flex items-center">
40
+ <Controller
41
+ control={control}
42
+ name={`queryParams.${i}.active`}
43
+ render={({ field }) => (
44
+ <Checkbox
45
+ variant="outline"
46
+ id={`queryParams.${i}.active`}
47
+ className="mr-2"
48
+ checked={field.value}
49
+ onCheckedChange={field.onChange}
66
50
  />
67
- <Controller
68
- control={control}
69
- render={({ field }) => (
70
- <InlineInput asChild>
71
- <label
72
- className="flex items-center cursor-pointer gap-1"
73
- htmlFor={`queryParams.${i}.active`}
74
- title={
75
- requiredFields[i] ? "Required field" : undefined
76
- }
77
- >
78
- {field.value}
79
- {requiredFields[i] && <sup>&nbsp;*</sup>}
80
- </label>
81
- </InlineInput>
82
- )}
83
- name={`queryParams.${i}.name`}
84
- />
85
- </td>
86
- <td className="w-7/12">
87
- <div className="flex justify-between items-center">
88
- <Controller
89
- control={control}
90
- render={({ field }) => {
91
- const hasEnum =
92
- currentParam?.enum && currentParam.enum.length > 0;
93
-
94
- if (!hasEnum) {
95
- return (
96
- <Input
97
- {...field}
98
- onChange={(e) => {
99
- field.onChange(e.target.value);
100
- if (e.target.value.length > 0) {
101
- form.setValue(
102
- `queryParams.${i}.active`,
103
- true,
104
- );
105
- }
106
- }}
107
- placeholder="Enter value"
108
- className="w-full border-0 shadow-none text-xs font-mono hover:bg-accent"
109
- />
110
- );
51
+ )}
52
+ />
53
+ <Controller
54
+ control={control}
55
+ render={({ field }) =>
56
+ !requiredFields[i] ? (
57
+ <Autocomplete
58
+ value={field.value}
59
+ options={queryParams.map((param) => param.name)}
60
+ onChange={(e) => {
61
+ field.onChange(e);
62
+ }}
63
+ className="border-0 font-mono text-xs bg-transparent hover:bg-transparent"
64
+ />
65
+ ) : (
66
+ <InlineInput asChild>
67
+ <label
68
+ className="flex items-center cursor-pointer gap-1"
69
+ htmlFor={`queryParams.${i}.active`}
70
+ title={
71
+ requiredFields[i] ? "Required field" : undefined
111
72
  }
73
+ >
74
+ {field.value}
75
+ {requiredFields[i] && <sup>&nbsp;*</sup>}
76
+ </label>
77
+ </InlineInput>
78
+ )
79
+ }
80
+ name={`queryParams.${i}.name`}
81
+ />
82
+ </div>
83
+ <div className="flex justify-between items-center">
84
+ <Controller
85
+ control={control}
86
+ render={({ field }) => {
87
+ const hasEnum =
88
+ currentParam?.enum && currentParam.enum.length > 0;
112
89
 
113
- const enumValues = currentParam.enum ?? [];
90
+ if (!hasEnum) {
91
+ return (
92
+ <Input
93
+ {...field}
94
+ onChange={(e) => {
95
+ field.onChange(e.target.value);
96
+ if (e.target.value.length > 0) {
97
+ form.setValue(`queryParams.${i}.active`, true);
98
+ }
99
+ }}
100
+ placeholder="Enter value"
101
+ className="w-full border-0 shadow-none text-xs font-mono"
102
+ />
103
+ );
104
+ }
114
105
 
115
- return (
116
- <EnumSelector
117
- value={field.value}
118
- enumValues={enumValues}
119
- onChange={field.onChange}
120
- onValueSelected={() => {
121
- form.setValue(`queryParams.${i}.active`, true);
122
- }}
123
- />
124
- );
106
+ return (
107
+ <Autocomplete
108
+ value={field.value}
109
+ options={currentParam.enum ?? []}
110
+ onChange={(e) => {
111
+ field.onChange(e);
112
+ form.setValue(`queryParams.${i}.active`, true);
125
113
  }}
126
- name={`queryParams.${i}.value`}
127
- />
128
- <Controller
129
- control={control}
130
- render={({ field }) => (
131
- <Button
132
- size="icon"
133
- type="button"
134
- variant="ghost"
135
- aria-label="Clear value"
136
- className={cn(
137
- "ms-2 mr-1",
138
- field.value.length === 0
139
- ? "opacity-0 pointer-events-none"
140
- : "opacity-100",
141
- )}
142
- title="Clear value"
143
- onClick={() => field.onChange("")}
144
- >
145
- <EraserIcon size={16} />
146
- </Button>
147
- )}
148
- name={`queryParams.${i}.value`}
114
+ className="font-mono text-xs border-0 ring-1 ring-ring"
149
115
  />
150
- </div>
151
- </td>
152
- </tr>
153
- );
154
- })}
155
- </tbody>
156
- </table>
116
+ );
117
+ }}
118
+ name={`queryParams.${i}.value`}
119
+ />
120
+ </div>
121
+ </ParamsGrid>
122
+ );
123
+ })}
124
+ </div>
157
125
  </Card>
158
126
  );
159
127
  };
@@ -0,0 +1,75 @@
1
+ import { ChevronDownIcon } from "lucide-react";
2
+ import { useState } from "react";
3
+ import { useFormContext } from "react-hook-form";
4
+ import { Button } from "zudoku/ui/Button.js";
5
+ import {
6
+ DropdownMenu,
7
+ DropdownMenuContent,
8
+ DropdownMenuItem,
9
+ DropdownMenuTrigger,
10
+ } from "zudoku/ui/DropdownMenu.js";
11
+ import { RadioGroup, RadioGroupItem } from "zudoku/ui/RadioGroup.js";
12
+ import { ApiIdentity } from "../../../core/ZudokuContext.js";
13
+ import { NO_IDENTITY } from "./Playground.js";
14
+
15
+ const SubmitButton = ({
16
+ identities,
17
+ formRef,
18
+ disabled,
19
+ }: {
20
+ identities: ApiIdentity[];
21
+ formRef?: React.RefObject<HTMLFormElement | null>;
22
+ disabled?: boolean;
23
+ }) => {
24
+ const { setValue } = useFormContext();
25
+ const [dropdownValue, setDropdownValue] = useState<string | undefined>();
26
+ if (identities.length === 0) {
27
+ return <Button disabled={disabled}>Send</Button>;
28
+ }
29
+ return (
30
+ <div className="flex">
31
+ <Button
32
+ className="rounded-r-none inset-shadow-sm"
33
+ disabled={disabled}
34
+ onClick={() => formRef?.current?.requestSubmit()}
35
+ >
36
+ Send
37
+ </Button>
38
+ <DropdownMenu>
39
+ <DropdownMenuTrigger asChild>
40
+ <Button
41
+ disabled={disabled}
42
+ className="rounded-l-none border-l border-border/40 inset-shadow-sm w-6"
43
+ size="icon"
44
+ >
45
+ <ChevronDownIcon className="w-4 h-4" />
46
+ </Button>
47
+ </DropdownMenuTrigger>
48
+ <RadioGroup value={dropdownValue}>
49
+ <DropdownMenuContent className="w-56" align="end" alignOffset={-150}>
50
+ {[{ id: NO_IDENTITY, label: "None" }, ...identities].map(
51
+ (identity) => (
52
+ <DropdownMenuItem
53
+ key={identity.id}
54
+ onClick={() => {
55
+ setDropdownValue(identity.id);
56
+ setValue("identity", identity.id);
57
+ formRef?.current?.requestSubmit();
58
+ }}
59
+ onMouseEnter={() => setDropdownValue(identity.id)}
60
+ onMouseLeave={() => setDropdownValue(undefined)}
61
+ >
62
+ <RadioGroupItem value={identity.id} className="mr-2" />
63
+
64
+ {identity.label}
65
+ </DropdownMenuItem>
66
+ ),
67
+ )}
68
+ </DropdownMenuContent>
69
+ </RadioGroup>
70
+ </DropdownMenu>
71
+ </div>
72
+ );
73
+ };
74
+
75
+ export default SubmitButton;
@@ -0,0 +1,73 @@
1
+ import { ChevronRightIcon } from "lucide-react";
2
+ import { Fragment } from "react";
3
+ import {
4
+ Collapsible,
5
+ CollapsibleContent,
6
+ CollapsibleTrigger,
7
+ } from "../../../../ui/Collapsible.js";
8
+ import { cn } from "../../../../util/cn.js";
9
+ import { methodForColor } from "../../util/methodToColor.js";
10
+
11
+ export const RequestTab = ({
12
+ method,
13
+ url,
14
+ headers,
15
+ body,
16
+ }: {
17
+ method: string;
18
+ url: string;
19
+ headers: Array<[string, string]>;
20
+ body?: string;
21
+ }) => {
22
+ return (
23
+ <div className="flex flex-col gap-2 font-mono text-xs">
24
+ <div className="gap-2 p-2 bg-muted rounded-md">
25
+ <span className={cn(methodForColor(method), "font-semibold")}>
26
+ {method}
27
+ </span>
28
+ &nbsp;
29
+ <span className="break-all">{url}</span>&nbsp;
30
+ <span className="text-muted-foreground">HTTP/1.1</span>
31
+ </div>
32
+ <div className="mx-1.5 flex flex-col gap-3">
33
+ <Collapsible defaultOpen>
34
+ <CollapsibleTrigger className="flex items-center gap-2 hover:text-primary group">
35
+ <ChevronRightIcon className="h-4 w-4 transition-transform duration-200 group-data-[state=open]:rotate-[90deg]" />
36
+ <span className="font-semibold">Headers</span>
37
+ </CollapsibleTrigger>
38
+ <CollapsibleContent>
39
+ <div className="grid grid-cols-[auto,1fr] gap-x-8 gap-y-1 pl-1.5 pt-2">
40
+ {headers.map(([key, value]) => (
41
+ <Fragment key={key}>
42
+ <div className="text-primary">{key}</div>
43
+ <div className="break-words">{value}</div>
44
+ </Fragment>
45
+ ))}
46
+ </div>
47
+ </CollapsibleContent>
48
+ </Collapsible>
49
+
50
+ <Collapsible defaultOpen>
51
+ <CollapsibleTrigger className="flex items-center gap-2 hover:text-primary group">
52
+ <ChevronRightIcon className="h-4 w-4 transition-transform duration-200 group-data-[state=open]:rotate-[90deg]" />
53
+ <span className="font-semibold">Body</span>
54
+ </CollapsibleTrigger>
55
+ <CollapsibleContent>
56
+ <div className="pl-0 pt-2">
57
+ <div
58
+ className={cn(
59
+ "whitespace-pre-wrap break-all bg-muted p-2 rounded-md",
60
+ !body && "text-muted-foreground",
61
+ )}
62
+ >
63
+ {body ?? "Empty body"}
64
+ </div>
65
+ </div>
66
+ </CollapsibleContent>
67
+ </Collapsible>
68
+ </div>
69
+ </div>
70
+ );
71
+ };
72
+
73
+ export default RequestTab;
@@ -0,0 +1,210 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { ChevronRightIcon } from "lucide-react";
3
+ import { Fragment, useState } from "react";
4
+ import {
5
+ Collapsible,
6
+ CollapsibleContent,
7
+ CollapsibleTrigger,
8
+ } from "zudoku/ui/Collapsible.js";
9
+ import {
10
+ Select,
11
+ SelectContent,
12
+ SelectItem,
13
+ SelectTrigger,
14
+ SelectValue,
15
+ } from "zudoku/ui/Select.js";
16
+ import { SyntaxHighlight } from "../../../../components/SyntaxHighlight.js";
17
+ import { Card } from "../../../../ui/Card.js";
18
+ import { convertToTypes } from "./convertToTypes.js";
19
+
20
+ const statusCodeMap: Record<number, string> = {
21
+ 200: "OK",
22
+ 201: "Created",
23
+ 202: "Accepted",
24
+ 204: "No Content",
25
+ 400: "Bad Request",
26
+ 401: "Unauthorized",
27
+ 403: "Forbidden",
28
+ 404: "Not Found",
29
+ 405: "Method Not Allowed",
30
+ 500: "Internal Server Error",
31
+ };
32
+
33
+ const mimeTypeToLanguage = (mimeType: string) => {
34
+ const mimeTypeMapping = {
35
+ "application/json": "json",
36
+ "text/json": "json",
37
+ "text/html": "html",
38
+ "text/css": "css",
39
+ "text/javascript": "javascript",
40
+ "application/xml": "xml",
41
+ "application/xhtml+xml": "xhtml",
42
+ };
43
+
44
+ return Object.entries(mimeTypeMapping).find(([mime]) =>
45
+ mimeType.includes(mime),
46
+ )?.[1];
47
+ };
48
+
49
+ const detectLanguage = (headers: Array<[string, string]>) => {
50
+ const contentType =
51
+ headers.find(([key, value]) => key === "Content-Type")?.[1] || "";
52
+ return mimeTypeToLanguage(contentType);
53
+ };
54
+
55
+ const tryParseJson = (body: string) => {
56
+ try {
57
+ return JSON.stringify(JSON.parse(body), null, 2);
58
+ } catch {
59
+ return null;
60
+ }
61
+ };
62
+
63
+ const sortHeadersByRelevance = (
64
+ headers: Array<[string, string]>,
65
+ ): Array<[string, string]> => {
66
+ const priorityOrder = [
67
+ "Content-Type",
68
+ "Content-Length",
69
+ "Authorization",
70
+ "X-RateLimit-Remaining",
71
+ "X-RateLimit-Limit",
72
+ "Cache-Control",
73
+ "ETag",
74
+ ].map((key) => key.toLowerCase());
75
+
76
+ return [...headers].sort(([keyA], [keyB]) => {
77
+ const indexA = priorityOrder.indexOf(keyA.toLowerCase());
78
+ const indexB = priorityOrder.indexOf(keyB.toLowerCase());
79
+ if (indexA === indexB) return 0;
80
+ if (indexA === -1) return 1;
81
+ if (indexB === -1) return -1;
82
+ return indexA - indexB;
83
+ });
84
+ };
85
+
86
+ export const ResponseTab = ({
87
+ body = "",
88
+ headers,
89
+ status,
90
+ time,
91
+ size,
92
+ url,
93
+ }: {
94
+ body?: string;
95
+ headers: Array<[string, string]>;
96
+ status: number;
97
+ time: number;
98
+ size: number;
99
+ url: string;
100
+ }) => {
101
+ const detectedLanguage = detectLanguage(headers);
102
+ const jsonContent = tryParseJson(body);
103
+ const beautifiedBody = jsonContent || body;
104
+ const [view, setView] = useState<"formatted" | "raw" | "types">(
105
+ jsonContent ? "formatted" : "raw",
106
+ );
107
+
108
+ const types = useQuery({
109
+ queryKey: ["types", beautifiedBody],
110
+ queryFn: async () => {
111
+ return convertToTypes(JSON.parse(beautifiedBody));
112
+ },
113
+ enabled: view === "types",
114
+ });
115
+
116
+ const sortedHeaders = sortHeadersByRelevance([...headers]);
117
+
118
+ return (
119
+ <div className="flex flex-col gap-2 h-full overflow-y-scroll max-h-[calc(100vh-220px)] py-4">
120
+ <Collapsible defaultOpen>
121
+ <CollapsibleTrigger className="flex items-center gap-2 hover:text-primary group">
122
+ <ChevronRightIcon className="h-4 w-4 transition-transform duration-200 group-data-[state=open]:rotate-[90deg]" />
123
+ <span className="font-semibold">Headers</span>
124
+ </CollapsibleTrigger>
125
+ <CollapsibleContent>
126
+ <div className="grid grid-cols-[auto,1fr] gap-x-8 gap-y-1 pl-1.5 pt-2 font-mono text-xs">
127
+ {sortedHeaders.slice(0, 5).map(([key, value]) => (
128
+ <Fragment key={key}>
129
+ <div className="text-primary whitespace-pre">{key}</div>
130
+ <div className="break-all">{value}</div>
131
+ </Fragment>
132
+ ))}
133
+ {sortedHeaders.length > 5 && (
134
+ <Collapsible className="col-span-full grid-cols-subgrid grid">
135
+ <CollapsibleTrigger className="col-span-2 text-xs text-muted-foreground hover:text-primary flex items-center gap-1 py-1">
136
+ <ChevronRightIcon className="h-3 w-3 transition-transform duration-200 group-data-[state=open]:rotate-[90deg]" />
137
+ Show {sortedHeaders.length - 5} more headers
138
+ </CollapsibleTrigger>
139
+ <CollapsibleContent className="col-span-full grid grid-cols-subgrid gap-x-8 gap-y-1 ">
140
+ {sortedHeaders.slice(5).map(([key, value]) => (
141
+ <Fragment key={key}>
142
+ <div className="text-primary whitespace-pre">{key}</div>
143
+ <div className="break-all">{value}</div>
144
+ </Fragment>
145
+ ))}
146
+ </CollapsibleContent>
147
+ </Collapsible>
148
+ )}
149
+ </div>
150
+ </CollapsibleContent>
151
+ </Collapsible>
152
+
153
+ <Card className="shadow-none">
154
+ <SyntaxHighlight
155
+ language={
156
+ view === "types"
157
+ ? "typescript"
158
+ : view === "raw"
159
+ ? jsonContent
160
+ ? "plain"
161
+ : detectedLanguage
162
+ : "json"
163
+ }
164
+ noBackground
165
+ // playground dialog has h-5/6 ≈ 83.333vh
166
+ className="overflow-x-auto p-4 text-xs max-h-[calc(83.333vh-180px)]"
167
+ code={
168
+ (view === "raw"
169
+ ? body
170
+ : view === "types"
171
+ ? types.data?.lines.join("\n")
172
+ : beautifiedBody) ?? ""
173
+ }
174
+ />
175
+ </Card>
176
+ <div className="flex gap-2 justify-between">
177
+ <div className="flex text-xs gap-2 border bg-muted rounded-md p-2 items-center h-8 font-mono divide-x">
178
+ <div>
179
+ <span className="text-muted-foreground">Status</span> {status}{" "}
180
+ {statusCodeMap[status] ?? ""}
181
+ </div>
182
+ <div>
183
+ <span className="text-muted-foreground">Time</span>{" "}
184
+ {time.toFixed(0)}ms
185
+ </div>
186
+ <div>
187
+ <span className="text-muted-foreground">Size</span> {size}B
188
+ </div>
189
+ </div>
190
+ {jsonContent && (
191
+ <div>
192
+ <Select
193
+ value={view}
194
+ onValueChange={(value) => setView(value as "formatted" | "raw")}
195
+ >
196
+ <SelectTrigger className="min-w-32">
197
+ <SelectValue placeholder="View" />
198
+ </SelectTrigger>
199
+ <SelectContent>
200
+ <SelectItem value="formatted">Formatted</SelectItem>
201
+ <SelectItem value="raw">Raw</SelectItem>
202
+ <SelectItem value="types">Types</SelectItem>
203
+ </SelectContent>
204
+ </Select>
205
+ </div>
206
+ )}
207
+ </div>
208
+ </div>
209
+ );
210
+ };