@scalar/api-client 2.38.2 → 2.38.3

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 (128) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{AddressBar-B4xnl66I.js → AddressBar-CX8xiYoe.js} +4 -4
  3. package/dist/{AddressBar-B4xnl66I.js.map → AddressBar-CX8xiYoe.js.map} +1 -1
  4. package/dist/{App-BVH4lIe8.js → App-BpNPKHmM.js} +4 -4
  5. package/dist/{App-BVH4lIe8.js.map → App-BpNPKHmM.js.map} +1 -1
  6. package/dist/{App-CvClwSlM.js → App-Ckirvnv1.js} +2 -2
  7. package/dist/{App-CvClwSlM.js.map → App-Ckirvnv1.js.map} +1 -1
  8. package/dist/{CodeInput-C-igR77V.js → CodeInput-BN7uw3Bh.js} +2 -2
  9. package/dist/{CodeInput-C-igR77V.js.map → CodeInput-BN7uw3Bh.js.map} +1 -1
  10. package/dist/{Collection-4MT9WmDD.js → Collection-ChAxs3rz.js} +2 -2
  11. package/dist/{Collection-4MT9WmDD.js.map → Collection-ChAxs3rz.js.map} +1 -1
  12. package/dist/{CollectionAuthentication-MHWQpw74.js → CollectionAuthentication-BDpvv8cA.js} +5 -5
  13. package/dist/{CollectionAuthentication-MHWQpw74.js.map → CollectionAuthentication-BDpvv8cA.js.map} +1 -1
  14. package/dist/{CollectionEnvironment-Dw35vIqo.js → CollectionEnvironment-dwisJ-h5.js} +4 -4
  15. package/dist/{CollectionEnvironment-Dw35vIqo.js.map → CollectionEnvironment-dwisJ-h5.js.map} +1 -1
  16. package/dist/{CollectionOverview-TUdDIu5f.js → CollectionOverview-CJ9-Vmei.js} +3 -3
  17. package/dist/{CollectionOverview-TUdDIu5f.js.map → CollectionOverview-CJ9-Vmei.js.map} +1 -1
  18. package/dist/{CollectionServers-BrjTCfDe.js → CollectionServers-BWkIGwz4.js} +5 -5
  19. package/dist/{CollectionServers-BrjTCfDe.js.map → CollectionServers-BWkIGwz4.js.map} +1 -1
  20. package/dist/{CollectionSettings-HVSlp2Gv.js → CollectionSettings-CqUUYOym.js} +2 -2
  21. package/dist/{CollectionSettings-HVSlp2Gv.js.map → CollectionSettings-CqUUYOym.js.map} +1 -1
  22. package/dist/{CommandPalette-CL8k4CoN.js → CommandPalette-BiA0IgO8.js} +2 -2
  23. package/dist/{CommandPalette-CL8k4CoN.js.map → CommandPalette-BiA0IgO8.js.map} +1 -1
  24. package/dist/{Cookies-DbOKTi1f.js → Cookies-CNRSxP8J.js} +8 -8
  25. package/dist/{Cookies-DbOKTi1f.js.map → Cookies-CNRSxP8J.js.map} +1 -1
  26. package/dist/{DataTableInput-yaU5g-kP.js → DataTableInput-SkIUPlrB.js} +2 -2
  27. package/dist/{DataTableInput-yaU5g-kP.js.map → DataTableInput-SkIUPlrB.js.map} +1 -1
  28. package/dist/{Environment-DJatRQIg.js → Environment-D_CbZk0A.js} +5 -5
  29. package/dist/{Environment-DJatRQIg.js.map → Environment-D_CbZk0A.js.map} +1 -1
  30. package/dist/{EnvironmentModal-DBEJ4Kzj.js → EnvironmentModal-CcyqnPc2.js} +2 -2
  31. package/dist/{EnvironmentModal-DBEJ4Kzj.js.map → EnvironmentModal-CcyqnPc2.js.map} +1 -1
  32. package/dist/{Form-CSKzyHGO.js → Form-bA4bV_oA.js} +3 -3
  33. package/dist/{Form-CSKzyHGO.js.map → Form-bA4bV_oA.js.map} +1 -1
  34. package/dist/{ImportCollection-DfX1UQ5u.js → ImportCollection-BIYMxB9Q.js} +2 -2
  35. package/dist/{ImportCollection-DfX1UQ5u.js.map → ImportCollection-BIYMxB9Q.js.map} +1 -1
  36. package/dist/{MainLayout-BEFMl1ud.js → MainLayout-oMIJ5QXF.js} +3 -3
  37. package/dist/{MainLayout-BEFMl1ud.js.map → MainLayout-oMIJ5QXF.js.map} +1 -1
  38. package/dist/{Modal-sQ9vH6MN.js → Modal-DkOa_KK0.js} +2 -2
  39. package/dist/{Modal-sQ9vH6MN.js.map → Modal-DkOa_KK0.js.map} +1 -1
  40. package/dist/{Request-gscRsGQ8.js → Request-BWfYWyBa.js} +10 -10
  41. package/dist/{Request-gscRsGQ8.js.map → Request-BWfYWyBa.js.map} +1 -1
  42. package/dist/{RequestAuth-BzBfIysT.js → RequestAuth-BU6ubH-c.js} +3 -3
  43. package/dist/{RequestAuth-BzBfIysT.js.map → RequestAuth-BU6ubH-c.js.map} +1 -1
  44. package/dist/{RequestRoot-3Bj8JZD-.js → RequestRoot-7xhK5_qr.js} +7 -7
  45. package/dist/{RequestRoot-3Bj8JZD-.js.map → RequestRoot-7xhK5_qr.js.map} +1 -1
  46. package/dist/{RequestSection-HhdJj9hW.js → RequestSection-Bx8UHW-k.js} +4 -4
  47. package/dist/{RequestSection-HhdJj9hW.js.map → RequestSection-Bx8UHW-k.js.map} +1 -1
  48. package/dist/{ResponseSection-DMJ0tw8E.js → ResponseSection-CLrgLMN_.js} +3 -3
  49. package/dist/{ResponseSection-DMJ0tw8E.js.map → ResponseSection-CLrgLMN_.js.map} +1 -1
  50. package/dist/{Server-DnA_BzPS.js → Server-BS4zjUdO.js} +2 -2
  51. package/dist/{Server-DnA_BzPS.js.map → Server-BS4zjUdO.js.map} +1 -1
  52. package/dist/{Settings-CYZzdJPO.js → Settings-BuLKHzRY.js} +2 -2
  53. package/dist/{Settings-CYZzdJPO.js.map → Settings-BuLKHzRY.js.map} +1 -1
  54. package/dist/{Sidebar-C6AdX6-N.js → Sidebar-Xl9_nFXX.js} +2 -2
  55. package/dist/{Sidebar-C6AdX6-N.js.map → Sidebar-Xl9_nFXX.js.map} +1 -1
  56. package/dist/components/AddressBar/index.js +3 -3
  57. package/dist/components/CodeInput/index.js +1 -1
  58. package/dist/components/CommandPalette/index.js +1 -1
  59. package/dist/components/DataTable/index.js +2 -2
  60. package/dist/components/ImportCollection/index.js +1 -1
  61. package/dist/components/Server/index.js +1 -1
  62. package/dist/components/Sidebar/index.js +1 -1
  63. package/dist/components/index.js +4 -4
  64. package/dist/{components-CSxJTn6F.js → components-DfJHvSLM.js} +2 -2
  65. package/dist/{components-CSxJTn6F.js.map → components-DfJHvSLM.js.map} +1 -1
  66. package/dist/get-resolved-url-SybDPV0U.js +85 -0
  67. package/dist/get-resolved-url-SybDPV0U.js.map +1 -0
  68. package/dist/{get-server-url-o3On8CEr.js → get-server-url-UVN-dx79.js} +1 -1
  69. package/dist/{get-server-url-o3On8CEr.js.map → get-server-url-UVN-dx79.js.map} +1 -1
  70. package/dist/index.js +5 -5
  71. package/dist/layouts/App/index.js +3 -3
  72. package/dist/layouts/Modal/index.js +1 -1
  73. package/dist/layouts/Web/index.js +4 -4
  74. package/dist/libs/index.js +1 -1
  75. package/dist/{operation-block-BnMIKAOh.js → operation-block-DE-hoO03.js} +67 -17
  76. package/dist/operation-block-DE-hoO03.js.map +1 -0
  77. package/dist/{operation-code-sample-ZUTueV3v.js → operation-code-sample-xgx4qi2H.js} +22 -10
  78. package/dist/operation-code-sample-xgx4qi2H.js.map +1 -0
  79. package/dist/{request-block-DwsGy64Q.js → request-block-N7dPFyrG.js} +4 -4
  80. package/dist/{request-block-DwsGy64Q.js.map → request-block-N7dPFyrG.js.map} +1 -1
  81. package/dist/{scalar-address-bar-block--Vs6IBU1.js → scalar-address-bar-block-BbysOhkE.js} +2 -2
  82. package/dist/{scalar-address-bar-block--Vs6IBU1.js.map → scalar-address-bar-block-BbysOhkE.js.map} +1 -1
  83. package/dist/{scalar-auth-selector-block-DI3DLag9.js → scalar-auth-selector-block-Bs79QOMA.js} +12 -9
  84. package/dist/scalar-auth-selector-block-Bs79QOMA.js.map +1 -0
  85. package/dist/store/index.js +1 -1
  86. package/dist/{store-DpSUVhjp.js → store-DaPoVtIS.js} +15 -15
  87. package/dist/{store-DpSUVhjp.js.map → store-DaPoVtIS.js.map} +1 -1
  88. package/dist/style.css +1 -1
  89. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
  90. package/dist/v2/blocks/operation-block/helpers/apply-allow-reserved-to-url.d.ts +6 -0
  91. package/dist/v2/blocks/operation-block/helpers/apply-allow-reserved-to-url.d.ts.map +1 -0
  92. package/dist/v2/blocks/operation-block/helpers/build-request-body.d.ts.map +1 -1
  93. package/dist/v2/blocks/operation-block/helpers/build-request-parameters.d.ts +1 -0
  94. package/dist/v2/blocks/operation-block/helpers/build-request-parameters.d.ts.map +1 -1
  95. package/dist/v2/blocks/operation-block/helpers/build-request.d.ts.map +1 -1
  96. package/dist/v2/blocks/operation-block/helpers/get-resolved-url.d.ts +2 -1
  97. package/dist/v2/blocks/operation-block/helpers/get-resolved-url.d.ts.map +1 -1
  98. package/dist/v2/blocks/operation-block/index.js +11 -11
  99. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.d.ts.map +1 -1
  100. package/dist/v2/blocks/operation-code-sample/index.js +1 -1
  101. package/dist/v2/blocks/request-block/helpers/get-default-headers.d.ts.map +1 -1
  102. package/dist/v2/blocks/request-block/index.js +5 -5
  103. package/dist/v2/blocks/response-block/index.js +2 -2
  104. package/dist/v2/blocks/scalar-address-bar-block/index.js +1 -1
  105. package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.d.ts.map +1 -1
  106. package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts.map +1 -1
  107. package/dist/v2/blocks/scalar-auth-selector-block/index.js +3 -3
  108. package/dist/v2/constants.d.ts +3 -0
  109. package/dist/v2/constants.d.ts.map +1 -0
  110. package/dist/v2/features/app/components/index.js +4 -4
  111. package/dist/v2/features/app/index.js +14 -14
  112. package/dist/v2/features/app/index.js.map +1 -1
  113. package/dist/v2/features/collection/components/Authentication.vue.d.ts.map +1 -1
  114. package/dist/v2/features/modal/index.js +10 -10
  115. package/dist/v2/features/operation/Operation.vue.d.ts.map +1 -1
  116. package/dist/v2/features/operation/helpers/get-selected-security.d.ts +6 -1
  117. package/dist/v2/features/operation/helpers/get-selected-security.d.ts.map +1 -1
  118. package/dist/v2/features/operation/index.js +10 -10
  119. package/dist/views/Request/RequestSection/RequestAuth/index.js +3 -3
  120. package/dist/views/Request/RequestSection/index.js +4 -4
  121. package/dist/views/Request/ResponseSection/index.js +3 -3
  122. package/dist/views/Request/components/index.js +1 -1
  123. package/package.json +13 -13
  124. package/dist/get-resolved-url-BUCwrBzc.js +0 -30
  125. package/dist/get-resolved-url-BUCwrBzc.js.map +0 -1
  126. package/dist/operation-block-BnMIKAOh.js.map +0 -1
  127. package/dist/operation-code-sample-ZUTueV3v.js.map +0 -1
  128. package/dist/scalar-auth-selector-block-DI3DLag9.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { n as formatMs } from "./formatters-DOGXZq9R.js";
2
2
  import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BmmBcIzD.js";
3
3
  import { t as HttpMethod_default } from "./HttpMethod-rnWEgC3T.js";
4
- import { t as getResolvedUrl } from "./get-resolved-url-BUCwrBzc.js";
4
+ import { t as getResolvedUrl } from "./get-resolved-url-SybDPV0U.js";
5
5
  import { t as CodeInput_default } from "./code-input-iq-moLxi.js";
6
6
  import { t as ValueEmitter_default } from "./ValueEmitter-QYkZ9Hdc.js";
7
7
  import { t as ServerDropdown_default } from "./server-tcI-OCyx.js";
@@ -422,4 +422,4 @@ var AddressBar_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @_
422
422
  //#endregion
423
423
  export { AddressBar_default as t };
424
424
 
