@scalar/api-client 3.18.0 → 3.19.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 (223) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/components/HttpMethod/HttpMethod.vue.d.ts +2 -2
  3. package/dist/components/SectionFilter.vue.d.ts +2 -1
  4. package/dist/components/SectionFilter.vue.d.ts.map +1 -1
  5. package/dist/components/SectionFilter.vue.js +1 -1
  6. package/dist/components/SectionFilter.vue.js.map +1 -1
  7. package/dist/components/SectionFilter.vue.script.js.map +1 -1
  8. package/dist/hooks/use-file-dialog.d.ts.map +1 -1
  9. package/dist/hooks/use-file-dialog.js +1 -0
  10. package/dist/hooks/use-file-dialog.js.map +1 -1
  11. package/dist/style.css +136 -90
  12. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts +2 -2
  13. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
  14. package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
  15. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +15 -10
  16. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
  17. package/dist/v2/blocks/operation-block/components/Header.vue.d.ts +1 -1
  18. package/dist/v2/blocks/operation-block/components/Header.vue.js +1 -1
  19. package/dist/v2/blocks/operation-block/components/Header.vue.js.map +1 -1
  20. package/dist/v2/blocks/operation-block/components/Header.vue.script.js.map +1 -1
  21. package/dist/v2/blocks/operation-block/helpers/send-request.d.ts +3 -1
  22. package/dist/v2/blocks/operation-block/helpers/send-request.d.ts.map +1 -1
  23. package/dist/v2/blocks/operation-block/helpers/send-request.js +9 -5
  24. package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
  25. package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.d.ts +1 -1
  26. package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.js +1 -1
  27. package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.js.map +1 -1
  28. package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts +3 -1
  29. package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts.map +1 -1
  30. package/dist/v2/blocks/request-block/RequestBlock.vue.js +1 -1
  31. package/dist/v2/blocks/request-block/RequestBlock.vue.js.map +1 -1
  32. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js +58 -3
  33. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
  34. package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts +11 -3
  35. package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
  36. package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
  37. package/dist/v2/blocks/request-block/components/RequestBody.vue.js.map +1 -1
  38. package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +59 -23
  39. package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
  40. package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.d.ts +5 -3
  41. package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.d.ts.map +1 -1
  42. package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.js.map +1 -1
  43. package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.script.js +6 -3
  44. package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.script.js.map +1 -1
  45. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.d.ts +1 -1
  46. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.d.ts.map +1 -1
  47. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.js.map +1 -1
  48. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.script.js +1 -0
  49. package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.script.js.map +1 -1
  50. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts.map +1 -1
  51. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.js.map +1 -1
  52. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +4 -3
  53. package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
  54. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts +2 -0
  55. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts.map +1 -1
  56. package/dist/v2/blocks/request-block/components/RequestTable.vue.js +1 -1
  57. package/dist/v2/blocks/request-block/components/RequestTable.vue.js.map +1 -1
  58. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js +7 -3
  59. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js.map +1 -1
  60. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts +7 -1
  61. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts.map +1 -1
  62. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.js.map +1 -1
  63. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js +17 -5
  64. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
  65. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.d.ts +1 -1
  66. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.js.map +1 -1
  67. package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js.map +1 -1
  68. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.d.ts +1 -1
  69. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.d.ts.map +1 -1
  70. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js +17 -8
  71. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js.map +1 -1
  72. package/dist/v2/blocks/request-block/helpers/fold-structured-body-rows.d.ts +1 -1
  73. package/dist/v2/blocks/request-block/helpers/fold-structured-body-rows.js.map +1 -1
  74. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.d.ts +3 -1
  75. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.d.ts.map +1 -1
  76. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js +34 -17
  77. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js.map +1 -1
  78. package/dist/v2/blocks/request-block/helpers/get-parameter-content.d.ts +1 -1
  79. package/dist/v2/blocks/request-block/helpers/get-parameter-content.js.map +1 -1
  80. package/dist/v2/blocks/request-block/helpers/get-parameter-schema.d.ts +1 -1
  81. package/dist/v2/blocks/request-block/helpers/get-parameter-schema.js.map +1 -1
  82. package/dist/v2/blocks/request-block/helpers/get-structured-body-rows.d.ts +1 -1
  83. package/dist/v2/blocks/request-block/helpers/get-structured-body-rows.js +1 -1
  84. package/dist/v2/blocks/request-block/helpers/get-structured-body-rows.js.map +1 -1
  85. package/dist/v2/blocks/request-block/helpers/group-by.d.ts +3 -4
  86. package/dist/v2/blocks/request-block/helpers/group-by.d.ts.map +1 -1
  87. package/dist/v2/blocks/request-block/helpers/group-by.js +12 -10
  88. package/dist/v2/blocks/request-block/helpers/group-by.js.map +1 -1
  89. package/dist/v2/blocks/request-block/helpers/validate-parameter.d.ts +1 -1
  90. package/dist/v2/blocks/request-block/helpers/validate-parameter.js.map +1 -1
  91. package/dist/v2/blocks/response-block/ResponseBlock.vue.js +1 -1
  92. package/dist/v2/blocks/response-block/ResponseBlock.vue.js.map +1 -1
  93. package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js +6 -1
  94. package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js.map +1 -1
  95. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.d.ts.map +1 -1
  96. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.js +1 -1
  97. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.js.map +1 -1
  98. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.script.js +42 -16
  99. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.script.js.map +1 -1
  100. package/dist/v2/blocks/response-block/helpers/media-types.d.ts.map +1 -1
  101. package/dist/v2/blocks/response-block/helpers/media-types.js +5 -0
  102. package/dist/v2/blocks/response-block/helpers/media-types.js.map +1 -1
  103. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts +2 -2
  104. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
  105. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
  106. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js.map +1 -1
  107. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js +2 -2
  108. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
  109. package/dist/v2/blocks/scalar-address-bar-block/helpers/refocus-blur-target.js.map +1 -1
  110. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.d.ts +1 -1
  111. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.js.map +1 -1
  112. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
  113. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts +5 -5
  114. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts.map +1 -1
  115. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.js.map +1 -1
  116. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js +10 -7
  117. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js.map +1 -1
  118. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.d.ts +16 -0
  119. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.d.ts.map +1 -0
  120. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.js +7 -0
  121. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.js.map +1 -0
  122. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.script.js +86 -0
  123. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2Metadata.vue.script.js.map +1 -0
  124. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.d.ts +1 -1
  125. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.js.map +1 -1
  126. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.script.js.map +1 -1
  127. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.d.ts +1 -1
  128. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.js.map +1 -1
  129. package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js.map +1 -1
  130. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.d.ts +1 -1
  131. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.js.map +1 -1
  132. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.script.js.map +1 -1
  133. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts +5 -5
  134. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts.map +1 -1
  135. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.js.map +1 -1
  136. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js +39 -156
  137. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js.map +1 -1
  138. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.d.ts +1 -1
  139. package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.js.map +1 -1
  140. package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.d.ts +1 -1
  141. package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.d.ts.map +1 -1
  142. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.d.ts +6 -0
  143. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.d.ts.map +1 -0
  144. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js +25 -0
  145. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js.map +1 -0
  146. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts +1 -2
  147. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts.map +1 -1
  148. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js +2 -2
  149. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js.map +1 -1
  150. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts +1 -1
  151. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts.map +1 -1
  152. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js +13 -9
  153. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
  154. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.d.ts +9 -0
  155. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.d.ts.map +1 -0
  156. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.js +36 -0
  157. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.js.map +1 -0
  158. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.js.map +1 -1
  159. package/dist/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize.d.ts +1 -1
  160. package/dist/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize.js.map +1 -1
  161. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts +1 -1
  162. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts.map +1 -1
  163. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js.map +1 -1
  164. package/dist/v2/components/code-input/CodeInput.vue.d.ts +2 -2
  165. package/dist/v2/components/code-input/CodeInput.vue.d.ts.map +1 -1
  166. package/dist/v2/components/code-input/CodeInput.vue.js +1 -1
  167. package/dist/v2/components/code-input/CodeInput.vue.js.map +1 -1
  168. package/dist/v2/components/code-input/CodeInput.vue.script.js +41 -10
  169. package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
  170. package/dist/v2/components/code-input/CodeInputLite.vue.d.ts.map +1 -1
  171. package/dist/v2/components/code-input/CodeInputLite.vue.js +1 -1
  172. package/dist/v2/components/code-input/CodeInputLite.vue.js.map +1 -1
  173. package/dist/v2/components/code-input/CodeInputLite.vue.script.js +7 -6
  174. package/dist/v2/components/code-input/CodeInputLite.vue.script.js.map +1 -1
  175. package/dist/v2/components/code-input/helpers/build-pill-context.d.ts.map +1 -1
  176. package/dist/v2/components/code-input/helpers/build-pill-context.js.map +1 -1
  177. package/dist/v2/components/data-table/DataTableCheckbox.vue.d.ts +1 -1
  178. package/dist/v2/components/data-table/DataTableCheckbox.vue.d.ts.map +1 -1
  179. package/dist/v2/components/layout/CollapsibleSection.vue.js.map +1 -1
  180. package/dist/v2/components/layout/CollapsibleSection.vue.script.js.map +1 -1
  181. package/dist/v2/components/server/ServerDropdown.vue.d.ts +1 -1
  182. package/dist/v2/components/server/ServerDropdown.vue.d.ts.map +1 -1
  183. package/dist/v2/components/server/ServerDropdown.vue.js.map +1 -1
  184. package/dist/v2/components/server/ServerDropdown.vue.script.js +1 -1
  185. package/dist/v2/components/server/ServerDropdown.vue.script.js.map +1 -1
  186. package/dist/v2/components/server/ServerDropdownItem.vue.d.ts +1 -1
  187. package/dist/v2/components/server/ServerDropdownItem.vue.js +1 -1
  188. package/dist/v2/components/server/ServerDropdownItem.vue.js.map +1 -1
  189. package/dist/v2/components/server/ServerDropdownItem.vue.script.js.map +1 -1
  190. package/dist/v2/constants.js +1 -1
  191. package/dist/v2/features/command-palette/components/CommandActionInput.vue.js.map +1 -1
  192. package/dist/v2/features/command-palette/components/CommandActionInput.vue.script.js +1 -1
  193. package/dist/v2/features/command-palette/components/CommandActionInput.vue.script.js.map +1 -1
  194. package/dist/v2/features/environments/components/EnvironmentColors.vue.js.map +1 -1
  195. package/dist/v2/features/environments/components/EnvironmentColors.vue.script.js +1 -1
  196. package/dist/v2/features/environments/components/EnvironmentColors.vue.script.js.map +1 -1
  197. package/dist/v2/features/modal/Modal.vue.d.ts +1 -1
  198. package/dist/v2/features/modal/Modal.vue.js.map +1 -1
  199. package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
  200. package/dist/v2/features/modal/helpers/create-api-client-modal.js.map +1 -1
  201. package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts +9 -3
  202. package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts.map +1 -1
  203. package/dist/v2/features/modal/helpers/resolve-route-parameters.js +1 -1
  204. package/dist/v2/features/modal/helpers/resolve-route-parameters.js.map +1 -1
  205. package/dist/v2/features/modal/hooks/use-modal-sidebar.js +1 -1
  206. package/dist/v2/features/modal/modal-events.d.ts.map +1 -1
  207. package/dist/v2/features/modal/modal-events.js +10 -1
  208. package/dist/v2/features/modal/modal-events.js.map +1 -1
  209. package/dist/v2/features/operation/Operation.vue.d.ts +1 -1
  210. package/dist/v2/features/operation/Operation.vue.js.map +1 -1
  211. package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
  212. package/dist/v2/features/search/components/DocumentSearchModal.vue.d.ts +1 -1
  213. package/dist/v2/features/search/components/DocumentSearchModal.vue.js +1 -1
  214. package/dist/v2/features/search/components/DocumentSearchModal.vue.js.map +1 -1
  215. package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js.map +1 -1
  216. package/dist/v2/features/search/helpers/create-search-index.d.ts +1 -1
  217. package/dist/v2/features/search/helpers/create-search-index.js.map +1 -1
  218. package/dist/v2/features/search/hooks/use-document-search.d.ts +1 -1
  219. package/dist/v2/features/search/hooks/use-document-search.js.map +1 -1
  220. package/dist/v2/features/search/hooks/use-search-index.d.ts +1 -1
  221. package/dist/v2/features/search/hooks/use-search-index.js.map +1 -1
  222. package/dist/vue-styles.css +97 -87
  223. package/package.json +16 -16
