zudoku 0.25.2 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/dist/app/demo.js +0 -1
  2. package/dist/app/demo.js.map +1 -1
  3. package/dist/app/standalone.js +0 -1
  4. package/dist/app/standalone.js.map +1 -1
  5. package/dist/cli/dev/handler.js +2 -2
  6. package/dist/cli/dev/handler.js.map +1 -1
  7. package/dist/config/validators/InputSidebarSchema.d.ts +2 -2
  8. package/dist/config/validators/common.d.ts +28 -28
  9. package/dist/config/validators/icon-types.d.ts +1 -1
  10. package/dist/config/validators/validate.d.ts +16 -16
  11. package/dist/lib/components/navigation/SidebarCategory.js +1 -1
  12. package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
  13. package/dist/lib/oas/graphql/index.d.ts +3 -0
  14. package/dist/lib/oas/graphql/index.js +12 -13
  15. package/dist/lib/oas/graphql/index.js.map +1 -1
  16. package/dist/lib/plugins/openapi/ColorizedParam.d.ts +10 -2
  17. package/dist/lib/plugins/openapi/ColorizedParam.js +16 -7
  18. package/dist/lib/plugins/openapi/ColorizedParam.js.map +1 -1
  19. package/dist/lib/plugins/openapi/OperationList.js +3 -0
  20. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  21. package/dist/lib/plugins/openapi/ParameterListItem.js +3 -2
  22. package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
  23. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js +2 -0
  24. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js.map +1 -1
  25. package/dist/lib/plugins/openapi/RequestBodySidecarBox.d.ts +3 -2
  26. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js +3 -6
  27. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
  28. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js +2 -6
  29. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js.map +1 -1
  30. package/dist/lib/plugins/openapi/Sidecar.js +9 -6
  31. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  32. package/dist/lib/plugins/openapi/SidecarBox.js +1 -1
  33. package/dist/lib/plugins/openapi/SidecarBox.js.map +1 -1
  34. package/dist/lib/plugins/openapi/{ExampleDisplay.d.ts → SidecarExamples.d.ts} +3 -6
  35. package/dist/lib/plugins/openapi/SidecarExamples.js +65 -0
  36. package/dist/lib/plugins/openapi/SidecarExamples.js.map +1 -0
  37. package/dist/lib/plugins/openapi/client/GraphQLClient.d.ts +1 -1
  38. package/dist/lib/plugins/openapi/client/GraphQLClient.js +22 -93
  39. package/dist/lib/plugins/openapi/client/GraphQLClient.js.map +1 -1
  40. package/dist/lib/plugins/openapi/client/createServer.d.ts +2 -1
  41. package/dist/lib/plugins/openapi/client/createServer.js +5 -2
  42. package/dist/lib/plugins/openapi/client/createServer.js.map +1 -1
  43. package/dist/lib/plugins/openapi/client/useCreateQuery.d.ts +1 -1
  44. package/dist/lib/plugins/openapi/client/useCreateQuery.js +2 -13
  45. package/dist/lib/plugins/openapi/client/useCreateQuery.js.map +1 -1
  46. package/dist/lib/plugins/openapi/index.d.ts +2 -1
  47. package/dist/lib/plugins/openapi/index.js.map +1 -1
  48. package/dist/lib/plugins/openapi/playground/EnumSelector.d.ts +8 -0
  49. package/dist/lib/plugins/openapi/playground/EnumSelector.js +21 -0
  50. package/dist/lib/plugins/openapi/playground/EnumSelector.js.map +1 -0
  51. package/dist/lib/plugins/openapi/playground/PathParams.js +9 -4
  52. package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
  53. package/dist/lib/plugins/openapi/playground/Playground.d.ts +3 -0
  54. package/dist/lib/plugins/openapi/playground/Playground.js +5 -2
  55. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  56. package/dist/lib/plugins/openapi/playground/QueryParams.js +23 -8
  57. package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
  58. package/dist/lib/plugins/openapi/schema/SchemaComponents.js +2 -1
  59. package/dist/lib/plugins/openapi/schema/SchemaComponents.js.map +1 -1
  60. package/dist/lib/plugins/openapi/util/generateSchemaExample.js +19 -11
  61. package/dist/lib/plugins/openapi/util/generateSchemaExample.js.map +1 -1
  62. package/dist/lib/ui/Badge.d.ts +1 -1
  63. package/dist/lib/ui/Badge.js +2 -1
  64. package/dist/lib/ui/Badge.js.map +1 -1
  65. package/dist/lib/ui/Button.d.ts +1 -1
  66. package/dist/lib/ui/Checkbox.d.ts +8 -2
  67. package/dist/lib/ui/Checkbox.js +13 -1
  68. package/dist/lib/ui/Checkbox.js.map +1 -1
  69. package/dist/lib/util/traverse.d.ts +8 -1
  70. package/dist/lib/util/traverse.js +7 -3
  71. package/dist/lib/util/traverse.js.map +1 -1
  72. package/dist/vite/api/schema-codegen.d.ts +12 -0
  73. package/dist/vite/api/schema-codegen.js +62 -0
  74. package/dist/vite/api/schema-codegen.js.map +1 -0
  75. package/dist/vite/api/schema-codegen.test.d.ts +1 -0
  76. package/dist/vite/api/schema-codegen.test.js +247 -0
  77. package/dist/vite/api/schema-codegen.test.js.map +1 -0
  78. package/dist/vite/config.js +0 -7
  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/plugin-api.js +110 -82
  83. package/dist/vite/plugin-api.js.map +1 -1
  84. package/dist/vite/plugin-component.js +0 -1
  85. package/dist/vite/plugin-component.js.map +1 -1
  86. package/lib/{AnchorLink-DFZZbmvr.js → AnchorLink-_Vu02ceN.js} +3 -3
  87. package/lib/{AnchorLink-DFZZbmvr.js.map → AnchorLink-_Vu02ceN.js.map} +1 -1
  88. package/lib/{AuthenticationPlugin-D7G3me8L.js → AuthenticationPlugin-DNXBcsVN.js} +4 -4
  89. package/lib/{AuthenticationPlugin-D7G3me8L.js.map → AuthenticationPlugin-DNXBcsVN.js.map} +1 -1
  90. package/lib/{Button-DeAoTouo.js → Button-oroWHXAy.js} +3 -3
  91. package/lib/{Button-DeAoTouo.js.map → Button-oroWHXAy.js.map} +1 -1
  92. package/lib/{CategoryHeading-CBconmtI.js → CategoryHeading-MYL1u_6K.js} +3 -3
  93. package/lib/{CategoryHeading-CBconmtI.js.map → CategoryHeading-MYL1u_6K.js.map} +1 -1
  94. package/lib/Command-D5DE0DD7.js +611 -0
  95. package/lib/Command-D5DE0DD7.js.map +1 -0
  96. package/lib/{Markdown-CZDLNOFc.js → Markdown-BrfrjEk_.js} +1041 -1041
  97. package/lib/{Markdown-CZDLNOFc.js.map → Markdown-BrfrjEk_.js.map} +1 -1
  98. package/lib/{MdxPage-DKMbBROv.js → MdxPage-LNZLj_A5.js} +24 -24
  99. package/lib/{MdxPage-DKMbBROv.js.map → MdxPage-LNZLj_A5.js.map} +1 -1
  100. package/lib/{OperationList-BLdHAQ39.js → OperationList-PCwzTp1r.js} +1899 -1877
  101. package/lib/OperationList-PCwzTp1r.js.map +1 -0
  102. package/lib/{Route-DYwKZ_c_.js → Route-Pzk6qwIk.js} +5 -5
  103. package/lib/{Route-DYwKZ_c_.js.map → Route-Pzk6qwIk.js.map} +1 -1
  104. package/lib/{Select-B_IxRUUC.js → Select-DkOpAG0c.js} +36 -36
  105. package/lib/{Select-B_IxRUUC.js.map → Select-DkOpAG0c.js.map} +1 -1
  106. package/lib/{SlotletProvider-pfc9oejW.js → SlotletProvider-DPbx9KdU.js} +53 -53
  107. package/lib/{SlotletProvider-pfc9oejW.js.map → SlotletProvider-DPbx9KdU.js.map} +1 -1
  108. package/lib/{Spinner-DuxJLLNE.js → Spinner-C5gHXrVz.js} +2 -2
  109. package/lib/{Spinner-DuxJLLNE.js.map → Spinner-C5gHXrVz.js.map} +1 -1
  110. package/lib/{SyntaxHighlight-Bz-lOJtH.js → SyntaxHighlight-CJCSPG1F.js} +297 -301
  111. package/lib/{SyntaxHighlight-Bz-lOJtH.js.map → SyntaxHighlight-CJCSPG1F.js.map} +1 -1
  112. package/lib/{ZudokuContext-hmLMUdf2.js → ZudokuContext-D3ayHjP-.js} +357 -356
  113. package/lib/ZudokuContext-D3ayHjP-.js.map +1 -0
  114. package/lib/{chunk-D52XG6IA-Dl7HLe6j.js → chunk-SYFQ2XB5-KWlHsT7t.js} +407 -410
  115. package/lib/chunk-SYFQ2XB5-KWlHsT7t.js.map +1 -0
  116. package/lib/context-rwLGh-6_.js +22 -0
  117. package/lib/{context-h_UkBLvr.js.map → context-rwLGh-6_.js.map} +1 -1
  118. package/lib/{createServer-Bf5_6o6G.js → createServer-BcaswoFO.js} +4363 -5302
  119. package/lib/createServer-BcaswoFO.js.map +1 -0
  120. package/lib/{hook-CHq7pFyz.js → hook-DUyACbIK.js} +17 -17
  121. package/lib/{hook-CHq7pFyz.js.map → hook-DUyACbIK.js.map} +1 -1
  122. package/lib/index-CaILD1AV.js +1292 -0
  123. package/lib/index-CaILD1AV.js.map +1 -0
  124. package/lib/index-Djenk2Hj.js +36 -0
  125. package/lib/{index-CPNSgwSb.js.map → index-Djenk2Hj.js.map} +1 -1
  126. package/lib/{index-CBXSgjaE.js → index-Dl3Yl0yb.js} +65 -69
  127. package/lib/index-Dl3Yl0yb.js.map +1 -0
  128. package/lib/index-TaRXY2w1.js +43 -0
  129. package/lib/index-TaRXY2w1.js.map +1 -0
  130. package/lib/{index.esm-BSV1C092.js → index.esm-9-TF9KQB.js} +52 -52
  131. package/lib/{index.esm-BSV1C092.js.map → index.esm-9-TF9KQB.js.map} +1 -1
  132. package/lib/index.esm-CrSoEshU.js +1207 -0
  133. package/lib/index.esm-CrSoEshU.js.map +1 -0
  134. package/lib/{jsx-runtime-Dx-03ztt.js → jsx-runtime-Bdg6XQ1m.js} +135 -135
  135. package/lib/{jsx-runtime-Dx-03ztt.js.map → jsx-runtime-Bdg6XQ1m.js.map} +1 -1
  136. package/lib/post-processors/removeExtensions.js +3 -3
  137. package/lib/post-processors/traverse.js +11 -8
  138. package/lib/post-processors/traverse.js.map +1 -1
  139. package/lib/{prism-bash.min-DadFsM4Z.js → prism-bash.min-HHIMdNJ_.js} +4 -4
  140. package/lib/{prism-bash.min-DadFsM4Z.js.map → prism-bash.min-HHIMdNJ_.js.map} +1 -1
  141. package/lib/{prism-csharp.min-DUwvItt4.js → prism-csharp.min-bQAo2pmx.js} +33 -33
  142. package/lib/{prism-csharp.min-DUwvItt4.js.map → prism-csharp.min-bQAo2pmx.js.map} +1 -1
  143. package/lib/{prism-java.min-BtgBR4yd.js → prism-java.min-BpvsOuIa.js} +12 -12
  144. package/lib/{prism-java.min-BtgBR4yd.js.map → prism-java.min-BpvsOuIa.js.map} +1 -1
  145. package/lib/{prism-markdown.min-F3U-vPBi.js → prism-markdown.min-C0Qn0m-5.js} +30 -30
  146. package/lib/{prism-markdown.min-F3U-vPBi.js.map → prism-markdown.min-C0Qn0m-5.js.map} +1 -1
  147. package/lib/{prism-ruby.min-DeDXCp1r.js → prism-ruby.min-Dx9KO9ds.js} +16 -16
  148. package/lib/{prism-ruby.min-DeDXCp1r.js.map → prism-ruby.min-Dx9KO9ds.js.map} +1 -1
  149. package/lib/prism-typescript.min-CD7H2IYQ.js.map +1 -1
  150. package/lib/state-mM7uaXTW.js +202 -0
  151. package/lib/state-mM7uaXTW.js.map +1 -0
  152. package/lib/ui/Accordion.js +1 -1
  153. package/lib/ui/ActionButton.js +3 -3
  154. package/lib/ui/Alert.js +2 -2
  155. package/lib/ui/AlertDialog.js +1 -1
  156. package/lib/ui/Badge.js +4 -3
  157. package/lib/ui/Badge.js.map +1 -1
  158. package/lib/ui/Breadcrumb.js +1 -1
  159. package/lib/ui/Button.js +2 -2
  160. package/lib/ui/Callout.js +1 -1
  161. package/lib/ui/Card.js +1 -1
  162. package/lib/ui/Carousel.js +3 -3
  163. package/lib/ui/Carousel.js.map +1 -1
  164. package/lib/ui/Checkbox.js +26 -15
  165. package/lib/ui/Checkbox.js.map +1 -1
  166. package/lib/ui/Command.js +14 -550
  167. package/lib/ui/Command.js.map +1 -1
  168. package/lib/ui/Dialog.js +1 -1
  169. package/lib/ui/Drawer.js +520 -519
  170. package/lib/ui/Drawer.js.map +1 -1
  171. package/lib/ui/DropdownMenu.js +1 -1
  172. package/lib/ui/Form.js +2 -2
  173. package/lib/ui/HoverCard.js +1 -1
  174. package/lib/ui/Input.js +1 -1
  175. package/lib/ui/Label.js +2 -2
  176. package/lib/ui/Pagination.js +7 -7
  177. package/lib/ui/Popover.js +1 -1
  178. package/lib/ui/Progress.js +1 -1
  179. package/lib/ui/RadioGroup.js +1 -1
  180. package/lib/ui/ScrollArea.js +1 -1
  181. package/lib/ui/Select.js +1 -1
  182. package/lib/ui/Skeleton.js +1 -1
  183. package/lib/ui/Slider.js +1 -1
  184. package/lib/ui/Switch.js +1 -1
  185. package/lib/ui/Tabs.js +1 -1
  186. package/lib/ui/Textarea.js +1 -1
  187. package/lib/ui/Toggle.js +2 -2
  188. package/lib/ui/ToggleGroup.js +1 -1
  189. package/lib/ui/Tooltip.js +1 -1
  190. package/lib/{useExposedProps-DE9lR6MF.js → useExposedProps-BBHR7aLM.js} +2 -2
  191. package/lib/{useExposedProps-DE9lR6MF.js.map → useExposedProps-BBHR7aLM.js.map} +1 -1
  192. package/lib/zudoku.auth-auth0.js +1 -1
  193. package/lib/zudoku.auth-clerk.js +18 -18
  194. package/lib/zudoku.auth-openid.js +5 -5
  195. package/lib/zudoku.components.js +492 -477
  196. package/lib/zudoku.components.js.map +1 -1
  197. package/lib/zudoku.plugin-api-catalog.js +5 -5
  198. package/lib/zudoku.plugin-api-keys.js +7 -7
  199. package/lib/zudoku.plugin-custom-pages.js +3 -3
  200. package/lib/zudoku.plugin-markdown.js +2 -2
  201. package/lib/zudoku.plugin-openapi.js +5 -5
  202. package/lib/zudoku.plugin-redirect.js +1 -1
  203. package/lib/zudoku.plugin-search-inkeep.js +9 -9
  204. package/package.json +48 -53
  205. package/src/app/demo.tsx +0 -1
  206. package/src/app/standalone.tsx +0 -1
  207. package/src/lib/components/navigation/SidebarCategory.tsx +2 -2
  208. package/src/lib/oas/graphql/index.ts +19 -15
  209. package/src/lib/plugins/openapi/ColorizedParam.tsx +29 -12
  210. package/src/lib/plugins/openapi/OperationList.tsx +4 -0
  211. package/src/lib/plugins/openapi/ParameterListItem.tsx +5 -7
  212. package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +2 -0
  213. package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +9 -8
  214. package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +5 -8
  215. package/src/lib/plugins/openapi/Sidecar.tsx +14 -7
  216. package/src/lib/plugins/openapi/SidecarBox.tsx +1 -1
  217. package/src/lib/plugins/openapi/SidecarExamples.tsx +163 -0
  218. package/src/lib/plugins/openapi/client/GraphQLClient.tsx +28 -120
  219. package/src/lib/plugins/openapi/client/createServer.ts +6 -2
  220. package/src/lib/plugins/openapi/client/useCreateQuery.ts +2 -17
  221. package/src/lib/plugins/openapi/index.tsx +2 -1
  222. package/src/lib/plugins/openapi/playground/EnumSelector.tsx +86 -0
  223. package/src/lib/plugins/openapi/playground/PathParams.tsx +72 -64
  224. package/src/lib/plugins/openapi/playground/Playground.tsx +26 -13
  225. package/src/lib/plugins/openapi/playground/QueryParams.tsx +102 -73
  226. package/src/lib/plugins/openapi/schema/SchemaComponents.tsx +4 -7
  227. package/src/lib/plugins/openapi/util/generateSchemaExample.ts +26 -11
  228. package/src/lib/ui/Badge.tsx +2 -1
  229. package/src/lib/ui/Checkbox.tsx +24 -7
  230. package/src/lib/util/traverse.ts +15 -5
  231. package/dist/lib/plugins/openapi/ExampleDisplay.js +0 -78
  232. package/dist/lib/plugins/openapi/ExampleDisplay.js.map +0 -1
  233. package/dist/lib/plugins/openapi/client/worker.d.ts +0 -4
  234. package/dist/lib/plugins/openapi/client/worker.js +0 -29
  235. package/dist/lib/plugins/openapi/client/worker.js.map +0 -1
  236. package/dist/lib/plugins/openapi-worker.d.ts +0 -1
  237. package/dist/lib/plugins/openapi-worker.js +0 -8
  238. package/dist/lib/plugins/openapi-worker.js.map +0 -1
  239. package/lib/Dialog-Bxv1yEIg.js +0 -67
  240. package/lib/Dialog-Bxv1yEIg.js.map +0 -1
  241. package/lib/OperationList-BLdHAQ39.js.map +0 -1
  242. package/lib/ZudokuContext-hmLMUdf2.js.map +0 -1
  243. package/lib/assets/index-C7jnHK4b.js +0 -4841
  244. package/lib/assets/index-C7jnHK4b.js.map +0 -1
  245. package/lib/assets/worker-Cbp2r2BQ.js +0 -18592
  246. package/lib/assets/worker-Cbp2r2BQ.js.map +0 -1
  247. package/lib/chunk-D52XG6IA-Dl7HLe6j.js.map +0 -1
  248. package/lib/context-h_UkBLvr.js +0 -22
  249. package/lib/createServer-Bf5_6o6G.js.map +0 -1
  250. package/lib/index-BNx95gkf.js +0 -1284
  251. package/lib/index-BNx95gkf.js.map +0 -1
  252. package/lib/index-CBXSgjaE.js.map +0 -1
  253. package/lib/index-CPNSgwSb.js +0 -36
  254. package/lib/index-DyBL--Kz.js +0 -826
  255. package/lib/index-DyBL--Kz.js.map +0 -1
  256. package/lib/index.esm-BnnBRKJX.js +0 -1214
  257. package/lib/index.esm-BnnBRKJX.js.map +0 -1
  258. package/lib/state-CFQsUZUP.js +0 -202
  259. package/lib/state-CFQsUZUP.js.map +0 -1
  260. package/lib/zudoku.openapi-worker.js +0 -15
  261. package/lib/zudoku.openapi-worker.js.map +0 -1
  262. package/src/lib/plugins/openapi/ExampleDisplay.tsx +0 -163
  263. package/src/lib/plugins/openapi/client/worker.ts +0 -44
  264. package/src/lib/plugins/openapi-worker.ts +0 -11