425
- //# sourceMappingURL=scalar-address-bar-block--Vs6IBU1.js.map
425
+ //# sourceMappingURL=scalar-address-bar-block-BbysOhkE.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scalar-address-bar-block--Vs6IBU1.js","names":[],"sources":["../src/v2/blocks/scalar-address-bar-block/hooks/use-loading-animation.ts","../src/v2/blocks/scalar-address-bar-block/components/httpStatusCodeColors.ts","../src/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue","../src/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue","../src/v2/blocks/scalar-address-bar-block/components/AddressBar.vue","../src/v2/blocks/scalar-address-bar-block/components/AddressBar.vue"],"sourcesContent":["import type { Ref } from 'vue'\nimport { ref } from 'vue'\n\n/**\n * Constants for the loading animation behavior.\n * These control how the progress bar animates during and after requests.\n */\nconst TICK_INTERVAL_MS = 20\nconst MAX_PERCENTAGE = 100\nconst MIN_PERCENTAGE = 0\nconst ASYMPTOTIC_LIMIT = 15 // Stops at 85% (100 - 15) to show ongoing progress\nconst ASYMPTOTIC_DIVISOR = 60 // Controls the speed of asymptotic approach\nconst FINISH_ANIMATION_DURATION_MS = 400\nconst FINISH_ANIMATION_STEPS = FINISH_ANIMATION_DURATION_MS / TICK_INTERVAL_MS\n\n/**\n * Manages the loading animation for the address bar.\n *\n * The animation has two phases:\n * 1. While requesting: Animates asymptotically toward 85% to indicate ongoing work\n * 2. After request completes: Animates linearly to 100% over 400ms for smooth completion\n *\n * This creates a natural feel where the bar does not instantly jump to 100%,\n * making the loading experience more predictable and less jarring.\n *\n * @returns An object with methods to control the loading animation and the current percentage\n */\nexport const useLoadingAnimation = (): {\n startLoading: () => void\n stopLoading: () => void\n percentage: Ref<number>\n isLoading: Ref<boolean>\n} => {\n /** The current loading percentage from 100 (not started) to 0 (complete) */\n const percentage = ref(MAX_PERCENTAGE)\n /** Tracks how much percentage was remaining when the request completed */\n const remaining = ref(0)\n /** Indicates whether a request is currently in progress */\n const isRequesting = ref(false)\n /** The interval timer that drives the animation */\n const interval = ref<ReturnType<typeof setInterval>>()\n\n /**\n * Resets the animation state to initial values.\n * This is called when the animation completes.\n */\n const resetAnimation = (): void => {\n clearInterval(interval.value)\n interval.value = undefined\n percentage.value = MAX_PERCENTAGE\n isRequesting.value = false\n }\n\n /**\n * Advances the loading animation by one tick.\n * Uses different animation strategies based on whether a request is active.\n */\n const load = (): void => {\n if (isRequesting.value) {\n // Asymptotic approach: Slows down as it nears 85% to indicate ongoing work\n // without reaching 100% until the request actually completes\n percentage.value -= (percentage.value - ASYMPTOTIC_LIMIT) / ASYMPTOTIC_DIVISOR\n } else {\n // Linear finish: Complete the remaining percentage smoothly over a fixed duration\n // to avoid jarring jumps when the request completes\n percentage.value -= remaining.value / FINISH_ANIMATION_STEPS\n }\n\n if (percentage.value <= MIN_PERCENTAGE) {\n resetAnimation()\n }\n }\n\n /**\n * Starts the loading animation.\n * If called while the finishing animation is running, it switches back to requesting mode.\n * This handles the case where a new request starts before the previous animation completes.\n */\n const startLoading = (): void => {\n if (interval.value) {\n // Switch back to requesting mode if we are in finishing mode.\n // This prevents the animation from completing while a new request is active.\n isRequesting.value = true\n return\n }\n isRequesting.value = true\n interval.value = setInterval(load, TICK_INTERVAL_MS)\n }\n\n /**\n * Marks the request as complete and begins the finish animation.\n * The animation will continue until it reaches 100% to provide visual feedback.\n */\n const stopLoading = (): void => {\n remaining.value = percentage.value\n isRequesting.value = false\n }\n\n return {\n startLoading,\n stopLoading,\n percentage,\n isLoading: isRequesting,\n }\n}\n","const STATUS_CODES_COLORS = {\n 100: {\n color: 'text-yellow',\n },\n 200: {\n color: 'text-green',\n },\n 202: {\n color: 'text-green',\n },\n 300: {\n color: 'text-blue',\n },\n 304: {\n color: 'text-blue',\n },\n 400: {\n color: 'text-red',\n },\n 401: {\n color: 'text-orange',\n },\n 422: {\n color: 'text-yellow',\n },\n 423: {\n color: 'text-purple',\n },\n 505: {\n color: 'text-orange',\n },\n} as const\n\ntype StatusCode = keyof typeof STATUS_CODES_COLORS\n\nexport const getStatusCodeColor = (statusCode: number) => {\n const code = statusCode as StatusCode\n return (\n STATUS_CODES_COLORS[code] || {\n /** default color */\n color: 'text-grey',\n }\n )\n}\n","<script setup lang=\"ts\">\nimport { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'\nimport {\n ScalarFloating,\n ScalarFloatingBackdrop,\n ScalarIcon,\n} from '@scalar/components'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { httpStatusCodes } from '@scalar/oas-utils/helpers'\n\nimport { HttpMethod } from '@/components/HttpMethod'\nimport { formatMs } from '@/libs/formatters'\nimport ValueEmitter from '@/v2/components/layout/ValueEmitter.vue'\n\nimport { getStatusCodeColor } from './httpStatusCodeColors'\n\nexport type History = {\n method: HttpMethodType\n path: string\n duration: number\n status: number\n}\n\nconst { target } = defineProps<{\n /** The id of the target to use for the popover (e.g. address bar) */\n target: string\n /** List of all request history items */\n history: History[]\n}>()\n\nconst emits = defineEmits<{\n /** Select a request history item by index */\n (e: 'select:history:item', payload: { index: number }): void\n /** Update the open state of the history popover */\n (e: 'update:open', value: boolean): void\n}>()\n</script>\n<template>\n <Menu\n v-slot=\"{ open }\"\n as=\"div\">\n <!-- Emit the slot value back out the parent -->\n <ValueEmitter\n :value=\"open\"\n @change=\"(value) => emits('update:open', value)\"\n @unmount=\"emits('update:open', false)\" />\n\n <ScalarFloating\n :offset=\"0\"\n resize\n :target=\"target\">\n <!-- History -->\n <MenuButton\n v-if=\"history.length\"\n class=\"address-bar-history-button text-c-3 focus:text-c-1 relative mr-1 rounded-lg p-1.5\">\n <ScalarIcon\n icon=\"History\"\n size=\"sm\"\n thickness=\"2.25\" />\n <span class=\"sr-only\">Request History</span>\n </MenuButton>\n <!-- History shadow and placement-->\n <template\n v-if=\"open\"\n #floating=\"{ width }\">\n <!-- History Item -->\n <MenuItems\n class=\"custom-scroll grid max-h-[inherit] grid-cols-[44px_1fr_repeat(3,auto)] items-center p-0.75\"\n static\n :style=\"{ width }\">\n <MenuItem\n v-for=\"(entry, index) in history\"\n :key=\"index\"\n as=\"button\"\n class=\"font-code ui-active:*:bg-b-2 text-c-2 contents text-sm font-medium *:flex *:h-8 *:cursor-pointer *:items-center *:rounded-none *:px-1.5 *:first:rounded-l *:last:rounded-r\"\n :value=\"index\"\n @click=\"emits('select:history:item', { index })\">\n <HttpMethod\n class=\"text-[11px]\"\n :method=\"entry.method\" />\n <div class=\"min-w-0\">\n <div class=\"text-c-1 min-w-0 truncate\">\n {{ entry.path }}\n </div>\n </div>\n <div>{{ formatMs(entry.duration) }}</div>\n <div :class=\"[getStatusCodeColor(entry.status).color]\">\n {{ entry.status }}\n </div>\n <div>\n {{ httpStatusCodes[entry.status]?.name }}\n </div>\n </MenuItem>\n </MenuItems>\n <ScalarFloatingBackdrop class=\"inset-x-px rounded-none rounded-b-lg\" />\n </template>\n </ScalarFloating>\n </Menu>\n</template>\n<style scoped>\n.address-bar-history-button:hover {\n background: var(--scalar-background-3);\n}\n.address-bar-history-button:focus-within {\n background: var(--scalar-background-2);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'\nimport {\n ScalarFloating,\n ScalarFloatingBackdrop,\n ScalarIcon,\n} from '@scalar/components'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { httpStatusCodes } from '@scalar/oas-utils/helpers'\n\nimport { HttpMethod } from '@/components/HttpMethod'\nimport { formatMs } from '@/libs/formatters'\nimport ValueEmitter from '@/v2/components/layout/ValueEmitter.vue'\n\nimport { getStatusCodeColor } from './httpStatusCodeColors'\n\nexport type History = {\n method: HttpMethodType\n path: string\n duration: number\n status: number\n}\n\nconst { target } = defineProps<{\n /** The id of the target to use for the popover (e.g. address bar) */\n target: string\n /** List of all request history items */\n history: History[]\n}>()\n\nconst emits = defineEmits<{\n /** Select a request history item by index */\n (e: 'select:history:item', payload: { index: number }): void\n /** Update the open state of the history popover */\n (e: 'update:open', value: boolean): void\n}>()\n</script>\n<template>\n <Menu\n v-slot=\"{ open }\"\n as=\"div\">\n <!-- Emit the slot value back out the parent -->\n <ValueEmitter\n :value=\"open\"\n @change=\"(value) => emits('update:open', value)\"\n @unmount=\"emits('update:open', false)\" />\n\n <ScalarFloating\n :offset=\"0\"\n resize\n :target=\"target\">\n <!-- History -->\n <MenuButton\n v-if=\"history.length\"\n class=\"address-bar-history-button text-c-3 focus:text-c-1 relative mr-1 rounded-lg p-1.5\">\n <ScalarIcon\n icon=\"History\"\n size=\"sm\"\n thickness=\"2.25\" />\n <span class=\"sr-only\">Request History</span>\n </MenuButton>\n <!-- History shadow and placement-->\n <template\n v-if=\"open\"\n #floating=\"{ width }\">\n <!-- History Item -->\n <MenuItems\n class=\"custom-scroll grid max-h-[inherit] grid-cols-[44px_1fr_repeat(3,auto)] items-center p-0.75\"\n static\n :style=\"{ width }\">\n <MenuItem\n v-for=\"(entry, index) in history\"\n :key=\"index\"\n as=\"button\"\n class=\"font-code ui-active:*:bg-b-2 text-c-2 contents text-sm font-medium *:flex *:h-8 *:cursor-pointer *:items-center *:rounded-none *:px-1.5 *:first:rounded-l *:last:rounded-r\"\n :value=\"index\"\n @click=\"emits('select:history:item', { index })\">\n <HttpMethod\n class=\"text-[11px]\"\n :method=\"entry.method\" />\n <div class=\"min-w-0\">\n <div class=\"text-c-1 min-w-0 truncate\">\n {{ entry.path }}\n </div>\n </div>\n <div>{{ formatMs(entry.duration) }}</div>\n <div :class=\"[getStatusCodeColor(entry.status).color]\">\n {{ entry.status }}\n </div>\n <div>\n {{ httpStatusCodes[entry.status]?.name }}\n </div>\n </MenuItem>\n </MenuItems>\n <ScalarFloatingBackdrop class=\"inset-x-px rounded-none rounded-b-lg\" />\n </template>\n </ScalarFloating>\n </Menu>\n</template>\n<style scoped>\n.address-bar-history-button:hover {\n background: var(--scalar-background-3);\n}\n.address-bar-history-button:focus-within {\n background: var(--scalar-background-2);\n}\n</style>\n","<script lang=\"ts\">\n/**\n * AddressBar component\n * This component is used to display the address bar for the operation block\n * It is used to display the path, method, server, and history for the operation\n */\nexport default {\n name: 'AddressBar',\n}\nexport type AddressBarProps = {\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** Currently selected server */\n server: ServerObject | null\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** List of request history */\n history: History[]\n /** Client layout */\n layout: ClientLayout\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Environment */\n environment: XScalarEnvironment\n /** Meta information for the server */\n serverMeta: ServerMeta\n}\n</script>\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarIcon,\n ScalarWrappingText,\n} from '@scalar/components'\nimport { REQUEST_METHODS } from '@scalar/helpers/http/http-info'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCopy, ScalarIconWarningCircle } from '@scalar/icons'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport type {\n ApiReferenceEvents,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport {\n computed,\n onBeforeUnmount,\n onMounted,\n ref,\n useId,\n useTemplateRef,\n} from 'vue'\n\nimport { HttpMethod } from '@/components/HttpMethod'\nimport { type ClientLayout } from '@/hooks'\nimport { getResolvedUrl } from '@/v2/blocks/operation-block/helpers/get-resolved-url'\nimport { useLoadingAnimation } from '@/v2/blocks/scalar-address-bar-block/hooks/use-loading-animation'\nimport { CodeInput } from '@/v2/components/code-input'\nimport { ServerDropdown } from '@/v2/components/server'\n\nimport AddressBarHistory, { type History } from './AddressBarHistory.vue'\n\nconst {\n path,\n method,\n layout,\n eventBus,\n history,\n server,\n servers,\n environment,\n serverMeta,\n} = defineProps<AddressBarProps>()\n\nconst emit = defineEmits<{\n /** Execute the current operation example */\n (e: 'execute'): void\n /** Select a request history item by index */\n (e: 'select:history:item', payload: { index: number }): void\n}>()\n\nconst id = useId()\nconst { percentage, startLoading, stopLoading, isLoading } =\n useLoadingAnimation()\n\n/** Calculate the style for the address bar */\nconst style = computed(() => ({\n backgroundColor: `color-mix(in srgb, transparent 90%, ${REQUEST_METHODS[method].colorVar})`,\n transform: `translate3d(-${percentage.value}%,0,0)`,\n}))\n\nconst pathConflict = ref<string | null>(null)\nconst methodConflict = ref<HttpMethodType | null>(null)\n\n/** Whether there is a path or method conflict */\nconst hasConflict = computed(() => methodConflict.value || pathConflict.value)\n\n/** Emit the path/method update event with conflict handling */\nconst emitPathMethodUpdate = (\n targetMethod: HttpMethodType,\n targetPath: string,\n /** We only want to debounce when the path changes */\n emitOptions?: { debounceKey?: string },\n): void => {\n const position = addressBarRef.value?.cursorPosition()\n eventBus.emit(\n 'operation:update:pathMethod',\n {\n meta: { method, path },\n payload: { method: targetMethod, path: targetPath },\n callback: (status) => {\n // Clear conflicts if the operation was successful or no change was made\n if (status === 'success' || status === 'no-change') {\n methodConflict.value = null\n pathConflict.value = null\n }\n if (status === 'success') {\n eventBus.emit('ui:focus:address-bar', { position })\n }\n // Otherwise set the conflict if needed\n else if (status === 'conflict') {\n if (targetMethod !== method) {\n methodConflict.value = targetMethod\n }\n if (targetPath !== path) {\n pathConflict.value = targetPath\n }\n }\n },\n },\n emitOptions,\n )\n}\n\n/** Update the operation's HTTP method, handling conflicts */\nconst handleMethodChange = (newMethod: HttpMethodType): void =>\n emitPathMethodUpdate(newMethod, pathConflict.value ?? path)\n\n/** Update the operation's path, handling conflicts */\nconst handlePathChange = (newPath: string): void => {\n const normalizedPath = newPath.startsWith('/') ? newPath : `/${newPath}`\n emitPathMethodUpdate(methodConflict.value ?? method, normalizedPath, {\n debounceKey: `operation:update:pathMethod-${path}-${method}`,\n })\n}\n\n/** Handle focus events */\nconst sendButtonRef = useTemplateRef('sendButtonRef')\nconst addressBarRef = useTemplateRef('addressBarRef')\nconst handleFocusSendButton = () => sendButtonRef.value?.$el?.focus()\n\nconst handleFocusAddressBar = (\n payload: ApiReferenceEvents['ui:focus:address-bar'],\n) => {\n // If it already has focus we just propagate native behavior which should focus the browser address bar\n if (addressBarRef.value?.isFocused && layout !== 'desktop') {\n return\n }\n\n const position = payload && 'position' in payload ? payload.position : 'end'\n addressBarRef.value?.focus(position)\n\n if (payload && 'event' in payload) {\n payload.event.preventDefault()\n }\n}\n\nonMounted(() => {\n eventBus.on('ui:focus:address-bar', handleFocusAddressBar)\n eventBus.on('ui:focus:send-button', handleFocusSendButton)\n eventBus.on('hooks:on:request:sent', startLoading)\n eventBus.on('hooks:on:request:complete', stopLoading)\n})\n\nonBeforeUnmount(() => {\n eventBus.off('ui:focus:address-bar', handleFocusAddressBar)\n eventBus.off('ui:focus:send-button', handleFocusSendButton)\n eventBus.off('hooks:on:request:sent', startLoading)\n eventBus.off('hooks:on:request:complete', stopLoading)\n\n // Stop the animation when the component is unmounted\n // This is to prevent the animation from continuing after the component is unmounted\n stopLoading()\n})\n\nconst { copyToClipboard } = useClipboard()\n\nconst copyUrl = async () => {\n await copyToClipboard(\n getResolvedUrl({ environment, server, path, pathVariables: {} }),\n )\n}\n\nconst isServerDropdownOpen = ref(false)\nconst isHistoryDropdownOpen = ref(false)\n\n/** Whether either dropdown is open */\nconst isDropdownOpen = computed(\n () => isServerDropdownOpen.value || isHistoryDropdownOpen.value,\n)\n\nconst navigateToServersPage = () => {\n if (serverMeta.type === 'operation') {\n return eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'servers',\n operationPath: serverMeta.path,\n method: serverMeta.method,\n })\n }\n return eventBus.emit('ui:navigate', {\n page: 'document',\n path: 'servers',\n })\n}\n\ndefineExpose({\n methodConflict,\n pathConflict,\n})\n</script>\n<template>\n <div\n :id=\"id\"\n class=\"scalar-address-bar order-last flex h-(--scalar-address-bar-height) w-full [--scalar-address-bar-height:32px] lg:order-0 lg:w-auto\">\n <!-- Address Bar -->\n <div\n class=\"address-bar-bg-states text-xxs group relative order-last flex w-full max-w-[calc(100dvw-24px)] flex-1 flex-row items-stretch rounded-lg p-0.75 lg:order-none lg:max-w-[580px] lg:min-w-[580px] xl:max-w-[720px] xl:min-w-[720px]\"\n :class=\"{\n 'outline-c-danger outline': hasConflict,\n 'rounded-b-none': isDropdownOpen,\n }\">\n <div\n class=\"pointer-events-none absolute top-0 left-0 block h-full w-full overflow-hidden rounded-lg border\"\n :class=\"{\n 'rounded-b-none': isDropdownOpen,\n }\">\n <div\n class=\"absolute top-0 left-0 h-full w-full\"\n :style />\n </div>\n <div class=\"flex gap-1\">\n <HttpMethod\n :isEditable=\"layout !== 'modal'\"\n isSquare\n :method=\"methodConflict ?? method\"\n teleport\n @change=\"handleMethodChange\" />\n </div>\n\n <div\n class=\"scroll-timeline-x scroll-timeline-x-hidden relative flex w-full bg-blend-normal\">\n <!-- Servers -->\n <ServerDropdown\n v-if=\"servers.length\"\n :layout=\"layout\"\n :meta=\"serverMeta\"\n :server=\"server\"\n :servers=\"servers\"\n :target=\"id\"\n @update:open=\"(value) => (isServerDropdownOpen = value)\"\n @update:selectedServer=\"\n (payload) => eventBus.emit('server:update:selected', payload)\n \"\n @update:servers=\"navigateToServersPage\"\n @update:variable=\"\n (payload) => eventBus.emit('server:update:variables', payload)\n \" />\n\n <div class=\"fade-left\" />\n <!-- Path + URL + env vars -->\n <CodeInput\n ref=\"addressBarRef\"\n alwaysEmitChange\n aria-label=\"Path\"\n class=\"min-w-fit outline-none\"\n disableCloseBrackets\n :disabled=\"layout === 'modal'\"\n disableEnter\n disableTabIndent\n :emitOnBlur=\"false\"\n :environment=\"environment\"\n importCurl\n :layout=\"layout\"\n :modelValue=\"path\"\n :placeholder=\"server ? '' : 'Enter a URL'\"\n server\n @submit=\"emit('execute')\"\n @update:modelValue=\"handlePathChange\" />\n <div class=\"fade-right\" />\n </div>\n\n <!-- Copy url button -->\n <ScalarButton\n class=\"hover:bg-b-3 mx-1\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"copyUrl\">\n <ScalarIconCopy />\n <span class=\"sr-only\">Copy URL</span>\n </ScalarButton>\n\n <AddressBarHistory\n :history=\"history\"\n :target=\"id\"\n @select:history:item=\"(payload) => emit('select:history:item', payload)\"\n @update:open=\"(value) => (isHistoryDropdownOpen = value)\" />\n <!-- Error message -->\n <div\n v-if=\"hasConflict\"\n class=\"absolute inset-x-0 top-[calc(100%+4px)] flex flex-col items-center rounded px-6\">\n <div\n class=\"text-c-danger bg-b-danger border-c-danger flex items-center gap-1 rounded border p-1\">\n <ScalarIconWarningCircle size=\"sm\" />\n <div class=\"min-w-0 flex-1\">\n A\n <em>{{ methodConflict?.toUpperCase() ?? method.toUpperCase() }}</em>\n request to\n <ScalarWrappingText :text=\"pathConflict ?? path\" />\n already exists in this document\n </div>\n </div>\n </div>\n <ScalarButton\n ref=\"sendButtonRef\"\n class=\"relative h-auto shrink-0 overflow-hidden py-1 pr-2.5 pl-2 font-bold\"\n :disabled=\"isLoading\"\n @click=\"emit('execute')\">\n <span\n aria-hidden=\"true\"\n class=\"inline-flex items-center gap-1\">\n <ScalarIcon\n class=\"relative shrink-0 fill-current\"\n icon=\"Play\"\n size=\"xs\" />\n <span class=\"text-xxs hidden lg:flex\">Send</span>\n </span>\n <span class=\"sr-only\">\n Send {{ method }} request to {{ server?.url ?? '' }}{{ path }}\n </span>\n </ScalarButton>\n </div>\n </div>\n</template>\n<style scoped>\n:deep(.cm-editor) {\n height: 100%;\n outline: none;\n width: 100%;\n}\n:deep(.cm-line) {\n padding: 0;\n}\n:deep(.cm-content) {\n padding: 0;\n display: flex;\n align-items: center;\n font-size: var(--scalar-small);\n}\n.scroll-timeline-x {\n scroll-timeline: --scroll-timeline x;\n /* Firefox supports */\n scroll-timeline: --scroll-timeline horizontal;\n -ms-overflow-style: none; /* IE and Edge */\n}\n.scroll-timeline-x-hidden {\n overflow-x: auto;\n}\n.scroll-timeline-x-hidden :deep(.cm-scroller) {\n scrollbar-width: none;\n -ms-overflow-style: none;\n padding-right: 20px;\n overflow: auto;\n}\n.scroll-timeline-x-hidden::-webkit-scrollbar {\n width: 0;\n height: 0;\n display: none;\n}\n.scroll-timeline-x-hidden :deep(.cm-scroller::-webkit-scrollbar) {\n width: 0;\n height: 0;\n display: none;\n}\n.scroll-timeline-x-address {\n line-height: 27px;\n scrollbar-width: none; /* Firefox */\n}\n/* make clickable are to left of send button */\n.scroll-timeline-x-address:after {\n content: '';\n position: absolute;\n height: 100%;\n width: 24px;\n right: 0;\n cursor: text;\n}\n.scroll-timeline-x-address:empty:before {\n content: 'Enter URL or cURL request';\n color: var(--scalar-color-3);\n pointer-events: none;\n}\n.fade-left,\n.fade-right {\n content: '';\n position: sticky;\n height: 100%;\n animation-name: fadein;\n animation-duration: 1ms;\n animation-direction: reverse;\n animation-timeline: --scroll-timeline;\n pointer-events: none;\n z-index: 1;\n}\n.fade-left {\n background: linear-gradient(\n -90deg,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 100%) 0%,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 20%) 30%,\n var(--scalar-address-bar-bg) 100%\n );\n left: -1px;\n min-width: 6px;\n animation-direction: normal;\n}\n.fade-right {\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 100%) 0%,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 20%) 30%,\n var(--scalar-address-bar-bg) 100%\n );\n right: -1px;\n min-width: 24px;\n}\n@keyframes fadein {\n 0% {\n opacity: 0;\n }\n 1% {\n opacity: 1;\n }\n}\n.address-bar-bg-states {\n --scalar-address-bar-bg: color-mix(\n in srgb,\n var(--scalar-background-1),\n var(--scalar-background-2)\n );\n background: var(--scalar-address-bar-bg);\n}\n.address-bar-bg-states:has(.cm-focused) {\n --scalar-address-bar-bg: var(--scalar-background-1);\n border-color: var(--scalar-border-color);\n outline-width: 1px;\n outline-style: solid;\n}\n.address-bar-bg-states:has(.cm-focused) .fade-left,\n.address-bar-bg-states:has(.cm-focused) .fade-right {\n --scalar-address-bar-bg: var(--scalar-background-1);\n}\n</style>\n","<script lang=\"ts\">\n/**\n * AddressBar component\n * This component is used to display the address bar for the operation block\n * It is used to display the path, method, server, and history for the operation\n */\nexport default {\n name: 'AddressBar',\n}\nexport type AddressBarProps = {\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** Currently selected server */\n server: ServerObject | null\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** List of request history */\n history: History[]\n /** Client layout */\n layout: ClientLayout\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Environment */\n environment: XScalarEnvironment\n /** Meta information for the server */\n serverMeta: ServerMeta\n}\n</script>\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarIcon,\n ScalarWrappingText,\n} from '@scalar/components'\nimport { REQUEST_METHODS } from '@scalar/helpers/http/http-info'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCopy, ScalarIconWarningCircle } from '@scalar/icons'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport type {\n ApiReferenceEvents,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport {\n computed,\n onBeforeUnmount,\n onMounted,\n ref,\n useId,\n useTemplateRef,\n} from 'vue'\n\nimport { HttpMethod } from '@/components/HttpMethod'\nimport { type ClientLayout } from '@/hooks'\nimport { getResolvedUrl } from '@/v2/blocks/operation-block/helpers/get-resolved-url'\nimport { useLoadingAnimation } from '@/v2/blocks/scalar-address-bar-block/hooks/use-loading-animation'\nimport { CodeInput } from '@/v2/components/code-input'\nimport { ServerDropdown } from '@/v2/components/server'\n\nimport AddressBarHistory, { type History } from './AddressBarHistory.vue'\n\nconst {\n path,\n method,\n layout,\n eventBus,\n history,\n server,\n servers,\n environment,\n serverMeta,\n} = defineProps<AddressBarProps>()\n\nconst emit = defineEmits<{\n /** Execute the current operation example */\n (e: 'execute'): void\n /** Select a request history item by index */\n (e: 'select:history:item', payload: { index: number }): void\n}>()\n\nconst id = useId()\nconst { percentage, startLoading, stopLoading, isLoading } =\n useLoadingAnimation()\n\n/** Calculate the style for the address bar */\nconst style = computed(() => ({\n backgroundColor: `color-mix(in srgb, transparent 90%, ${REQUEST_METHODS[method].colorVar})`,\n transform: `translate3d(-${percentage.value}%,0,0)`,\n}))\n\nconst pathConflict = ref<string | null>(null)\nconst methodConflict = ref<HttpMethodType | null>(null)\n\n/** Whether there is a path or method conflict */\nconst hasConflict = computed(() => methodConflict.value || pathConflict.value)\n\n/** Emit the path/method update event with conflict handling */\nconst emitPathMethodUpdate = (\n targetMethod: HttpMethodType,\n targetPath: string,\n /** We only want to debounce when the path changes */\n emitOptions?: { debounceKey?: string },\n): void => {\n const position = addressBarRef.value?.cursorPosition()\n eventBus.emit(\n 'operation:update:pathMethod',\n {\n meta: { method, path },\n payload: { method: targetMethod, path: targetPath },\n callback: (status) => {\n // Clear conflicts if the operation was successful or no change was made\n if (status === 'success' || status === 'no-change') {\n methodConflict.value = null\n pathConflict.value = null\n }\n if (status === 'success') {\n eventBus.emit('ui:focus:address-bar', { position })\n }\n // Otherwise set the conflict if needed\n else if (status === 'conflict') {\n if (targetMethod !== method) {\n methodConflict.value = targetMethod\n }\n if (targetPath !== path) {\n pathConflict.value = targetPath\n }\n }\n },\n },\n emitOptions,\n )\n}\n\n/** Update the operation's HTTP method, handling conflicts */\nconst handleMethodChange = (newMethod: HttpMethodType): void =>\n emitPathMethodUpdate(newMethod, pathConflict.value ?? path)\n\n/** Update the operation's path, handling conflicts */\nconst handlePathChange = (newPath: string): void => {\n const normalizedPath = newPath.startsWith('/') ? newPath : `/${newPath}`\n emitPathMethodUpdate(methodConflict.value ?? method, normalizedPath, {\n debounceKey: `operation:update:pathMethod-${path}-${method}`,\n })\n}\n\n/** Handle focus events */\nconst sendButtonRef = useTemplateRef('sendButtonRef')\nconst addressBarRef = useTemplateRef('addressBarRef')\nconst handleFocusSendButton = () => sendButtonRef.value?.$el?.focus()\n\nconst handleFocusAddressBar = (\n payload: ApiReferenceEvents['ui:focus:address-bar'],\n) => {\n // If it already has focus we just propagate native behavior which should focus the browser address bar\n if (addressBarRef.value?.isFocused && layout !== 'desktop') {\n return\n }\n\n const position = payload && 'position' in payload ? payload.position : 'end'\n addressBarRef.value?.focus(position)\n\n if (payload && 'event' in payload) {\n payload.event.preventDefault()\n }\n}\n\nonMounted(() => {\n eventBus.on('ui:focus:address-bar', handleFocusAddressBar)\n eventBus.on('ui:focus:send-button', handleFocusSendButton)\n eventBus.on('hooks:on:request:sent', startLoading)\n eventBus.on('hooks:on:request:complete', stopLoading)\n})\n\nonBeforeUnmount(() => {\n eventBus.off('ui:focus:address-bar', handleFocusAddressBar)\n eventBus.off('ui:focus:send-button', handleFocusSendButton)\n eventBus.off('hooks:on:request:sent', startLoading)\n eventBus.off('hooks:on:request:complete', stopLoading)\n\n // Stop the animation when the component is unmounted\n // This is to prevent the animation from continuing after the component is unmounted\n stopLoading()\n})\n\nconst { copyToClipboard } = useClipboard()\n\nconst copyUrl = async () => {\n await copyToClipboard(\n getResolvedUrl({ environment, server, path, pathVariables: {} }),\n )\n}\n\nconst isServerDropdownOpen = ref(false)\nconst isHistoryDropdownOpen = ref(false)\n\n/** Whether either dropdown is open */\nconst isDropdownOpen = computed(\n () => isServerDropdownOpen.value || isHistoryDropdownOpen.value,\n)\n\nconst navigateToServersPage = () => {\n if (serverMeta.type === 'operation') {\n return eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'servers',\n operationPath: serverMeta.path,\n method: serverMeta.method,\n })\n }\n return eventBus.emit('ui:navigate', {\n page: 'document',\n path: 'servers',\n })\n}\n\ndefineExpose({\n methodConflict,\n pathConflict,\n})\n</script>\n<template>\n <div\n :id=\"id\"\n class=\"scalar-address-bar order-last flex h-(--scalar-address-bar-height) w-full [--scalar-address-bar-height:32px] lg:order-0 lg:w-auto\">\n <!-- Address Bar -->\n <div\n class=\"address-bar-bg-states text-xxs group relative order-last flex w-full max-w-[calc(100dvw-24px)] flex-1 flex-row items-stretch rounded-lg p-0.75 lg:order-none lg:max-w-[580px] lg:min-w-[580px] xl:max-w-[720px] xl:min-w-[720px]\"\n :class=\"{\n 'outline-c-danger outline': hasConflict,\n 'rounded-b-none': isDropdownOpen,\n }\">\n <div\n class=\"pointer-events-none absolute top-0 left-0 block h-full w-full overflow-hidden rounded-lg border\"\n :class=\"{\n 'rounded-b-none': isDropdownOpen,\n }\">\n <div\n class=\"absolute top-0 left-0 h-full w-full\"\n :style />\n </div>\n <div class=\"flex gap-1\">\n <HttpMethod\n :isEditable=\"layout !== 'modal'\"\n isSquare\n :method=\"methodConflict ?? method\"\n teleport\n @change=\"handleMethodChange\" />\n </div>\n\n <div\n class=\"scroll-timeline-x scroll-timeline-x-hidden relative flex w-full bg-blend-normal\">\n <!-- Servers -->\n <ServerDropdown\n v-if=\"servers.length\"\n :layout=\"layout\"\n :meta=\"serverMeta\"\n :server=\"server\"\n :servers=\"servers\"\n :target=\"id\"\n @update:open=\"(value) => (isServerDropdownOpen = value)\"\n @update:selectedServer=\"\n (payload) => eventBus.emit('server:update:selected', payload)\n \"\n @update:servers=\"navigateToServersPage\"\n @update:variable=\"\n (payload) => eventBus.emit('server:update:variables', payload)\n \" />\n\n <div class=\"fade-left\" />\n <!-- Path + URL + env vars -->\n <CodeInput\n ref=\"addressBarRef\"\n alwaysEmitChange\n aria-label=\"Path\"\n class=\"min-w-fit outline-none\"\n disableCloseBrackets\n :disabled=\"layout === 'modal'\"\n disableEnter\n disableTabIndent\n :emitOnBlur=\"false\"\n :environment=\"environment\"\n importCurl\n :layout=\"layout\"\n :modelValue=\"path\"\n :placeholder=\"server ? '' : 'Enter a URL'\"\n server\n @submit=\"emit('execute')\"\n @update:modelValue=\"handlePathChange\" />\n <div class=\"fade-right\" />\n </div>\n\n <!-- Copy url button -->\n <ScalarButton\n class=\"hover:bg-b-3 mx-1\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"copyUrl\">\n <ScalarIconCopy />\n <span class=\"sr-only\">Copy URL</span>\n </ScalarButton>\n\n <AddressBarHistory\n :history=\"history\"\n :target=\"id\"\n @select:history:item=\"(payload) => emit('select:history:item', payload)\"\n @update:open=\"(value) => (isHistoryDropdownOpen = value)\" />\n <!-- Error message -->\n <div\n v-if=\"hasConflict\"\n class=\"absolute inset-x-0 top-[calc(100%+4px)] flex flex-col items-center rounded px-6\">\n <div\n class=\"text-c-danger bg-b-danger border-c-danger flex items-center gap-1 rounded border p-1\">\n <ScalarIconWarningCircle size=\"sm\" />\n <div class=\"min-w-0 flex-1\">\n A\n <em>{{ methodConflict?.toUpperCase() ?? method.toUpperCase() }}</em>\n request to\n <ScalarWrappingText :text=\"pathConflict ?? path\" />\n already exists in this document\n </div>\n </div>\n </div>\n <ScalarButton\n ref=\"sendButtonRef\"\n class=\"relative h-auto shrink-0 overflow-hidden py-1 pr-2.5 pl-2 font-bold\"\n :disabled=\"isLoading\"\n @click=\"emit('execute')\">\n <span\n aria-hidden=\"true\"\n class=\"inline-flex items-center gap-1\">\n <ScalarIcon\n class=\"relative shrink-0 fill-current\"\n icon=\"Play\"\n size=\"xs\" />\n <span class=\"text-xxs hidden lg:flex\">Send</span>\n </span>\n <span class=\"sr-only\">\n Send {{ method }} request to {{ server?.url ?? '' }}{{ path }}\n </span>\n </ScalarButton>\n </div>\n </div>\n</template>\n<style scoped>\n:deep(.cm-editor) {\n height: 100%;\n outline: none;\n width: 100%;\n}\n:deep(.cm-line) {\n padding: 0;\n}\n:deep(.cm-content) {\n padding: 0;\n display: flex;\n align-items: center;\n font-size: var(--scalar-small);\n}\n.scroll-timeline-x {\n scroll-timeline: --scroll-timeline x;\n /* Firefox supports */\n scroll-timeline: --scroll-timeline horizontal;\n -ms-overflow-style: none; /* IE and Edge */\n}\n.scroll-timeline-x-hidden {\n overflow-x: auto;\n}\n.scroll-timeline-x-hidden :deep(.cm-scroller) {\n scrollbar-width: none;\n -ms-overflow-style: none;\n padding-right: 20px;\n overflow: auto;\n}\n.scroll-timeline-x-hidden::-webkit-scrollbar {\n width: 0;\n height: 0;\n display: none;\n}\n.scroll-timeline-x-hidden :deep(.cm-scroller::-webkit-scrollbar) {\n width: 0;\n height: 0;\n display: none;\n}\n.scroll-timeline-x-address {\n line-height: 27px;\n scrollbar-width: none; /* Firefox */\n}\n/* make clickable are to left of send button */\n.scroll-timeline-x-address:after {\n content: '';\n position: absolute;\n height: 100%;\n width: 24px;\n right: 0;\n cursor: text;\n}\n.scroll-timeline-x-address:empty:before {\n content: 'Enter URL or cURL request';\n color: var(--scalar-color-3);\n pointer-events: none;\n}\n.fade-left,\n.fade-right {\n content: '';\n position: sticky;\n height: 100%;\n animation-name: fadein;\n animation-duration: 1ms;\n animation-direction: reverse;\n animation-timeline: --scroll-timeline;\n pointer-events: none;\n z-index: 1;\n}\n.fade-left {\n background: linear-gradient(\n -90deg,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 100%) 0%,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 20%) 30%,\n var(--scalar-address-bar-bg) 100%\n );\n left: -1px;\n min-width: 6px;\n animation-direction: normal;\n}\n.fade-right {\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 100%) 0%,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 20%) 30%,\n var(--scalar-address-bar-bg) 100%\n );\n right: -1px;\n min-width: 24px;\n}\n@keyframes fadein {\n 0% {\n opacity: 0;\n }\n 1% {\n opacity: 1;\n }\n}\n.address-bar-bg-states {\n --scalar-address-bar-bg: color-mix(\n in srgb,\n var(--scalar-background-1),\n var(--scalar-background-2)\n );\n background: var(--scalar-address-bar-bg);\n}\n.address-bar-bg-states:has(.cm-focused) {\n --scalar-address-bar-bg: var(--scalar-background-1);\n border-color: var(--scalar-border-color);\n outline-width: 1px;\n outline-style: solid;\n}\n.address-bar-bg-states:has(.cm-focused) .fade-left,\n.address-bar-bg-states:has(.cm-focused) .fade-right {\n --scalar-address-bar-bg: var(--scalar-background-1);\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"scalar-address-bar-block-BbysOhkE.js","names":[],"sources":["../src/v2/blocks/scalar-address-bar-block/hooks/use-loading-animation.ts","../src/v2/blocks/scalar-address-bar-block/components/httpStatusCodeColors.ts","../src/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue","../src/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue","../src/v2/blocks/scalar-address-bar-block/components/AddressBar.vue","../src/v2/blocks/scalar-address-bar-block/components/AddressBar.vue"],"sourcesContent":["import type { Ref } from 'vue'\nimport { ref } from 'vue'\n\n/**\n * Constants for the loading animation behavior.\n * These control how the progress bar animates during and after requests.\n */\nconst TICK_INTERVAL_MS = 20\nconst MAX_PERCENTAGE = 100\nconst MIN_PERCENTAGE = 0\nconst ASYMPTOTIC_LIMIT = 15 // Stops at 85% (100 - 15) to show ongoing progress\nconst ASYMPTOTIC_DIVISOR = 60 // Controls the speed of asymptotic approach\nconst FINISH_ANIMATION_DURATION_MS = 400\nconst FINISH_ANIMATION_STEPS = FINISH_ANIMATION_DURATION_MS / TICK_INTERVAL_MS\n\n/**\n * Manages the loading animation for the address bar.\n *\n * The animation has two phases:\n * 1. While requesting: Animates asymptotically toward 85% to indicate ongoing work\n * 2. After request completes: Animates linearly to 100% over 400ms for smooth completion\n *\n * This creates a natural feel where the bar does not instantly jump to 100%,\n * making the loading experience more predictable and less jarring.\n *\n * @returns An object with methods to control the loading animation and the current percentage\n */\nexport const useLoadingAnimation = (): {\n startLoading: () => void\n stopLoading: () => void\n percentage: Ref<number>\n isLoading: Ref<boolean>\n} => {\n /** The current loading percentage from 100 (not started) to 0 (complete) */\n const percentage = ref(MAX_PERCENTAGE)\n /** Tracks how much percentage was remaining when the request completed */\n const remaining = ref(0)\n /** Indicates whether a request is currently in progress */\n const isRequesting = ref(false)\n /** The interval timer that drives the animation */\n const interval = ref<ReturnType<typeof setInterval>>()\n\n /**\n * Resets the animation state to initial values.\n * This is called when the animation completes.\n */\n const resetAnimation = (): void => {\n clearInterval(interval.value)\n interval.value = undefined\n percentage.value = MAX_PERCENTAGE\n isRequesting.value = false\n }\n\n /**\n * Advances the loading animation by one tick.\n * Uses different animation strategies based on whether a request is active.\n */\n const load = (): void => {\n if (isRequesting.value) {\n // Asymptotic approach: Slows down as it nears 85% to indicate ongoing work\n // without reaching 100% until the request actually completes\n percentage.value -= (percentage.value - ASYMPTOTIC_LIMIT) / ASYMPTOTIC_DIVISOR\n } else {\n // Linear finish: Complete the remaining percentage smoothly over a fixed duration\n // to avoid jarring jumps when the request completes\n percentage.value -= remaining.value / FINISH_ANIMATION_STEPS\n }\n\n if (percentage.value <= MIN_PERCENTAGE) {\n resetAnimation()\n }\n }\n\n /**\n * Starts the loading animation.\n * If called while the finishing animation is running, it switches back to requesting mode.\n * This handles the case where a new request starts before the previous animation completes.\n */\n const startLoading = (): void => {\n if (interval.value) {\n // Switch back to requesting mode if we are in finishing mode.\n // This prevents the animation from completing while a new request is active.\n isRequesting.value = true\n return\n }\n isRequesting.value = true\n interval.value = setInterval(load, TICK_INTERVAL_MS)\n }\n\n /**\n * Marks the request as complete and begins the finish animation.\n * The animation will continue until it reaches 100% to provide visual feedback.\n */\n const stopLoading = (): void => {\n remaining.value = percentage.value\n isRequesting.value = false\n }\n\n return {\n startLoading,\n stopLoading,\n percentage,\n isLoading: isRequesting,\n }\n}\n","const STATUS_CODES_COLORS = {\n 100: {\n color: 'text-yellow',\n },\n 200: {\n color: 'text-green',\n },\n 202: {\n color: 'text-green',\n },\n 300: {\n color: 'text-blue',\n },\n 304: {\n color: 'text-blue',\n },\n 400: {\n color: 'text-red',\n },\n 401: {\n color: 'text-orange',\n },\n 422: {\n color: 'text-yellow',\n },\n 423: {\n color: 'text-purple',\n },\n 505: {\n color: 'text-orange',\n },\n} as const\n\ntype StatusCode = keyof typeof STATUS_CODES_COLORS\n\nexport const getStatusCodeColor = (statusCode: number) => {\n const code = statusCode as StatusCode\n return (\n STATUS_CODES_COLORS[code] || {\n /** default color */\n color: 'text-grey',\n }\n )\n}\n","<script setup lang=\"ts\">\nimport { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'\nimport {\n ScalarFloating,\n ScalarFloatingBackdrop,\n ScalarIcon,\n} from '@scalar/components'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { httpStatusCodes } from '@scalar/oas-utils/helpers'\n\nimport { HttpMethod } from '@/components/HttpMethod'\nimport { formatMs } from '@/libs/formatters'\nimport ValueEmitter from '@/v2/components/layout/ValueEmitter.vue'\n\nimport { getStatusCodeColor } from './httpStatusCodeColors'\n\nexport type History = {\n method: HttpMethodType\n path: string\n duration: number\n status: number\n}\n\nconst { target } = defineProps<{\n /** The id of the target to use for the popover (e.g. address bar) */\n target: string\n /** List of all request history items */\n history: History[]\n}>()\n\nconst emits = defineEmits<{\n /** Select a request history item by index */\n (e: 'select:history:item', payload: { index: number }): void\n /** Update the open state of the history popover */\n (e: 'update:open', value: boolean): void\n}>()\n</script>\n<template>\n <Menu\n v-slot=\"{ open }\"\n as=\"div\">\n <!-- Emit the slot value back out the parent -->\n <ValueEmitter\n :value=\"open\"\n @change=\"(value) => emits('update:open', value)\"\n @unmount=\"emits('update:open', false)\" />\n\n <ScalarFloating\n :offset=\"0\"\n resize\n :target=\"target\">\n <!-- History -->\n <MenuButton\n v-if=\"history.length\"\n class=\"address-bar-history-button text-c-3 focus:text-c-1 relative mr-1 rounded-lg p-1.5\">\n <ScalarIcon\n icon=\"History\"\n size=\"sm\"\n thickness=\"2.25\" />\n <span class=\"sr-only\">Request History</span>\n </MenuButton>\n <!-- History shadow and placement-->\n <template\n v-if=\"open\"\n #floating=\"{ width }\">\n <!-- History Item -->\n <MenuItems\n class=\"custom-scroll grid max-h-[inherit] grid-cols-[44px_1fr_repeat(3,auto)] items-center p-0.75\"\n static\n :style=\"{ width }\">\n <MenuItem\n v-for=\"(entry, index) in history\"\n :key=\"index\"\n as=\"button\"\n class=\"font-code ui-active:*:bg-b-2 text-c-2 contents text-sm font-medium *:flex *:h-8 *:cursor-pointer *:items-center *:rounded-none *:px-1.5 *:first:rounded-l *:last:rounded-r\"\n :value=\"index\"\n @click=\"emits('select:history:item', { index })\">\n <HttpMethod\n class=\"text-[11px]\"\n :method=\"entry.method\" />\n <div class=\"min-w-0\">\n <div class=\"text-c-1 min-w-0 truncate\">\n {{ entry.path }}\n </div>\n </div>\n <div>{{ formatMs(entry.duration) }}</div>\n <div :class=\"[getStatusCodeColor(entry.status).color]\">\n {{ entry.status }}\n </div>\n <div>\n {{ httpStatusCodes[entry.status]?.name }}\n </div>\n </MenuItem>\n </MenuItems>\n <ScalarFloatingBackdrop class=\"inset-x-px rounded-none rounded-b-lg\" />\n </template>\n </ScalarFloating>\n </Menu>\n</template>\n<style scoped>\n.address-bar-history-button:hover {\n background: var(--scalar-background-3);\n}\n.address-bar-history-button:focus-within {\n background: var(--scalar-background-2);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'\nimport {\n ScalarFloating,\n ScalarFloatingBackdrop,\n ScalarIcon,\n} from '@scalar/components'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { httpStatusCodes } from '@scalar/oas-utils/helpers'\n\nimport { HttpMethod } from '@/components/HttpMethod'\nimport { formatMs } from '@/libs/formatters'\nimport ValueEmitter from '@/v2/components/layout/ValueEmitter.vue'\n\nimport { getStatusCodeColor } from './httpStatusCodeColors'\n\nexport type History = {\n method: HttpMethodType\n path: string\n duration: number\n status: number\n}\n\nconst { target } = defineProps<{\n /** The id of the target to use for the popover (e.g. address bar) */\n target: string\n /** List of all request history items */\n history: History[]\n}>()\n\nconst emits = defineEmits<{\n /** Select a request history item by index */\n (e: 'select:history:item', payload: { index: number }): void\n /** Update the open state of the history popover */\n (e: 'update:open', value: boolean): void\n}>()\n</script>\n<template>\n <Menu\n v-slot=\"{ open }\"\n as=\"div\">\n <!-- Emit the slot value back out the parent -->\n <ValueEmitter\n :value=\"open\"\n @change=\"(value) => emits('update:open', value)\"\n @unmount=\"emits('update:open', false)\" />\n\n <ScalarFloating\n :offset=\"0\"\n resize\n :target=\"target\">\n <!-- History -->\n <MenuButton\n v-if=\"history.length\"\n class=\"address-bar-history-button text-c-3 focus:text-c-1 relative mr-1 rounded-lg p-1.5\">\n <ScalarIcon\n icon=\"History\"\n size=\"sm\"\n thickness=\"2.25\" />\n <span class=\"sr-only\">Request History</span>\n </MenuButton>\n <!-- History shadow and placement-->\n <template\n v-if=\"open\"\n #floating=\"{ width }\">\n <!-- History Item -->\n <MenuItems\n class=\"custom-scroll grid max-h-[inherit] grid-cols-[44px_1fr_repeat(3,auto)] items-center p-0.75\"\n static\n :style=\"{ width }\">\n <MenuItem\n v-for=\"(entry, index) in history\"\n :key=\"index\"\n as=\"button\"\n class=\"font-code ui-active:*:bg-b-2 text-c-2 contents text-sm font-medium *:flex *:h-8 *:cursor-pointer *:items-center *:rounded-none *:px-1.5 *:first:rounded-l *:last:rounded-r\"\n :value=\"index\"\n @click=\"emits('select:history:item', { index })\">\n <HttpMethod\n class=\"text-[11px]\"\n :method=\"entry.method\" />\n <div class=\"min-w-0\">\n <div class=\"text-c-1 min-w-0 truncate\">\n {{ entry.path }}\n </div>\n </div>\n <div>{{ formatMs(entry.duration) }}</div>\n <div :class=\"[getStatusCodeColor(entry.status).color]\">\n {{ entry.status }}\n </div>\n <div>\n {{ httpStatusCodes[entry.status]?.name }}\n </div>\n </MenuItem>\n </MenuItems>\n <ScalarFloatingBackdrop class=\"inset-x-px rounded-none rounded-b-lg\" />\n </template>\n </ScalarFloating>\n </Menu>\n</template>\n<style scoped>\n.address-bar-history-button:hover {\n background: var(--scalar-background-3);\n}\n.address-bar-history-button:focus-within {\n background: var(--scalar-background-2);\n}\n</style>\n","<script lang=\"ts\">\n/**\n * AddressBar component\n * This component is used to display the address bar for the operation block\n * It is used to display the path, method, server, and history for the operation\n */\nexport default {\n name: 'AddressBar',\n}\nexport type AddressBarProps = {\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** Currently selected server */\n server: ServerObject | null\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** List of request history */\n history: History[]\n /** Client layout */\n layout: ClientLayout\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Environment */\n environment: XScalarEnvironment\n /** Meta information for the server */\n serverMeta: ServerMeta\n}\n</script>\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarIcon,\n ScalarWrappingText,\n} from '@scalar/components'\nimport { REQUEST_METHODS } from '@scalar/helpers/http/http-info'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCopy, ScalarIconWarningCircle } from '@scalar/icons'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport type {\n ApiReferenceEvents,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport {\n computed,\n onBeforeUnmount,\n onMounted,\n ref,\n useId,\n useTemplateRef,\n} from 'vue'\n\nimport { HttpMethod } from '@/components/HttpMethod'\nimport { type ClientLayout } from '@/hooks'\nimport { getResolvedUrl } from '@/v2/blocks/operation-block/helpers/get-resolved-url'\nimport { useLoadingAnimation } from '@/v2/blocks/scalar-address-bar-block/hooks/use-loading-animation'\nimport { CodeInput } from '@/v2/components/code-input'\nimport { ServerDropdown } from '@/v2/components/server'\n\nimport AddressBarHistory, { type History } from './AddressBarHistory.vue'\n\nconst {\n path,\n method,\n layout,\n eventBus,\n history,\n server,\n servers,\n environment,\n serverMeta,\n} = defineProps<AddressBarProps>()\n\nconst emit = defineEmits<{\n /** Execute the current operation example */\n (e: 'execute'): void\n /** Select a request history item by index */\n (e: 'select:history:item', payload: { index: number }): void\n}>()\n\nconst id = useId()\nconst { percentage, startLoading, stopLoading, isLoading } =\n useLoadingAnimation()\n\n/** Calculate the style for the address bar */\nconst style = computed(() => ({\n backgroundColor: `color-mix(in srgb, transparent 90%, ${REQUEST_METHODS[method].colorVar})`,\n transform: `translate3d(-${percentage.value}%,0,0)`,\n}))\n\nconst pathConflict = ref<string | null>(null)\nconst methodConflict = ref<HttpMethodType | null>(null)\n\n/** Whether there is a path or method conflict */\nconst hasConflict = computed(() => methodConflict.value || pathConflict.value)\n\n/** Emit the path/method update event with conflict handling */\nconst emitPathMethodUpdate = (\n targetMethod: HttpMethodType,\n targetPath: string,\n /** We only want to debounce when the path changes */\n emitOptions?: { debounceKey?: string },\n): void => {\n const position = addressBarRef.value?.cursorPosition()\n eventBus.emit(\n 'operation:update:pathMethod',\n {\n meta: { method, path },\n payload: { method: targetMethod, path: targetPath },\n callback: (status) => {\n // Clear conflicts if the operation was successful or no change was made\n if (status === 'success' || status === 'no-change') {\n methodConflict.value = null\n pathConflict.value = null\n }\n if (status === 'success') {\n eventBus.emit('ui:focus:address-bar', { position })\n }\n // Otherwise set the conflict if needed\n else if (status === 'conflict') {\n if (targetMethod !== method) {\n methodConflict.value = targetMethod\n }\n if (targetPath !== path) {\n pathConflict.value = targetPath\n }\n }\n },\n },\n emitOptions,\n )\n}\n\n/** Update the operation's HTTP method, handling conflicts */\nconst handleMethodChange = (newMethod: HttpMethodType): void =>\n emitPathMethodUpdate(newMethod, pathConflict.value ?? path)\n\n/** Update the operation's path, handling conflicts */\nconst handlePathChange = (newPath: string): void => {\n const normalizedPath = newPath.startsWith('/') ? newPath : `/${newPath}`\n emitPathMethodUpdate(methodConflict.value ?? method, normalizedPath, {\n debounceKey: `operation:update:pathMethod-${path}-${method}`,\n })\n}\n\n/** Handle focus events */\nconst sendButtonRef = useTemplateRef('sendButtonRef')\nconst addressBarRef = useTemplateRef('addressBarRef')\nconst handleFocusSendButton = () => sendButtonRef.value?.$el?.focus()\n\nconst handleFocusAddressBar = (\n payload: ApiReferenceEvents['ui:focus:address-bar'],\n) => {\n // If it already has focus we just propagate native behavior which should focus the browser address bar\n if (addressBarRef.value?.isFocused && layout !== 'desktop') {\n return\n }\n\n const position = payload && 'position' in payload ? payload.position : 'end'\n addressBarRef.value?.focus(position)\n\n if (payload && 'event' in payload) {\n payload.event.preventDefault()\n }\n}\n\nonMounted(() => {\n eventBus.on('ui:focus:address-bar', handleFocusAddressBar)\n eventBus.on('ui:focus:send-button', handleFocusSendButton)\n eventBus.on('hooks:on:request:sent', startLoading)\n eventBus.on('hooks:on:request:complete', stopLoading)\n})\n\nonBeforeUnmount(() => {\n eventBus.off('ui:focus:address-bar', handleFocusAddressBar)\n eventBus.off('ui:focus:send-button', handleFocusSendButton)\n eventBus.off('hooks:on:request:sent', startLoading)\n eventBus.off('hooks:on:request:complete', stopLoading)\n\n // Stop the animation when the component is unmounted\n // This is to prevent the animation from continuing after the component is unmounted\n stopLoading()\n})\n\nconst { copyToClipboard } = useClipboard()\n\nconst copyUrl = async () => {\n await copyToClipboard(\n getResolvedUrl({ environment, server, path, pathVariables: {} }),\n )\n}\n\nconst isServerDropdownOpen = ref(false)\nconst isHistoryDropdownOpen = ref(false)\n\n/** Whether either dropdown is open */\nconst isDropdownOpen = computed(\n () => isServerDropdownOpen.value || isHistoryDropdownOpen.value,\n)\n\nconst navigateToServersPage = () => {\n if (serverMeta.type === 'operation') {\n return eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'servers',\n operationPath: serverMeta.path,\n method: serverMeta.method,\n })\n }\n return eventBus.emit('ui:navigate', {\n page: 'document',\n path: 'servers',\n })\n}\n\ndefineExpose({\n methodConflict,\n pathConflict,\n})\n</script>\n<template>\n <div\n :id=\"id\"\n class=\"scalar-address-bar order-last flex h-(--scalar-address-bar-height) w-full [--scalar-address-bar-height:32px] lg:order-0 lg:w-auto\">\n <!-- Address Bar -->\n <div\n class=\"address-bar-bg-states text-xxs group relative order-last flex w-full max-w-[calc(100dvw-24px)] flex-1 flex-row items-stretch rounded-lg p-0.75 lg:order-none lg:max-w-[580px] lg:min-w-[580px] xl:max-w-[720px] xl:min-w-[720px]\"\n :class=\"{\n 'outline-c-danger outline': hasConflict,\n 'rounded-b-none': isDropdownOpen,\n }\">\n <div\n class=\"pointer-events-none absolute top-0 left-0 block h-full w-full overflow-hidden rounded-lg border\"\n :class=\"{\n 'rounded-b-none': isDropdownOpen,\n }\">\n <div\n class=\"absolute top-0 left-0 h-full w-full\"\n :style />\n </div>\n <div class=\"flex gap-1\">\n <HttpMethod\n :isEditable=\"layout !== 'modal'\"\n isSquare\n :method=\"methodConflict ?? method\"\n teleport\n @change=\"handleMethodChange\" />\n </div>\n\n <div\n class=\"scroll-timeline-x scroll-timeline-x-hidden relative flex w-full bg-blend-normal\">\n <!-- Servers -->\n <ServerDropdown\n v-if=\"servers.length\"\n :layout=\"layout\"\n :meta=\"serverMeta\"\n :server=\"server\"\n :servers=\"servers\"\n :target=\"id\"\n @update:open=\"(value) => (isServerDropdownOpen = value)\"\n @update:selectedServer=\"\n (payload) => eventBus.emit('server:update:selected', payload)\n \"\n @update:servers=\"navigateToServersPage\"\n @update:variable=\"\n (payload) => eventBus.emit('server:update:variables', payload)\n \" />\n\n <div class=\"fade-left\" />\n <!-- Path + URL + env vars -->\n <CodeInput\n ref=\"addressBarRef\"\n alwaysEmitChange\n aria-label=\"Path\"\n class=\"min-w-fit outline-none\"\n disableCloseBrackets\n :disabled=\"layout === 'modal'\"\n disableEnter\n disableTabIndent\n :emitOnBlur=\"false\"\n :environment=\"environment\"\n importCurl\n :layout=\"layout\"\n :modelValue=\"path\"\n :placeholder=\"server ? '' : 'Enter a URL'\"\n server\n @submit=\"emit('execute')\"\n @update:modelValue=\"handlePathChange\" />\n <div class=\"fade-right\" />\n </div>\n\n <!-- Copy url button -->\n <ScalarButton\n class=\"hover:bg-b-3 mx-1\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"copyUrl\">\n <ScalarIconCopy />\n <span class=\"sr-only\">Copy URL</span>\n </ScalarButton>\n\n <AddressBarHistory\n :history=\"history\"\n :target=\"id\"\n @select:history:item=\"(payload) => emit('select:history:item', payload)\"\n @update:open=\"(value) => (isHistoryDropdownOpen = value)\" />\n <!-- Error message -->\n <div\n v-if=\"hasConflict\"\n class=\"absolute inset-x-0 top-[calc(100%+4px)] flex flex-col items-center rounded px-6\">\n <div\n class=\"text-c-danger bg-b-danger border-c-danger flex items-center gap-1 rounded border p-1\">\n <ScalarIconWarningCircle size=\"sm\" />\n <div class=\"min-w-0 flex-1\">\n A\n <em>{{ methodConflict?.toUpperCase() ?? method.toUpperCase() }}</em>\n request to\n <ScalarWrappingText :text=\"pathConflict ?? path\" />\n already exists in this document\n </div>\n </div>\n </div>\n <ScalarButton\n ref=\"sendButtonRef\"\n class=\"relative h-auto shrink-0 overflow-hidden py-1 pr-2.5 pl-2 font-bold\"\n :disabled=\"isLoading\"\n @click=\"emit('execute')\">\n <span\n aria-hidden=\"true\"\n class=\"inline-flex items-center gap-1\">\n <ScalarIcon\n class=\"relative shrink-0 fill-current\"\n icon=\"Play\"\n size=\"xs\" />\n <span class=\"text-xxs hidden lg:flex\">Send</span>\n </span>\n <span class=\"sr-only\">\n Send {{ method }} request to {{ server?.url ?? '' }}{{ path }}\n </span>\n </ScalarButton>\n </div>\n </div>\n</template>\n<style scoped>\n:deep(.cm-editor) {\n height: 100%;\n outline: none;\n width: 100%;\n}\n:deep(.cm-line) {\n padding: 0;\n}\n:deep(.cm-content) {\n padding: 0;\n display: flex;\n align-items: center;\n font-size: var(--scalar-small);\n}\n.scroll-timeline-x {\n scroll-timeline: --scroll-timeline x;\n /* Firefox supports */\n scroll-timeline: --scroll-timeline horizontal;\n -ms-overflow-style: none; /* IE and Edge */\n}\n.scroll-timeline-x-hidden {\n overflow-x: auto;\n}\n.scroll-timeline-x-hidden :deep(.cm-scroller) {\n scrollbar-width: none;\n -ms-overflow-style: none;\n padding-right: 20px;\n overflow: auto;\n}\n.scroll-timeline-x-hidden::-webkit-scrollbar {\n width: 0;\n height: 0;\n display: none;\n}\n.scroll-timeline-x-hidden :deep(.cm-scroller::-webkit-scrollbar) {\n width: 0;\n height: 0;\n display: none;\n}\n.scroll-timeline-x-address {\n line-height: 27px;\n scrollbar-width: none; /* Firefox */\n}\n/* make clickable are to left of send button */\n.scroll-timeline-x-address:after {\n content: '';\n position: absolute;\n height: 100%;\n width: 24px;\n right: 0;\n cursor: text;\n}\n.scroll-timeline-x-address:empty:before {\n content: 'Enter URL or cURL request';\n color: var(--scalar-color-3);\n pointer-events: none;\n}\n.fade-left,\n.fade-right {\n content: '';\n position: sticky;\n height: 100%;\n animation-name: fadein;\n animation-duration: 1ms;\n animation-direction: reverse;\n animation-timeline: --scroll-timeline;\n pointer-events: none;\n z-index: 1;\n}\n.fade-left {\n background: linear-gradient(\n -90deg,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 100%) 0%,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 20%) 30%,\n var(--scalar-address-bar-bg) 100%\n );\n left: -1px;\n min-width: 6px;\n animation-direction: normal;\n}\n.fade-right {\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 100%) 0%,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 20%) 30%,\n var(--scalar-address-bar-bg) 100%\n );\n right: -1px;\n min-width: 24px;\n}\n@keyframes fadein {\n 0% {\n opacity: 0;\n }\n 1% {\n opacity: 1;\n }\n}\n.address-bar-bg-states {\n --scalar-address-bar-bg: color-mix(\n in srgb,\n var(--scalar-background-1),\n var(--scalar-background-2)\n );\n background: var(--scalar-address-bar-bg);\n}\n.address-bar-bg-states:has(.cm-focused) {\n --scalar-address-bar-bg: var(--scalar-background-1);\n border-color: var(--scalar-border-color);\n outline-width: 1px;\n outline-style: solid;\n}\n.address-bar-bg-states:has(.cm-focused) .fade-left,\n.address-bar-bg-states:has(.cm-focused) .fade-right {\n --scalar-address-bar-bg: var(--scalar-background-1);\n}\n</style>\n","<script lang=\"ts\">\n/**\n * AddressBar component\n * This component is used to display the address bar for the operation block\n * It is used to display the path, method, server, and history for the operation\n */\nexport default {\n name: 'AddressBar',\n}\nexport type AddressBarProps = {\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** Currently selected server */\n server: ServerObject | null\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** List of request history */\n history: History[]\n /** Client layout */\n layout: ClientLayout\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Environment */\n environment: XScalarEnvironment\n /** Meta information for the server */\n serverMeta: ServerMeta\n}\n</script>\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarIcon,\n ScalarWrappingText,\n} from '@scalar/components'\nimport { REQUEST_METHODS } from '@scalar/helpers/http/http-info'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCopy, ScalarIconWarningCircle } from '@scalar/icons'\nimport { useClipboard } from '@scalar/use-hooks/useClipboard'\nimport type {\n ApiReferenceEvents,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport {\n computed,\n onBeforeUnmount,\n onMounted,\n ref,\n useId,\n useTemplateRef,\n} from 'vue'\n\nimport { HttpMethod } from '@/components/HttpMethod'\nimport { type ClientLayout } from '@/hooks'\nimport { getResolvedUrl } from '@/v2/blocks/operation-block/helpers/get-resolved-url'\nimport { useLoadingAnimation } from '@/v2/blocks/scalar-address-bar-block/hooks/use-loading-animation'\nimport { CodeInput } from '@/v2/components/code-input'\nimport { ServerDropdown } from '@/v2/components/server'\n\nimport AddressBarHistory, { type History } from './AddressBarHistory.vue'\n\nconst {\n path,\n method,\n layout,\n eventBus,\n history,\n server,\n servers,\n environment,\n serverMeta,\n} = defineProps<AddressBarProps>()\n\nconst emit = defineEmits<{\n /** Execute the current operation example */\n (e: 'execute'): void\n /** Select a request history item by index */\n (e: 'select:history:item', payload: { index: number }): void\n}>()\n\nconst id = useId()\nconst { percentage, startLoading, stopLoading, isLoading } =\n useLoadingAnimation()\n\n/** Calculate the style for the address bar */\nconst style = computed(() => ({\n backgroundColor: `color-mix(in srgb, transparent 90%, ${REQUEST_METHODS[method].colorVar})`,\n transform: `translate3d(-${percentage.value}%,0,0)`,\n}))\n\nconst pathConflict = ref<string | null>(null)\nconst methodConflict = ref<HttpMethodType | null>(null)\n\n/** Whether there is a path or method conflict */\nconst hasConflict = computed(() => methodConflict.value || pathConflict.value)\n\n/** Emit the path/method update event with conflict handling */\nconst emitPathMethodUpdate = (\n targetMethod: HttpMethodType,\n targetPath: string,\n /** We only want to debounce when the path changes */\n emitOptions?: { debounceKey?: string },\n): void => {\n const position = addressBarRef.value?.cursorPosition()\n eventBus.emit(\n 'operation:update:pathMethod',\n {\n meta: { method, path },\n payload: { method: targetMethod, path: targetPath },\n callback: (status) => {\n // Clear conflicts if the operation was successful or no change was made\n if (status === 'success' || status === 'no-change') {\n methodConflict.value = null\n pathConflict.value = null\n }\n if (status === 'success') {\n eventBus.emit('ui:focus:address-bar', { position })\n }\n // Otherwise set the conflict if needed\n else if (status === 'conflict') {\n if (targetMethod !== method) {\n methodConflict.value = targetMethod\n }\n if (targetPath !== path) {\n pathConflict.value = targetPath\n }\n }\n },\n },\n emitOptions,\n )\n}\n\n/** Update the operation's HTTP method, handling conflicts */\nconst handleMethodChange = (newMethod: HttpMethodType): void =>\n emitPathMethodUpdate(newMethod, pathConflict.value ?? path)\n\n/** Update the operation's path, handling conflicts */\nconst handlePathChange = (newPath: string): void => {\n const normalizedPath = newPath.startsWith('/') ? newPath : `/${newPath}`\n emitPathMethodUpdate(methodConflict.value ?? method, normalizedPath, {\n debounceKey: `operation:update:pathMethod-${path}-${method}`,\n })\n}\n\n/** Handle focus events */\nconst sendButtonRef = useTemplateRef('sendButtonRef')\nconst addressBarRef = useTemplateRef('addressBarRef')\nconst handleFocusSendButton = () => sendButtonRef.value?.$el?.focus()\n\nconst handleFocusAddressBar = (\n payload: ApiReferenceEvents['ui:focus:address-bar'],\n) => {\n // If it already has focus we just propagate native behavior which should focus the browser address bar\n if (addressBarRef.value?.isFocused && layout !== 'desktop') {\n return\n }\n\n const position = payload && 'position' in payload ? payload.position : 'end'\n addressBarRef.value?.focus(position)\n\n if (payload && 'event' in payload) {\n payload.event.preventDefault()\n }\n}\n\nonMounted(() => {\n eventBus.on('ui:focus:address-bar', handleFocusAddressBar)\n eventBus.on('ui:focus:send-button', handleFocusSendButton)\n eventBus.on('hooks:on:request:sent', startLoading)\n eventBus.on('hooks:on:request:complete', stopLoading)\n})\n\nonBeforeUnmount(() => {\n eventBus.off('ui:focus:address-bar', handleFocusAddressBar)\n eventBus.off('ui:focus:send-button', handleFocusSendButton)\n eventBus.off('hooks:on:request:sent', startLoading)\n eventBus.off('hooks:on:request:complete', stopLoading)\n\n // Stop the animation when the component is unmounted\n // This is to prevent the animation from continuing after the component is unmounted\n stopLoading()\n})\n\nconst { copyToClipboard } = useClipboard()\n\nconst copyUrl = async () => {\n await copyToClipboard(\n getResolvedUrl({ environment, server, path, pathVariables: {} }),\n )\n}\n\nconst isServerDropdownOpen = ref(false)\nconst isHistoryDropdownOpen = ref(false)\n\n/** Whether either dropdown is open */\nconst isDropdownOpen = computed(\n () => isServerDropdownOpen.value || isHistoryDropdownOpen.value,\n)\n\nconst navigateToServersPage = () => {\n if (serverMeta.type === 'operation') {\n return eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'servers',\n operationPath: serverMeta.path,\n method: serverMeta.method,\n })\n }\n return eventBus.emit('ui:navigate', {\n page: 'document',\n path: 'servers',\n })\n}\n\ndefineExpose({\n methodConflict,\n pathConflict,\n})\n</script>\n<template>\n <div\n :id=\"id\"\n class=\"scalar-address-bar order-last flex h-(--scalar-address-bar-height) w-full [--scalar-address-bar-height:32px] lg:order-0 lg:w-auto\">\n <!-- Address Bar -->\n <div\n class=\"address-bar-bg-states text-xxs group relative order-last flex w-full max-w-[calc(100dvw-24px)] flex-1 flex-row items-stretch rounded-lg p-0.75 lg:order-none lg:max-w-[580px] lg:min-w-[580px] xl:max-w-[720px] xl:min-w-[720px]\"\n :class=\"{\n 'outline-c-danger outline': hasConflict,\n 'rounded-b-none': isDropdownOpen,\n }\">\n <div\n class=\"pointer-events-none absolute top-0 left-0 block h-full w-full overflow-hidden rounded-lg border\"\n :class=\"{\n 'rounded-b-none': isDropdownOpen,\n }\">\n <div\n class=\"absolute top-0 left-0 h-full w-full\"\n :style />\n </div>\n <div class=\"flex gap-1\">\n <HttpMethod\n :isEditable=\"layout !== 'modal'\"\n isSquare\n :method=\"methodConflict ?? method\"\n teleport\n @change=\"handleMethodChange\" />\n </div>\n\n <div\n class=\"scroll-timeline-x scroll-timeline-x-hidden relative flex w-full bg-blend-normal\">\n <!-- Servers -->\n <ServerDropdown\n v-if=\"servers.length\"\n :layout=\"layout\"\n :meta=\"serverMeta\"\n :server=\"server\"\n :servers=\"servers\"\n :target=\"id\"\n @update:open=\"(value) => (isServerDropdownOpen = value)\"\n @update:selectedServer=\"\n (payload) => eventBus.emit('server:update:selected', payload)\n \"\n @update:servers=\"navigateToServersPage\"\n @update:variable=\"\n (payload) => eventBus.emit('server:update:variables', payload)\n \" />\n\n <div class=\"fade-left\" />\n <!-- Path + URL + env vars -->\n <CodeInput\n ref=\"addressBarRef\"\n alwaysEmitChange\n aria-label=\"Path\"\n class=\"min-w-fit outline-none\"\n disableCloseBrackets\n :disabled=\"layout === 'modal'\"\n disableEnter\n disableTabIndent\n :emitOnBlur=\"false\"\n :environment=\"environment\"\n importCurl\n :layout=\"layout\"\n :modelValue=\"path\"\n :placeholder=\"server ? '' : 'Enter a URL'\"\n server\n @submit=\"emit('execute')\"\n @update:modelValue=\"handlePathChange\" />\n <div class=\"fade-right\" />\n </div>\n\n <!-- Copy url button -->\n <ScalarButton\n class=\"hover:bg-b-3 mx-1\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"copyUrl\">\n <ScalarIconCopy />\n <span class=\"sr-only\">Copy URL</span>\n </ScalarButton>\n\n <AddressBarHistory\n :history=\"history\"\n :target=\"id\"\n @select:history:item=\"(payload) => emit('select:history:item', payload)\"\n @update:open=\"(value) => (isHistoryDropdownOpen = value)\" />\n <!-- Error message -->\n <div\n v-if=\"hasConflict\"\n class=\"absolute inset-x-0 top-[calc(100%+4px)] flex flex-col items-center rounded px-6\">\n <div\n class=\"text-c-danger bg-b-danger border-c-danger flex items-center gap-1 rounded border p-1\">\n <ScalarIconWarningCircle size=\"sm\" />\n <div class=\"min-w-0 flex-1\">\n A\n <em>{{ methodConflict?.toUpperCase() ?? method.toUpperCase() }}</em>\n request to\n <ScalarWrappingText :text=\"pathConflict ?? path\" />\n already exists in this document\n </div>\n </div>\n </div>\n <ScalarButton\n ref=\"sendButtonRef\"\n class=\"relative h-auto shrink-0 overflow-hidden py-1 pr-2.5 pl-2 font-bold\"\n :disabled=\"isLoading\"\n @click=\"emit('execute')\">\n <span\n aria-hidden=\"true\"\n class=\"inline-flex items-center gap-1\">\n <ScalarIcon\n class=\"relative shrink-0 fill-current\"\n icon=\"Play\"\n size=\"xs\" />\n <span class=\"text-xxs hidden lg:flex\">Send</span>\n </span>\n <span class=\"sr-only\">\n Send {{ method }} request to {{ server?.url ?? '' }}{{ path }}\n </span>\n </ScalarButton>\n </div>\n </div>\n</template>\n<style scoped>\n:deep(.cm-editor) {\n height: 100%;\n outline: none;\n width: 100%;\n}\n:deep(.cm-line) {\n padding: 0;\n}\n:deep(.cm-content) {\n padding: 0;\n display: flex;\n align-items: center;\n font-size: var(--scalar-small);\n}\n.scroll-timeline-x {\n scroll-timeline: --scroll-timeline x;\n /* Firefox supports */\n scroll-timeline: --scroll-timeline horizontal;\n -ms-overflow-style: none; /* IE and Edge */\n}\n.scroll-timeline-x-hidden {\n overflow-x: auto;\n}\n.scroll-timeline-x-hidden :deep(.cm-scroller) {\n scrollbar-width: none;\n -ms-overflow-style: none;\n padding-right: 20px;\n overflow: auto;\n}\n.scroll-timeline-x-hidden::-webkit-scrollbar {\n width: 0;\n height: 0;\n display: none;\n}\n.scroll-timeline-x-hidden :deep(.cm-scroller::-webkit-scrollbar) {\n width: 0;\n height: 0;\n display: none;\n}\n.scroll-timeline-x-address {\n line-height: 27px;\n scrollbar-width: none; /* Firefox */\n}\n/* make clickable are to left of send button */\n.scroll-timeline-x-address:after {\n content: '';\n position: absolute;\n height: 100%;\n width: 24px;\n right: 0;\n cursor: text;\n}\n.scroll-timeline-x-address:empty:before {\n content: 'Enter URL or cURL request';\n color: var(--scalar-color-3);\n pointer-events: none;\n}\n.fade-left,\n.fade-right {\n content: '';\n position: sticky;\n height: 100%;\n animation-name: fadein;\n animation-duration: 1ms;\n animation-direction: reverse;\n animation-timeline: --scroll-timeline;\n pointer-events: none;\n z-index: 1;\n}\n.fade-left {\n background: linear-gradient(\n -90deg,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 100%) 0%,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 20%) 30%,\n var(--scalar-address-bar-bg) 100%\n );\n left: -1px;\n min-width: 6px;\n animation-direction: normal;\n}\n.fade-right {\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 100%) 0%,\n color-mix(in srgb, var(--scalar-address-bar-bg), transparent 20%) 30%,\n var(--scalar-address-bar-bg) 100%\n );\n right: -1px;\n min-width: 24px;\n}\n@keyframes fadein {\n 0% {\n opacity: 0;\n }\n 1% {\n opacity: 1;\n }\n}\n.address-bar-bg-states {\n --scalar-address-bar-bg: color-mix(\n in srgb,\n var(--scalar-background-1),\n var(--scalar-background-2)\n );\n background: var(--scalar-address-bar-bg);\n}\n.address-bar-bg-states:has(.cm-focused) {\n --scalar-address-bar-bg: var(--scalar-background-1);\n border-color: var(--scalar-border-color);\n outline-width: 1px;\n outline-style: solid;\n}\n.address-bar-bg-states:has(.cm-focused) .fade-left,\n.address-bar-bg-states:has(.cm-focused) .fade-right {\n --scalar-address-bar-bg: var(--scalar-background-1);\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAOA,IAAM,mBAAmB;AACzB,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AACvB,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAE3B,IAAM,yBAD+B,MACyB;;;;;;;;;;;;;AAc9D,IAAa,4BAKR;;CAEH,MAAM,aAAa,IAAI,eAAe;;CAEtC,MAAM,YAAY,IAAI,EAAE;;CAExB,MAAM,eAAe,IAAI,MAAM;;CAE/B,MAAM,WAAW,KAAqC;;;;;CAMtD,MAAM,uBAA6B;AACjC,gBAAc,SAAS,MAAM;AAC7B,WAAS,QAAQ,KAAA;AACjB,aAAW,QAAQ;AACnB,eAAa,QAAQ;;;;;;CAOvB,MAAM,aAAmB;AACvB,MAAI,aAAa,MAGf,YAAW,UAAU,WAAW,QAAQ,oBAAoB;MAI5D,YAAW,SAAS,UAAU,QAAQ;AAGxC,MAAI,WAAW,SAAS,eACtB,iBAAgB;;;;;;;CASpB,MAAM,qBAA2B;AAC/B,MAAI,SAAS,OAAO;AAGlB,gBAAa,QAAQ;AACrB;;AAEF,eAAa,QAAQ;AACrB,WAAS,QAAQ,YAAY,MAAM,iBAAiB;;;;;;CAOtD,MAAM,oBAA0B;AAC9B,YAAU,QAAQ,WAAW;AAC7B,eAAa,QAAQ;;AAGvB,QAAO;EACL;EACA;EACA;EACA,WAAW;EACZ;;;;ACvGH,IAAM,sBAAsB;CAC1B,KAAK,EACH,OAAO,eACR;CACD,KAAK,EACH,OAAO,cACR;CACD,KAAK,EACH,OAAO,cACR;CACD,KAAK,EACH,OAAO,aACR;CACD,KAAK,EACH,OAAO,aACR;CACD,KAAK,EACH,OAAO,YACR;CACD,KAAK,EACH,OAAO,eACR;CACD,KAAK,EACH,OAAO,eACR;CACD,KAAK,EACH,OAAO,eACR;CACD,KAAK,EACH,OAAO,eACR;CACF;AAID,IAAa,sBAAsB,eAAuB;AAExD,QACE,oBAFW,eAEkB,EAE3B,OAAO,aACR;;;;;;;;;;;;;;;;EEXL,MAAM,QAAQ;;uBAQZ,YA2DO,MAAA,KAAA,EAAA,EAzDL,IAAG,OAAK,EAAA;sBAKmC,EANjC,WAAI,CAGd,YAG2C,sBAAA;KAFxC,OAAO;KACP,UAAM,OAAA,OAAA,OAAA,MAAG,UAAU,MAAK,eAAgB,MAAK;KAC7C,WAAO,OAAA,OAAA,OAAA,MAAA,WAAE,MAAK,eAAA,MAAA;4BAEjB,YAiDiB,MAAA,eAAA,EAAA;KAhDd,QAAQ;KACT,QAAA;KACC,QAAQ,QAAA;;4BAUI,CAPL,QAAA,QAAQ,UAAA,WAAA,EADhB,YAQa,MAAA,WAAA,EAAA;;MANX,OAAM;;6BAIe,CAHrB,YAGqB,MAAA,WAAA,EAAA;OAFnB,MAAK;OACL,MAAK;OACL,WAAU;oCACZ,mBAA4C,QAAA,EAAtC,OAAM,WAAS,EAAC,mBAAe,GAAA,EAAA,CAAA;;;;QAI/B,OAAA;WACL;kBA6BW,EA7BC,YAAK,CAElB,YA2BY,MAAA,UAAA,EAAA;MA1BV,OAAM;MACN,QAAA;MACC,OAAK,eAAA,EAAI,OAAK,CAAA;;6BAEoB,EAAA,UAAA,KAAA,EADnC,mBAsBW,UAAA,MAAA,WArBgB,QAAA,UAAjB,OAAO,UAAK;2BADtB,YAsBW,MAAA,SAAA,EAAA;QApBR,KAAK;QACN,IAAG;QACH,OAAM;QACL,OAAO;QACP,UAAK,WAAE,MAAK,uBAAA,EAA0B,OAAK,CAAA;;+BAGjB;SAF3B,YAE2B,MAAA,mBAAA,EAAA;UADzB,OAAM;UACL,QAAQ,MAAM;;SACjB,mBAIM,OAJN,cAIM,CAHJ,mBAEM,OAFN,cAEM,gBADD,MAAM,KAAI,EAAA,EAAA,CAAA,CAAA;SAGjB,mBAAyC,OAAA,MAAA,gBAAjC,MAAA,SAAQ,CAAC,MAAM,SAAQ,CAAA,EAAA,EAAA;SAC/B,mBAEM,OAAA,EAFA,OAAK,eAAA,CAAG,MAAA,mBAAkB,CAAC,MAAM,OAAM,CAAE,MAAK,CAAA,EAAA,EAAA,gBAC/C,MAAM,OAAM,EAAA,EAAA;SAEjB,mBAEM,OAAA,MAAA,gBADD,MAAA,gBAAe,CAAC,MAAM,SAAS,KAAI,EAAA,EAAA;;;;;;uBAI5C,YAAuE,MAAA,uBAAA,EAAA,EAA/C,OAAM,wCAAsC,CAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;CEvF1E,MAAM;;;;;;;;;;;;;;EAsER,MAAM,OAAO;EAOb,MAAM,KAAK,OAAM;EACjB,MAAM,EAAE,YAAY,cAAc,aAAa,cAC7C,qBAAoB;;EAGtB,MAAM,QAAQ,gBAAgB;GAC5B,iBAAiB,uCAAuC,gBAAgB,QAAA,QAAQ,SAAS;GACzF,WAAW,gBAAgB,WAAW,MAAM;GAC7C,EAAC;EAEF,MAAM,eAAe,IAAmB,KAAI;EAC5C,MAAM,iBAAiB,IAA2B,KAAI;;EAGtD,MAAM,cAAc,eAAe,eAAe,SAAS,aAAa,MAAK;;EAG7E,MAAM,wBACJ,cACA,YAEA,gBACS;GACT,MAAM,WAAW,cAAc,OAAO,gBAAe;AACrD,WAAA,SAAS,KACP,+BACA;IACE,MAAM;KAAE,QAAK,QAAA;KAAG,MAAG,QAAA;KAAG;IACtB,SAAS;KAAE,QAAQ;KAAc,MAAM;KAAY;IACnD,WAAW,WAAW;AAEpB,SAAI,WAAW,aAAa,WAAW,aAAa;AAClD,qBAAe,QAAQ;AACvB,mBAAa,QAAQ;;AAEvB,SAAI,WAAW,UACb,SAAA,SAAS,KAAK,wBAAwB,EAAE,UAAU,CAAA;cAG3C,WAAW,YAAY;AAC9B,UAAI,iBAAiB,QAAA,OACnB,gBAAe,QAAQ;AAEzB,UAAI,eAAe,QAAA,KACjB,cAAa,QAAQ;;;IAI5B,EACD,YACF;;;EAIF,MAAM,sBAAsB,cAC1B,qBAAqB,WAAW,aAAa,SAAS,QAAA,KAAI;;EAG5D,MAAM,oBAAoB,YAA0B;GAClD,MAAM,iBAAiB,QAAQ,WAAW,IAAI,GAAG,UAAU,IAAI;AAC/D,wBAAqB,eAAe,SAAS,QAAA,QAAQ,gBAAgB,EACnE,aAAa,+BAA+B,QAAA,KAAK,GAAG,QAAA,UACrD,CAAA;;;EAIH,MAAM,gBAAgB,eAAe,gBAAe;EACpD,MAAM,gBAAgB,eAAe,gBAAe;EACpD,MAAM,8BAA8B,cAAc,OAAO,KAAK,OAAM;EAEpE,MAAM,yBACJ,YACG;AAEH,OAAI,cAAc,OAAO,aAAa,QAAA,WAAW,UAC/C;GAGF,MAAM,WAAW,WAAW,cAAc,UAAU,QAAQ,WAAW;AACvE,iBAAc,OAAO,MAAM,SAAQ;AAEnC,OAAI,WAAW,WAAW,QACxB,SAAQ,MAAM,gBAAe;;AAIjC,kBAAgB;AACd,WAAA,SAAS,GAAG,wBAAwB,sBAAqB;AACzD,WAAA,SAAS,GAAG,wBAAwB,sBAAqB;AACzD,WAAA,SAAS,GAAG,yBAAyB,aAAY;AACjD,WAAA,SAAS,GAAG,6BAA6B,YAAW;IACrD;AAED,wBAAsB;AACpB,WAAA,SAAS,IAAI,wBAAwB,sBAAqB;AAC1D,WAAA,SAAS,IAAI,wBAAwB,sBAAqB;AAC1D,WAAA,SAAS,IAAI,yBAAyB,aAAY;AAClD,WAAA,SAAS,IAAI,6BAA6B,YAAW;AAIrD,gBAAY;IACb;EAED,MAAM,EAAE,oBAAoB,cAAa;EAEzC,MAAM,UAAU,YAAY;AAC1B,SAAM,gBACJ,eAAe;IAAE,aAAU,QAAA;IAAG,QAAK,QAAA;IAAG,MAAG,QAAA;IAAG,eAAe,EAAE;IAAE,CAAC,CAClE;;EAGF,MAAM,uBAAuB,IAAI,MAAK;EACtC,MAAM,wBAAwB,IAAI,MAAK;;EAGvC,MAAM,iBAAiB,eACf,qBAAqB,SAAS,sBAAsB,MAC5D;EAEA,MAAM,8BAA8B;AAClC,OAAI,QAAA,WAAW,SAAS,YACtB,QAAO,QAAA,SAAS,KAAK,eAAe;IAClC,MAAM;IACN,MAAM;IACN,eAAe,QAAA,WAAW;IAC1B,QAAQ,QAAA,WAAW;IACpB,CAAA;AAEH,UAAO,QAAA,SAAS,KAAK,eAAe;IAClC,MAAM;IACN,MAAM;IACP,CAAA;;AAGH,WAAa;GACX;GACA;GACD,CAAA;;uBAGC,mBAwHM,OAAA;IAvHH,IAAI,MAAA,GAAE;IACP,OAAM;OAEN,mBAmHM,OAAA,EAlHJ,OAAK,eAAA,CAAC,oOAAkO;gCAC1L,YAAA;sBAAuC,eAAA;;IAIrF,mBAQM,OAAA,EAPJ,OAAK,eAAA,CAAC,mGAAiG,EAAA,kBACjE,eAAA,OAAA,CAAA,CAAA,EAAA,EAAA,CAGtC,mBAEW,OAAA;KADT,OAAM;KACL,OAAK,eAAL,MAAA,MAAK;;IAEV,mBAOM,OAPN,YAOM,CANJ,YAKiC,MAAA,mBAAA,EAAA;KAJ9B,YAAY,QAAA,WAAM;KACnB,UAAA;KACC,QAAQ,eAAA,SAAkB,QAAA;KAC3B,UAAA;KACC,UAAQ;;IAGb,mBAwCM,OAxCN,YAwCM;KApCI,QAAA,QAAQ,UAAA,WAAA,EADhB,YAcM,MAAA,uBAAA,EAAA;;MAZH,QAAQ,QAAA;MACR,MAAM,QAAA;MACN,QAAQ,QAAA;MACR,SAAS,QAAA;MACT,QAAQ,MAAA,GAAE;MACV,iBAAW,OAAA,OAAA,OAAA,MAAG,UAAW,qBAAA,QAAuB;MAChD,2BAAqB,OAAA,OAAA,OAAA,MAAgB,YAAY,QAAA,SAAS,KAAI,0BAA2B,QAAO;MAGhG,oBAAgB;MAChB,qBAAe,OAAA,OAAA,OAAA,MAAgB,YAAY,QAAA,SAAS,KAAI,2BAA4B,QAAO;;;;;;;;+BAI9F,mBAAyB,OAAA,EAApB,OAAM,aAAW,EAAA,MAAA,GAAA;KAEtB,YAiB0C,MAAA,kBAAA,EAAA;eAhBpC;MAAJ,KAAI;MACJ,kBAAA;MACA,cAAW;MACX,OAAM;MACN,sBAAA;MACC,UAAU,QAAA,WAAM;MACjB,cAAA;MACA,kBAAA;MACC,YAAY;MACZ,aAAa,QAAA;MACd,YAAA;MACC,QAAQ,QAAA;MACR,YAAY,QAAA;MACZ,aAAa,QAAA,SAAM,KAAA;MACpB,QAAA;MACC,UAAM,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,UAAA;MACZ,uBAAmB;;;;;;;;+BACtB,mBAA0B,OAAA,EAArB,OAAM,cAAY,EAAA,MAAA,GAAA;;IAIzB,YAOe,MAAA,aAAA,EAAA;KANb,OAAM;KACN,MAAK;KACL,SAAQ;KACP,SAAO;;4BACU,CAAlB,YAAkB,MAAA,eAAA,CAAA,EAAA,OAAA,OAAA,OAAA,KAClB,mBAAqC,QAAA,EAA/B,OAAM,WAAS,EAAC,YAAQ,GAAA,EAAA,CAAA;;;IAGhC,YAI8D,2BAAA;KAH3D,SAAS,QAAA;KACT,QAAQ,MAAA,GAAE;KACV,yBAAmB,OAAA,OAAA,OAAA,MAAG,YAAY,KAAI,uBAAwB,QAAO;KACrE,iBAAW,OAAA,OAAA,OAAA,MAAG,UAAW,sBAAA,QAAwB;;IAG5C,YAAA,SAAA,WAAA,EADR,mBAcM,OAdN,YAcM,CAXJ,mBAUM,OAVN,YAUM,CARJ,YAAqC,MAAA,wBAAA,EAAA,EAAZ,MAAK,MAAI,CAAA,EAClC,mBAMM,OANN,YAMM;iDANsB,OAE1B,GAAA;KAAA,mBAAoE,MAAA,MAAA,gBAA7D,eAAA,OAAgB,aAAW,IAAM,QAAA,OAAO,aAAW,CAAA,EAAA,EAAA;iDAAU,gBAEpE,GAAA;KAAA,YAAmD,MAAA,mBAAA,EAAA,EAA9B,MAAM,aAAA,SAAgB,QAAA,MAAA,EAAA,MAAA,GAAA,CAAA,OAAA,CAAA;iDAAQ,qCAErD,GAAA;;IAGJ,YAiBe,MAAA,aAAA,EAAA;cAhBT;KAAJ,KAAI;KACJ,OAAM;KACL,UAAU,MAAA,UAAS;KACnB,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,UAAA;;4BASL,CARP,mBAQO,QARP,YAQO,CALL,YAGc,MAAA,WAAA,EAAA;MAFZ,OAAM;MACN,MAAK;MACL,MAAK;qCACP,mBAAiD,QAAA,EAA3C,OAAM,2BAAyB,EAAC,QAAI,GAAA,EAAA,CAAA,EAE5C,mBAEO,QAFP,YAAsB,WACf,gBAAG,QAAA,OAAM,GAAG,iBAAY,gBAAG,QAAA,QAAQ,OAAG,GAAA,GAAA,gBAAY,QAAA,KAAI,EAAA,EAAA,CAAA,CAAA"}
@@ -2,7 +2,7 @@ import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-hel
2
2
  import { n as CommandActionForm_default, t as CommandActionInput_default } from "./CommandActionInput-TkcAx6E8.js";