package/CHANGELOG.md CHANGED
@@ -1,5 +1,56 @@
1
1
  # @scalar/api-client
2
2
 
3
+ ## 3.19.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#10229](https://github.com/scalar/scalar/pull/10229): Fix the API client modal getting stuck on "Select an operation to view details" for a document's first operation after its active document re-syncs. The reference used to hand the modal a route to a nonexistent path and method during that re-sync; the modal now leaves the current operation in place instead.
8
+ - [#9912](https://github.com/scalar/scalar/pull/9912): add line wrapping toggle for request and response bodies
9
+ - [#10179](https://github.com/scalar/scalar/pull/10179): Support OpenAPI 3.2 OAuth2 metadata URLs in workspace schemas and the shared authentication UI. Fetch HTTPS authorization server metadata or HTTP metadata from local development URLs to discover flows or fill missing endpoints while preserving explicit configuration.
10
+
11
+ For local development, Scalar deliberately relaxes the OpenAPI 3.2 TLS requirement: metadata URLs and discovered endpoints may use HTTP for local development URLs recognized by the shared `isLocalUrl` helper, including loopback hosts, `0.0.0.0`, and reserved development domains such as `*.test` and `*.example`. Other hosts require HTTPS.
12
+
13
+ Discovery leaves `refreshUrl` unchanged. Token refresh already falls back to the flow's token URL when no refresh URL is configured, so a discovered token endpoint also supports refresh without overriding an explicit refresh URL.
14
+
15
+ - [#9852](https://github.com/scalar/scalar/pull/9852): Render OpenAPI 3.2 response summaries, server names in the server selectors, and a strikethrough on deprecated security schemes.
16
+ - [#9889](https://github.com/scalar/scalar/pull/9889): feat: add a copy button to the request body editor
17
+
18
+ The raw request body editor now shows a copy-to-clipboard button (revealed on hover, matching the response panel) so you can grab the whole body without selecting the text by hand. The editor stays fully editable at any size.
19
+
20
+ - [#10231](https://github.com/scalar/scalar/pull/10231): Trim surrounding whitespace from OAuth2 client IDs and client secrets when authorizing and refreshing tokens.
21
+ - [#10238](https://github.com/scalar/scalar/pull/10238): Display responses with vendor `+xml` media types as XML text and use `.xml` for downloads.
22
+
23
+ ## 3.19.0
24
+
25
+ ### Minor Changes
26
+
27
+ - [#10102](https://github.com/scalar/scalar/pull/10102): Allow response hooks to return a replacement Response before the client processes its body, status, and headers. Add the onResponseReceived configuration callback for API References. Existing hooks can still read responses and return nothing.
28
+
29
+ ### Patch Changes
30
+
31
+ - [#10123](https://github.com/scalar/scalar/pull/10123): Fall back to the requested URL when a custom fetch returns a response without one. Errors raised while reading the response body are now returned as an error result instead of escaping the request helper.
32
+ - [#10086](https://github.com/scalar/scalar/pull/10086): Enable optional query parameters when their value is entered.
33
+ - [#10080](https://github.com/scalar/scalar/pull/10080): Fix the Test Request body showing schema defaults instead of the example on first open. This happened for the first operation when its body used oneOf/anyOf and had a named example.
34
+ - [#10160](https://github.com/scalar/scalar/pull/10160): Pass request duration to post-response scripts as `pm.response.responseTime` in milliseconds and enable the response-time example.
35
+ - [#10072](https://github.com/scalar/scalar/pull/10072): Add a "generate example from schema" button to the request body, so the schema-generated fields stay reachable once an operation ships custom examples
36
+ - [#10081](https://github.com/scalar/scalar/pull/10081): Keep the `mutualTLS` security scheme type instead of turning it into an apiKey form, and show read-only authentication guidance for mutual TLS and unsupported browser broker credentials.
37
+ - [#10167](https://github.com/scalar/scalar/pull/10167): fix: hide the code snippet section when all clients are hidden
38
+ - [#10170](https://github.com/scalar/scalar/pull/10170): Keep form fields checked for composed body schemas so the initial form matches the fields sent in the request.
39
+ - [#10148](https://github.com/scalar/scalar/pull/10148): Typing a value into an unchecked optional form body row now enables that row, so the value is sent with the request. This matches how optional query parameters already behave.
40
+ - [#10136](https://github.com/scalar/scalar/pull/10136): Restore modal and single-file reference tests, update layout selectors, and remove stale comments. Named-resource resolution remains unsupported and is tested explicitly.
41
+ - [#10140](https://github.com/scalar/scalar/pull/10140): Replace redundant type assertions with compiler-checked annotations, typed accumulators, and existing guards across helpers, API conversion, request handling, and schema rendering.
42
+
43
+ Narrow DOM elements and caught errors before accessing their properties. Correct header lookup to include missing values and handle them during PowerShell snippet generation.
44
+
45
+ Validate release-note provider responses, represent unresolved references and absent groups in helper return types, and require narrowing merged object values. Preserve AsyncAPI broker credentials separately from HTTP authentication schemes.
46
+
47
+ - [#10149](https://github.com/scalar/scalar/pull/10149): Keep focus while editing request body field names by saving name changes on blur.
48
+ - [#10142](https://github.com/scalar/scalar/pull/10142): Send multipart array properties as separate parts with the same field name, applying encoding to each item. Preserve JSON item content types, uploaded files, and array values after form edits, and generate matching code snippets.
49
+
50
+ Send JSON form fields without an upload filename and preserve fields and files in request history.
51
+
52
+ Rename the RestSharp snippet's internal `getMethod` helper so it no longer clashes with the `getMethod` that Nitro bundles into server builds (the new multipart imports shifted chunking and surfaced the collision).
53
+
3
54
  ## 3.18.0
4
55
 
5
56
  ### Minor Changes
@@ -4,9 +4,9 @@ type __VLS_Props = {
4
4
  isEditable?: boolean;
5
5
  };
6
6
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
7
- change: (value: "head" | "delete" | "get" | "options" | "patch" | "post" | "put" | "trace") => any;
7
+ change: (value: "head" | "delete" | "get" | "options" | "patch" | "post" | "put" | "query" | "trace") => any;
8
8
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
9
- onChange?: ((value: "head" | "delete" | "get" | "options" | "patch" | "post" | "put" | "trace") => any) | undefined;
9
+ onChange?: ((value: "head" | "delete" | "get" | "options" | "patch" | "post" | "put" | "query" | "trace") => any) | undefined;
10
10
  }>, {
11
11
  isSquare: boolean;
12
12
  isEditable: boolean;
@@ -1,7 +1,8 @@
1
1
  declare const __VLS_export: <T extends string>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
2
2
  props: import("vue").PublicProps & __VLS_PrettifyLocal<({
3
3
  filters?: T[];
4
- filterIds?: Record<T, string>;
4
+ /** IDs for the currently available sections. */
5
+ filterIds?: Partial<Record<T, string>>;
5
6
  } & {
6
7
  modelValue?: T;
7
8
  }) & {
@@ -1 +1 @@
1
- {"version":3,"file":"SectionFilter.vue.d.ts","sourceRoot":"","sources":["../../src/components/SectionFilter.vue"],"names":[],"mappings":"AAuKA,QAAA,MAAM,YAAY,GAAK,CAAC,SAAS,MAAM,EACtC,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,gBAAgB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClE;WAiNO,OAAO,KAAK,EAAE,WAAW,GAAG,mBAAmB,CAAC;kBA/M5C,CAAC,EAAE;oBACD,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC;;qBAkClB,CAAC;;;KA4K6E,CAAC,GAAG,CAAC,OAAO,UAAU,SAAS;QAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC5J,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI;WACtB,GAAG;WACH,EAAE;;EAGN,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CAAI,CAAC;wBACpE,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC,GAAG,EAAE,CAAC"}
1
+ {"version":3,"file":"SectionFilter.vue.d.ts","sourceRoot":"","sources":["../../src/components/SectionFilter.vue"],"names":[],"mappings":"AAwKA,QAAA,MAAM,YAAY,GAAK,CAAC,SAAS,MAAM,EACtC,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,gBAAgB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClE;WAkNO,OAAO,KAAK,EAAE,WAAW,GAAG,mBAAmB,CAAC;kBAhN5C,CAAC,EAAE;QACb,gDAAgD;oBACpC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;;qBAkC3B,CAAC;;;KA4K6E,CAAC,GAAG,CAAC,OAAO,UAAU,SAAS;QAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC5J,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI;WACtB,GAAG;WACH,EAAE;;EAGN,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CAAI,CAAC;wBACpE,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC,GAAG,EAAE,CAAC"}
@@ -2,7 +2,7 @@ import _plugin_vue_export_helper_default from "../_virtual/_plugin-vue_export-he
2
2
  import SectionFilter_vue_vue_type_script_setup_true_lang_default from "./SectionFilter.vue.script.js";
3
3
  /* empty css */
4
4
  //#region src/components/SectionFilter.vue
5
- var SectionFilter_default = /*#__PURE__*/ _plugin_vue_export_helper_default(SectionFilter_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-07ff8fc3"]]);
5
+ var SectionFilter_default = /*#__PURE__*/ _plugin_vue_export_helper_default(SectionFilter_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-ac788106"]]);
6
6
  //#endregion
7
7
  export { SectionFilter_default as default };
8
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"SectionFilter.vue.js","names":[],"sources":["../../src/components/SectionFilter.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends string\">\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { nextTick, ref } from 'vue'\n\nimport SectionFilterButton from '@/components/SectionFilterButton.vue'\n\nconst { filters = [], filterIds } = defineProps<{\n filters?: T[]\n filterIds?: Record<T, string>\n}>()\n\nconst model = defineModel<T>()\n\nconst tablist = ref<HTMLDivElement>()\n\n/** Keyboard navigation */\nconst navigateSection = (direction: 'next' | 'prev') => {\n const offset = direction === 'prev' ? -1 : 1\n const index = model.value ? filters.indexOf(model.value) : 0\n const length = filters.length\n\n // Ensures we loop around the array by using the remainder\n const newIndex = (index + offset + length) % length\n model.value = filters[newIndex]\n\n // Focus the selected button\n nextTick(() => {\n if (tablist.value) {\n const selectedButton = tablist.value.querySelector(\n `button[aria-selected=\"true\"]`,\n ) satisfies HTMLButtonElement | null\n if (selectedButton) {\n selectedButton.focus()\n }\n }\n })\n}\n</script>\n<template>\n <div\n ref=\"tablist\"\n class=\"filter-hover context-bar-group ml-auto hidden lg:flex\"\n role=\"tablist\"\n @keydown.left=\"navigateSection('prev')\"\n @keydown.right=\"navigateSection('next')\">\n <div\n class=\"request-section-content request-section-content-filter fade-request-section-content text-c-3 pointer-events-auto relative hidden w-full justify-end gap-[1.5px] rounded py-1.75 text-xs xl:flex\">\n <SectionFilterButton\n v-for=\"filter in filters\"\n :key=\"filter\"\n class=\"filter-hover-item\"\n :controls=\"filterIds?.[filter]\"\n role=\"tab\"\n :selected=\"model === filter\"\n @click=\"model = filter\">\n {{ filter }}\n </SectionFilterButton>\n <div\n class=\"filter-button context-bar-group-hover:text-c-1 absolute -right-[30px] flex items-center\">\n <span class=\"context-bar-group-hover:hidden mr-1.5\">{{ model }}</span>\n <ScalarIcon\n icon=\"FilterList\"\n size=\"md\"\n thickness=\"2\" />\n </div>\n </div>\n </div>\n</template>\n<style scoped>\n.fade-request-section-content {\n background: linear-gradient(\n to left,\n var(--scalar-background-1) 64%,\n transparent\n );\n}\n.filter-hover {\n height: 100%;\n padding-right: 39px;\n padding-left: 24px;\n position: absolute;\n right: 0;\n transition: width 0s ease-in-out 0.2s;\n overflow: hidden;\n}\n.filter-hover:hover,\n.filter-hover:has(:focus-visible) {\n width: 100%;\n z-index: 10;\n}\n.filter-hover:before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: fit-content;\n background-color: var(--scalar-background-1);\n opacity: 0;\n transition: all 0.3s ease-in-out;\n pointer-events: none;\n}\n.filter-hover-item {\n opacity: 0;\n}\n.filter-hover-item:not(:last-of-type) {\n transform: translate3d(0, 3px, 0);\n}\n.filter-hover:hover .filter-hover-item {\n transition:\n opacity 0.2s ease-in-out,\n transform 0.2s ease-in-out;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(1) {\n transition-delay: 0.05s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(2) {\n transition-delay: 0.1s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(3) {\n transition-delay: 0.15s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(4) {\n transition-delay: 0.2s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(5) {\n transition-delay: 0.25s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(6) {\n transition-delay: 0.3s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(7) {\n transition-delay: 0.35s;\n}\n.filter-hover:hover .filter-hover-item,\n.filter-hover:has(:focus-visible) .filter-hover-item {\n opacity: 1;\n transform: translate3d(0, 0, 0);\n}\n.filter-hover:hover:before,\n.filter-hover:has(:focus-visible):before {\n opacity: 0.9;\n backdrop-filter: blur(10px);\n}\n.filter-button {\n top: 50%;\n transform: translateY(-50%);\n}\n.context-bar-group:hover .context-bar-group-hover\\:text-c-1,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:text-c-1 {\n --tw-text-opacity: 1;\n color: rgb(var(--scalar-color-1) / var(--tw-text-opacity));\n}\n\n.context-bar-group:hover .context-bar-group-hover\\:hidden,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:hidden {\n display: none;\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"SectionFilter.vue.js","names":[],"sources":["../../src/components/SectionFilter.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends string\">\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { nextTick, ref } from 'vue'\n\nimport SectionFilterButton from '@/components/SectionFilterButton.vue'\n\nconst { filters = [], filterIds } = defineProps<{\n filters?: T[]\n /** IDs for the currently available sections. */\n filterIds?: Partial<Record<T, string>>\n}>()\n\nconst model = defineModel<T>()\n\nconst tablist = ref<HTMLDivElement>()\n\n/** Keyboard navigation */\nconst navigateSection = (direction: 'next' | 'prev') => {\n const offset = direction === 'prev' ? -1 : 1\n const index = model.value ? filters.indexOf(model.value) : 0\n const length = filters.length\n\n // Ensures we loop around the array by using the remainder\n const newIndex = (index + offset + length) % length\n model.value = filters[newIndex]\n\n // Focus the selected button\n nextTick(() => {\n if (tablist.value) {\n const selectedButton = tablist.value.querySelector(\n `button[aria-selected=\"true\"]`,\n ) satisfies HTMLButtonElement | null\n if (selectedButton) {\n selectedButton.focus()\n }\n }\n })\n}\n</script>\n<template>\n <div\n ref=\"tablist\"\n class=\"filter-hover context-bar-group ml-auto hidden lg:flex\"\n role=\"tablist\"\n @keydown.left=\"navigateSection('prev')\"\n @keydown.right=\"navigateSection('next')\">\n <div\n class=\"request-section-content request-section-content-filter fade-request-section-content text-c-3 pointer-events-auto relative hidden w-full justify-end gap-[1.5px] rounded py-1.75 text-xs xl:flex\">\n <SectionFilterButton\n v-for=\"filter in filters\"\n :key=\"filter\"\n class=\"filter-hover-item\"\n :controls=\"filterIds?.[filter]\"\n role=\"tab\"\n :selected=\"model === filter\"\n @click=\"model = filter\">\n {{ filter }}\n </SectionFilterButton>\n <div\n class=\"filter-button context-bar-group-hover:text-c-1 absolute -right-[30px] flex items-center\">\n <span class=\"context-bar-group-hover:hidden mr-1.5\">{{ model }}</span>\n <ScalarIcon\n icon=\"FilterList\"\n size=\"md\"\n thickness=\"2\" />\n </div>\n </div>\n </div>\n</template>\n<style scoped>\n.fade-request-section-content {\n background: linear-gradient(\n to left,\n var(--scalar-background-1) 64%,\n transparent\n );\n}\n.filter-hover {\n height: 100%;\n padding-right: 39px;\n padding-left: 24px;\n position: absolute;\n right: 0;\n transition: width 0s ease-in-out 0.2s;\n overflow: hidden;\n}\n.filter-hover:hover,\n.filter-hover:has(:focus-visible) {\n width: 100%;\n z-index: 10;\n}\n.filter-hover:before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: fit-content;\n background-color: var(--scalar-background-1);\n opacity: 0;\n transition: all 0.3s ease-in-out;\n pointer-events: none;\n}\n.filter-hover-item {\n opacity: 0;\n}\n.filter-hover-item:not(:last-of-type) {\n transform: translate3d(0, 3px, 0);\n}\n.filter-hover:hover .filter-hover-item {\n transition:\n opacity 0.2s ease-in-out,\n transform 0.2s ease-in-out;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(1) {\n transition-delay: 0.05s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(2) {\n transition-delay: 0.1s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(3) {\n transition-delay: 0.15s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(4) {\n transition-delay: 0.2s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(5) {\n transition-delay: 0.25s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(6) {\n transition-delay: 0.3s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(7) {\n transition-delay: 0.35s;\n}\n.filter-hover:hover .filter-hover-item,\n.filter-hover:has(:focus-visible) .filter-hover-item {\n opacity: 1;\n transform: translate3d(0, 0, 0);\n}\n.filter-hover:hover:before,\n.filter-hover:has(:focus-visible):before {\n opacity: 0.9;\n backdrop-filter: blur(10px);\n}\n.filter-button {\n top: 50%;\n transform: translateY(-50%);\n}\n.context-bar-group:hover .context-bar-group-hover\\:text-c-1,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:text-c-1 {\n --tw-text-opacity: 1;\n color: rgb(var(--scalar-color-1) / var(--tw-text-opacity));\n}\n\n.context-bar-group:hover .context-bar-group-hover\\:hidden,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:hidden {\n display: none;\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"SectionFilter.vue.script.js","names":[],"sources":["../../src/components/SectionFilter.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends string\">\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { nextTick, ref } from 'vue'\n\nimport SectionFilterButton from '@/components/SectionFilterButton.vue'\n\nconst { filters = [], filterIds } = defineProps<{\n filters?: T[]\n filterIds?: Record<T, string>\n}>()\n\nconst model = defineModel<T>()\n\nconst tablist = ref<HTMLDivElement>()\n\n/** Keyboard navigation */\nconst navigateSection = (direction: 'next' | 'prev') => {\n const offset = direction === 'prev' ? -1 : 1\n const index = model.value ? filters.indexOf(model.value) : 0\n const length = filters.length\n\n // Ensures we loop around the array by using the remainder\n const newIndex = (index + offset + length) % length\n model.value = filters[newIndex]\n\n // Focus the selected button\n nextTick(() => {\n if (tablist.value) {\n const selectedButton = tablist.value.querySelector(\n `button[aria-selected=\"true\"]`,\n ) satisfies HTMLButtonElement | null\n if (selectedButton) {\n selectedButton.focus()\n }\n }\n })\n}\n</script>\n<template>\n <div\n ref=\"tablist\"\n class=\"filter-hover context-bar-group ml-auto hidden lg:flex\"\n role=\"tablist\"\n @keydown.left=\"navigateSection('prev')\"\n @keydown.right=\"navigateSection('next')\">\n <div\n class=\"request-section-content request-section-content-filter fade-request-section-content text-c-3 pointer-events-auto relative hidden w-full justify-end gap-[1.5px] rounded py-1.75 text-xs xl:flex\">\n <SectionFilterButton\n v-for=\"filter in filters\"\n :key=\"filter\"\n class=\"filter-hover-item\"\n :controls=\"filterIds?.[filter]\"\n role=\"tab\"\n :selected=\"model === filter\"\n @click=\"model = filter\">\n {{ filter }}\n </SectionFilterButton>\n <div\n class=\"filter-button context-bar-group-hover:text-c-1 absolute -right-[30px] flex items-center\">\n <span class=\"context-bar-group-hover:hidden mr-1.5\">{{ model }}</span>\n <ScalarIcon\n icon=\"FilterList\"\n size=\"md\"\n thickness=\"2\" />\n </div>\n </div>\n </div>\n</template>\n<style scoped>\n.fade-request-section-content {\n background: linear-gradient(\n to left,\n var(--scalar-background-1) 64%,\n transparent\n );\n}\n.filter-hover {\n height: 100%;\n padding-right: 39px;\n padding-left: 24px;\n position: absolute;\n right: 0;\n transition: width 0s ease-in-out 0.2s;\n overflow: hidden;\n}\n.filter-hover:hover,\n.filter-hover:has(:focus-visible) {\n width: 100%;\n z-index: 10;\n}\n.filter-hover:before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: fit-content;\n background-color: var(--scalar-background-1);\n opacity: 0;\n transition: all 0.3s ease-in-out;\n pointer-events: none;\n}\n.filter-hover-item {\n opacity: 0;\n}\n.filter-hover-item:not(:last-of-type) {\n transform: translate3d(0, 3px, 0);\n}\n.filter-hover:hover .filter-hover-item {\n transition:\n opacity 0.2s ease-in-out,\n transform 0.2s ease-in-out;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(1) {\n transition-delay: 0.05s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(2) {\n transition-delay: 0.1s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(3) {\n transition-delay: 0.15s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(4) {\n transition-delay: 0.2s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(5) {\n transition-delay: 0.25s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(6) {\n transition-delay: 0.3s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(7) {\n transition-delay: 0.35s;\n}\n.filter-hover:hover .filter-hover-item,\n.filter-hover:has(:focus-visible) .filter-hover-item {\n opacity: 1;\n transform: translate3d(0, 0, 0);\n}\n.filter-hover:hover:before,\n.filter-hover:has(:focus-visible):before {\n opacity: 0.9;\n backdrop-filter: blur(10px);\n}\n.filter-button {\n top: 50%;\n transform: translateY(-50%);\n}\n.context-bar-group:hover .context-bar-group-hover\\:text-c-1,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:text-c-1 {\n --tw-text-opacity: 1;\n color: rgb(var(--scalar-color-1) / var(--tw-text-opacity));\n}\n\n.context-bar-group:hover .context-bar-group-hover\\:hidden,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:hidden {\n display: none;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAWA,MAAM,QAAQ,SAAc,SAAA,YAAC;EAE7B,MAAM,UAAU,IAAoB;;EAGpC,MAAM,mBAAmB,cAA+B;GACtD,MAAM,SAAS,cAAc,SAAS,KAAK;GAC3C,MAAM,QAAQ,MAAM,QAAQ,QAAA,QAAQ,QAAQ,MAAM,KAAK,IAAI;GAC3D,MAAM,SAAS,QAAA,QAAQ;GAGvB,MAAM,YAAY,QAAQ,SAAS,UAAU;GAC7C,MAAM,QAAQ,QAAA,QAAQ;GAGtB,eAAe;IACb,IAAI,QAAQ,OAAO;KACjB,MAAM,iBAAiB,QAAQ,MAAM,cACnC,8BACF;KACA,IAAI,gBACF,eAAe,MAAM;IAEzB;GACF,CAAC;EACH;;uBAGE,mBA2BM,OAAA;aA1BA;IAAJ,KAAI;IACJ,OAAM;IACN,MAAK;IACJ,WAAO,CAAA,OAAA,OAAA,OAAA,KAAA,UAAA,WAAO,gBAAe,MAAA,GAAA,CAAA,MAAA,CAAA,IAAA,OAAA,OAAA,OAAA,KAAA,UAAA,WACd,gBAAe,MAAA,GAAA,CAAA,OAAA,CAAA,EAAA;OAC/B,mBAoBM,OApBN,YAoBM,EAAA,UAAA,IAAA,GAlBJ,mBASsB,UAAA,MAAA,WARH,QAAA,UAAV,WAAM;wBADf,YASsB,6BAAA;KAPnB,KAAK;KACN,OAAM;KACL,UAAU,QAAA,YAAY;KACvB,MAAK;KACJ,UAAU,MAAA,UAAU;KACpB,UAAK,WAAE,MAAA,QAAQ;;4BACJ,CAAA,gBAAA,gBAAT,MAAM,GAAA,CAAA,CAAA,CAAA;;;;;;;cAEX,mBAOM,OAPN,YAOM,CALJ,mBAAsE,QAAtE,YAAsE,gBAAf,MAAA,KAAK,GAAA,CAAA,GAC5D,YAGkB,MAAA,UAAA,GAAA;IAFhB,MAAK;IACL,MAAK;IACL,WAAU"}
1
+ {"version":3,"file":"SectionFilter.vue.script.js","names":[],"sources":["../../src/components/SectionFilter.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends string\">\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { nextTick, ref } from 'vue'\n\nimport SectionFilterButton from '@/components/SectionFilterButton.vue'\n\nconst { filters = [], filterIds } = defineProps<{\n filters?: T[]\n /** IDs for the currently available sections. */\n filterIds?: Partial<Record<T, string>>\n}>()\n\nconst model = defineModel<T>()\n\nconst tablist = ref<HTMLDivElement>()\n\n/** Keyboard navigation */\nconst navigateSection = (direction: 'next' | 'prev') => {\n const offset = direction === 'prev' ? -1 : 1\n const index = model.value ? filters.indexOf(model.value) : 0\n const length = filters.length\n\n // Ensures we loop around the array by using the remainder\n const newIndex = (index + offset + length) % length\n model.value = filters[newIndex]\n\n // Focus the selected button\n nextTick(() => {\n if (tablist.value) {\n const selectedButton = tablist.value.querySelector(\n `button[aria-selected=\"true\"]`,\n ) satisfies HTMLButtonElement | null\n if (selectedButton) {\n selectedButton.focus()\n }\n }\n })\n}\n</script>\n<template>\n <div\n ref=\"tablist\"\n class=\"filter-hover context-bar-group ml-auto hidden lg:flex\"\n role=\"tablist\"\n @keydown.left=\"navigateSection('prev')\"\n @keydown.right=\"navigateSection('next')\">\n <div\n class=\"request-section-content request-section-content-filter fade-request-section-content text-c-3 pointer-events-auto relative hidden w-full justify-end gap-[1.5px] rounded py-1.75 text-xs xl:flex\">\n <SectionFilterButton\n v-for=\"filter in filters\"\n :key=\"filter\"\n class=\"filter-hover-item\"\n :controls=\"filterIds?.[filter]\"\n role=\"tab\"\n :selected=\"model === filter\"\n @click=\"model = filter\">\n {{ filter }}\n </SectionFilterButton>\n <div\n class=\"filter-button context-bar-group-hover:text-c-1 absolute -right-[30px] flex items-center\">\n <span class=\"context-bar-group-hover:hidden mr-1.5\">{{ model }}</span>\n <ScalarIcon\n icon=\"FilterList\"\n size=\"md\"\n thickness=\"2\" />\n </div>\n </div>\n </div>\n</template>\n<style scoped>\n.fade-request-section-content {\n background: linear-gradient(\n to left,\n var(--scalar-background-1) 64%,\n transparent\n );\n}\n.filter-hover {\n height: 100%;\n padding-right: 39px;\n padding-left: 24px;\n position: absolute;\n right: 0;\n transition: width 0s ease-in-out 0.2s;\n overflow: hidden;\n}\n.filter-hover:hover,\n.filter-hover:has(:focus-visible) {\n width: 100%;\n z-index: 10;\n}\n.filter-hover:before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: fit-content;\n background-color: var(--scalar-background-1);\n opacity: 0;\n transition: all 0.3s ease-in-out;\n pointer-events: none;\n}\n.filter-hover-item {\n opacity: 0;\n}\n.filter-hover-item:not(:last-of-type) {\n transform: translate3d(0, 3px, 0);\n}\n.filter-hover:hover .filter-hover-item {\n transition:\n opacity 0.2s ease-in-out,\n transform 0.2s ease-in-out;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(1) {\n transition-delay: 0.05s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(2) {\n transition-delay: 0.1s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(3) {\n transition-delay: 0.15s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(4) {\n transition-delay: 0.2s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(5) {\n transition-delay: 0.25s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(6) {\n transition-delay: 0.3s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(7) {\n transition-delay: 0.35s;\n}\n.filter-hover:hover .filter-hover-item,\n.filter-hover:has(:focus-visible) .filter-hover-item {\n opacity: 1;\n transform: translate3d(0, 0, 0);\n}\n.filter-hover:hover:before,\n.filter-hover:has(:focus-visible):before {\n opacity: 0.9;\n backdrop-filter: blur(10px);\n}\n.filter-button {\n top: 50%;\n transform: translateY(-50%);\n}\n.context-bar-group:hover .context-bar-group-hover\\:text-c-1,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:text-c-1 {\n --tw-text-opacity: 1;\n color: rgb(var(--scalar-color-1) / var(--tw-text-opacity));\n}\n\n.context-bar-group:hover .context-bar-group-hover\\:hidden,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:hidden {\n display: none;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAYA,MAAM,QAAQ,SAAc,SAAA,YAAC;EAE7B,MAAM,UAAU,IAAoB;;EAGpC,MAAM,mBAAmB,cAA+B;GACtD,MAAM,SAAS,cAAc,SAAS,KAAK;GAC3C,MAAM,QAAQ,MAAM,QAAQ,QAAA,QAAQ,QAAQ,MAAM,KAAK,IAAI;GAC3D,MAAM,SAAS,QAAA,QAAQ;GAGvB,MAAM,YAAY,QAAQ,SAAS,UAAU;GAC7C,MAAM,QAAQ,QAAA,QAAQ;GAGtB,eAAe;IACb,IAAI,QAAQ,OAAO;KACjB,MAAM,iBAAiB,QAAQ,MAAM,cACnC,8BACF;KACA,IAAI,gBACF,eAAe,MAAM;IAEzB;GACF,CAAC;EACH;;uBAGE,mBA2BM,OAAA;aA1BA;IAAJ,KAAI;IACJ,OAAM;IACN,MAAK;IACJ,WAAO,CAAA,OAAA,OAAA,OAAA,KAAA,UAAA,WAAO,gBAAe,MAAA,GAAA,CAAA,MAAA,CAAA,IAAA,OAAA,OAAA,OAAA,KAAA,UAAA,WACd,gBAAe,MAAA,GAAA,CAAA,OAAA,CAAA,EAAA;OAC/B,mBAoBM,OApBN,YAoBM,EAAA,UAAA,IAAA,GAlBJ,mBASsB,UAAA,MAAA,WARH,QAAA,UAAV,WAAM;wBADf,YASsB,6BAAA;KAPnB,KAAK;KACN,OAAM;KACL,UAAU,QAAA,YAAY;KACvB,MAAK;KACJ,UAAU,MAAA,UAAU;KACpB,UAAK,WAAE,MAAA,QAAQ;;4BACJ,CAAA,gBAAA,gBAAT,MAAM,GAAA,CAAA,CAAA,CAAA;;;;;;;cAEX,mBAOM,OAPN,YAOM,CALJ,mBAAsE,QAAtE,YAAsE,gBAAf,MAAA,KAAK,GAAA,CAAA,GAC5D,YAGkB,MAAA,UAAA,GAAA;IAFhB,MAAK;IACL,MAAK;IACL,WAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-file-dialog.d.ts","sourceRoot":"","sources":["../../src/hooks/use-file-dialog.ts"],"names":[],"mappings":"AAEA,KAAK,oBAAoB,GAAG;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3D,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACrC,CAAA;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAE,oBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgC/F"}
1
+ {"version":3,"file":"use-file-dialog.d.ts","sourceRoot":"","sources":["../../src/hooks/use-file-dialog.ts"],"names":[],"mappings":"AAEA,KAAK,oBAAoB,GAAG;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3D,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACrC,CAAA;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAE,oBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmC/F"}
@@ -11,6 +11,7 @@ function useFileDialog({ multiple, accept, onChange, onError } = {}) {
11
11
  input = document.createElement("input");
12
12
  input.type = "file";
13
13
  input.onchange = (event) => {
14
+ if (!(event.target instanceof HTMLInputElement)) return;
14
15
  const result = event.target;
15
16
  files.value = result.files;
16
17
  onChange?.(files.value);
@@ -1 +1 @@
1
- {"version":3,"file":"use-file-dialog.js","names":[],"sources":["../../src/hooks/use-file-dialog.ts"],"sourcesContent":["import { readonly, ref } from 'vue'\n\ntype UseFileDialogOptions = {\n multiple?: boolean\n /** @default '*' */\n accept?: string\n onChange?: (files: FileList | null) => void | Promise<void>\n onError?: () => void | Promise<void>\n}\n\n/**\n * Simplified interface for opening a file picker dialog\n * Derived from vueuse @see https://vueuse.org/useFileDialog\n */\nexport function useFileDialog({ multiple, accept, onChange, onError }: UseFileDialogOptions = {}) {\n const files = ref<FileList | null>(null)\n\n let input: HTMLInputElement | undefined\n if (typeof document !== 'undefined') {\n input = document.createElement('input')\n input.type = 'file'\n\n input.onchange = (event: Event) => {\n const result = event.target as HTMLInputElement\n files.value = result.files\n onChange?.(files.value)\n }\n\n input.onerror = () => onError?.()\n\n input.multiple = multiple!\n input.accept = accept!\n }\n\n const open = () => {\n if (!input) {\n return onError?.()\n }\n\n input.click()\n }\n\n return {\n files: readonly(files),\n open,\n }\n}\n"],"mappings":";;;;;;AAcA,SAAgB,cAAc,EAAE,UAAU,QAAQ,UAAU,YAAkC,CAAC,GAAG;CAChG,MAAM,QAAQ,IAAqB,IAAI;CAEvC,IAAI;CACJ,IAAI,OAAO,aAAa,aAAa;EACnC,QAAQ,SAAS,cAAc,OAAO;EACtC,MAAM,OAAO;EAEb,MAAM,YAAY,UAAiB;GACjC,MAAM,SAAS,MAAM;GACrB,MAAM,QAAQ,OAAO;GACrB,WAAW,MAAM,KAAK;EACxB;EAEA,MAAM,gBAAgB,UAAU;EAEhC,MAAM,WAAW;EACjB,MAAM,SAAS;CACjB;CAEA,MAAM,aAAa;EACjB,IAAI,CAAC,OACH,OAAO,UAAU;EAGnB,MAAM,MAAM;CACd;CAEA,OAAO;EACL,OAAO,SAAS,KAAK;EACrB;CACF;AACF"}
1
+ {"version":3,"file":"use-file-dialog.js","names":[],"sources":["../../src/hooks/use-file-dialog.ts"],"sourcesContent":["import { readonly, ref } from 'vue'\n\ntype UseFileDialogOptions = {\n multiple?: boolean\n /** @default '*' */\n accept?: string\n onChange?: (files: FileList | null) => void | Promise<void>\n onError?: () => void | Promise<void>\n}\n\n/**\n * Simplified interface for opening a file picker dialog\n * Derived from vueuse @see https://vueuse.org/useFileDialog\n */\nexport function useFileDialog({ multiple, accept, onChange, onError }: UseFileDialogOptions = {}) {\n const files = ref<FileList | null>(null)\n\n let input: HTMLInputElement | undefined\n if (typeof document !== 'undefined') {\n input = document.createElement('input')\n input.type = 'file'\n\n input.onchange = (event: Event) => {\n if (!(event.target instanceof HTMLInputElement)) {\n return\n }\n const result = event.target\n files.value = result.files\n onChange?.(files.value)\n }\n\n input.onerror = () => onError?.()\n\n input.multiple = multiple!\n input.accept = accept!\n }\n\n const open = () => {\n if (!input) {\n return onError?.()\n }\n\n input.click()\n }\n\n return {\n files: readonly(files),\n open,\n }\n}\n"],"mappings":";;;;;;AAcA,SAAgB,cAAc,EAAE,UAAU,QAAQ,UAAU,YAAkC,CAAC,GAAG;CAChG,MAAM,QAAQ,IAAqB,IAAI;CAEvC,IAAI;CACJ,IAAI,OAAO,aAAa,aAAa;EACnC,QAAQ,SAAS,cAAc,OAAO;EACtC,MAAM,OAAO;EAEb,MAAM,YAAY,UAAiB;GACjC,IAAI,EAAE,MAAM,kBAAkB,mBAC5B;GAEF,MAAM,SAAS,MAAM;GACrB,MAAM,QAAQ,OAAO;GACrB,WAAW,MAAM,KAAK;EACxB;EAEA,MAAM,gBAAgB,UAAU;EAEhC,MAAM,WAAW;EACjB,MAAM,SAAS;CACjB;CAEA,MAAM,aAAa;EACjB,IAAI,CAAC,OACH,OAAO,UAAU;EAGnB,MAAM,MAAM;CACd;CAEA,OAAO;EACL,OAAO,SAAS,KAAK;EACrB;CACF;AACF"}