zudoku 0.64.2 → 0.65.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 (279) hide show
  1. package/dist/app/main.d.ts +91 -1
  2. package/dist/app/main.js +5 -1
  3. package/dist/app/main.js.map +1 -1
  4. package/dist/config/validators/InputNavigationSchema.d.ts +16 -16
  5. package/dist/config/validators/NavigationSchema.js +2 -4
  6. package/dist/config/validators/NavigationSchema.js.map +1 -1
  7. package/dist/config/validators/validate.d.ts +53 -1
  8. package/dist/config/validators/validate.js +7 -0
  9. package/dist/config/validators/validate.js.map +1 -1
  10. package/dist/config/validators/validate.test.js +43 -0
  11. package/dist/config/validators/validate.test.js.map +1 -1
  12. package/dist/flat-config.d.ts +6 -0
  13. package/dist/lib/authentication/providers/auth0.js +6 -1
  14. package/dist/lib/authentication/providers/auth0.js.map +1 -1
  15. package/dist/lib/components/Autocomplete.d.ts +3 -1
  16. package/dist/lib/components/Autocomplete.js +6 -2
  17. package/dist/lib/components/Autocomplete.js.map +1 -1
  18. package/dist/lib/components/Layout.js +3 -2
  19. package/dist/lib/components/Layout.js.map +1 -1
  20. package/dist/lib/components/navigation/NavigationItem.js +2 -2
  21. package/dist/lib/components/navigation/NavigationItem.js.map +1 -1
  22. package/dist/lib/errors/ErrorAlert.js +1 -1
  23. package/dist/lib/errors/RouterError.d.ts +3 -1
  24. package/dist/lib/errors/RouterError.js +3 -2
  25. package/dist/lib/errors/RouterError.js.map +1 -1
  26. package/dist/lib/plugins/openapi/GeneratedExampleSidecarBox.js +1 -1
  27. package/dist/lib/plugins/openapi/GeneratedExampleSidecarBox.js.map +1 -1
  28. package/dist/lib/plugins/openapi/OperationList.js +2 -1
  29. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  30. package/dist/lib/plugins/openapi/OperationListItem.js +2 -1
  31. package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
  32. package/dist/lib/plugins/openapi/ParameterList.js +7 -4
  33. package/dist/lib/plugins/openapi/ParameterList.js.map +1 -1
  34. package/dist/lib/plugins/openapi/ParameterListItem.js +17 -6
  35. package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
  36. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js +4 -1
  37. package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
  38. package/dist/lib/plugins/openapi/ResponsesSidecarBox.d.ts +1 -2
  39. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js +15 -6
  40. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js.map +1 -1
  41. package/dist/lib/plugins/openapi/Sidecar.d.ts +1 -2
  42. package/dist/lib/plugins/openapi/Sidecar.js +39 -15
  43. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  44. package/dist/lib/plugins/openapi/SidecarBox.js +4 -4
  45. package/dist/lib/plugins/openapi/SidecarBox.js.map +1 -1
  46. package/dist/lib/plugins/openapi/SidecarExamples.js +15 -16
  47. package/dist/lib/plugins/openapi/SidecarExamples.js.map +1 -1
  48. package/dist/lib/plugins/openapi/components/ConstValue.js +1 -1
  49. package/dist/lib/plugins/openapi/components/ConstValue.js.map +1 -1
  50. package/dist/lib/plugins/openapi/components/EnumValues.js +1 -1
  51. package/dist/lib/plugins/openapi/components/EnumValues.js.map +1 -1
  52. package/dist/lib/plugins/openapi/components/ResponseContent.js +5 -6
  53. package/dist/lib/plugins/openapi/components/ResponseContent.js.map +1 -1
  54. package/dist/lib/plugins/openapi/interfaces.d.ts +13 -0
  55. package/dist/lib/plugins/openapi/playground/BodyPanel.js +67 -15
  56. package/dist/lib/plugins/openapi/playground/BodyPanel.js.map +1 -1
  57. package/dist/lib/plugins/openapi/playground/CollapsibleHeader.js +2 -2
  58. package/dist/lib/plugins/openapi/playground/CollapsibleHeader.js.map +1 -1
  59. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.js +1 -1
  60. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.js.map +1 -1
  61. package/dist/lib/plugins/openapi/playground/Headers.js +23 -83
  62. package/dist/lib/plugins/openapi/playground/Headers.js.map +1 -1
  63. package/dist/lib/plugins/openapi/playground/ParamsGrid.d.ts +8 -0
  64. package/dist/lib/plugins/openapi/playground/ParamsGrid.js +8 -1
  65. package/dist/lib/plugins/openapi/playground/ParamsGrid.js.map +1 -1
  66. package/dist/lib/plugins/openapi/playground/PathParams.js +2 -3
  67. package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
  68. package/dist/lib/plugins/openapi/playground/Playground.d.ts +7 -0
  69. package/dist/lib/plugins/openapi/playground/Playground.js +56 -28
  70. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  71. package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js +3 -2
  72. package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js.map +1 -1
  73. package/dist/lib/plugins/openapi/playground/QueryParams.js +16 -40
  74. package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
  75. package/dist/lib/plugins/openapi/playground/request-panel/MultipartField.d.ts +8 -0
  76. package/dist/lib/plugins/openapi/playground/request-panel/MultipartField.js +19 -0
  77. package/dist/lib/plugins/openapi/playground/request-panel/MultipartField.js.map +1 -0
  78. package/dist/lib/plugins/openapi/playground/request-panel/UrlQueryParams.js +1 -1
  79. package/dist/lib/plugins/openapi/playground/request-panel/UrlQueryParams.js.map +1 -1
  80. package/dist/lib/plugins/openapi/playground/request-panel/fieldManager/useKeyValueFieldManager.test.d.ts +1 -0
  81. package/dist/lib/plugins/openapi/playground/request-panel/fieldManager/useKeyValueFieldManager.test.js +540 -0
  82. package/dist/lib/plugins/openapi/playground/request-panel/fieldManager/useKeyValueFieldManager.test.js.map +1 -0
  83. package/dist/lib/plugins/openapi/playground/request-panel/useKeyValueFieldManager.d.ts +40 -0
  84. package/dist/lib/plugins/openapi/playground/request-panel/useKeyValueFieldManager.js +205 -0
  85. package/dist/lib/plugins/openapi/playground/request-panel/useKeyValueFieldManager.js.map +1 -0
  86. package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js +2 -2
  87. package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js.map +1 -1
  88. package/dist/lib/plugins/openapi/schema/SchemaExampleAndDefault.js +1 -1
  89. package/dist/lib/plugins/openapi/schema/SchemaExampleAndDefault.js.map +1 -1
  90. package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js +17 -7
  91. package/dist/lib/plugins/openapi/schema/SchemaPropertyItem.js.map +1 -1
  92. package/dist/lib/plugins/openapi/schema/SchemaView.d.ts +1 -1
  93. package/dist/lib/plugins/openapi/schema/SchemaView.js +20 -9
  94. package/dist/lib/plugins/openapi/schema/SchemaView.js.map +1 -1
  95. package/dist/lib/plugins/openapi/schema/UnionView.js +2 -5
  96. package/dist/lib/plugins/openapi/schema/UnionView.js.map +1 -1
  97. package/dist/lib/ui/Badge.d.ts +3 -3
  98. package/dist/lib/ui/Badge.js +9 -7
  99. package/dist/lib/ui/Badge.js.map +1 -1
  100. package/dist/lib/ui/Button.d.ts +1 -1
  101. package/dist/lib/ui/Button.js +1 -0
  102. package/dist/lib/ui/Button.js.map +1 -1
  103. package/dist/lib/ui/Checkbox.d.ts +2 -2
  104. package/dist/lib/ui/Checkbox.js +4 -4
  105. package/dist/lib/ui/Checkbox.js.map +1 -1
  106. package/dist/lib/ui/CodeBlock.js +1 -1
  107. package/dist/lib/ui/CodeBlock.js.map +1 -1
  108. package/dist/lib/ui/Collapsible.d.ts +4 -4
  109. package/dist/lib/ui/Collapsible.js +11 -4
  110. package/dist/lib/ui/Collapsible.js.map +1 -1
  111. package/dist/lib/ui/EmbeddedCodeBlock.js +3 -2
  112. package/dist/lib/ui/EmbeddedCodeBlock.js.map +1 -1
  113. package/dist/lib/ui/Frame.d.ts +8 -0
  114. package/dist/lib/ui/Frame.js +22 -0
  115. package/dist/lib/ui/Frame.js.map +1 -0
  116. package/dist/lib/ui/Item.d.ts +23 -0
  117. package/dist/lib/ui/Item.js +67 -0
  118. package/dist/lib/ui/Item.js.map +1 -0
  119. package/dist/lib/ui/NativeSelect.d.ts +5 -0
  120. package/dist/lib/ui/NativeSelect.js +14 -0
  121. package/dist/lib/ui/NativeSelect.js.map +1 -0
  122. package/dist/lib/ui/Select.d.ts +13 -11
  123. package/dist/lib/ui/Select.js +34 -23
  124. package/dist/lib/ui/Select.js.map +1 -1
  125. package/dist/lib/util/readFrontmatter.d.ts +6 -0
  126. package/dist/lib/util/readFrontmatter.js +12 -0
  127. package/dist/lib/util/readFrontmatter.js.map +1 -0
  128. package/dist/vite/mdx/remark-last-modified.js +57 -3
  129. package/dist/vite/mdx/remark-last-modified.js.map +1 -1
  130. package/dist/vite/plugin-api.js +2 -2
  131. package/dist/vite/plugin-api.js.map +1 -1
  132. package/dist/vite/plugin-frontmatter.js +3 -5
  133. package/dist/vite/plugin-frontmatter.js.map +1 -1
  134. package/dist/vite/plugin-markdown-export.js +3 -4
  135. package/dist/vite/plugin-markdown-export.js.map +1 -1
  136. package/lib/{Button-DmS4u8Lj.js → Button-B3ucvvQw.js} +7 -6
  137. package/lib/Button-B3ucvvQw.js.map +1 -0
  138. package/lib/{ErrorAlert--3alJ_-b.js → ErrorAlert-D5LKLFOd.js} +1100 -1112
  139. package/lib/ErrorAlert-D5LKLFOd.js.map +1 -0
  140. package/lib/{MdxPage-Bpa9tL63.js → MdxPage-hOCN-u-L.js} +6 -6
  141. package/lib/{MdxPage-Bpa9tL63.js.map → MdxPage-hOCN-u-L.js.map} +1 -1
  142. package/lib/{OAuthErrorPage-B79J86Fo.js → OAuthErrorPage-oXnxcJg4.js} +4 -4
  143. package/lib/{OAuthErrorPage-B79J86Fo.js.map → OAuthErrorPage-oXnxcJg4.js.map} +1 -1
  144. package/lib/{OasProvider-jr0oDSFy.js → OasProvider-BuBeRIHB.js} +2 -2
  145. package/lib/{OasProvider-jr0oDSFy.js.map → OasProvider-BuBeRIHB.js.map} +1 -1
  146. package/lib/{OperationList-DLEAg4qw.js → OperationList-Cx8TGKhB.js} +2053 -1830
  147. package/lib/OperationList-Cx8TGKhB.js.map +1 -0
  148. package/lib/{Pagination-H2HW9-Er.js → Pagination-lLSoHnxa.js} +2 -2
  149. package/lib/{Pagination-H2HW9-Er.js.map → Pagination-lLSoHnxa.js.map} +1 -1
  150. package/lib/{RouteGuard-CjzxosTf.js → RouteGuard-Brz95MSt.js} +2 -2
  151. package/lib/{RouteGuard-CjzxosTf.js.map → RouteGuard-Brz95MSt.js.map} +1 -1
  152. package/lib/RouterError-VGZB_wg4.js +42 -0
  153. package/lib/RouterError-VGZB_wg4.js.map +1 -0
  154. package/lib/{SchemaList-CSDSazqV.js → SchemaList-rBWXYJEb.js} +7 -7
  155. package/lib/{SchemaList-CSDSazqV.js.map → SchemaList-rBWXYJEb.js.map} +1 -1
  156. package/lib/SchemaView-jouS_xvc.js +586 -0
  157. package/lib/SchemaView-jouS_xvc.js.map +1 -0
  158. package/lib/Select-DFRCS31-.js +399 -0
  159. package/lib/Select-DFRCS31-.js.map +1 -0
  160. package/lib/{SignUp-Fycafbyg.js → SignUp-D2mmQOkg.js} +2 -2
  161. package/lib/{SignUp-Fycafbyg.js.map → SignUp-D2mmQOkg.js.map} +1 -1
  162. package/lib/{Toc-ChkOg2UU.js → Toc-CBWfFCVf.js} +2 -2
  163. package/lib/{Toc-ChkOg2UU.js.map → Toc-CBWfFCVf.js.map} +1 -1
  164. package/lib/{circular-DGfd8SGc.js → circular-CGkbVs2O.js} +6360 -5953
  165. package/lib/circular-CGkbVs2O.js.map +1 -0
  166. package/lib/{createServer-DGD8hEzT.js → createServer-CcV_75PW.js} +770 -735
  167. package/lib/createServer-CcV_75PW.js.map +1 -0
  168. package/lib/{errors-BTpjwHS6.js → errors-D7xzOd8X.js} +2 -2
  169. package/lib/{errors-BTpjwHS6.js.map → errors-D7xzOd8X.js.map} +1 -1
  170. package/lib/{index-Bvas0H4x.js → index-CF7_erXq.js} +2 -2
  171. package/lib/{index-Bvas0H4x.js.map → index-CF7_erXq.js.map} +1 -1
  172. package/lib/{index-FNRZUtwo.js → index-CPws05Tb.js} +3 -3
  173. package/lib/{index-FNRZUtwo.js.map → index-CPws05Tb.js.map} +1 -1
  174. package/lib/index-I4zC7Yht.js +3680 -0
  175. package/lib/index-I4zC7Yht.js.map +1 -0
  176. package/lib/ui/ActionButton.js +1 -1
  177. package/lib/ui/Badge.js +27 -13
  178. package/lib/ui/Badge.js.map +1 -1
  179. package/lib/ui/Button.js +6 -5
  180. package/lib/ui/Button.js.map +1 -1
  181. package/lib/ui/Checkbox.js +29 -26
  182. package/lib/ui/Checkbox.js.map +1 -1
  183. package/lib/ui/CodeBlock.js +7 -7
  184. package/lib/ui/CodeBlock.js.map +1 -1
  185. package/lib/ui/Collapsible.js +32 -5
  186. package/lib/ui/Collapsible.js.map +1 -1
  187. package/lib/ui/EmbeddedCodeBlock.js +19 -18
  188. package/lib/ui/EmbeddedCodeBlock.js.map +1 -1
  189. package/lib/ui/Frame.js +81 -0
  190. package/lib/ui/Frame.js.map +1 -0
  191. package/lib/ui/Item.js +188 -0
  192. package/lib/ui/Item.js.map +1 -0
  193. package/lib/ui/NativeSelect.js +57 -0
  194. package/lib/ui/NativeSelect.js.map +1 -0
  195. package/lib/ui/Select.js +166 -116
  196. package/lib/ui/Select.js.map +1 -1
  197. package/lib/ui/Tabs.js +10 -10
  198. package/lib/zudoku.__internal.js +345 -345
  199. package/lib/zudoku.__internal.js.map +1 -1
  200. package/lib/zudoku.auth-auth0.js +7 -7
  201. package/lib/zudoku.auth-auth0.js.map +1 -1
  202. package/lib/zudoku.auth-azureb2c.js +3 -3
  203. package/lib/zudoku.auth-clerk.js +1 -1
  204. package/lib/zudoku.auth-openid.js +3 -3
  205. package/lib/zudoku.auth-supabase.js +3 -3
  206. package/lib/zudoku.components.js +2 -2
  207. package/lib/zudoku.plugin-api-catalog.js +3 -3
  208. package/lib/zudoku.plugin-api-keys.js +4 -4
  209. package/lib/zudoku.plugin-markdown.js +1 -1
  210. package/lib/zudoku.plugin-openapi.js +1 -1
  211. package/lib/zudoku.plugin-search-pagefind.js +2 -2
  212. package/package.json +4 -4
  213. package/src/app/main.tsx +5 -1
  214. package/src/lib/authentication/providers/auth0.tsx +6 -1
  215. package/src/lib/components/Autocomplete.tsx +11 -2
  216. package/src/lib/components/Layout.tsx +3 -2
  217. package/src/lib/components/navigation/NavigationItem.tsx +7 -20
  218. package/src/lib/errors/ErrorAlert.tsx +1 -1
  219. package/src/lib/errors/RouterError.tsx +7 -2
  220. package/src/lib/plugins/openapi/GeneratedExampleSidecarBox.tsx +2 -2
  221. package/src/lib/plugins/openapi/OperationList.tsx +3 -1
  222. package/src/lib/plugins/openapi/OperationListItem.tsx +7 -7
  223. package/src/lib/plugins/openapi/ParameterList.tsx +37 -23
  224. package/src/lib/plugins/openapi/ParameterListItem.tsx +105 -54
  225. package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +36 -13
  226. package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +67 -44
  227. package/src/lib/plugins/openapi/Sidecar.tsx +84 -41
  228. package/src/lib/plugins/openapi/SidecarBox.tsx +26 -4
  229. package/src/lib/plugins/openapi/SidecarExamples.tsx +59 -37
  230. package/src/lib/plugins/openapi/components/ConstValue.tsx +1 -1
  231. package/src/lib/plugins/openapi/components/EnumValues.tsx +2 -2
  232. package/src/lib/plugins/openapi/components/ResponseContent.tsx +63 -53
  233. package/src/lib/plugins/openapi/interfaces.ts +12 -0
  234. package/src/lib/plugins/openapi/playground/BodyPanel.tsx +246 -30
  235. package/src/lib/plugins/openapi/playground/CollapsibleHeader.tsx +10 -6
  236. package/src/lib/plugins/openapi/playground/ExamplesDropdown.tsx +3 -2
  237. package/src/lib/plugins/openapi/playground/Headers.tsx +103 -219
  238. package/src/lib/plugins/openapi/playground/ParamsGrid.tsx +33 -1
  239. package/src/lib/plugins/openapi/playground/PathParams.tsx +26 -34
  240. package/src/lib/plugins/openapi/playground/Playground.tsx +73 -35
  241. package/src/lib/plugins/openapi/playground/PlaygroundDialog.tsx +9 -30
  242. package/src/lib/plugins/openapi/playground/QueryParams.tsx +82 -136
  243. package/src/lib/plugins/openapi/playground/request-panel/MultipartField.tsx +91 -0
  244. package/src/lib/plugins/openapi/playground/request-panel/UrlQueryParams.tsx +1 -1
  245. package/src/lib/plugins/openapi/playground/request-panel/fieldManager/useKeyValueFieldManager.test.tsx +872 -0
  246. package/src/lib/plugins/openapi/playground/request-panel/useKeyValueFieldManager.ts +349 -0
  247. package/src/lib/plugins/openapi/playground/result-panel/ResponseTab.tsx +2 -6
  248. package/src/lib/plugins/openapi/schema/SchemaExampleAndDefault.tsx +1 -1
  249. package/src/lib/plugins/openapi/schema/SchemaPropertyItem.tsx +89 -52
  250. package/src/lib/plugins/openapi/schema/SchemaView.tsx +82 -48
  251. package/src/lib/plugins/openapi/schema/UnionView.tsx +6 -17
  252. package/src/lib/ui/Badge.tsx +21 -12
  253. package/src/lib/ui/Button.tsx +1 -0
  254. package/src/lib/ui/Checkbox.tsx +23 -24
  255. package/src/lib/ui/CodeBlock.tsx +3 -3
  256. package/src/lib/ui/Collapsible.tsx +26 -4
  257. package/src/lib/ui/EmbeddedCodeBlock.tsx +21 -18
  258. package/src/lib/ui/Frame.tsx +81 -0
  259. package/src/lib/ui/Item.tsx +192 -0
  260. package/src/lib/ui/NativeSelect.tsx +47 -0
  261. package/src/lib/ui/Select.tsx +153 -126
  262. package/src/lib/util/readFrontmatter.ts +13 -0
  263. package/dist/lib/plugins/openapi/playground/InlineInput.d.ts +0 -4
  264. package/dist/lib/plugins/openapi/playground/InlineInput.js +0 -3
  265. package/dist/lib/plugins/openapi/playground/InlineInput.js.map +0 -1
  266. package/lib/Button-DmS4u8Lj.js.map +0 -1
  267. package/lib/ErrorAlert--3alJ_-b.js.map +0 -1
  268. package/lib/OperationList-DLEAg4qw.js.map +0 -1
  269. package/lib/RouterError-DZS2d6Sc.js +0 -41
  270. package/lib/RouterError-DZS2d6Sc.js.map +0 -1
  271. package/lib/SchemaView-DJiBd0_5.js +0 -397
  272. package/lib/SchemaView-DJiBd0_5.js.map +0 -1
  273. package/lib/Select-C1DeCqKv.js +0 -372
  274. package/lib/Select-C1DeCqKv.js.map +0 -1
  275. package/lib/circular-DGfd8SGc.js.map +0 -1
  276. package/lib/createServer-DGD8hEzT.js.map +0 -1
  277. package/lib/index-DP1xZgfJ.js +0 -3364
  278. package/lib/index-DP1xZgfJ.js.map +0 -1
  279. package/src/lib/plugins/openapi/playground/InlineInput.tsx +0 -6