3
3
  import { n as DataTableCell_default, t as DataTableRow_default } from "./DataTableRow-c3XveEUO.js";
4
4
  import { n as DataTableCheckbox_default } from "./DataTable-BqbZKW3K.js";
5
- import { n as getEnvironmentVariables, t as getServerUrl } from "./get-server-url-o3On8CEr.js";
5
+ import { n as getEnvironmentVariables, t as getServerUrl } from "./get-server-url-UVN-dx79.js";
6
6
  import { n as DataTableRow_default$1, o as DataTableCell_default$1, r as DataTableInput_default, s as DataTable_default } from "./data-table-PL7e8NRO.js";
7
7
  import { t as CollapsibleSection_default } from "./layout-BWiL7dfb.js";
8
8
  import { Fragment, capitalize, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, mergeProps, normalizeClass, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useId, useModel, watch, withCtx, withModifiers } from "vue";
@@ -168,6 +168,7 @@ var authOptions = {
168
168
  };
169
169
  //#endregion
170
170
  //#region src/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.ts
171
+ var requirementSignature = (requirement) => JSON.stringify(Object.keys(requirement));
171
172
  /**
172
173
  * Format a scheme object into a display object
173
174
  *
@@ -206,13 +207,14 @@ var formatSecurityRequirement = (requirement, securitySchemes) => {
206
207
  * Contains either a flat list, or different groups of required, available, and add new
207
208
  */