@@ -1,11 +1,31 @@
1
1
  import { EraserIcon } from "lucide-react";
2
2
  import { Control, Controller, useFieldArray } from "react-hook-form";
3
+ import { Card } from "zudoku/ui/Card.js";
3
4
  import { Button } from "../../../ui/Button.js";
4
5
  import { Input } from "../../../ui/Input.js";
5
6
  import { cn } from "../../../util/cn.js";
6
- import { ColorizedParam } from "../ColorizedParam.js";
7
+ import { ColorizedParam, useParamColor } from "../ColorizedParam.js";
7
8
  import type { PlaygroundForm } from "./Playground.js";
8
9
 
10
+ const PathParamLabel = ({ name }: { name: string }) => {
11
+ const color = useParamColor(name);
12
+
13
+ return (
14
+ <div className="flex items-center">
15
+ <div
16
+ className="w-2 h-2 rounded-full"
17
+ style={{ backgroundColor: `hsl(${color})` }}
18
+ />
19
+
20
+ <ColorizedParam
21
+ slug={name}
22
+ name={name}
23
+ className="font-mono text-xs m-2 px-1"
24
+ />
25
+ </div>
26
+ );
27
+ };
28
+
9
29
  export const PathParams = ({
10
30
  control,
11
31
  }: {
@@ -17,72 +37,60 @@ export const PathParams = ({
17
37
  });
18
38
 
19
39
  return (
20
- <table className="w-full table-auto [&_td]:border [&_td]:py-1 [&_td]:px-2">
21
- <tbody>
22
- {fields.map((part, i) => (
23
- <tr key={part.id} className="hover:bg-accent/40">
24
- <td>
25
- <Controller
26
- control={control}
27
- name={`pathParams.${i}.value`}
28
- render={({ field }) => (
29
- <div>
30
- <ColorizedParam
31
- slug={part.name}
32
- name={part.name}
33
- backgroundOpacity="25%"
34
- borderOpacity={field.value ? "100%" : "0"}
35
- className={cn(
36
- "font-mono text-xs m-2",
37
- !field.value && "opacity-60",
38
- )}
39
- />
40
- *
41
- </div>
42
- )}
43
- />
44
- </td>
45
- <td>
46
- <div className="flex justify-between items-center">
47
- <Controller
48
- control={control}
49
- name={`pathParams.${i}.value`}
50
- render={({ field }) => (
51
- <Input
52
- {...field}
53
- required
54
- placeholder="Enter value"
55
- className="border-0 shadow-none ring-0 font-mono text-xs"
56
- />
57
- )}
58
- />
40
+ <Card className="rounded-lg">
41
+ <table className="w-full">
42
+ <tbody>
43
+ {fields.map((part, i) => (
44
+ <tr key={part.id} className="hover:bg-accent/40">
45
+ <td className="w-5/12">
59
46
  <Controller
60
47
  control={control}
61
48
  name={`pathParams.${i}.value`}
62
- render={({ field }) => (
63
- <Button
64
- size="icon"
65
- type="button"
66
- variant="ghost"
67
- aria-label="Clear value"
68
- className={cn(
69
- "ms-2",
70
- field.value.length === 0
71
- ? "opacity-0 pointer-events-none"
72
- : "opacity-100",
73
- )}
74
- title="Clear value"
75
- onClick={() => field.onChange("")}
76
- >
77
- <EraserIcon size={16} />
78
- </Button>
79
- )}
49
+ render={() => <PathParamLabel name={part.name} />}
80
50
  />
81
- </div>
82
- </td>
83
- </tr>
84
- ))}
85
- </tbody>
86
- </table>
51
+ </td>
52
+ <td className="w-7/12">
53
+ <div className="flex justify-between items-center">
54
+ <Controller
55
+ control={control}
56
+ name={`pathParams.${i}.value`}
57
+ render={({ field }) => (
58
+ <Input
59
+ {...field}
60
+ required
61
+ placeholder="Enter value"
62
+ className="w-full border-0 shadow-none text-xs font-mono hover:bg-accent"
63
+ />
64
+ )}
65
+ />
66
+ <Controller
67
+ control={control}
68
+ name={`pathParams.${i}.value`}
69
+ render={({ field }) => (
70
+ <Button
71
+ size="icon"
72
+ type="button"
73
+ variant="ghost"
74
+ aria-label="Clear value"
75
+ className={cn(
76
+ "ms-2 mr-1",
77
+ field.value.length === 0
78
+ ? "opacity-0 pointer-events-none"
79
+ : "opacity-100",
80
+ )}
81
+ title="Clear value"
82
+ onClick={() => field.onChange("")}
83
+ >
84
+ <EraserIcon size={16} />
85
+ </Button>
86
+ )}
87
+ />
88
+ </div>
89
+ </td>
90
+ </tr>
91
+ ))}
92
+ </tbody>
93
+ </table>
94
+ </Card>
87
95
  );
88
96
  };
@@ -46,6 +46,8 @@ export type QueryParam = {
46
46
  defaultValue?: string;
47
47
  defaultActive?: boolean;
48
48
  isRequired?: boolean;
49
+ enum?: string[];
50
+ type?: string;
49
51
  };
50
52
  export type PathParam = {
51
53
  name: string;
@@ -55,9 +57,17 @@ export type PathParam = {
55
57
 
56
58
  export type PlaygroundForm = {
57
59
  body: string;
58
- queryParams: Array<{ name: string; value: string; active: boolean }>;
60
+ queryParams: Array<{
61
+ name: string;
62
+ value: string;
63
+ active: boolean;
64
+ enum?: string[];
65
+ }>;
59
66
  pathParams: Array<{ name: string; value: string }>;
60
- headers: Array<{ name: string; value: string }>;
67
+ headers: Array<{
68
+ name: string;
69
+ value: string;
70
+ }>;
61
71
  identity?: string;
62
72
  };
63
73
 
@@ -92,6 +102,7 @@ export const Playground = ({
92
102
  name: param.name,
93
103
  value: param.defaultValue ?? "",
94
104
  active: param.defaultActive ?? false,
105
+ enum: param.enum ?? [],
95
106
  })),
96
107
  pathParams: pathParams.map((param) => ({
97
108
  name: param.name,
@@ -171,17 +182,19 @@ export const Playground = ({
171
182
  const replaced = part.replace(/[:{}]/g, "");
172
183
  const value = formState.pathParams.find((p) => p.name === replaced)?.value;
173
184
 
174
- const pathParamValue = value ? (
175
- <ColorizedParam backgroundOpacity="25%" name={part} slug={part}>
176
- {encodeURIComponent(value)}
177
- </ColorizedParam>
178
- ) : (
179
- <span
180
- className="underline decoration-wavy decoration-red-500"
181
- title={`Missing value for path parameter \`${replaced}\``}
185
+ const pathParamValue = (
186
+ <ColorizedParam
187
+ backgroundOpacity="25%"
188
+ name={part}
189
+ slug={part}
190
+ title={
191
+ !value
192
+ ? `Missing value for path parameter \`${replaced}\``
193
+ : undefined
194
+ }
182
195
  >
183
- {part}
184
- </span>
196
+ {value ? encodeURIComponent(value) : part}
197
+ </ColorizedParam>
185
198
  );
186
199
 
187
200
  return (
@@ -240,7 +253,7 @@ export const Playground = ({
240
253
  >
241
254
  <form onSubmit={handleSubmit((data) => queryMutation.mutateAsync(data))}>
242
255
  <div className="grid grid-cols-[8fr_7fr] text-sm h-full">
243
- <div className="flex flex-col gap-4 p-8 bg-muted/50 after:bg-muted-foreground/20 relative after:absolute after:w-px after:inset-0 after:left-auto">
256
+ <div className="flex flex-col gap-4 p-4 after:bg-muted-foreground/20 relative after:absolute after:w-px after:inset-0 after:left-auto">
244
257
  <div className="flex gap-2 items-stretch">
245
258
  <div className="flex flex-1 items-center w-full border rounded-md">
246
259
  <div className="border-r p-2 bg-muted rounded-l-md self-stretch font-semibold font-mono">
@@ -5,9 +5,12 @@ import {
5
5
  useFieldArray,
6
6
  useFormContext,
7
7
  } from "react-hook-form";
8
+ import { Card } from "zudoku/ui/Card.js";
9
+ import { Checkbox } from "zudoku/ui/Checkbox.js";
8
10
  import { Button } from "../../../ui/Button.js";
9
11
  import { Input } from "../../../ui/Input.js";
10
12
  import { cn } from "../../../util/cn.js";
13
+ import { EnumSelector } from "./EnumSelector.js";
11
14
  import { InlineInput } from "./InlineInput.js";
12
15
  import {
13
16
  NO_IDENTITY,
@@ -34,97 +37,123 @@ export const QueryParams = ({
34
37
  const hasSelectedIdentity = selectedIdentity !== NO_IDENTITY;
35
38
 
36
39
  return (
37
- <div className="">
38
- <table className="w-full [&_td]:border [&_td]:p-1.5 [&_td]:px-2">
40
+ <Card className="rounded-lg">
41
+ <table className="w-full">
39
42
  <tbody>
40
43
  {fields
41
44
  .filter(
42
45
  // TODO remove this hack for Accu or make it more generic
43
46
  (field) => !(hasSelectedIdentity && field.name === "apikey"),
44
47
  )
45
- .map((field, i) => (
46
- <tr key={field.id} className="hover:bg-accent/40">
47
- <td className="text-center">
48
- <Controller
49
- control={control}
50
- name={`queryParams.${i}.active`}
51
- render={({ field }) => (
52
- <input
53
- type="checkbox"
54
- id={`queryParams.${i}.active`}
55
- checked={field.value}
56
- onChange={field.onChange}
57
- />
58
- )}
59
- />
60
- </td>
61
- <td>
62
- <Controller
63
- control={control}
64
- render={({ field }) => (
65
- <InlineInput asChild>
66
- <label
67
- className="flex items-center cursor-pointer"
68
- htmlFor={`queryParams.${i}.active`}
69
- title={
70
- requiredFields[i] ? "Required field" : undefined
71
- }
72
- >
73
- {field.value}
74
- {requiredFields[i] && <sup>&nbsp;*</sup>}
75
- </label>
76
- </InlineInput>
77
- )}
78
- name={`queryParams.${i}.name`}
79
- />
80
- </td>
81
- <td>
82
- <div className="flex justify-between items-center">
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">
83
55
  <Controller
84
56
  control={control}
57
+ name={`queryParams.${i}.active`}
85
58
  render={({ field }) => (
86
- <Input
87
- {...field}
88
- onChange={(e) => {
89
- field.onChange(e.target.value);
90
- if (e.target.value.length > 0) {
91
- form.setValue(`queryParams.${i}.active`, true);
92
- }
93
- }}
94
- placeholder="Enter value"
95
- className="w-full border-0 shadow-none text-xs font-mono"
59
+ <Checkbox
60
+ variant="outline"
61
+ id={`queryParams.${i}.active`}
62
+ checked={field.value}
63
+ onCheckedChange={field.onChange}
96
64
  />
97
65
  )}
98
- name={`queryParams.${i}.value`}
99
66
  />
100
67
  <Controller
101
68
  control={control}
102
69
  render={({ field }) => (
103
- <Button
104
- size="icon"
105
- type="button"
106
- variant="ghost"
107
- aria-label="Clear value"
108
- className={cn(
109
- "ms-2",
110
- field.value.length === 0
111
- ? "opacity-0 pointer-events-none"
112
- : "opacity-100",
113
- )}
114
- title="Clear value"
115
- onClick={() => field.onChange("")}
116
- >
117
- <EraserIcon size={16} />
118
- </Button>
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>
119
82
  )}
120
- name={`queryParams.${i}.value`}
83
+ name={`queryParams.${i}.name`}
121
84
  />
122
- </div>
123
- </td>
124
- </tr>
125
- ))}
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
+ );
111
+ }
112
+
113
+ const enumValues = currentParam.enum ?? [];
114
+
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
+ );
125
+ }}
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`}
149
+ />
150
+ </div>
151
+ </td>
152
+ </tr>
153
+ );
154
+ })}
126
155
  </tbody>
127
156
  </table>
128
- </div>
157
+ </Card>
129
158
  );
130
159
  };
@@ -1,6 +1,7 @@
1
1
  import * as Collapsible from "@radix-ui/react-collapsible";
2
2
  import { ListPlusIcon, RefreshCcwDotIcon } from "lucide-react";
3
3
  import { useCallback, useState } from "react";
4
+ import { Badge } from "zudoku/ui/Badge.js";
4
5
  import { Markdown, ProseClasses } from "../../../components/Markdown.js";
5
6
  import { CIRCULAR_REF } from "../../../oas/parser/dereference/index.js";
6
7
  import type { SchemaObject } from "../../../oas/parser/index.js";
@@ -85,7 +86,7 @@ export const SchemaPropertyItem = ({
85
86
  <div className="flex flex-col gap-1 justify-between text-sm">
86
87
  <div className="flex gap-2 items-center">
87
88
  <code>{name}</code>
88
- <span className="text-muted-foreground">
89
+ <Badge variant="muted">
89
90
  {schema.type === "array" && schema.items.type ? (
90
91
  <span>{schema.items.type}[]</span>
91
92
  ) : Array.isArray(schema.type) ? (
@@ -93,12 +94,8 @@ export const SchemaPropertyItem = ({
93
94
  ) : (
94
95
  <span>{schema.type}</span>
95
96
  )}
96
- </span>
97
- {group === "optional" && (
98
- <span className="py-px px-1.5 font-medium border rounded-lg">
99
- optional
100
- </span>
101
- )}
97
+ </Badge>
98
+ {group === "optional" && <Badge variant="outline">optional</Badge>}
102
99
  </div>
103
100
 
104
101
  {schema.description && (
@@ -5,24 +5,35 @@ export const generateSchemaExample = (
5
5
  name?: string,
6
6
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
7
  ): any => {
8
- // Directly return the example or default if they exist
8
+ // Check for schema-level example first
9
9
  if (schema.example !== undefined) {
10
10
  return schema.example;
11
- } else if (schema.examples) {
12
- return Object.values(schema.examples)[0];
13
- } else if (schema.default !== undefined) {
14
- return schema.default;
15
11
  }
16
12
 
17
- if (schema.properties || schema.type === "object") {
18
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
- const example: any = {};
13
+ // Then check for schema-level examples
14
+ if (
15
+ schema.examples &&
16
+ typeof schema.examples === "object" &&
17
+ "default" in schema.examples
18
+ ) {
19
+ const defaultExample = schema.examples.default;
20
+ if (defaultExample !== null) {
21
+ return typeof defaultExample === "object" && "value" in defaultExample
22
+ ? defaultExample.value
23
+ : defaultExample;
24
+ }
25
+ }
26
+
27
+ // For object schemas with properties
28
+ if (schema.type === "object" && schema.properties) {
29
+ const example: Record<string, any> = {};
20
30
 
21
- if (schema.properties) {
22
- for (const [key, propSchema] of Object.entries(schema.properties)) {
31
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
32
+ if (typeof propSchema === "object") {
23
33
  example[key] = generateSchemaExample(propSchema as SchemaObject, key);
24
34
  }
25
35
  }
36
+
26
37
  return example;
27
38
  }
28
39
 
@@ -31,7 +42,9 @@ export const generateSchemaExample = (
31
42
  return schema.items.map((itemSchema) =>
32
43
  generateSchemaExample(itemSchema as SchemaObject),
33
44
  );
34
- } else if (schema.items) {
45
+ }
46
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- OpenAPI schemas don't always adhere to spec
47
+ if (schema.items) {
35
48
  return [generateSchemaExample(schema.items as SchemaObject)];
36
49
  }
37
50
  return [];
@@ -51,6 +64,8 @@ export const generateSchemaExample = (
51
64
  return true;
52
65
  case "null":
53
66
  return null;
67
+ case "object":
68
+ return {};
54
69
  case undefined:
55
70
  default:
56
71
  return {};
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import { cn } from "../util/cn.js";
5
5
 
6
6
  const badgeVariants = cva(
7
- "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
7
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8
8
  {
9
9
  variants: {
10
10
  variant: {
@@ -12,6 +12,7 @@ const badgeVariants = cva(
12
12
  "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
13
13
  secondary:
14
14
  "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15
+ muted: "bg-muted text-muted-foreground ",
15
16
  destructive:
16
17
  "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
17
18
  outline: "text-foreground",
@@ -1,19 +1,36 @@
1
1
  import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
2
+ import { cva, type VariantProps } from "class-variance-authority";
2
3
  import { Check } from "lucide-react";
3
4
  import * as React from "react";
4
5
 
5
6
  import { cn } from "../util/cn.js";
6
7
 
8
+ const checkboxVariants = cva(
9
+ "peer h-4 w-4 shrink-0 rounded-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:text-primary",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default: "border border-primary data-[state=checked]:bg-primary",
14
+ outline: "border border-input data-[state=checked]:bg-accent",
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ variant: "default",
19
+ },
20
+ },
21
+ );
22
+
23
+ interface CheckboxProps
24
+ extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>,
25
+ VariantProps<typeof checkboxVariants> {}
26
+
7
27
  const Checkbox = React.forwardRef<
8
28
  React.ElementRef<typeof CheckboxPrimitive.Root>,
9
- React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
10
- >(({ className, ...props }, ref) => (
29
+ CheckboxProps
30
+ >(({ className, variant, ...props }, ref) => (
11
31
  <CheckboxPrimitive.Root
12
32
  ref={ref}
13
- className={cn(
14
- "peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
15
- className,
16
- )}
33
+ className={cn(checkboxVariants({ variant, className }))}
17
34
  {...props}
18
35
  >
19
36
  <CheckboxPrimitive.Indicator
@@ -25,4 +42,4 @@ const Checkbox = React.forwardRef<
25
42
  ));
26
43
  Checkbox.displayName = CheckboxPrimitive.Root.displayName;
27
44
 
28
- export { Checkbox };
45
+ export { Checkbox, type CheckboxProps };
@@ -1,13 +1,23 @@
1
1
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
2
  export type RecordAny = Record<string, any>;
3
3
 
4
- export const traverse = (
4
+ type JsonPrimitive = string | number | boolean | null;
5
+ type JsonArray = JsonValue[];
6
+ type JsonObject = { [key: string]: JsonValue };
7
+ type JsonValue = JsonPrimitive | JsonArray | JsonObject;
8
+
9
+ export const traverse = <T extends JsonValue = RecordAny>(
5
10
  specification: RecordAny,
6
- transform: (specification: RecordAny) => RecordAny,
11
+ transform: (specification: RecordAny) => T,
7
12
  ) => {
8
- const result: RecordAny = {};
13
+ const transformed = transform(specification);
14
+ if (typeof transformed !== "object" || transformed === null) {
15
+ return transformed;
16
+ }
17
+
18
+ const result: RecordAny = Array.isArray(transformed) ? [] : {};
9
19
 
10
- for (const [key, value] of Object.entries(specification)) {
20
+ for (const [key, value] of Object.entries(transformed)) {
11
21
  if (Array.isArray(value)) {
12
22
  result[key] = value.map((item) =>
13
23
  typeof item === "object" && item !== null
@@ -21,5 +31,5 @@ export const traverse = (
21
31
  }
22
32
  }
23
33
 
24
- return transform(result);
34
+ return result;
25
35
  };