@@ -1,4 +1,4 @@
1
- import { ChevronUpIcon } from "lucide-react";
1
+ import { ChevronsDownUpIcon, ChevronsUpDownIcon } from "lucide-react";
2
2
  import { CollapsibleTrigger } from "zudoku/ui/Collapsible.js";
3
3
  import { cn } from "../../../util/cn.js";
4
4
 
@@ -12,20 +12,24 @@ export const CollapsibleHeaderTrigger = ({
12
12
  return (
13
13
  <div
14
14
  className={cn(
15
- "grid grid-cols-[max-content_1fr_min-content_max-content] items-center gap-2 group bg-muted w-full h-10 ps-4 pe-2 border-b",
15
+ "grid grid-cols-[max-content_1fr_max-content] items-center gap-2 group bg-muted w-full h-10 ps-4 pe-2 border-b",
16
16
  className,
17
17
  )}
18
18
  >
19
19
  {children}
20
20
  <CollapsibleTrigger
21
21
  className={cn(
22
- "flex items-center gap-4 group bg-muted w-full p-2 hover:bg-accent hover:brightness-95 rounded-md",
22
+ "flex items-center gap-4 group bg-muted w-full p-2 hover:bg-accent hover:brightness-95 opacity-75 rounded-md",
23
23
  className,
24
24
  )}
25
25
  >
26
- <ChevronUpIcon
27
- className="group-data-[state=open]:rotate-180 transition-transform shrink-0"
28
- size={16}
26
+ <ChevronsDownUpIcon
27
+ className="group-data-[state=closed]:hidden shrink-0"
28
+ size={14}
29
+ />
30
+ <ChevronsUpDownIcon
31
+ className="group-data-[state=open]:hidden shrink-0"
32
+ size={14}
29
33
  />
30
34
  </CollapsibleTrigger>
31
35
  </div>
@@ -24,9 +24,10 @@ const ExamplesDropdown = ({
24
24
  <Button
25
25
  variant="ghost"
26
26
  size="sm"
27
- className="hover:bg-accent hover:brightness-95"
27
+ className="hover:bg-accent hover:brightness-95 gap-2"
28
28
  >
29
- Use Example <PlusCircleIcon size={16} className="ml-2" />
29
+ Use Example
30
+ <PlusCircleIcon size={14} />
30
31
  </Button>
31
32
  </DropdownMenuTrigger>
32
33
  <DropdownMenuContent className="max-w-72">
@@ -1,57 +1,28 @@
1
- import {
2
- CircleAlertIcon,
3
- LockIcon,
4
- PlusCircleIcon,
5
- TableOfContentsIcon,
6
- XIcon,
7
- } from "lucide-react";
8
- import { useCallback, useEffect, useRef } from "react";
9
- import {
10
- type Control,
11
- Controller,
12
- useFieldArray,
13
- useFormContext,
14
- } from "react-hook-form";
1
+ import { CircleAlertIcon, LockIcon, TableOfContentsIcon } from "lucide-react";
2
+ import { type Control, useFormContext } from "react-hook-form";
15
3
  import { Checkbox } from "zudoku/ui/Checkbox.js";
16
4
  import { Collapsible, CollapsibleContent } from "zudoku/ui/Collapsible.js";
17
5
  import { Tooltip, TooltipContent, TooltipTrigger } from "zudoku/ui/Tooltip.js";
18
6
  import { Autocomplete } from "../../../components/Autocomplete.js";
19
- import { Button } from "../../../ui/Button.js";
20
- import { Input } from "../../../ui/Input.js";
21
7
  import { cn } from "../../../util/cn.js";
22
8
  import {
23
9
  CollapsibleHeader,
24
10
  CollapsibleHeaderTrigger,
25
11
  } from "./CollapsibleHeader.js";
26
- import ParamsGrid, { ParamsGridItem } from "./ParamsGrid.js";
12
+ import ParamsGrid, {
13
+ ParamsGridInput,
14
+ ParamsGridItem,
15
+ ParamsGridRemoveButton,
16
+ } from "./ParamsGrid.js";
27
17
  import type { Header, PlaygroundForm } from "./Playground.js";
18
+ import { useKeyValueFieldManager } from "./request-panel/useKeyValueFieldManager.js";
28
19
 
20
+ // biome-ignore format: Easier to read
29
21
  const headerOptions = Object.freeze([
30
- "Accept",
31
- "Accept-Encoding",
32
- "Accept-Language",
33
- "Authorization",
34
- "Cache-Control",
35
- "Connection",
36
- "Content-Disposition",
37
- "Content-Encoding",
38
- "Content-Language",
39
- "Content-Length",
40
- "Content-Range",
41
- "Content-Security-Policy",
42
- "Content-Type",
43
- "Cookie",
44
- "Date",
45
- "ETag",
46
- "Expires",
47
- "Host",
48
- "If-Modified-Since",
49
- "Location",
50
- "Origin",
51
- "Pragma",
52
- "Referer",
53
- "Set-Cookie",
54
- "User-Agent",
22
+ "Accept", "Accept-Encoding", "Accept-Language", "Authorization", "Cache-Control", "Connection",
23
+ "Content-Disposition", "Content-Encoding", "Content-Language", "Content-Length", "Content-Range",
24
+ "Content-Security-Policy", "Content-Type", "Cookie", "Date", "ETag", "Expires", "Host",
25
+ "If-Modified-Since", "Location", "Origin", "Pragma", "Referer", "Set-Cookie", "User-Agent",
55
26
  "X-Requested-With",
56
27
  ]);
57
28
 
@@ -64,43 +35,20 @@ export const Headers = ({
64
35
  schemaHeaders: Header[];
65
36
  lockedHeaders?: string[];
66
37
  }) => {
67
- const { fields, append, remove } = useFieldArray<PlaygroundForm, "headers">({
38
+ const { watch, formState } = useFormContext<PlaygroundForm>();
39
+ const watchedHeaders = watch("headers");
40
+
41
+ const manager = useKeyValueFieldManager<PlaygroundForm, "headers">({
68
42
  control,
69
43
  name: "headers",
44
+ defaultValue: { name: "", value: "", active: false },
70
45
  });
71
- const { setValue, watch, formState } = useFormContext<PlaygroundForm>();
72
- const valueRefs = useRef<Array<HTMLInputElement | null>>([]);
73
- const nameRefs = useRef<Array<HTMLInputElement | null>>([]);
74
- const watchedHeaders = watch("headers");
75
-
76
- const addNewHeader = useCallback(
77
- (e?: React.MouseEvent<HTMLButtonElement>) => {
78
- e?.stopPropagation();
79
- append({ name: "", value: "", active: false }, { shouldFocus: true });
80
- },
81
- [append],
82
- );
83
-
84
- useEffect(() => {
85
- if (watchedHeaders.length === 0) {
86
- addNewHeader();
87
- }
88
- }, [watchedHeaders, addNewHeader]);
89
-
90
- const handleHeaderEnter = (index: number) => {
91
- valueRefs.current[index]?.focus();
92
- };
93
-
94
- const handleValueEnter = (index: number) => {
95
- addNewHeader();
96
- requestAnimationFrame(() => nameRefs.current[index + 1]?.focus());
97
- };
98
46
 
99
47
  const missingHeaders = schemaHeaders
100
48
  .filter((h) => !watchedHeaders.some((f) => f.name === h.name))
101
49
  .map(({ name }) => name);
102
50
 
103
- const hiddenHeadersIndex = fields.flatMap((f, index) => {
51
+ const hiddenHeadersIndex = manager.fields.flatMap((f, index) => {
104
52
  const keep = !lockedHeaders
105
53
  ?.map((h) => h.toLowerCase())
106
54
  .includes(f.name.toLowerCase());
@@ -120,176 +68,112 @@ export const Headers = ({
120
68
  return (
121
69
  <Collapsible defaultOpen>
122
70
  <CollapsibleHeaderTrigger>
123
- <TableOfContentsIcon size={16} />
71
+ <TableOfContentsIcon size={14} />
124
72
  <CollapsibleHeader>Headers</CollapsibleHeader>
125
- <Button
126
- onClick={addNewHeader}
127
- type="button"
128
- size="sm"
129
- variant="ghost"
130
- className="hover:bg-accent hover:brightness-95 flex gap-2"
131
- >
132
- Add header <PlusCircleIcon size={16} />
133
- </Button>
134
73
  </CollapsibleHeaderTrigger>
135
74
  <CollapsibleContent className="CollapsibleContent">
136
75
  <div className="flex flex-col gap-2">
137
76
  <div className="overflow-hidden">
138
77
  <ParamsGrid>
139
- {lockedHeaderFields.map((field) => {
140
- return (
141
- <Tooltip key={field.id}>
142
- <TooltipTrigger asChild>
143
- <ParamsGridItem
144
- key={field.id}
145
- className="opacity-50 cursor-not-allowed font-mono text-xs min-h-10"
146
- >
147
- <LockIcon size={16} />
148
- <Input
149
- value={field.name}
150
- disabled
151
- className="w-full border-0 p-0 m-0 shadow-none text-xs focus-visible:ring-0 font-mono"
152
- />
153
- <div>{field.value}</div>
154
- </ParamsGridItem>
155
- </TooltipTrigger>
156
- <TooltipContent
157
- alignOffset={10}
158
- side="bottom"
159
- align="start"
78
+ {lockedHeaderFields.map((field) => (
79
+ <Tooltip key={field.id}>
80
+ <TooltipTrigger asChild>
81
+ <ParamsGridItem
82
+ key={field.id}
83
+ className="opacity-50 cursor-not-allowed font-mono text-xs min-h-10"
160
84
  >
161
- <p>This header is set by the selected authentication.</p>
162
- </TooltipContent>
163
- </Tooltip>
164
- );
165
- })}
166
- {fields.map((field, i) => {
85
+ <LockIcon size={16} />
86
+ <ParamsGridInput value={field.name} disabled />
87
+ <div>{field.value}</div>
88
+ </ParamsGridItem>
89
+ </TooltipTrigger>
90
+ <TooltipContent alignOffset={10} side="bottom" align="start">
91
+ <p>This header is set by the selected authentication.</p>
92
+ </TooltipContent>
93
+ </Tooltip>
94
+ ))}
95
+ {manager.fields.map((field, i) => {
167
96
  const currentSchemaHeader = schemaHeaders.find(
168
97
  (h) => h.name === watchedHeaders.at(i)?.name,
169
98
  );
99
+ const hasEnum =
100
+ currentSchemaHeader?.enum &&
101
+ currentSchemaHeader.enum.length > 0;
102
+ const isHidden = hiddenHeadersIndex.includes(i);
103
+ const nameInputProps = manager.getNameInputProps(i);
104
+ const valueInputProps = manager.getValueInputProps(i);
105
+
170
106
  return (
171
107
  <ParamsGridItem
172
108
  key={field.id}
173
109
  className={cn(
174
- hiddenHeadersIndex.includes(i) && "text-amber-600",
175
- hiddenHeadersIndex.includes(i) &&
110
+ isHidden && "text-amber-600",
111
+ isHidden &&
176
112
  !formState.dirtyFields.headers?.[i]?.value &&
177
113
  "hidden",
178
114
  )}
179
115
  >
180
- <Controller
181
- control={control}
182
- name={`headers.${i}.active`}
183
- render={({ field }) => (
184
- <>
185
- <Checkbox
186
- id={`headers.${i}.active`}
187
- className={cn(
188
- hiddenHeadersIndex.includes(i) && "hidden",
189
- )}
190
- checked={field.value}
191
- onCheckedChange={(checked) => {
192
- field.onChange(checked);
193
- }}
194
- />
195
- <Tooltip>
196
- <TooltipTrigger asChild>
197
- <CircleAlertIcon
198
- className={cn(
199
- "text-amber-600",
200
- !hiddenHeadersIndex.includes(i) && "hidden",
201
- )}
202
- size={16}
203
- />
204
- </TooltipTrigger>
205
- <TooltipContent
206
- alignOffset={10}
207
- side="bottom"
208
- align="start"
209
- >
210
- <p>
211
- This header will be overwritten by the selected
212
- authentication.
213
- </p>
214
- </TooltipContent>
215
- </Tooltip>
216
- </>
217
- )}
116
+ <Checkbox
117
+ className={cn(isHidden && "hidden")}
118
+ {...manager.getCheckboxProps(i)}
218
119
  />
219
- <Controller
220
- control={control}
221
- name={`headers.${i}.name`}
222
- render={({ field }) => (
223
- <Autocomplete
224
- {...field}
225
- placeholder="Name"
226
- className="border-0 p-0 m-0 shadow-none focus-visible:ring-0 bg-transparent hover:bg-transparent text-xs font-mono"
227
- options={[...missingHeaders, ...headerOptions]}
228
- onEnterPress={() => handleHeaderEnter(i)}
229
- onChange={(e) => {
230
- field.onChange(e);
231
- setValue(`headers.${i}.active`, true);
232
- }}
233
- ref={(el) => {
234
- nameRefs.current[i] = el;
235
- }}
120
+ <Tooltip>
121
+ <TooltipTrigger asChild>
122
+ <CircleAlertIcon
123
+ className={cn(
124
+ "text-amber-600",
125
+ !isHidden && "hidden",
126
+ )}
127
+ size={16}
236
128
  />
237
- )}
238
- />
129
+ </TooltipTrigger>
130
+ <TooltipContent
131
+ alignOffset={10}
132
+ side="bottom"
133
+ align="start"
134
+ >
135
+ <p>
136
+ This header will be overwritten by the selected
137
+ authentication.
138
+ </p>
139
+ </TooltipContent>
140
+ </Tooltip>
141
+ <ParamsGridInput asChild>
142
+ <Autocomplete
143
+ {...nameInputProps}
144
+ value={String(manager.getValue(i, "name"))}
145
+ placeholder="Name"
146
+ options={[...missingHeaders, ...headerOptions]}
147
+ onChange={(v) => manager.setValue(i, "name", v)}
148
+ onSelect={(v) =>
149
+ manager.setValue(i, "name", v, { focus: "next" })
150
+ }
151
+ />
152
+ </ParamsGridInput>
239
153
  <div className="flex items-center gap-2">
240
- <Controller
241
- control={control}
242
- name={`headers.${i}.value`}
243
- render={({ field }) => {
244
- const hasEnum =
245
- currentSchemaHeader?.enum &&
246
- currentSchemaHeader.enum.length > 0;
247
-
248
- if (!hasEnum) {
249
- return (
250
- <Input
251
- placeholder="Value"
252
- className="w-full truncate border-0 p-0 m-0 shadow-none text-xs focus-visible:ring-0 font-mono"
253
- autoComplete="off"
254
- {...field}
255
- ref={(el) => {
256
- valueRefs.current[i] = el;
257
- }}
258
- onKeyDown={(e) => {
259
- if (
260
- e.key === "Enter" &&
261
- e.currentTarget.value.trim()
262
- ) {
263
- handleValueEnter(i);
264
- }
265
- }}
266
- />
267
- );
268
- }
269
-
270
- return (
271
- <Autocomplete
272
- shouldFilter={false}
273
- value={field.value}
274
- options={currentSchemaHeader.enum ?? []}
275
- onChange={(e) => {
276
- field.onChange(e);
277
- setValue(`headers.${i}.active`, true);
278
- }}
279
- className="border-0 p-0 m-0 shadow-none focus-visible:ring-0 bg-transparent hover:bg-transparent text-xs font-mono"
280
- />
281
- );
282
- }}
154
+ {!hasEnum ? (
155
+ <ParamsGridInput
156
+ placeholder="Value"
157
+ autoComplete="off"
158
+ {...valueInputProps}
159
+ />
160
+ ) : (
161
+ <ParamsGridInput asChild>
162
+ <Autocomplete
163
+ {...valueInputProps}
164
+ value={String(manager.getValue(i, "value"))}
165
+ shouldFilter={false}
166
+ options={currentSchemaHeader.enum ?? []}
167
+ onChange={(v) => manager.setValue(i, "value", v)}
168
+ onSelect={(v) =>
169
+ manager.setValue(i, "value", v, { focus: "next" })
170
+ }
171
+ />
172
+ </ParamsGridInput>
173
+ )}
174
+ <ParamsGridRemoveButton
175
+ {...manager.getRemoveButtonProps(i)}
283
176
  />
284
- <Button
285
- size="icon-xs"
286
- variant="ghost"
287
- className="text-muted-foreground opacity-0 group-hover:brightness-95 group-hover:opacity-100"
288
- onClick={() => remove(i)}
289
- type="button"
290
- >
291
- <XIcon size={16} />
292
- </Button>
293
177
  </div>
294
178
  </ParamsGridItem>
295
179
  );
@@ -1,8 +1,12 @@
1
+ import { XIcon } from "lucide-react";
2
+ import { Button } from "zudoku/components";
3
+ import { Input } from "zudoku/ui/Input.js";
4
+ import { cn } from "../../../util/cn.js";
1
5
  import createVariantComponent from "../../../util/createVariantComponent.js";
2
6
 
3
7
  const ParamsGrid = createVariantComponent(
4
8
  "div",
5
- "grid grid-cols-[min-content_2fr_3fr] items-center gap-x-5",
9
+ "grid grid-cols-[min-content_2fr_3fr] items-center gap-x-5 [&>*:last-child_[data-slot=remove-button]]:invisible",
6
10
  );
7
11
 
8
12
  export const ParamsGridItem = createVariantComponent(
@@ -10,4 +14,32 @@ export const ParamsGridItem = createVariantComponent(
10
14
  "group h-9 hover:bg-accent/75 ps-4 pe-2 grid col-span-full grid-cols-subgrid items-center border-b",
11
15
  );
12
16
 
17
+ export const ParamsGridInput = createVariantComponent(
18
+ Input,
19
+ "w-full truncate border-0 p-0 m-0 shadow-none text-xs focus-visible:ring-0 font-mono",
20
+ );
21
+
22
+ export const ParamsGridRemoveButton = ({
23
+ onClick,
24
+ className,
25
+ }: {
26
+ onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
27
+ className?: string;
28
+ }) => (
29
+ <Button
30
+ size="icon-xs"
31
+ variant="ghost"
32
+ className={cn(
33
+ "text-muted-foreground opacity-0 group-hover:brightness-95 focus-visible:opacity-100 group-hover:opacity-100",
34
+ className,
35
+ )}
36
+ onClick={onClick}
37
+ type="button"
38
+ // In the last row the remove button will be hidden by the ParamsGridItem selector
39
+ data-slot="remove-button"
40
+ >
41
+ <XIcon size={14} />
42
+ </Button>
43
+ );
44
+
13
45
  export default ParamsGrid;
@@ -1,7 +1,6 @@
1
1
  import { type Control, Controller, useFieldArray } from "react-hook-form";
2
- import { Input } from "../../../ui/Input.js";
3
2
  import { ColorizedParam } from "../ColorizedParam.js";
4
- import ParamsGrid, { ParamsGridItem } from "./ParamsGrid.js";
3
+ import ParamsGrid, { ParamsGridInput, ParamsGridItem } from "./ParamsGrid.js";
5
4
  import type { PlaygroundForm } from "./Playground.js";
6
5
 
7
6
  export const PathParams = ({
@@ -21,41 +20,34 @@ export const PathParams = ({
21
20
  );
22
21
 
23
22
  return (
24
- <div className="overflow-hidden">
25
- <ParamsGrid>
26
- {sortedFields.map((field, i) => (
27
- <ParamsGridItem key={field.id}>
23
+ <ParamsGrid>
24
+ {sortedFields.map((field, i) => (
25
+ <ParamsGridItem key={field.id}>
26
+ <Controller
27
+ control={control}
28
+ name={`pathParams.${i}.name`}
29
+ render={() => (
30
+ <div className="flex items-center">
31
+ <ColorizedParam
32
+ slug={field.name}
33
+ name={field.name}
34
+ className="font-mono text-xs px-2"
35
+ />
36
+ </div>
37
+ )}
38
+ />
39
+
40
+ <div className="flex justify-between items-center col-span-2">
28
41
  <Controller
29
42
  control={control}
30
- name={`pathParams.${i}.name`}
31
- render={() => (
32
- <div className="flex items-center">
33
- <ColorizedParam
34
- slug={field.name}
35
- name={field.name}
36
- className="font-mono text-xs px-2"
37
- />
38
- </div>
43
+ name={`pathParams.${i}.value`}
44
+ render={({ field }) => (
45
+ <ParamsGridInput {...field} required placeholder="Value" />
39
46
  )}
40
47
  />
41
-
42
- <div className="flex justify-between items-center col-span-2">
43
- <Controller
44
- control={control}
45
- name={`pathParams.${i}.value`}
46
- render={({ field }) => (
47
- <Input
48
- {...field}
49
- required
50
- placeholder="Value"
51
- className="w-full truncate border-0 p-0 m-0 shadow-none text-xs font-mono focus-visible:ring-0"
52
- />
53
- )}
54
- />
55
- </div>
56
- </ParamsGridItem>
57
- ))}
58
- </ParamsGrid>
59
- </div>
48
+ </div>
49
+ </ParamsGridItem>
50
+ ))}
51
+ </ParamsGrid>
60
52
  );
61
53
  };