208
209
  var getSecuritySchemeOptions = (security, securitySchemes, selectedSchemes, canAddNewAuth = false) => {
210
+ const selectedByRequirement = new Map(selectedSchemes.map((selectedScheme) => [requirementSignature(selectedScheme), selectedScheme]));
209
211
  /**
210
212
  * Build required schemes formatted as options and track scheme names in a single pass.
211
213
  * We use names (not full IDs) because we want to exclude any scheme that is already
212
214
  * required, regardless of its specific scopes or hash.
213
215
  */
214
216
  const { requiredFormatted, requiredSchemeNames, existingIds } = security.reduce((acc, requirement) => {
215
- const formatted = formatSecurityRequirement(requirement, securitySchemes);
217
+ const formatted = formatSecurityRequirement(selectedByRequirement.get(requirementSignature(requirement)) ?? requirement, securitySchemes);
216
218
  if (formatted) {
217
219
  acc.requiredFormatted.push(formatted);
218
220
  acc.existingIds.add(formatted.id);
@@ -603,10 +605,9 @@ var authorizeServers = async (flows, type, scopes, { code, pkce, proxyUrl } = {}
603
605
  if (scopes && (type === "clientCredentials" || type === "password")) formData.set("scope", scopes);
604
606
  /** Where to add the credentials */
605
607
  const addCredentialsToBody = flow["x-scalar-credentials-location"] === "body";
606
- if (addCredentialsToBody) {
607
- formData.set("client_id", flow["x-scalar-secret-client-id"]);
608
- formData.set("client_secret", flow["x-scalar-secret-client-secret"]);
609
- }
608
+ const hasClientSecret = Boolean(flow["x-scalar-secret-client-secret"]);
609
+ if (addCredentialsToBody || type === "authorizationCode" && !hasClientSecret) formData.set("client_id", flow["x-scalar-secret-client-id"]);
610
+ if (addCredentialsToBody && hasClientSecret) formData.set("client_secret", flow["x-scalar-secret-client-secret"]);
610
611
  if ("x-scalar-secret-redirect-uri" in flow && flow["x-scalar-secret-redirect-uri"]) formData.set("redirect_uri", flow["x-scalar-secret-redirect-uri"]);
611
612
  if (code) {
612
613
  formData.set("code", code);
@@ -623,7 +624,7 @@ var authorizeServers = async (flows, type, scopes, { code, pkce, proxyUrl } = {}
623
624
  });
624
625
  try {
625
626
  const headers = { "Content-Type": "application/x-www-form-urlencoded" };
626
- if (!addCredentialsToBody) headers.Authorization = `Basic ${encode(`${flow["x-scalar-secret-client-id"]}:${flow["x-scalar-secret-client-secret"]}`)}`;
627
+ if (!addCredentialsToBody && hasClientSecret) headers.Authorization = `Basic ${encode(`${flow["x-scalar-secret-client-id"]}:${flow["x-scalar-secret-client-secret"]}`)}`;
627
628
  const tokenUrl = makeUrlAbsolute(flow["x-scalar-secret-token-url"] ?? flow.tokenUrl, getActiveServerBase(activeServer, environmentVariables));
628
629
  const url = shouldUseProxy(proxyUrl, tokenUrl) ? `${proxyUrl}?${new URLSearchParams([["scalar_url", tokenUrl]]).toString()}` : tokenUrl;
629
630
  const responseData = await (await fetch(url, {
@@ -1842,10 +1843,12 @@ var extractSecuritySchemeSecrets = (scheme, authStore, name, documentSlug) => {
1842
1843
  if (scheme.type === "oauth2") {
1843
1844
  const storeSecrets = secrets?.type === "oauth2" ? secrets : void 0;
1844
1845
  const extracted = extractOAuthFlowSecrets(scheme.flows, storeSecrets);
1846
+ const configuredDefaultScopes = Array.isArray(scheme["x-default-scopes"]) ? scheme["x-default-scopes"].filter((scope) => typeof scope === "string") : [];
1847
+ const mergedDefaultScopes = Array.from(new Set([...configuredDefaultScopes, ...extracted.selectedScopes]));
1845
1848
  return {
1846
1849
  ...scheme,
1847
1850
  flows: extracted.flows,
1848
- "x-default-scopes": extracted.selectedScopes
1851
+ "x-default-scopes": mergedDefaultScopes
1849
1852
  };
1850
1853
  }
1851
1854
  if (scheme.type === "openIdConnect") {
@@ -1883,4 +1886,4 @@ var mergeSecurity = (documentSecuritySchemes = {}, configSecuritySchemes = {}, a
1883
1886
  //#endregion
1884
1887
  export { AuthSelector_default as n, isAuthOptional as r, mergeSecurity as t };
1885
1888
 
1886
- //# sourceMappingURL=scalar-auth-selector-block-DI3DLag9.js.map
1889
+ //# sourceMappingURL=scalar-auth-selector-block-Bs79QOMA.js.map