@scalar/api-reference 1.59.2 → 1.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/blocks/scalar-info-block/components/InfoLinks.vue.d.ts.map +1 -1
  3. package/dist/blocks/scalar-info-block/components/InfoLinks.vue.js.map +1 -1
  4. package/dist/blocks/scalar-info-block/components/InfoLinks.vue.script.js +12 -7
  5. package/dist/blocks/scalar-info-block/components/InfoLinks.vue.script.js.map +1 -1
  6. package/dist/blocks/scalar-info-block/components/IntroductionLayout.vue.d.ts +4 -4
  7. package/dist/blocks/scalar-info-block/components/IntroductionLayout.vue.d.ts.map +1 -1
  8. package/dist/blocks/scalar-info-block/components/IntroductionLayout.vue.js +1 -1
  9. package/dist/blocks/scalar-info-block/components/IntroductionLayout.vue.js.map +1 -1
  10. package/dist/blocks/scalar-info-block/components/IntroductionLayout.vue.script.js +14 -17
  11. package/dist/blocks/scalar-info-block/components/IntroductionLayout.vue.script.js.map +1 -1
  12. package/dist/blocks/scalar-info-block/components/IntroductionLoading.vue.d.ts +12 -0
  13. package/dist/blocks/scalar-info-block/components/IntroductionLoading.vue.d.ts.map +1 -0
  14. package/dist/blocks/scalar-info-block/components/IntroductionLoading.vue.js +9 -0
  15. package/dist/blocks/scalar-info-block/components/IntroductionLoading.vue.js.map +1 -0
  16. package/dist/blocks/scalar-info-block/components/IntroductionLoading.vue.script.js +63 -0
  17. package/dist/blocks/scalar-info-block/components/IntroductionLoading.vue.script.js.map +1 -0
  18. package/dist/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue.d.ts +13 -0
  19. package/dist/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue.d.ts.map +1 -1
  20. package/dist/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue.js +1 -1
  21. package/dist/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue.js.map +1 -1
  22. package/dist/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue.script.js +32 -8
  23. package/dist/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue.script.js.map +1 -1
  24. package/dist/browser/chunks/AgentScalarChatInterface-CesFQ_Ax.js +27 -0
  25. package/dist/browser/chunks/ScalarTextInput.vue-C14zmVNI.js +27 -0
  26. package/dist/browser/chunks/basic-shape-diamond.svg-BTEOT1FL.js +1 -1
  27. package/dist/browser/chunks/basic-shape-hexagon.svg-BSPzaCgF.js +1 -1
  28. package/dist/browser/chunks/basic-shape-primary-circle-ellipse-round.svg-DKmZ8UUU.js +1 -1
  29. package/dist/browser/chunks/basic-shape-primary-square-rectangle.svg-n2YRykHD.js +1 -1
  30. package/dist/browser/chunks/basic-shape-shield.svg-Bec9cJDA.js +1 -1
  31. package/dist/browser/chunks/browser-67K6wmG9.js +1 -1
  32. package/dist/browser/chunks/computer-device-desktop-monitor.svg-m6j893Hb.js +1 -1
  33. package/dist/browser/chunks/computer-device-desktop.svg-Dk1VVO7k.js +1 -1
  34. package/dist/browser/chunks/computer-device-laptop.svg-BNGVUCYS.js +1 -1
  35. package/dist/browser/chunks/computer-device-mobile-phone-android-samsung-back.svg-CC4UUTFw.js +1 -1
  36. package/dist/browser/chunks/computer-device-mobile-phone-android-samsung.svg-D8ExpMpL.js +1 -1
  37. package/dist/browser/chunks/computer-device-mobile-phone-iphone-x-back.svg-CLm7sgMM.js +1 -1
  38. package/dist/browser/chunks/computer-device-mobile-phone-iphone-x.svg-Xrttg6_7.js +1 -1
  39. package/dist/browser/chunks/computer-device-mobile-tablet-touch.svg-DQ2oTvOG.js +1 -1
  40. package/dist/browser/chunks/computer-device-mobile-tablet.svg-DCr0XlRc.js +1 -1
  41. package/dist/browser/chunks/computer-device-network-ethernet-cat6.svg-AK9l0iOl.js +1 -1
  42. package/dist/browser/chunks/computer-device-network-lan-www.svg-gUIdFBlE.js +1 -1
  43. package/dist/browser/chunks/computer-device-network-wifi-connection.svg-Be-EMm4e.js +1 -1
  44. package/dist/browser/chunks/computer-device-network-wifi-router.svg-Dc2VzyqK.js +1 -1
  45. package/dist/browser/chunks/ecology-science-erlenmeyer-flask.svg-DHgy7Jfd.js +1 -1
  46. package/dist/browser/chunks/image-flash-lightning.svg-EETR_y1q.js +1 -1
  47. package/dist/browser/chunks/image-picture-flower.svg-DN1AYzJU.js +1 -1
  48. package/dist/browser/chunks/interface-alert-exclamation-diamond.svg-C5NozMV_.js +1 -1
  49. package/dist/browser/chunks/interface-alert-exclamation-triangle-warning.svg-DaAg2fF5.js +1 -1
  50. package/dist/browser/chunks/interface-alert-information-circle.svg-ckkkt9Mv.js +1 -1
  51. package/dist/browser/chunks/interface-award-crown.svg-pjvn9hY-.js +1 -1
  52. package/dist/browser/chunks/interface-bookmark-tag.svg-r2r-lQq4.js +1 -1
  53. package/dist/browser/chunks/interface-bookmark.svg-BK9HKQBT.js +1 -1
  54. package/dist/browser/chunks/interface-calendar-date-one.svg-DNnF0M1I.js +1 -1
  55. package/dist/browser/chunks/interface-content-book-open-pages.svg-CQj_w9Vp.js +1 -1
  56. package/dist/browser/chunks/interface-content-book-page.svg-DppoeJRe.js +1 -1
  57. package/dist/browser/chunks/interface-content-file.svg-CvcD7OiY.js +1 -1
  58. package/dist/browser/chunks/interface-content-folder.svg-BmtS5I9A.js +1 -1
  59. package/dist/browser/chunks/interface-copy-clipboard.svg-Be6EI50X.js +1 -1
  60. package/dist/browser/chunks/interface-edit-attachment.svg-G5TKzpWX.js +1 -1
  61. package/dist/browser/chunks/interface-edit-binocular.svg-jzL-DvGB.js +1 -1
  62. package/dist/browser/chunks/interface-edit-magic-wand.svg-BOTlymvp.js +1 -1
  63. package/dist/browser/chunks/interface-edit-tool-paint-roller.svg-s9dwryx7.js +1 -1
  64. package/dist/browser/chunks/interface-edit-tool-pencil.svg-C7v0dbB3.js +1 -1
  65. package/dist/browser/chunks/interface-favorite-award.svg-CYHUgUG0.js +1 -1
  66. package/dist/browser/chunks/interface-favorite-flag.svg-C10zlKOb.js +1 -1
  67. package/dist/browser/chunks/interface-favorite-heart.svg-eoduXxlz.js +1 -1
  68. package/dist/browser/chunks/interface-favorite-star.svg-BSmxJetr.js +1 -1
  69. package/dist/browser/chunks/interface-favorite-stars-sparkles.svg-JTFLj3Ls.js +1 -1
  70. package/dist/browser/chunks/interface-hierarchy-flowchart.svg-Cg_Wy0kN.js +1 -1
  71. package/dist/browser/chunks/interface-home-house.svg-DytoGRnv.js +1 -1
  72. package/dist/browser/chunks/interface-hyperlink.svg-CuEfmmQI.js +1 -1
  73. package/dist/browser/chunks/interface-lighting-brightness.svg-DSK0h_Pa.js +1 -1
  74. package/dist/browser/chunks/interface-lock-closed.svg-Cn6TaLYv.js +1 -1
  75. package/dist/browser/chunks/interface-lock-open-unlock.svg-CVkG5-9W.js +1 -1
  76. package/dist/browser/chunks/interface-login-key.svg-y-cwwXjN.js +1 -1
  77. package/dist/browser/chunks/interface-search.svg-S-puVFJB.js +1 -1
  78. package/dist/browser/chunks/interface-setting-cog.svg-CTH4_lLg.js +1 -1
  79. package/dist/browser/chunks/interface-share-megaphone-bullhorn.svg-Pbp39MyC.js +1 -1
  80. package/dist/browser/chunks/interface-share-rocket.svg-BgCsIRZO.js +1 -1
  81. package/dist/browser/chunks/interface-share-satellite.svg-DAMN9d5G.js +1 -1
  82. package/dist/browser/chunks/interface-share-space-ship.svg-Dt-Mejxk.js +1 -1
  83. package/dist/browser/chunks/interface-share.svg-vFYTXSti.js +1 -1
  84. package/dist/browser/chunks/interface-signal-square.svg-DNG4LpAe.js +1 -1
  85. package/dist/browser/chunks/interface-time-clock-circle.svg-Bpz-nLxo.js +1 -1
  86. package/dist/browser/chunks/interface-time-hour-glass.svg-D7agfKsH.js +1 -1
  87. package/dist/browser/chunks/interface-users-multiple.svg-CkPJBBnG.js +1 -1
  88. package/dist/browser/chunks/interface-weather-moon.svg-CaTZFMPO.js +1 -1
  89. package/dist/browser/chunks/mail-chat-bubble-square.svg-DC8RIihp.js +1 -1
  90. package/dist/browser/chunks/mail-send-email-paper-airplane.svg-D8OLs9jz.js +1 -1
  91. package/dist/browser/chunks/mail-send-envelope.svg-CV33h5Sx.js +1 -1
  92. package/dist/browser/chunks/modal-BZzcBkVp.js +99 -0
  93. package/dist/browser/chunks/{modal-CgDbMGa1.js → modal-LBDjZSmM.js} +2 -2
  94. package/dist/browser/chunks/money-cashier-receipt.svg-CJL8C2gs.js +1 -1
  95. package/dist/browser/chunks/money-currency-dollar-pay.svg-VdBplCTx.js +1 -1
  96. package/dist/browser/chunks/money-graph-arrow-increase.svg-DcRov3zk.js +1 -1
  97. package/dist/browser/chunks/money-graph-bar-chart-increase.svg-Cc7KxjX-.js +1 -1
  98. package/dist/browser/chunks/nature-ecology-leaf.svg-DR3cTZxt.js +1 -1
  99. package/dist/browser/chunks/phone-telephone.svg-DyY0gUlk.js +1 -1
  100. package/dist/browser/chunks/programming-bug.svg-BHLT-Qhp.js +1 -1
  101. package/dist/browser/chunks/programming-cloud.svg-B6YW33ba.js +1 -1
  102. package/dist/browser/chunks/programming-computer-database-server.svg-B6o5Sdn-.js +1 -1
  103. package/dist/browser/chunks/programming-computer-database.svg-Cl7OVtpJ.js +1 -1
  104. package/dist/browser/chunks/programming-module-four-layout.svg-BQrerL1x.js +1 -1
  105. package/dist/browser/chunks/programming-module-three.svg-B2KTQzBM.js +1 -1
  106. package/dist/browser/chunks/programming-module.svg-CiID7kPm.js +1 -1
  107. package/dist/browser/chunks/programming-script-code.svg-D1M5rtkN.js +1 -1
  108. package/dist/browser/chunks/runtime-core.esm-bundler-Byrbbu5Q.js +1 -1
  109. package/dist/browser/chunks/shopping-cart.svg-BEegiIR9.js +1 -1
  110. package/dist/browser/chunks/shopping-gift-present.svg-BUHwuLix.js +1 -1
  111. package/dist/browser/chunks/shopping-shipping-box-parcel-package.svg-D6fxWdYx.js +1 -1
  112. package/dist/browser/chunks/tag-new-circle.svg-jsg1bGs0.js +1 -1
  113. package/dist/browser/chunks/travel-map-earth-globe.svg-ClbMiU-f.js +1 -1
  114. package/dist/browser/chunks/vendor-wW8jg8wN.js +306 -0
  115. package/dist/browser/standalone.esm.js +20 -20
  116. package/dist/browser/standalone.js +249 -248
  117. package/dist/components/ApiReference.vue.d.ts.map +1 -1
  118. package/dist/components/ApiReference.vue.js +1 -1
  119. package/dist/components/ApiReference.vue.js.map +1 -1
  120. package/dist/components/ApiReference.vue.script.js +39 -11
  121. package/dist/components/ApiReference.vue.script.js.map +1 -1
  122. package/dist/components/Content/AsyncApi/AsyncApiTraversedEntry.vue.d.ts.map +1 -1
  123. package/dist/components/Content/AsyncApi/AsyncApiTraversedEntry.vue.js.map +1 -1
  124. package/dist/components/Content/AsyncApi/AsyncApiTraversedEntry.vue.script.js +0 -1
  125. package/dist/components/Content/AsyncApi/AsyncApiTraversedEntry.vue.script.js.map +1 -1
  126. package/dist/components/Content/Content.vue.d.ts +4 -2
  127. package/dist/components/Content/Content.vue.d.ts.map +1 -1
  128. package/dist/components/Content/Content.vue.js.map +1 -1
  129. package/dist/components/Content/Content.vue.script.js +25 -2
  130. package/dist/components/Content/Content.vue.script.js.map +1 -1
  131. package/dist/components/Content/Operations/TraversedEntry.vue.d.ts.map +1 -1
  132. package/dist/components/Content/Operations/TraversedEntry.vue.js.map +1 -1
  133. package/dist/components/Content/Operations/TraversedEntry.vue.script.js +2 -2
  134. package/dist/components/Content/Operations/TraversedEntry.vue.script.js.map +1 -1
  135. package/dist/components/Content/Schema/Schema.vue.d.ts.map +1 -1
  136. package/dist/components/Content/Schema/Schema.vue.js +1 -1
  137. package/dist/components/Content/Schema/Schema.vue.js.map +1 -1
  138. package/dist/components/Content/Schema/Schema.vue.script.js +22 -2
  139. package/dist/components/Content/Schema/Schema.vue.script.js.map +1 -1
  140. package/dist/components/Content/Schema/SchemaProperty.vue.d.ts +0 -6
  141. package/dist/components/Content/Schema/SchemaProperty.vue.d.ts.map +1 -1
  142. package/dist/components/Content/Schema/SchemaProperty.vue.js +1 -1
  143. package/dist/components/Content/Schema/SchemaProperty.vue.js.map +1 -1
  144. package/dist/components/Content/Schema/SchemaProperty.vue.script.js +16 -2
  145. package/dist/components/Content/Schema/SchemaProperty.vue.script.js.map +1 -1
  146. package/dist/components/Content/Schema/helpers/should-display-description.d.ts.map +1 -1
  147. package/dist/components/Content/Schema/helpers/should-display-description.js +1 -1
  148. package/dist/components/Content/Schema/helpers/should-display-description.js.map +1 -1
  149. package/dist/components/Content/Tags/Tag.vue.d.ts +0 -1
  150. package/dist/components/Content/Tags/Tag.vue.d.ts.map +1 -1
  151. package/dist/components/Content/Tags/Tag.vue.js.map +1 -1
  152. package/dist/components/Content/Tags/Tag.vue.script.js +0 -3
  153. package/dist/components/Content/Tags/Tag.vue.script.js.map +1 -1
  154. package/dist/components/Content/Tags/components/ModernLayout.vue.d.ts +0 -1
  155. package/dist/components/Content/Tags/components/ModernLayout.vue.d.ts.map +1 -1
  156. package/dist/components/Content/Tags/components/ModernLayout.vue.js +1 -1
  157. package/dist/components/Content/Tags/components/ModernLayout.vue.js.map +1 -1
  158. package/dist/components/Content/Tags/components/ModernLayout.vue.script.js +0 -3
  159. package/dist/components/Content/Tags/components/ModernLayout.vue.script.js.map +1 -1
  160. package/dist/components/Content/Tags/components/TagSection.vue.d.ts +0 -1
  161. package/dist/components/Content/Tags/components/TagSection.vue.d.ts.map +1 -1
  162. package/dist/components/Content/Tags/components/TagSection.vue.js.map +1 -1
  163. package/dist/components/Content/Tags/components/TagSection.vue.script.js +5 -6
  164. package/dist/components/Content/Tags/components/TagSection.vue.script.js.map +1 -1
  165. package/dist/components/RenderPlugins/RenderPluginView.vue.d.ts +11 -0
  166. package/dist/components/RenderPlugins/RenderPluginView.vue.d.ts.map +1 -0
  167. package/dist/components/RenderPlugins/RenderPluginView.vue.js +7 -0
  168. package/dist/components/RenderPlugins/RenderPluginView.vue.js.map +1 -0
  169. package/dist/components/RenderPlugins/RenderPluginView.vue.script.js +45 -0
  170. package/dist/components/RenderPlugins/RenderPluginView.vue.script.js.map +1 -0
  171. package/dist/components/RenderPlugins/RenderPlugins.vue.d.ts +5 -1
  172. package/dist/components/RenderPlugins/RenderPlugins.vue.d.ts.map +1 -1
  173. package/dist/components/RenderPlugins/RenderPlugins.vue.js.map +1 -1
  174. package/dist/components/RenderPlugins/RenderPlugins.vue.script.js +17 -22
  175. package/dist/components/RenderPlugins/RenderPlugins.vue.script.js.map +1 -1
  176. package/dist/components/Section/SectionContent.vue.d.ts +1 -6
  177. package/dist/components/Section/SectionContent.vue.d.ts.map +1 -1
  178. package/dist/components/Section/SectionContent.vue.js +7 -2
  179. package/dist/components/Section/SectionContent.vue.js.map +1 -1
  180. package/dist/components/Section/SectionHeader.vue.d.ts +3 -4
  181. package/dist/components/Section/SectionHeader.vue.d.ts.map +1 -1
  182. package/dist/components/Section/SectionHeader.vue.js +1 -1
  183. package/dist/components/Section/SectionHeader.vue.js.map +1 -1
  184. package/dist/components/Section/SectionHeader.vue.script.js +5 -10
  185. package/dist/components/Section/SectionHeader.vue.script.js.map +1 -1
  186. package/dist/features/Search/helpers/create-search-index.d.ts.map +1 -1
  187. package/dist/features/Search/helpers/create-search-index.js +4 -3
  188. package/dist/features/Search/helpers/create-search-index.js.map +1 -1
  189. package/dist/helpers/id-routing.d.ts +6 -13
  190. package/dist/helpers/id-routing.d.ts.map +1 -1
  191. package/dist/helpers/id-routing.js +104 -34
  192. package/dist/helpers/id-routing.js.map +1 -1
  193. package/dist/helpers/lazy-bus.d.ts +10 -0
  194. package/dist/helpers/lazy-bus.d.ts.map +1 -1
  195. package/dist/helpers/lazy-bus.js +22 -1
  196. package/dist/helpers/lazy-bus.js.map +1 -1
  197. package/dist/plugins/index.d.ts +1 -1
  198. package/dist/plugins/index.d.ts.map +1 -1
  199. package/dist/plugins/plugin-manager.d.ts +27 -2
  200. package/dist/plugins/plugin-manager.d.ts.map +1 -1
  201. package/dist/plugins/plugin-manager.js +32 -2
  202. package/dist/plugins/plugin-manager.js.map +1 -1
  203. package/dist/style.css +440 -265
  204. package/dist/vue-styles.css +157 -159
  205. package/package.json +15 -13
  206. package/dist/browser/chunks/AgentScalarChatInterface-D4DCmV5y.js +0 -27
  207. package/dist/browser/chunks/ScalarTextInput.vue-C5aaO8tA.js +0 -27
  208. package/dist/browser/chunks/modal-B4LeCbAi.js +0 -66
  209. package/dist/browser/chunks/vendor-BNhbieDE.js +0 -338
  210. package/dist/components/LoadingSkeleton.vue.d.ts +0 -9
  211. package/dist/components/LoadingSkeleton.vue.d.ts.map +0 -1
  212. package/dist/components/LoadingSkeleton.vue.js +0 -9
  213. package/dist/components/LoadingSkeleton.vue.js.map +0 -1
  214. package/dist/components/LoadingSkeleton.vue.script.js +0 -20
  215. package/dist/components/LoadingSkeleton.vue.script.js.map +0 -1
  216. package/dist/components/Section/SectionContent.vue.script.js +0 -23
  217. package/dist/components/Section/SectionContent.vue.script.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @scalar/api-reference
2
2
 
3
+ ## 1.60.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#9478](https://github.com/scalar/scalar/pull/9478): Add `content.start` plugin view slot and `sidebar` visibility option for plugin view components.
8
+ - **`content.start`**: A new view slot that renders custom plugin components **before** the Introduction/Info section (at the top of the content area).
9
+ - **`sidebar` option on `ViewComponent`**: Plugins can now opt-in to display a sidebar entry for their custom views by providing `sidebar: { show: true, label: 'My Page' }`. Omitting `sidebar` or setting `show: false` hides the entry from the sidebar. The entry hooks into the existing navigation, so clicking it scrolls to the plugin view and it highlights as it scrolls into view.
10
+
11
+ ### Patch Changes
12
+
13
+ - [#9504](https://github.com/scalar/scalar/pull/9504): Fix extra nesting and duplicated description when array items are wrapped in a single-item composition (`allOf`, `oneOf`, or `anyOf`)
14
+ - [#9526](https://github.com/scalar/scalar/pull/9526): Fix anchor links to schema properties that are hidden inside collapsed sections. Deep links now expand the disclosures on the path to the target property and scroll to it, so links work without enabling `expandAllSchemaProperties`.
15
+ - [#9484](https://github.com/scalar/scalar/pull/9484): Fix the schema description being hidden for responses when `expandAllResponses` is enabled. A response's own description and its content schema's description are now both shown.
16
+ - [#9531](https://github.com/scalar/scalar/pull/9531): fix: the introduction loading skeleton now mirrors the actual layout (badges, title, links, description and selector cards) instead of generic stacked bars, so the page no longer jumps once the document loads
17
+ - [#9524](https://github.com/scalar/scalar/pull/9524): Fix sidebar overlapping the content at exactly 1000px wide. The layout grid switched to the mobile (stacked) layout at `max-width: 1000px` while the sidebar visibility is driven by Tailwind's `lg:` variant (`min-width: 1000px`), so both fired at 1000px. The mobile breakpoint now uses `width < 1000px`, the exact complement of `lg:`, so 1000px is treated as desktop.
18
+
19
+ ## 1.59.3
20
+
21
+ ### Patch Changes
22
+
23
+ - [#9396](https://github.com/scalar/scalar/pull/9396): Refactor URL redirects into a routing-agnostic, list-driven engine. Redirects now operate on the bare navigation id, so each rule works across hash, hash-base-path, and path routing automatically. Also redirect old `models/<name>` bookmarks to the configured models section slug when the section label is customized (e.g. `schemas/`).
24
+ - [#9489](https://github.com/scalar/scalar/pull/9489): Do not render the info link list when no links are available.
25
+ - [#9342](https://github.com/scalar/scalar/pull/9342): fix: resolve operations when OpenAPI path items use `$ref`
26
+
27
+ Path entries and webhooks can reference `components.pathItems` instead of inlining operations. Navigation, mutators, search, and markdown export now resolve path-item references before reading HTTP methods and path-level parameters.
28
+
29
+ - [#9498](https://github.com/scalar/scalar/pull/9498): Sync the SDK installation tabs with the operation code examples: picking a language under "Client Libraries" now switches every operation's code sample to that language's custom example
30
+
3
31
  ## 1.59.2
4
32
 
5
33
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"InfoLinks.vue.d.ts","sourceRoot":"","sources":["../../../../src/blocks/scalar-info-block/components/InfoLinks.vue"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAEpE,OAAO,KAAK,EACV,2BAA2B,EAC3B,UAAU,EACX,MAAM,8DAA8D,CAAA;AAMrE,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,UAAU,GAAG,kBAAkB,CAAA;IACrC,YAAY,CAAC,EAAE,2BAA2B,CAAA;CAC3C,CAAC;AAwFF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"InfoLinks.vue.d.ts","sourceRoot":"","sources":["../../../../src/blocks/scalar-info-block/components/InfoLinks.vue"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAEpE,OAAO,KAAK,EACV,2BAA2B,EAC3B,UAAU,EACX,MAAM,8DAA8D,CAAA;AAOrE,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,UAAU,GAAG,kBAAkB,CAAA;IACrC,YAAY,CAAC,EAAE,2BAA2B,CAAA;CAC3C,CAAC;AAmGF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1 +1 @@
1
- {"version":3,"file":"InfoLinks.vue.js","names":[],"sources":["../../../../src/blocks/scalar-info-block/components/InfoLinks.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { AsyncApiInfoObject } from '@scalar/types/asyncapi/3.1'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type {\n ExternalDocumentationObject,\n InfoObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport { LinkList } from '@/components/LinkList'\nimport { ExternalDocs } from '@/features/external-docs'\nimport { Contact, License, TermsOfService } from '@/features/info-object'\n\ndefineProps<{\n info: InfoObject | AsyncApiInfoObject\n externalDocs?: ExternalDocumentationObject\n}>()\n</script>\n\n<template>\n <LinkList>\n <ExternalDocs :value=\"externalDocs\" />\n <Contact\n v-if=\"info.contact\"\n :value=\"info.contact\" />\n <License\n v-if=\"info.license\"\n :value=\"getResolvedRef(info.license)\" />\n <TermsOfService\n v-if=\"info.termsOfService\"\n :value=\"info.termsOfService\" />\n </LinkList>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"InfoLinks.vue.js","names":[],"sources":["../../../../src/blocks/scalar-info-block/components/InfoLinks.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { AsyncApiInfoObject } from '@scalar/types/asyncapi/3.1'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type {\n ExternalDocumentationObject,\n InfoObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed } from 'vue'\n\nimport { LinkList } from '@/components/LinkList'\nimport { ExternalDocs } from '@/features/external-docs'\nimport { Contact, License, TermsOfService } from '@/features/info-object'\n\nconst { info, externalDocs } = defineProps<{\n info: InfoObject | AsyncApiInfoObject\n externalDocs?: ExternalDocumentationObject\n}>()\n\n/** Whether there is at least one link to show, so we do not render an empty list */\nconst hasLinks = computed(() =>\n Boolean(externalDocs || info.contact || info.license || info.termsOfService),\n)\n</script>\n\n<template>\n <LinkList v-if=\"hasLinks\">\n <ExternalDocs\n v-if=\"externalDocs\"\n :value=\"externalDocs\" />\n <Contact\n v-if=\"info.contact\"\n :value=\"info.contact\" />\n <License\n v-if=\"info.license\"\n :value=\"getResolvedRef(info.license)\" />\n <TermsOfService\n v-if=\"info.termsOfService\"\n :value=\"info.termsOfService\" />\n </LinkList>\n</template>\n"],"mappings":""}
@@ -3,7 +3,7 @@ import ExternalDocs_default from "../../../features/external-docs/ExternalDocs.v
3
3
  import Contact_default from "../../../features/info-object/Contact.vue.js";
4
4
  import License_default from "../../../features/info-object/License.vue.js";
5
5
  import TermsOfService_default from "../../../features/info-object/TermsOfService.vue.js";
6
- import { createBlock, createCommentVNode, createVNode, defineComponent, openBlock, unref, withCtx } from "vue";
6
+ import { computed, createBlock, createCommentVNode, defineComponent, openBlock, unref, withCtx } from "vue";
7
7
  import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
8
8
  //#region src/blocks/scalar-info-block/components/InfoLinks.vue?vue&type=script&setup=true&lang.ts
9
9
  var InfoLinks_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
@@ -13,25 +13,30 @@ var InfoLinks_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defi
13
13
  externalDocs: {}
14
14
  },
15
15
  setup(__props) {
16
+ /** Whether there is at least one link to show, so we do not render an empty list */
17
+ const hasLinks = computed(() => Boolean(__props.externalDocs || __props.info.contact || __props.info.license || __props.info.termsOfService));
16
18
  return (_ctx, _cache) => {
17
- return openBlock(), createBlock(unref(LinkList_default), null, {
19
+ return hasLinks.value ? (openBlock(), createBlock(unref(LinkList_default), { key: 0 }, {
18
20
  default: withCtx(() => [
19
- createVNode(unref(ExternalDocs_default), { value: __props.externalDocs }, null, 8, ["value"]),
20
- __props.info.contact ? (openBlock(), createBlock(unref(Contact_default), {
21
+ __props.externalDocs ? (openBlock(), createBlock(unref(ExternalDocs_default), {
21
22
  key: 0,
23
+ value: __props.externalDocs
24
+ }, null, 8, ["value"])) : createCommentVNode("", true),
25
+ __props.info.contact ? (openBlock(), createBlock(unref(Contact_default), {
26
+ key: 1,
22
27
  value: __props.info.contact
23
28
  }, null, 8, ["value"])) : createCommentVNode("", true),
24
29
  __props.info.license ? (openBlock(), createBlock(unref(License_default), {
25
- key: 1,
30
+ key: 2,
26
31
  value: unref(getResolvedRef)(__props.info.license)
27
32
  }, null, 8, ["value"])) : createCommentVNode("", true),
28
33
  __props.info.termsOfService ? (openBlock(), createBlock(unref(TermsOfService_default), {
29
- key: 2,
34
+ key: 3,
30
35
  value: __props.info.termsOfService
31
36
  }, null, 8, ["value"])) : createCommentVNode("", true)
32
37
  ]),
33
38
  _: 1
34
- });
39
+ })) : createCommentVNode("", true);
35
40
  };
36
41
  }
37
42
  });
@@ -1 +1 @@
1
- {"version":3,"file":"InfoLinks.vue.script.js","names":[],"sources":["../../../../src/blocks/scalar-info-block/components/InfoLinks.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { AsyncApiInfoObject } from '@scalar/types/asyncapi/3.1'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type {\n ExternalDocumentationObject,\n InfoObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport { LinkList } from '@/components/LinkList'\nimport { ExternalDocs } from '@/features/external-docs'\nimport { Contact, License, TermsOfService } from '@/features/info-object'\n\ndefineProps<{\n info: InfoObject | AsyncApiInfoObject\n externalDocs?: ExternalDocumentationObject\n}>()\n</script>\n\n<template>\n <LinkList>\n <ExternalDocs :value=\"externalDocs\" />\n <Contact\n v-if=\"info.contact\"\n :value=\"info.contact\" />\n <License\n v-if=\"info.license\"\n :value=\"getResolvedRef(info.license)\" />\n <TermsOfService\n v-if=\"info.termsOfService\"\n :value=\"info.termsOfService\" />\n </LinkList>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;uBAmBE,YAWW,MAAA,iBAAA,EAAA,MAAA;2BAV6B;KAAtC,YAAsC,MAAA,qBAAA,EAAA,EAAvB,OAAO,QAAA,cAAY,EAAA,MAAA,GAAA,CAAA,QAAA,CAAA;KAE1B,QAAA,KAAK,WAAA,WAAA,EADb,YAE0B,MAAA,gBAAA,EAAA;;MAAvB,OAAO,QAAA,KAAK;;KAEP,QAAA,KAAK,WAAA,WAAA,EADb,YAE0C,MAAA,gBAAA,EAAA;;MAAvC,OAAO,MAAA,eAAc,CAAC,QAAA,KAAK,QAAO;;KAE7B,QAAA,KAAK,kBAAA,WAAA,EADb,YAEiC,MAAA,uBAAA,EAAA;;MAA9B,OAAO,QAAA,KAAK"}
1
+ {"version":3,"file":"InfoLinks.vue.script.js","names":[],"sources":["../../../../src/blocks/scalar-info-block/components/InfoLinks.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { AsyncApiInfoObject } from '@scalar/types/asyncapi/3.1'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type {\n ExternalDocumentationObject,\n InfoObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed } from 'vue'\n\nimport { LinkList } from '@/components/LinkList'\nimport { ExternalDocs } from '@/features/external-docs'\nimport { Contact, License, TermsOfService } from '@/features/info-object'\n\nconst { info, externalDocs } = defineProps<{\n info: InfoObject | AsyncApiInfoObject\n externalDocs?: ExternalDocumentationObject\n}>()\n\n/** Whether there is at least one link to show, so we do not render an empty list */\nconst hasLinks = computed(() =>\n Boolean(externalDocs || info.contact || info.license || info.termsOfService),\n)\n</script>\n\n<template>\n <LinkList v-if=\"hasLinks\">\n <ExternalDocs\n v-if=\"externalDocs\"\n :value=\"externalDocs\" />\n <Contact\n v-if=\"info.contact\"\n :value=\"info.contact\" />\n <License\n v-if=\"info.license\"\n :value=\"getResolvedRef(info.license)\" />\n <TermsOfService\n v-if=\"info.termsOfService\"\n :value=\"info.termsOfService\" />\n </LinkList>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;EAmBA,MAAM,WAAW,eACf,QAAQ,QAAA,gBAAgB,QAAA,KAAK,WAAW,QAAA,KAAK,WAAW,QAAA,KAAK,eAAe,CAC9E;;UAIkB,SAAA,SAAA,WAAA,EAAhB,YAaW,MAAA,iBAAA,EAAA,EAAA,KAAA,GAAA,EAAA;2BAViB;KADlB,QAAA,gBAAA,WAAA,EADR,YAE0B,MAAA,qBAAA,EAAA;;MAAvB,OAAO,QAAA;;KAEF,QAAA,KAAK,WAAA,WAAA,EADb,YAE0B,MAAA,gBAAA,EAAA;;MAAvB,OAAO,QAAA,KAAK;;KAEP,QAAA,KAAK,WAAA,WAAA,EADb,YAE0C,MAAA,gBAAA,EAAA;;MAAvC,OAAO,MAAA,eAAc,CAAC,QAAA,KAAK,QAAO;;KAE7B,QAAA,KAAK,kBAAA,WAAA,EADb,YAEiC,MAAA,uBAAA,EAAA;;MAA9B,OAAO,QAAA,KAAK"}
@@ -13,13 +13,13 @@ type __VLS_Props = {
13
13
  headingSlugGenerator: (heading: Heading) => string;
14
14
  eventBus: WorkspaceEventBus | null;
15
15
  };
16
- declare var __VLS_62: {}, __VLS_75: {}, __VLS_87: {};
16
+ declare var __VLS_67: {}, __VLS_80: {}, __VLS_92: {};
17
17
  type __VLS_Slots = {} & {
18
- 'download-link'?: (props: typeof __VLS_62) => any;
18
+ 'download-link'?: (props: typeof __VLS_67) => any;
19
19
  } & {
20
- aside?: (props: typeof __VLS_75) => any;
20
+ aside?: (props: typeof __VLS_80) => any;
21
21
  } & {
22
- after?: (props: typeof __VLS_87) => any;
22
+ after?: (props: typeof __VLS_92) => any;
23
23
  };
24
24
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
25
25
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1 +1 @@
1
- {"version":3,"file":"IntroductionLayout.vue.d.ts","sourceRoot":"","sources":["../../../../src/blocks/scalar-info-block/components/IntroductionLayout.vue"],"names":[],"mappings":"AAuGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AACpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AACvE,OAAO,KAAK,EACV,2BAA2B,EAC3B,UAAU,EACX,MAAM,8DAA8D,CAAA;AAkBrE,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,GAAG,SAAS,CAAA;IACtB,YAAY,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;IACrC,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,IAAI,EAAE,UAAU,GAAG,kBAAkB,GAAG,SAAS,CAAA;IACjD,YAAY,CAAC,EAAE,2BAA2B,CAAA;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,oBAAoB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAA;IAClD,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;CACnC,CAAC;AAgPF,QAAA,IAAI,QAAQ,IAAW,EAAE,QAAQ,IAAW,EAAE,QAAQ,IAAY,CAAE;AACpE,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,GACrD;IAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,GAC3C;IAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAK9C,QAAA,MAAM,UAAU,kSAEd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"IntroductionLayout.vue.d.ts","sourceRoot":"","sources":["../../../../src/blocks/scalar-info-block/components/IntroductionLayout.vue"],"names":[],"mappings":"AA0GA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AACpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AACvE,OAAO,KAAK,EACV,2BAA2B,EAC3B,UAAU,EACX,MAAM,8DAA8D,CAAA;AAmBrE,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,GAAG,SAAS,CAAA;IACtB,YAAY,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;IACrC,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,IAAI,EAAE,UAAU,GAAG,kBAAkB,GAAG,SAAS,CAAA;IACjD,YAAY,CAAC,EAAE,2BAA2B,CAAA;IAC1C,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,oBAAoB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAA;IAClD,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;CACnC,CAAC;AAoPF,QAAA,IAAI,QAAQ,IAAW,EAAE,QAAQ,IAAW,EAAE,QAAQ,IAAY,CAAE;AACpE,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,GACrD;IAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,GAC3C;IAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAK9C,QAAA,MAAM,UAAU,kSAEd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -2,7 +2,7 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_exp
2
2
  import IntroductionLayout_vue_vue_type_script_setup_true_lang_default from "./IntroductionLayout.vue.script.js";
3
3
  /* empty css */
4
4
  //#region src/blocks/scalar-info-block/components/IntroductionLayout.vue
5
- var IntroductionLayout_default = /* @__PURE__ */ _plugin_vue_export_helper_default(IntroductionLayout_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-bd137508"]]);
5
+ var IntroductionLayout_default = /* @__PURE__ */ _plugin_vue_export_helper_default(IntroductionLayout_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-4e3a9e30"]]);
6
6
  //#endregion
7
7
  export { IntroductionLayout_default as default };
8
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"IntroductionLayout.vue.js","names":[],"sources":["../../../../src/blocks/scalar-info-block/components/IntroductionLayout.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { AsyncApiInfoObject } from '@scalar/types/asyncapi/3.1'\nimport type { Heading } from '@scalar/types/legacy'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport type {\n ExternalDocumentationObject,\n InfoObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport {\n Section,\n SectionColumn,\n SectionColumns,\n SectionContainer,\n SectionContent,\n SectionHeader,\n SectionHeaderTag,\n} from '@/components/Section'\nimport { SpecificationExtension } from '@/features/specification-extension'\n\nimport InfoDescription from './InfoDescription.vue'\nimport InfoLinks from './InfoLinks.vue'\nimport InfoVersion from './InfoVersion.vue'\nimport SpecificationVersion from './SpecificationVersion.vue'\n\ndefineProps<{\n id: string | undefined\n documentType?: 'openapi' | 'asyncapi'\n specificationVersion: string | undefined\n info: InfoObject | AsyncApiInfoObject | undefined\n externalDocs?: ExternalDocumentationObject\n documentExtensions?: Record<string, unknown>\n infoExtensions?: Record<string, unknown>\n headingSlugGenerator: (heading: Heading) => string\n eventBus: WorkspaceEventBus | null\n}>()\n</script>\n\n<template>\n <SectionContainer>\n <!-- If the #after slot is used, we need to add a gap to the section. -->\n <Section\n :id=\"id\"\n aria-label=\"Introduction\"\n class=\"introduction-section z-1 gap-12\"\n @intersecting=\"\n () => id && eventBus?.emit('intersecting:nav-item', { id })\n \">\n <SectionContent :loading=\"!info\">\n <div class=\"flex gap-1.5\">\n <InfoVersion\n v-if=\"info\"\n :version=\"info?.version\" />\n <SpecificationVersion\n :documentType\n :version=\"specificationVersion\" />\n </div>\n <SectionHeader\n :loading=\"!info?.title\"\n tight>\n <SectionHeaderTag :level=\"1\">\n {{ info?.title }}\n </SectionHeaderTag>\n <template #links>\n <InfoLinks\n v-if=\"info\"\n :externalDocs=\"externalDocs\"\n :info=\"info\" />\n </template>\n </SectionHeader>\n <SectionColumns>\n <SectionColumn>\n <slot name=\"download-link\" />\n <InfoDescription\n :description=\"info?.description\"\n :eventBus=\"eventBus\"\n :headingSlugGenerator=\"headingSlugGenerator\" />\n </SectionColumn>\n <SectionColumn v-if=\"$slots.aside\">\n <div class=\"sticky-cards\">\n <slot name=\"aside\" />\n </div>\n </SectionColumn>\n </SectionColumns>\n <SpecificationExtension :value=\"documentExtensions\" />\n <SpecificationExtension :value=\"infoExtensions\" />\n </SectionContent>\n <slot name=\"after\" />\n </Section>\n </SectionContainer>\n</template>\n\n<style scoped>\n.sticky-cards {\n display: flex;\n flex-direction: column;\n position: sticky;\n top: calc(var(--refs-viewport-offset) + 24px);\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"IntroductionLayout.vue.js","names":[],"sources":["../../../../src/blocks/scalar-info-block/components/IntroductionLayout.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { AsyncApiInfoObject } from '@scalar/types/asyncapi/3.1'\nimport type { Heading } from '@scalar/types/legacy'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport type {\n ExternalDocumentationObject,\n InfoObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport {\n Section,\n SectionColumn,\n SectionColumns,\n SectionContainer,\n SectionContent,\n SectionHeader,\n SectionHeaderTag,\n} from '@/components/Section'\nimport { SpecificationExtension } from '@/features/specification-extension'\n\nimport InfoDescription from './InfoDescription.vue'\nimport InfoLinks from './InfoLinks.vue'\nimport InfoVersion from './InfoVersion.vue'\nimport IntroductionLoading from './IntroductionLoading.vue'\nimport SpecificationVersion from './SpecificationVersion.vue'\n\ndefineProps<{\n id: string | undefined\n documentType?: 'openapi' | 'asyncapi'\n specificationVersion: string | undefined\n info: InfoObject | AsyncApiInfoObject | undefined\n externalDocs?: ExternalDocumentationObject\n documentExtensions?: Record<string, unknown>\n infoExtensions?: Record<string, unknown>\n headingSlugGenerator: (heading: Heading) => string\n eventBus: WorkspaceEventBus | null\n}>()\n</script>\n\n<template>\n <SectionContainer>\n <!-- If the #after slot is used, we need to add a gap to the section. -->\n <Section\n :id=\"id\"\n aria-label=\"Introduction\"\n class=\"introduction-section z-1 gap-12\"\n @intersecting=\"\n () => id && eventBus?.emit('intersecting:nav-item', { id })\n \">\n <SectionContent>\n <!-- While the document loads we show a skeleton that mirrors this layout. -->\n <IntroductionLoading\n v-if=\"!info\"\n :hasAside=\"Boolean($slots.aside)\" />\n\n <template v-else>\n <div class=\"flex gap-1.5\">\n <InfoVersion :version=\"info?.version\" />\n <SpecificationVersion\n :documentType\n :version=\"specificationVersion\" />\n </div>\n <SectionHeader tight>\n <SectionHeaderTag :level=\"1\">\n {{ info?.title }}\n </SectionHeaderTag>\n <template #links>\n <InfoLinks\n :externalDocs=\"externalDocs\"\n :info=\"info\" />\n </template>\n </SectionHeader>\n <SectionColumns>\n <SectionColumn>\n <slot name=\"download-link\" />\n <InfoDescription\n :description=\"info?.description\"\n :eventBus=\"eventBus\"\n :headingSlugGenerator=\"headingSlugGenerator\" />\n </SectionColumn>\n <SectionColumn v-if=\"$slots.aside\">\n <div class=\"sticky-cards\">\n <slot name=\"aside\" />\n </div>\n </SectionColumn>\n </SectionColumns>\n <SpecificationExtension :value=\"documentExtensions\" />\n <SpecificationExtension :value=\"infoExtensions\" />\n </template>\n </SectionContent>\n <slot name=\"after\" />\n </Section>\n </SectionContainer>\n</template>\n\n<style scoped>\n.sticky-cards {\n display: flex;\n flex-direction: column;\n position: sticky;\n top: calc(var(--refs-viewport-offset) + 24px);\n}\n</style>\n"],"mappings":""}
@@ -9,8 +9,9 @@ import SpecificationExtension_default from "../../../features/specification-exte
9
9
  import InfoDescription_default from "./InfoDescription.vue.js";
10
10
  import InfoLinks_default from "./InfoLinks.vue.js";
11
11
  import InfoVersion_default from "./InfoVersion.vue.js";
12
+ import IntroductionLoading_default from "./IntroductionLoading.vue.js";
12
13
  import SpecificationVersion_default from "./SpecificationVersion.vue.js";
13
- import { createBlock, createCommentVNode, createElementVNode, createTextVNode, createVNode, defineComponent, openBlock, renderSlot, toDisplayString, unref, withCtx } from "vue";
14
+ import { Fragment, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, openBlock, renderSlot, toDisplayString, unref, withCtx } from "vue";
14
15
  //#region src/blocks/scalar-info-block/components/IntroductionLayout.vue?vue&type=script&setup=true&lang.ts
15
16
  var _hoisted_1 = { class: "flex gap-1.5" };
16
17
  var _hoisted_2 = { class: "sticky-cards" };
@@ -36,30 +37,26 @@ var IntroductionLayout_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
36
37
  class: "introduction-section z-1 gap-12",
37
38
  onIntersecting: _cache[0] || (_cache[0] = () => __props.id && __props.eventBus?.emit("intersecting:nav-item", { id: __props.id }))
38
39
  }, {
39
- default: withCtx(() => [createVNode(unref(SectionContent_default), { loading: !__props.info }, {
40
- default: withCtx(() => [
41
- createElementVNode("div", _hoisted_1, [__props.info ? (openBlock(), createBlock(InfoVersion_default, {
42
- key: 0,
43
- version: __props.info?.version
44
- }, null, 8, ["version"])) : createCommentVNode("", true), createVNode(SpecificationVersion_default, {
40
+ default: withCtx(() => [createVNode(unref(SectionContent_default), null, {
41
+ default: withCtx(() => [!__props.info ? (openBlock(), createBlock(IntroductionLoading_default, {
42
+ key: 0,
43
+ hasAside: Boolean(_ctx.$slots.aside)
44
+ }, null, 8, ["hasAside"])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
45
+ createElementVNode("div", _hoisted_1, [createVNode(InfoVersion_default, { version: __props.info?.version }, null, 8, ["version"]), createVNode(SpecificationVersion_default, {
45
46
  documentType: __props.documentType,
46
47
  version: __props.specificationVersion
47
48
  }, null, 8, ["documentType", "version"])]),
48
- createVNode(unref(SectionHeader_default), {
49
- loading: !__props.info?.title,
50
- tight: ""
51
- }, {
52
- links: withCtx(() => [__props.info ? (openBlock(), createBlock(InfoLinks_default, {
53
- key: 0,
49
+ createVNode(unref(SectionHeader_default), { tight: "" }, {
50
+ links: withCtx(() => [createVNode(InfoLinks_default, {
54
51
  externalDocs: __props.externalDocs,
55
52
  info: __props.info
56
- }, null, 8, ["externalDocs", "info"])) : createCommentVNode("", true)]),
53
+ }, null, 8, ["externalDocs", "info"])]),
57
54
  default: withCtx(() => [createVNode(unref(SectionHeaderTag_default), { level: 1 }, {
58
55
  default: withCtx(() => [createTextVNode(toDisplayString(__props.info?.title), 1)]),
59
56
  _: 1
60
57
  })]),
61
58
  _: 1
62
- }, 8, ["loading"]),
59
+ }),
63
60
  createVNode(unref(SectionColumns_default), null, {
64
61
  default: withCtx(() => [createVNode(unref(SectionColumn_default), null, {
65
62
  default: withCtx(() => [renderSlot(_ctx.$slots, "download-link", {}, void 0, true), createVNode(InfoDescription_default, {
@@ -80,9 +77,9 @@ var IntroductionLayout_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
80
77
  }),
81
78
  createVNode(unref(SpecificationExtension_default), { value: __props.documentExtensions }, null, 8, ["value"]),
82
79
  createVNode(unref(SpecificationExtension_default), { value: __props.infoExtensions }, null, 8, ["value"])
83
- ]),
80
+ ], 64))]),
84
81
  _: 3
85
- }, 8, ["loading"]), renderSlot(_ctx.$slots, "after", {}, void 0, true)]),
82
+ }), renderSlot(_ctx.$slots, "after", {}, void 0, true)]),
86
83
  _: 3
87
84
  }, 8, ["id"])]),
88
85
  _: 3
@@ -1 +1 @@
1
- {"version":3,"file":"IntroductionLayout.vue.script.js","names":["$slots"],"sources":["../../../../src/blocks/scalar-info-block/components/IntroductionLayout.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { AsyncApiInfoObject } from '@scalar/types/asyncapi/3.1'\nimport type { Heading } from '@scalar/types/legacy'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport type {\n ExternalDocumentationObject,\n InfoObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport {\n Section,\n SectionColumn,\n SectionColumns,\n SectionContainer,\n SectionContent,\n SectionHeader,\n SectionHeaderTag,\n} from '@/components/Section'\nimport { SpecificationExtension } from '@/features/specification-extension'\n\nimport InfoDescription from './InfoDescription.vue'\nimport InfoLinks from './InfoLinks.vue'\nimport InfoVersion from './InfoVersion.vue'\nimport SpecificationVersion from './SpecificationVersion.vue'\n\ndefineProps<{\n id: string | undefined\n documentType?: 'openapi' | 'asyncapi'\n specificationVersion: string | undefined\n info: InfoObject | AsyncApiInfoObject | undefined\n externalDocs?: ExternalDocumentationObject\n documentExtensions?: Record<string, unknown>\n infoExtensions?: Record<string, unknown>\n headingSlugGenerator: (heading: Heading) => string\n eventBus: WorkspaceEventBus | null\n}>()\n</script>\n\n<template>\n <SectionContainer>\n <!-- If the #after slot is used, we need to add a gap to the section. -->\n <Section\n :id=\"id\"\n aria-label=\"Introduction\"\n class=\"introduction-section z-1 gap-12\"\n @intersecting=\"\n () => id && eventBus?.emit('intersecting:nav-item', { id })\n \">\n <SectionContent :loading=\"!info\">\n <div class=\"flex gap-1.5\">\n <InfoVersion\n v-if=\"info\"\n :version=\"info?.version\" />\n <SpecificationVersion\n :documentType\n :version=\"specificationVersion\" />\n </div>\n <SectionHeader\n :loading=\"!info?.title\"\n tight>\n <SectionHeaderTag :level=\"1\">\n {{ info?.title }}\n </SectionHeaderTag>\n <template #links>\n <InfoLinks\n v-if=\"info\"\n :externalDocs=\"externalDocs\"\n :info=\"info\" />\n </template>\n </SectionHeader>\n <SectionColumns>\n <SectionColumn>\n <slot name=\"download-link\" />\n <InfoDescription\n :description=\"info?.description\"\n :eventBus=\"eventBus\"\n :headingSlugGenerator=\"headingSlugGenerator\" />\n </SectionColumn>\n <SectionColumn v-if=\"$slots.aside\">\n <div class=\"sticky-cards\">\n <slot name=\"aside\" />\n </div>\n </SectionColumn>\n </SectionColumns>\n <SpecificationExtension :value=\"documentExtensions\" />\n <SpecificationExtension :value=\"infoExtensions\" />\n </SectionContent>\n <slot name=\"after\" />\n </Section>\n </SectionContainer>\n</template>\n\n<style scoped>\n.sticky-cards {\n display: flex;\n flex-direction: column;\n position: sticky;\n top: calc(var(--refs-viewport-offset) + 24px);\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAuCE,YAkDmB,MAAA,yBAAA,EAAA,MAAA;2BADP,CA/CV,YA+CU,MAAA,gBAAA,EAAA;KA9CP,IAAI,QAAA;KACL,cAAW;KACX,OAAM;KACL,gBAAY,OAAA,OAAA,OAAA,WAAiB,QAAA,MAAM,QAAA,UAAU,KAAI,yBAAA,EAAA,IAA4B,QAAA,IAAE,CAAA;;4BAyC/D,CAtCjB,YAsCiB,MAAA,uBAAA,EAAA,EAtCA,SAAO,CAAG,QAAA,MAAA,EAAA;6BAQnB;OAPN,mBAOM,OAPN,YAOM,CALI,QAAA,QAAA,WAAA,EADR,YAE6B,qBAAA;;QAA1B,SAAS,QAAA,MAAM;iEAClB,YAEoC,8BAAA;QADjC,cAAA,QAAA;QACA,SAAS,QAAA;;OAEd,YAYgB,MAAA,sBAAA,EAAA;QAXb,SAAO,CAAG,QAAA,MAAM;QACjB,OAAA;;QAIW,OAAK,cAIG,CAFT,QAAA,QAAA,WAAA,EADR,YAGiB,mBAAA;;SADd,cAAc,QAAA;SACd,MAAM,QAAA;;+BALQ,CAFnB,YAEmB,MAAA,yBAAA,EAAA,EAFA,OAAO,GAAC,EAAA;gCACR,CAAA,gBAAA,gBAAd,QAAA,MAAM,MAAK,EAAA,EAAA,CAAA,CAAA;;;;;OASlB,YAaiB,MAAA,uBAAA,EAAA,MAAA;+BANC,CANhB,YAMgB,MAAA,sBAAA,EAAA,MAAA;gCALe,CAA7B,WAA6B,KAAA,QAAA,iBAAA,EAAA,EAAA,KAAA,GAAA,KAAA,EAC7B,YAGiD,yBAAA;UAF9C,aAAa,QAAA,MAAM;UACnB,UAAU,QAAA;UACV,sBAAsB,QAAA;;;;;;;YAENA,KAAAA,OAAO,SAAA,WAAA,EAA5B,YAIgB,MAAA,sBAAA,EAAA,EAAA,KAAA,GAAA,EAAA;gCADR,CAFN,mBAEM,OAFN,YAEM,CADJ,WAAqB,KAAA,QAAA,SAAA,EAAA,EAAA,KAAA,GAAA,KAAA,CAAA,CAAA,CAAA,CAAA;;;;;OAI3B,YAAsD,MAAA,+BAAA,EAAA,EAA7B,OAAO,QAAA,oBAAkB,EAAA,MAAA,GAAA,CAAA,QAAA,CAAA;OAClD,YAAkD,MAAA,+BAAA,EAAA,EAAzB,OAAO,QAAA,gBAAc,EAAA,MAAA,GAAA,CAAA,QAAA,CAAA;;;yBAEhD,WAAqB,KAAA,QAAA,SAAA,EAAA,EAAA,KAAA,GAAA,KAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"IntroductionLayout.vue.script.js","names":["$slots"],"sources":["../../../../src/blocks/scalar-info-block/components/IntroductionLayout.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { AsyncApiInfoObject } from '@scalar/types/asyncapi/3.1'\nimport type { Heading } from '@scalar/types/legacy'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport type {\n ExternalDocumentationObject,\n InfoObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\n\nimport {\n Section,\n SectionColumn,\n SectionColumns,\n SectionContainer,\n SectionContent,\n SectionHeader,\n SectionHeaderTag,\n} from '@/components/Section'\nimport { SpecificationExtension } from '@/features/specification-extension'\n\nimport InfoDescription from './InfoDescription.vue'\nimport InfoLinks from './InfoLinks.vue'\nimport InfoVersion from './InfoVersion.vue'\nimport IntroductionLoading from './IntroductionLoading.vue'\nimport SpecificationVersion from './SpecificationVersion.vue'\n\ndefineProps<{\n id: string | undefined\n documentType?: 'openapi' | 'asyncapi'\n specificationVersion: string | undefined\n info: InfoObject | AsyncApiInfoObject | undefined\n externalDocs?: ExternalDocumentationObject\n documentExtensions?: Record<string, unknown>\n infoExtensions?: Record<string, unknown>\n headingSlugGenerator: (heading: Heading) => string\n eventBus: WorkspaceEventBus | null\n}>()\n</script>\n\n<template>\n <SectionContainer>\n <!-- If the #after slot is used, we need to add a gap to the section. -->\n <Section\n :id=\"id\"\n aria-label=\"Introduction\"\n class=\"introduction-section z-1 gap-12\"\n @intersecting=\"\n () => id && eventBus?.emit('intersecting:nav-item', { id })\n \">\n <SectionContent>\n <!-- While the document loads we show a skeleton that mirrors this layout. -->\n <IntroductionLoading\n v-if=\"!info\"\n :hasAside=\"Boolean($slots.aside)\" />\n\n <template v-else>\n <div class=\"flex gap-1.5\">\n <InfoVersion :version=\"info?.version\" />\n <SpecificationVersion\n :documentType\n :version=\"specificationVersion\" />\n </div>\n <SectionHeader tight>\n <SectionHeaderTag :level=\"1\">\n {{ info?.title }}\n </SectionHeaderTag>\n <template #links>\n <InfoLinks\n :externalDocs=\"externalDocs\"\n :info=\"info\" />\n </template>\n </SectionHeader>\n <SectionColumns>\n <SectionColumn>\n <slot name=\"download-link\" />\n <InfoDescription\n :description=\"info?.description\"\n :eventBus=\"eventBus\"\n :headingSlugGenerator=\"headingSlugGenerator\" />\n </SectionColumn>\n <SectionColumn v-if=\"$slots.aside\">\n <div class=\"sticky-cards\">\n <slot name=\"aside\" />\n </div>\n </SectionColumn>\n </SectionColumns>\n <SpecificationExtension :value=\"documentExtensions\" />\n <SpecificationExtension :value=\"infoExtensions\" />\n </template>\n </SectionContent>\n <slot name=\"after\" />\n </Section>\n </SectionContainer>\n</template>\n\n<style scoped>\n.sticky-cards {\n display: flex;\n flex-direction: column;\n position: sticky;\n top: calc(var(--refs-viewport-offset) + 24px);\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAwCE,YAoDmB,MAAA,yBAAA,EAAA,MAAA;2BADP,CAjDV,YAiDU,MAAA,gBAAA,EAAA;KAhDP,IAAI,QAAA;KACL,cAAW;KACX,OAAM;KACL,gBAAY,OAAA,OAAA,OAAA,WAAiB,QAAA,MAAM,QAAA,UAAU,KAAI,yBAAA,EAAA,IAA4B,QAAA,IAAE,CAAA;;4BA2C/D,CAxCjB,YAwCiB,MAAA,uBAAA,EAAA,MAAA;6BApCuB,CAAA,CAD7B,QAAA,QAAA,WAAA,EADT,YAEsC,6BAAA;;OAAnC,UAAU,QAAQA,KAAAA,OAAO,MAAK;iDAEjC,mBAiCW,UAAA,EAAA,KAAA,GAAA,EAAA;OAhCT,mBAKM,OALN,YAKM,CAJJ,YAAwC,qBAAA,EAA1B,SAAS,QAAA,MAAM,SAAA,EAAA,MAAA,GAAA,CAAA,UAAA,CAAA,EAC7B,YAEoC,8BAAA;QADjC,cAAA,QAAA;QACA,SAAS,QAAA;;OAEd,YASgB,MAAA,sBAAA,EAAA,EATD,OAAA,IAAK,EAAA;QAIP,OAAK,cAGG,CAFjB,YAEiB,mBAAA;SADd,cAAc,QAAA;SACd,MAAM,QAAA;;+BAJQ,CAFnB,YAEmB,MAAA,yBAAA,EAAA,EAFA,OAAO,GAAC,EAAA;gCACR,CAAA,gBAAA,gBAAd,QAAA,MAAM,MAAK,EAAA,EAAA,CAAA,CAAA;;;;;OAQlB,YAaiB,MAAA,uBAAA,EAAA,MAAA;+BANC,CANhB,YAMgB,MAAA,sBAAA,EAAA,MAAA;gCALe,CAA7B,WAA6B,KAAA,QAAA,iBAAA,EAAA,EAAA,KAAA,GAAA,KAAA,EAC7B,YAGiD,yBAAA;UAF9C,aAAa,QAAA,MAAM;UACnB,UAAU,QAAA;UACV,sBAAsB,QAAA;;;;;;;YAENA,KAAAA,OAAO,SAAA,WAAA,EAA5B,YAIgB,MAAA,sBAAA,EAAA,EAAA,KAAA,GAAA,EAAA;gCADR,CAFN,mBAEM,OAFN,YAEM,CADJ,WAAqB,KAAA,QAAA,SAAA,EAAA,EAAA,KAAA,GAAA,KAAA,CAAA,CAAA,CAAA,CAAA;;;;;OAI3B,YAAsD,MAAA,+BAAA,EAAA,EAA7B,OAAO,QAAA,oBAAkB,EAAA,MAAA,GAAA,CAAA,QAAA,CAAA;OAClD,YAAkD,MAAA,+BAAA,EAAA,EAAzB,OAAO,QAAA,gBAAc,EAAA,MAAA,GAAA,CAAA,QAAA,CAAA;;;SAGlD,WAAqB,KAAA,QAAA,SAAA,EAAA,EAAA,KAAA,GAAA,KAAA,CAAA,CAAA"}
@@ -0,0 +1,12 @@
1
+ type __VLS_Props = {
2
+ /**
3
+ * Whether the selector cards live in a sticky aside column (modern layout)
4
+ * or in a row below the description (classic layout). Mirrors the
5
+ * `$slots.aside` check in the loaded layout.
6
+ */
7
+ hasAside?: boolean;
8
+ };
9
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ declare const _default: typeof __VLS_export;
11
+ export default _default;
12
+ //# sourceMappingURL=IntroductionLoading.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntroductionLoading.vue.d.ts","sourceRoot":"","sources":["../../../../src/blocks/scalar-info-block/components/IntroductionLoading.vue"],"names":[],"mappings":"AAyGA,KAAK,WAAW,GAAG;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAC;AA8PF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -0,0 +1,9 @@
1
+ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_export-helper.js";
2
+ import IntroductionLoading_vue_vue_type_script_setup_true_lang_default from "./IntroductionLoading.vue.script.js";
3
+ /* empty css */
4
+ //#region src/blocks/scalar-info-block/components/IntroductionLoading.vue
5
+ var IntroductionLoading_default = /* @__PURE__ */ _plugin_vue_export_helper_default(IntroductionLoading_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-1bd6e256"]]);
6
+ //#endregion
7
+ export { IntroductionLoading_default as default };
8
+
9
+ //# sourceMappingURL=IntroductionLoading.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntroductionLoading.vue.js","names":[],"sources":["../../../../src/blocks/scalar-info-block/components/IntroductionLoading.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Loading skeleton for the introduction block. It mirrors the real layout\n * (badges, title, links, description and selector cards) so the page does not\n * jump once the document has loaded.\n */\nimport { SectionColumn, SectionColumns } from '@/components/Section'\n\nconst { hasAside = true } = defineProps<{\n /**\n * Whether the selector cards live in a sticky aside column (modern layout)\n * or in a row below the description (classic layout). Mirrors the\n * `$slots.aside` check in the loaded layout.\n */\n hasAside?: boolean\n}>()\n</script>\n\n<template>\n <div\n class=\"introduction-loading flex flex-col gap-5\"\n aria-hidden=\"true\">\n <!-- Version and specification badges -->\n <div class=\"flex gap-1.5\">\n <div class=\"introduction-skeleton h-6 w-14 rounded-full\" />\n <div class=\"introduction-skeleton h-6 w-24 rounded-full\" />\n </div>\n <!-- Title and links (mirrors SectionHeader's two-column grid at xl) -->\n <div class=\"grid grid-cols-1 gap-3 xl:grid-cols-2 xl:gap-12\">\n <div class=\"introduction-skeleton h-9 w-3/5 rounded-lg\" />\n <div class=\"flex flex-wrap items-center gap-2 xl:justify-end\">\n <div class=\"introduction-skeleton h-5 w-28 rounded\" />\n <div class=\"introduction-skeleton h-5 w-28 rounded\" />\n <div class=\"introduction-skeleton h-5 w-12 rounded\" />\n </div>\n </div>\n <SectionColumns>\n <SectionColumn>\n <div class=\"flex flex-col gap-3\">\n <!-- Download link -->\n <div class=\"introduction-skeleton mb-2 h-5 w-56 rounded\" />\n <!-- Description -->\n <div class=\"introduction-skeleton h-4 w-full rounded\" />\n <div class=\"introduction-skeleton h-4 w-11/12 rounded\" />\n <div class=\"introduction-skeleton h-4 w-4/5 rounded\" />\n <!-- Section heading -->\n <div class=\"introduction-skeleton mt-4 h-6 w-40 rounded\" />\n <div class=\"introduction-skeleton h-4 w-3/4 rounded\" />\n <div class=\"introduction-skeleton h-4 w-2/3 rounded\" />\n <div class=\"introduction-skeleton h-4 w-1/2 rounded\" />\n </div>\n </SectionColumn>\n <!-- Modern layout: selector cards in a sticky aside column -->\n <SectionColumn v-if=\"hasAside\">\n <div class=\"sticky-cards gap-3\">\n <div class=\"introduction-skeleton h-20 w-full rounded-lg\" />\n <div class=\"introduction-skeleton h-28 w-full rounded-lg\" />\n <div class=\"introduction-skeleton h-28 w-full rounded-lg\" />\n </div>\n </SectionColumn>\n </SectionColumns>\n <!-- Classic layout: selector cards in a row below the description -->\n <div\n v-if=\"!hasAside\"\n class=\"flex flex-col gap-3 sm:flex-row sm:gap-6\">\n <div class=\"introduction-skeleton h-28 w-full flex-1 rounded-lg\" />\n <div class=\"introduction-skeleton h-28 w-full flex-1 rounded-lg\" />\n <div class=\"introduction-skeleton h-28 w-full flex-1 rounded-lg\" />\n </div>\n </div>\n</template>\n\n<style scoped>\n.sticky-cards {\n display: flex;\n flex-direction: column;\n position: sticky;\n top: calc(var(--refs-viewport-offset) + 24px);\n}\n\n/* Pulsing placeholder, matching the look of the rest of the loading states. */\n.introduction-skeleton {\n background: var(--scalar-background-3);\n animation: introduction-skeleton-pulse 1.5s infinite alternate;\n}\n\n@keyframes introduction-skeleton-pulse {\n from {\n opacity: 1;\n }\n to {\n opacity: 0.33;\n }\n}\n</style>\n"],"mappings":""}
@@ -0,0 +1,63 @@
1
+ import SectionColumn_default from "../../../components/Section/SectionColumn.vue.js";
2
+ import SectionColumns_default from "../../../components/Section/SectionColumns.vue.js";
3
+ import { createBlock, createCommentVNode, createElementBlock, createElementVNode, createStaticVNode, createVNode, defineComponent, openBlock, unref, withCtx } from "vue";
4
+ //#region src/blocks/scalar-info-block/components/IntroductionLoading.vue?vue&type=script&setup=true&lang.ts
5
+ var _hoisted_1 = {
6
+ class: "introduction-loading flex flex-col gap-5",
7
+ "aria-hidden": "true"
8
+ };
9
+ var _hoisted_2 = {
10
+ key: 0,
11
+ class: "flex flex-col gap-3 sm:flex-row sm:gap-6"
12
+ };
13
+ var IntroductionLoading_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
14
+ __name: "IntroductionLoading",
15
+ props: { hasAside: {
16
+ type: Boolean,
17
+ default: true
18
+ } },
19
+ setup(__props) {
20
+ /**
21
+ * Loading skeleton for the introduction block. It mirrors the real layout
22
+ * (badges, title, links, description and selector cards) so the page does not
23
+ * jump once the document has loaded.
24
+ */
25
+ return (_ctx, _cache) => {
26
+ return openBlock(), createElementBlock("div", _hoisted_1, [
27
+ _cache[3] || (_cache[3] = createStaticVNode("<div class=\"flex gap-1.5\" data-v-1bd6e256><div class=\"introduction-skeleton h-6 w-14 rounded-full\" data-v-1bd6e256></div><div class=\"introduction-skeleton h-6 w-24 rounded-full\" data-v-1bd6e256></div></div><div class=\"grid grid-cols-1 gap-3 xl:grid-cols-2 xl:gap-12\" data-v-1bd6e256><div class=\"introduction-skeleton h-9 w-3/5 rounded-lg\" data-v-1bd6e256></div><div class=\"flex flex-wrap items-center gap-2 xl:justify-end\" data-v-1bd6e256><div class=\"introduction-skeleton h-5 w-28 rounded\" data-v-1bd6e256></div><div class=\"introduction-skeleton h-5 w-28 rounded\" data-v-1bd6e256></div><div class=\"introduction-skeleton h-5 w-12 rounded\" data-v-1bd6e256></div></div></div>", 2)),
28
+ createVNode(unref(SectionColumns_default), null, {
29
+ default: withCtx(() => [createVNode(unref(SectionColumn_default), null, {
30
+ default: withCtx(() => [..._cache[0] || (_cache[0] = [createElementVNode("div", { class: "flex flex-col gap-3" }, [
31
+ createElementVNode("div", { class: "introduction-skeleton mb-2 h-5 w-56 rounded" }),
32
+ createElementVNode("div", { class: "introduction-skeleton h-4 w-full rounded" }),
33
+ createElementVNode("div", { class: "introduction-skeleton h-4 w-11/12 rounded" }),
34
+ createElementVNode("div", { class: "introduction-skeleton h-4 w-4/5 rounded" }),
35
+ createElementVNode("div", { class: "introduction-skeleton mt-4 h-6 w-40 rounded" }),
36
+ createElementVNode("div", { class: "introduction-skeleton h-4 w-3/4 rounded" }),
37
+ createElementVNode("div", { class: "introduction-skeleton h-4 w-2/3 rounded" }),
38
+ createElementVNode("div", { class: "introduction-skeleton h-4 w-1/2 rounded" })
39
+ ], -1)])]),
40
+ _: 1
41
+ }), __props.hasAside ? (openBlock(), createBlock(unref(SectionColumn_default), { key: 0 }, {
42
+ default: withCtx(() => [..._cache[1] || (_cache[1] = [createElementVNode("div", { class: "sticky-cards gap-3" }, [
43
+ createElementVNode("div", { class: "introduction-skeleton h-20 w-full rounded-lg" }),
44
+ createElementVNode("div", { class: "introduction-skeleton h-28 w-full rounded-lg" }),
45
+ createElementVNode("div", { class: "introduction-skeleton h-28 w-full rounded-lg" })
46
+ ], -1)])]),
47
+ _: 1
48
+ })) : createCommentVNode("", true)]),
49
+ _: 1
50
+ }),
51
+ !__props.hasAside ? (openBlock(), createElementBlock("div", _hoisted_2, [..._cache[2] || (_cache[2] = [
52
+ createElementVNode("div", { class: "introduction-skeleton h-28 w-full flex-1 rounded-lg" }, null, -1),
53
+ createElementVNode("div", { class: "introduction-skeleton h-28 w-full flex-1 rounded-lg" }, null, -1),
54
+ createElementVNode("div", { class: "introduction-skeleton h-28 w-full flex-1 rounded-lg" }, null, -1)
55
+ ])])) : createCommentVNode("", true)
56
+ ]);
57
+ };
58
+ }
59
+ });
60
+ //#endregion
61
+ export { IntroductionLoading_vue_vue_type_script_setup_true_lang_default as default };
62
+
63
+ //# sourceMappingURL=IntroductionLoading.vue.script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntroductionLoading.vue.script.js","names":[],"sources":["../../../../src/blocks/scalar-info-block/components/IntroductionLoading.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Loading skeleton for the introduction block. It mirrors the real layout\n * (badges, title, links, description and selector cards) so the page does not\n * jump once the document has loaded.\n */\nimport { SectionColumn, SectionColumns } from '@/components/Section'\n\nconst { hasAside = true } = defineProps<{\n /**\n * Whether the selector cards live in a sticky aside column (modern layout)\n * or in a row below the description (classic layout). Mirrors the\n * `$slots.aside` check in the loaded layout.\n */\n hasAside?: boolean\n}>()\n</script>\n\n<template>\n <div\n class=\"introduction-loading flex flex-col gap-5\"\n aria-hidden=\"true\">\n <!-- Version and specification badges -->\n <div class=\"flex gap-1.5\">\n <div class=\"introduction-skeleton h-6 w-14 rounded-full\" />\n <div class=\"introduction-skeleton h-6 w-24 rounded-full\" />\n </div>\n <!-- Title and links (mirrors SectionHeader's two-column grid at xl) -->\n <div class=\"grid grid-cols-1 gap-3 xl:grid-cols-2 xl:gap-12\">\n <div class=\"introduction-skeleton h-9 w-3/5 rounded-lg\" />\n <div class=\"flex flex-wrap items-center gap-2 xl:justify-end\">\n <div class=\"introduction-skeleton h-5 w-28 rounded\" />\n <div class=\"introduction-skeleton h-5 w-28 rounded\" />\n <div class=\"introduction-skeleton h-5 w-12 rounded\" />\n </div>\n </div>\n <SectionColumns>\n <SectionColumn>\n <div class=\"flex flex-col gap-3\">\n <!-- Download link -->\n <div class=\"introduction-skeleton mb-2 h-5 w-56 rounded\" />\n <!-- Description -->\n <div class=\"introduction-skeleton h-4 w-full rounded\" />\n <div class=\"introduction-skeleton h-4 w-11/12 rounded\" />\n <div class=\"introduction-skeleton h-4 w-4/5 rounded\" />\n <!-- Section heading -->\n <div class=\"introduction-skeleton mt-4 h-6 w-40 rounded\" />\n <div class=\"introduction-skeleton h-4 w-3/4 rounded\" />\n <div class=\"introduction-skeleton h-4 w-2/3 rounded\" />\n <div class=\"introduction-skeleton h-4 w-1/2 rounded\" />\n </div>\n </SectionColumn>\n <!-- Modern layout: selector cards in a sticky aside column -->\n <SectionColumn v-if=\"hasAside\">\n <div class=\"sticky-cards gap-3\">\n <div class=\"introduction-skeleton h-20 w-full rounded-lg\" />\n <div class=\"introduction-skeleton h-28 w-full rounded-lg\" />\n <div class=\"introduction-skeleton h-28 w-full rounded-lg\" />\n </div>\n </SectionColumn>\n </SectionColumns>\n <!-- Classic layout: selector cards in a row below the description -->\n <div\n v-if=\"!hasAside\"\n class=\"flex flex-col gap-3 sm:flex-row sm:gap-6\">\n <div class=\"introduction-skeleton h-28 w-full flex-1 rounded-lg\" />\n <div class=\"introduction-skeleton h-28 w-full flex-1 rounded-lg\" />\n <div class=\"introduction-skeleton h-28 w-full flex-1 rounded-lg\" />\n </div>\n </div>\n</template>\n\n<style scoped>\n.sticky-cards {\n display: flex;\n flex-direction: column;\n position: sticky;\n top: calc(var(--refs-viewport-offset) + 24px);\n}\n\n/* Pulsing placeholder, matching the look of the rest of the loading states. */\n.introduction-skeleton {\n background: var(--scalar-background-3);\n animation: introduction-skeleton-pulse 1.5s infinite alternate;\n}\n\n@keyframes introduction-skeleton-pulse {\n from {\n opacity: 1;\n }\n to {\n opacity: 0.33;\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;uBAmBE,mBAkDM,OAlDN,YAkDM;;IAjCJ,YAwBiB,MAAA,uBAAA,EAAA,MAAA;4BATC,CAdhB,YAcgB,MAAA,sBAAA,EAAA,MAAA;6BADR,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAZN,mBAYM,OAAA,EAZD,OAAM,uBAAqB,EAAA;OAE9B,mBAA2D,OAAA,EAAtD,OAAM,+CAA6C,CAAA;OAExD,mBAAwD,OAAA,EAAnD,OAAM,4CAA0C,CAAA;OACrD,mBAAyD,OAAA,EAApD,OAAM,6CAA2C,CAAA;OACtD,mBAAuD,OAAA,EAAlD,OAAM,2CAAyC,CAAA;OAEpD,mBAA2D,OAAA,EAAtD,OAAM,+CAA6C,CAAA;OACxD,mBAAuD,OAAA,EAAlD,OAAM,2CAAyC,CAAA;OACpD,mBAAuD,OAAA,EAAlD,OAAM,2CAAyC,CAAA;OACpD,mBAAuD,OAAA,EAAlD,OAAM,2CAAyC,CAAA;;;SAInC,QAAA,YAAA,WAAA,EAArB,YAMgB,MAAA,sBAAA,EAAA,EAAA,KAAA,GAAA,EAAA;6BADR,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAJN,mBAIM,OAAA,EAJD,OAAM,sBAAoB,EAAA;OAC7B,mBAA4D,OAAA,EAAvD,OAAM,gDAA8C,CAAA;OACzD,mBAA4D,OAAA,EAAvD,OAAM,gDAA8C,CAAA;OACzD,mBAA4D,OAAA,EAAvD,OAAM,gDAA8C,CAAA;;;;;;KAMtD,QAAA,YAAA,WAAA,EADT,mBAMM,OANN,YAMM,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA;KAHJ,mBAAmE,OAAA,EAA9D,OAAM,uDAAqD,EAAA,MAAA,GAAA;KAChE,mBAAmE,OAAA,EAA9D,OAAM,uDAAqD,EAAA,MAAA,GAAA;KAChE,mBAAmE,OAAA,EAA9D,OAAM,uDAAqD,EAAA,MAAA,GAAA"}
@@ -1,7 +1,20 @@
1
+ import { type WorkspaceEventBus } from '@scalar/workspace-store/events';
1
2
  import type { XScalarSdkInstallation } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-sdk-installation';
2
3
  type __VLS_Props = {
3
4
  /** Custom SDK installation instructions from `x-scalar-sdk-installation` */
4
5
  xScalarSdkInstallation?: XScalarSdkInstallation['x-scalar-sdk-installation'];
6
+ /**
7
+ * The globally selected client id. When it matches one of the SDK languages
8
+ * (as a `custom/<lang>` id) the matching tab is shown as active, keeping the
9
+ * tabs in sync with the operation code samples.
10
+ */
11
+ selectedClient?: string;
12
+ /**
13
+ * Event bus used to broadcast the selected client. Picking a language here
14
+ * switches the operation code samples to that language's custom example, the
15
+ * same channel the generic client selector uses.
16
+ */
17
+ eventBus?: WorkspaceEventBus;
5
18
  };
6
19
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
20
  declare const _default: typeof __VLS_export;
@@ -1 +1 @@
1
- {"version":3,"file":"SdkInstallationInstructions.vue.d.ts","sourceRoot":"","sources":["../../../../src/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue"],"names":[],"mappings":"AA0cA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+EAA+E,CAAA;AAe3H,KAAK,WAAW,GAAG;IACjB,4EAA4E;IAC5E,sBAAsB,CAAC,EAAE,sBAAsB,CAAC,2BAA2B,CAAC,CAAA;CAC7E,CAAC;AA+cF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"SdkInstallationInstructions.vue.d.ts","sourceRoot":"","sources":["../../../../src/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue"],"names":[],"mappings":"AA8fA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AACvE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+EAA+E,CAAA;AAe3H,KAAK,WAAW,GAAG;IACjB,4EAA4E;IAC5E,sBAAsB,CAAC,EAAE,sBAAsB,CAAC,2BAA2B,CAAC,CAAA;IAC5E;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,iBAAiB,CAAA;CAC7B,CAAC;AAqfF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -2,7 +2,7 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_exp
2
2
  import SdkInstallationInstructions_vue_vue_type_script_setup_true_lang_default from "./SdkInstallationInstructions.vue.script.js";
3
3
  /* empty css */
4
4
  //#region src/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue
5
- var SdkInstallationInstructions_default = /* @__PURE__ */ _plugin_vue_export_helper_default(SdkInstallationInstructions_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-9931144b"]]);
5
+ var SdkInstallationInstructions_default = /* @__PURE__ */ _plugin_vue_export_helper_default(SdkInstallationInstructions_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-4bb21500"]]);
6
6
  //#endregion
7
7
  export { SdkInstallationInstructions_default as default };
8
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"SdkInstallationInstructions.vue.js","names":[],"sources":["../../../../src/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarCombobox,\n type ScalarComboboxOption,\n} from '@scalar/components/combobox'\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { ScalarMarkdown } from '@scalar/components/markdown'\nimport type { XScalarSdkInstallation } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-sdk-installation'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n useId,\n watch,\n} from 'vue'\n\nimport { getLanguageIcon } from '../helpers/language-icon'\nimport { getRenderableSdks } from '../helpers/renderable-sdks'\nimport { getVisibleTabCount } from '../helpers/visible-tab-count'\n\nconst { xScalarSdkInstallation } = defineProps<{\n /** Custom SDK installation instructions from `x-scalar-sdk-installation` */\n xScalarSdkInstallation?: XScalarSdkInstallation['x-scalar-sdk-installation']\n}>()\n\nconst headingId = useId()\n/** Base id used to associate each tab with the shared panel for assistive tech */\nconst baseId = useId()\nconst panelId = `${baseId}-panel`\n\n/** Only the SDKs that actually have something to show, with their resolved icon */\nconst sdks = computed(() =>\n getRenderableSdks(xScalarSdkInstallation).map((sdk) => ({\n ...sdk,\n icon: getLanguageIcon(sdk.lang),\n })),\n)\n\n/** Index of the currently selected SDK */\nconst selectedIndex = ref(0)\n\n/** The currently selected SDK */\nconst selected = computed(() => sdks.value[selectedIndex.value])\n\n// Keep the selection in range and re-measure whenever the set of SDKs changes.\n// Keying on the languages (not just the count) also catches documents that swap\n// in a different set of the same size, which would otherwise leave the cached\n// tab widths — and the \"More\" overflow logic — stale.\nwatch(\n () => sdks.value.map((sdk) => sdk.lang).join('\\n'),\n () => {\n if (selectedIndex.value > sdks.value.length - 1) {\n selectedIndex.value = 0\n }\n void nextTick(measure)\n },\n)\n\nconst tabsRef = ref<HTMLElement>()\nconst measureRef = ref<HTMLElement>()\n\n/** The width available to render the tabs in */\nconst availableWidth = ref(0)\n/** The natural width of each tab */\nconst tabWidths = ref<number[]>([])\n/** The width of the \"More\" dropdown trigger */\nconst moreWidth = ref(0)\n\n/** Measure the available width and the natural width of each tab */\nconst measure = () => {\n const measureEl = measureRef.value\n const tabsEl = tabsRef.value\n\n if (!measureEl || !tabsEl) {\n return\n }\n\n // The measuring row renders every tab followed by the \"More\" trigger\n const widths = Array.from(measureEl.children).map(\n (child) => (child as HTMLElement).offsetWidth,\n )\n\n tabWidths.value = widths.slice(0, sdks.value.length)\n moreWidth.value = widths[sdks.value.length] ?? 0\n availableWidth.value = tabsEl.clientWidth\n}\n\n/** How many tabs fit inline before we need the \"More\" dropdown */\nconst visibleCount = computed(() => {\n // Until we have measured, render everything (also the server-rendered state)\n if (!tabWidths.value.length || availableWidth.value <= 0) {\n return sdks.value.length\n }\n\n return getVisibleTabCount(\n tabWidths.value,\n availableWidth.value,\n moreWidth.value,\n )\n})\n\n/** The SDKs shown as inline tabs */\nconst visibleSdks = computed(() => sdks.value.slice(0, visibleCount.value))\n\n/** Whether the selected SDK lives in the \"More\" dropdown */\nconst isMoreActive = computed(() => selectedIndex.value >= visibleCount.value)\n\n/** The overflowing SDKs as combobox options, keyed by their original index */\nconst moreOptions = computed<ScalarComboboxOption[]>(() =>\n sdks.value.slice(visibleCount.value).map((sdk, index) => ({\n id: String(visibleCount.value + index),\n label: sdk.lang,\n })),\n)\n\n/** The selected option within the \"More\" dropdown, if any */\nconst selectedMoreOption = computed(() =>\n moreOptions.value.find((option) => option.id === String(selectedIndex.value)),\n)\n\nconst selectMore = (option: ScalarComboboxOption | undefined) => {\n if (option) {\n selectedIndex.value = Number(option.id)\n }\n}\n\n/** The id of the tab that labels the panel (falls back to the heading when the selection lives in \"More\") */\nconst activeTabId = computed(() =>\n isMoreActive.value ? headingId : `${baseId}-tab-${selectedIndex.value}`,\n)\n\n/**\n * The visible tab that holds the roving tabindex. When the selection lives in\n * the \"More\" dropdown, that trigger is the tab stop instead, so no inline tab\n * should be focusable.\n */\nconst tabStopIndex = computed(() =>\n isMoreActive.value ? -1 : selectedIndex.value,\n)\n\n/** Focus a visible tab by index after the DOM has settled */\nconst focusTab = (index: number) => {\n void nextTick(() => {\n tabsRef.value\n ?.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]')\n [index]?.focus()\n })\n}\n\n/** Arrow / Home / End keyboard navigation across the visible tabs (WAI-ARIA tabs pattern) */\nconst onTabKeydown = (event: KeyboardEvent, index: number) => {\n const lastVisible = visibleCount.value - 1\n\n let next = index\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowDown':\n next = index >= lastVisible ? 0 : index + 1\n break\n case 'ArrowLeft':\n case 'ArrowUp':\n next = index <= 0 ? lastVisible : index - 1\n break\n case 'Home':\n next = 0\n break\n case 'End':\n next = lastVisible\n break\n default:\n return\n }\n\n event.preventDefault()\n selectedIndex.value = next\n focusTab(next)\n}\n\nlet observer: ResizeObserver | undefined\nlet frame = 0\n\n/** Coalesce resize bursts into a single measure before the next paint */\nconst scheduleMeasure = () => {\n if (typeof requestAnimationFrame === 'undefined') {\n measure()\n return\n }\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(measure)\n}\n\nonMounted(() => {\n if (typeof ResizeObserver !== 'undefined') {\n observer = new ResizeObserver(scheduleMeasure)\n // Observe the visible row for the available width, and the hidden measure\n // row for the natural tab widths. The latter catches changes the container\n // never sees — web fonts loading, or labels changing without the count\n // changing — which would otherwise leave the overflow logic stale.\n if (tabsRef.value) {\n observer.observe(tabsRef.value)\n }\n if (measureRef.value) {\n observer.observe(measureRef.value)\n }\n }\n measure()\n})\n\nonBeforeUnmount(() => {\n observer?.disconnect()\n if (typeof cancelAnimationFrame !== 'undefined') {\n cancelAnimationFrame(frame)\n }\n})\n</script>\n<template>\n <div v-if=\"sdks.length\">\n <div\n :id=\"headingId\"\n class=\"client-libraries-heading\">\n Client Libraries\n </div>\n\n <!-- Tabs -->\n <div class=\"client-libraries-content\">\n <div\n ref=\"tabsRef\"\n :aria-labelledby=\"headingId\"\n class=\"client-libraries-row\"\n role=\"tablist\">\n <button\n v-for=\"(sdk, index) in visibleSdks\"\n :id=\"`${baseId}-tab-${index}`\"\n :key=\"index\"\n :aria-controls=\"panelId\"\n :aria-selected=\"index === selectedIndex\"\n class=\"client-libraries\"\n :class=\"{ 'client-libraries__active': index === selectedIndex }\"\n role=\"tab\"\n :tabindex=\"index === tabStopIndex ? 0 : -1\"\n type=\"button\"\n @click=\"selectedIndex = index\"\n @keydown=\"onTabKeydown($event, index)\">\n <ScalarIcon\n v-if=\"sdk.icon\"\n class=\"client-libraries-icon\"\n :icon=\"sdk.icon\" />\n <span class=\"client-libraries-text\">{{ sdk.lang }}</span>\n </button>\n\n <!-- More dropdown -->\n <ScalarCombobox\n v-if=\"visibleCount < sdks.length\"\n :modelValue=\"selectedMoreOption\"\n :options=\"moreOptions\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectMore\">\n <button\n class=\"client-libraries client-libraries-more\"\n :class=\"{ 'client-libraries__active': isMoreActive }\"\n type=\"button\">\n <ScalarIcon\n class=\"client-libraries-icon\"\n :icon=\"\n isMoreActive && selected?.icon ? selected.icon : 'Ellipses'\n \" />\n <span class=\"client-libraries-text\">More</span>\n </button>\n </ScalarCombobox>\n </div>\n\n <!-- Hidden row used to measure the natural width of every tab. It is\n clipped to a zero-size box so it never contributes to the scrollable\n width of the (horizontally scrollable) row above. -->\n <div\n aria-hidden=\"true\"\n class=\"client-libraries-measure-clip\">\n <div\n ref=\"measureRef\"\n class=\"client-libraries-row client-libraries-row--measure\">\n <span\n v-for=\"(sdk, index) in sdks\"\n :key=\"index\"\n class=\"client-libraries\">\n <ScalarIcon\n v-if=\"sdk.icon\"\n class=\"client-libraries-icon\"\n :icon=\"sdk.icon\" />\n <span class=\"client-libraries-text\">{{ sdk.lang }}</span>\n </span>\n <span class=\"client-libraries\">\n <ScalarIcon\n class=\"client-libraries-icon\"\n icon=\"Ellipses\" />\n <span class=\"client-libraries-text\">More</span>\n </span>\n </div>\n </div>\n </div>\n\n <!-- Content: Markdown installation instructions (supports code blocks) -->\n <div\n v-if=\"selected?.description\"\n :id=\"panelId\"\n :aria-labelledby=\"activeTabId\"\n class=\"selected-client\"\n role=\"tabpanel\"\n tabindex=\"0\">\n <ScalarMarkdown :value=\"selected.description\" />\n </div>\n </div>\n</template>\n<style scoped>\n/* One panel holds the Markdown installation instructions */\n.selected-client {\n display: flex;\n flex-direction: column;\n gap: 9px;\n color: var(--scalar-color-1);\n font-size: var(--scalar-small);\n padding: 9px 12px;\n background: var(--scalar-background-1);\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-top: none;\n border-bottom-left-radius: var(--scalar-radius-xl);\n border-bottom-right-radius: var(--scalar-radius-xl);\n}\n.client-libraries-heading {\n font-size: var(--scalar-small);\n font-weight: var(--scalar-font-medium);\n color: var(--scalar-color-1);\n padding: 9px 12px;\n background-color: var(--scalar-background-2);\n display: flex;\n align-items: center;\n max-height: 32px;\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-top-left-radius: var(--scalar-radius-xl);\n border-top-right-radius: var(--scalar-radius-xl);\n}\n.client-libraries-content {\n position: relative;\n /*\n * Scroll horizontally rather than clip: before JS measures the tab widths\n * (and without JS at all) every tab is rendered, so overflowing tabs must\n * stay reachable. Once measured, the \"More\" dropdown absorbs the overflow and\n * no scrollbar is shown. The bar itself is hidden — keyboard focus and touch\n * still scroll clipped tabs into view.\n */\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n padding: 0 12px;\n background-color: var(--scalar-background-1);\n border-left: var(--scalar-border-width) solid var(--scalar-border-color);\n border-right: var(--scalar-border-width) solid var(--scalar-border-color);\n border-bottom: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n.client-libraries-content::-webkit-scrollbar {\n display: none;\n}\n.client-libraries-row {\n display: flex;\n justify-content: flex-start;\n}\n/* Zero-size clip so the measure row never adds to the scrollable width */\n.client-libraries-measure-clip {\n position: absolute;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n overflow: hidden;\n}\n/* Off-screen row used only to measure natural tab widths */\n.client-libraries-row--measure {\n width: max-content;\n visibility: hidden;\n pointer-events: none;\n}\n.client-libraries {\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n cursor: pointer;\n white-space: nowrap;\n /* Keep tabs at their natural (measured) width so they scroll rather than squish */\n flex-shrink: 0;\n padding: 8px 12px;\n gap: 6px;\n color: var(--scalar-color-3);\n border-bottom: 1px solid transparent;\n background: transparent;\n user-select: none;\n}\n.client-libraries:not(.client-libraries__active):hover:before {\n content: '';\n position: absolute;\n width: calc(100% - 4px);\n height: calc(100% - 4px);\n background: var(--scalar-background-2);\n left: 2px;\n top: 2px;\n z-index: 0;\n border-radius: var(--scalar-radius);\n}\n.client-libraries:active {\n color: var(--scalar-color-1);\n}\n.client-libraries:focus-visible {\n outline: none;\n box-shadow: inset 0 0 0 1px var(--scalar-color-accent);\n}\n.client-libraries__active {\n color: var(--scalar-color-1);\n border-bottom: 1px solid var(--scalar-color-1);\n}\n/* Always pin the \"More\" dropdown to the right edge */\n.client-libraries-more {\n margin-left: auto;\n}\n.client-libraries-icon {\n max-width: 14px;\n max-height: 14px;\n min-width: 14px;\n width: 100%;\n aspect-ratio: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n box-sizing: border-box;\n color: currentColor;\n}\n.client-libraries .client-libraries-text {\n font-size: var(--scalar-small);\n position: relative;\n display: flex;\n align-items: center;\n}\n.client-libraries__active .client-libraries-text {\n color: var(--scalar-color-1);\n font-weight: var(--scalar-semibold);\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"SdkInstallationInstructions.vue.js","names":[],"sources":["../../../../src/blocks/scalar-sdk-installation-instructions/components/SdkInstallationInstructions.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getCustomClientIds } from '@scalar/api-client/blocks/operation-code-sample'\nimport {\n ScalarCombobox,\n type ScalarComboboxOption,\n} from '@scalar/components/combobox'\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { ScalarMarkdown } from '@scalar/components/markdown'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport type { XScalarSdkInstallation } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-sdk-installation'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n useId,\n watch,\n} from 'vue'\n\nimport { getLanguageIcon } from '../helpers/language-icon'\nimport { getRenderableSdks } from '../helpers/renderable-sdks'\nimport { getVisibleTabCount } from '../helpers/visible-tab-count'\n\nconst { xScalarSdkInstallation, selectedClient, eventBus } = defineProps<{\n /** Custom SDK installation instructions from `x-scalar-sdk-installation` */\n xScalarSdkInstallation?: XScalarSdkInstallation['x-scalar-sdk-installation']\n /**\n * The globally selected client id. When it matches one of the SDK languages\n * (as a `custom/<lang>` id) the matching tab is shown as active, keeping the\n * tabs in sync with the operation code samples.\n */\n selectedClient?: string\n /**\n * Event bus used to broadcast the selected client. Picking a language here\n * switches the operation code samples to that language's custom example, the\n * same channel the generic client selector uses.\n */\n eventBus?: WorkspaceEventBus\n}>()\n\nconst headingId = useId()\n/** Base id used to associate each tab with the shared panel for assistive tech */\nconst baseId = useId()\nconst panelId = `${baseId}-panel`\n\n/** Only the SDKs that actually have something to show, with their resolved icon */\nconst sdks = computed(() =>\n getRenderableSdks(xScalarSdkInstallation).map((sdk) => ({\n ...sdk,\n icon: getLanguageIcon(sdk.lang),\n })),\n)\n\n/** Index of the currently selected SDK */\nconst selectedIndex = ref(0)\n\n/** The currently selected SDK */\nconst selected = computed(() => sdks.value[selectedIndex.value])\n\n/**\n * The `custom/<lang>` client id for each SDK, aligned by index with `sdks`.\n *\n * We reuse the exact id scheme the operation code samples use for their custom\n * examples, so selecting a language here resolves to the same id those samples\n * are keyed by — that shared id is what keeps the two surfaces in sync.\n */\nconst sdkClientIds = computed(() =>\n getCustomClientIds(sdks.value.map((sdk) => ({ lang: sdk.lang, source: '' }))),\n)\n\n/** Select an SDK by index and broadcast it so the operation code samples follow */\nconst select = (index: number) => {\n selectedIndex.value = index\n\n const id = sdkClientIds.value[index]\n if (id) {\n eventBus?.emit('workspace:update:selected-client', id)\n }\n}\n\n// Keep the active tab aligned with the global selection, re-evaluating whenever\n// either the selection or the available SDKs change. Watching `sdkClientIds`\n// (not just `selectedClient`) is what stops the intro tab and the operation\n// samples from disagreeing after the SDK list is reordered or resized: the tab\n// follows the selected language to its new position. When the selection is a\n// built-in client (or a language this document has no install entry for) we keep\n// the current tab, only clamping it back into range if the list shrank past it.\nwatch(\n [() => selectedClient, sdkClientIds],\n ([client, ids]) => {\n const matched = client ? ids.findIndex((id) => id === client) : -1\n\n if (matched >= 0) {\n selectedIndex.value = matched\n } else if (selectedIndex.value > ids.length - 1) {\n selectedIndex.value = 0\n }\n },\n { immediate: true },\n)\n\n// Re-measure whenever the set of SDKs changes. Keying on the languages (not just\n// the count) also catches documents that swap in a different set of the same\n// size, which would otherwise leave the cached tab widths — and the \"More\"\n// overflow logic — stale.\nwatch(\n () => sdks.value.map((sdk) => sdk.lang).join('\\n'),\n () => void nextTick(measure),\n)\n\nconst tabsRef = ref<HTMLElement>()\nconst measureRef = ref<HTMLElement>()\n\n/** The width available to render the tabs in */\nconst availableWidth = ref(0)\n/** The natural width of each tab */\nconst tabWidths = ref<number[]>([])\n/** The width of the \"More\" dropdown trigger */\nconst moreWidth = ref(0)\n\n/** Measure the available width and the natural width of each tab */\nconst measure = () => {\n const measureEl = measureRef.value\n const tabsEl = tabsRef.value\n\n if (!measureEl || !tabsEl) {\n return\n }\n\n // The measuring row renders every tab followed by the \"More\" trigger\n const widths = Array.from(measureEl.children).map(\n (child) => (child as HTMLElement).offsetWidth,\n )\n\n tabWidths.value = widths.slice(0, sdks.value.length)\n moreWidth.value = widths[sdks.value.length] ?? 0\n availableWidth.value = tabsEl.clientWidth\n}\n\n/** How many tabs fit inline before we need the \"More\" dropdown */\nconst visibleCount = computed(() => {\n // Until we have measured, render everything (also the server-rendered state)\n if (!tabWidths.value.length || availableWidth.value <= 0) {\n return sdks.value.length\n }\n\n return getVisibleTabCount(\n tabWidths.value,\n availableWidth.value,\n moreWidth.value,\n )\n})\n\n/** The SDKs shown as inline tabs */\nconst visibleSdks = computed(() => sdks.value.slice(0, visibleCount.value))\n\n/** Whether the selected SDK lives in the \"More\" dropdown */\nconst isMoreActive = computed(() => selectedIndex.value >= visibleCount.value)\n\n/** The overflowing SDKs as combobox options, keyed by their original index */\nconst moreOptions = computed<ScalarComboboxOption[]>(() =>\n sdks.value.slice(visibleCount.value).map((sdk, index) => ({\n id: String(visibleCount.value + index),\n label: sdk.lang,\n })),\n)\n\n/** The selected option within the \"More\" dropdown, if any */\nconst selectedMoreOption = computed(() =>\n moreOptions.value.find((option) => option.id === String(selectedIndex.value)),\n)\n\nconst selectMore = (option: ScalarComboboxOption | undefined) => {\n if (option) {\n select(Number(option.id))\n }\n}\n\n/** The id of the tab that labels the panel (falls back to the heading when the selection lives in \"More\") */\nconst activeTabId = computed(() =>\n isMoreActive.value ? headingId : `${baseId}-tab-${selectedIndex.value}`,\n)\n\n/**\n * The visible tab that holds the roving tabindex. When the selection lives in\n * the \"More\" dropdown, that trigger is the tab stop instead, so no inline tab\n * should be focusable.\n */\nconst tabStopIndex = computed(() =>\n isMoreActive.value ? -1 : selectedIndex.value,\n)\n\n/** Focus a visible tab by index after the DOM has settled */\nconst focusTab = (index: number) => {\n void nextTick(() => {\n tabsRef.value\n ?.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]')\n [index]?.focus()\n })\n}\n\n/** Arrow / Home / End keyboard navigation across the visible tabs (WAI-ARIA tabs pattern) */\nconst onTabKeydown = (event: KeyboardEvent, index: number) => {\n const lastVisible = visibleCount.value - 1\n\n let next = index\n switch (event.key) {\n case 'ArrowRight':\n case 'ArrowDown':\n next = index >= lastVisible ? 0 : index + 1\n break\n case 'ArrowLeft':\n case 'ArrowUp':\n next = index <= 0 ? lastVisible : index - 1\n break\n case 'Home':\n next = 0\n break\n case 'End':\n next = lastVisible\n break\n default:\n return\n }\n\n event.preventDefault()\n select(next)\n focusTab(next)\n}\n\nlet observer: ResizeObserver | undefined\nlet frame = 0\n\n/** Coalesce resize bursts into a single measure before the next paint */\nconst scheduleMeasure = () => {\n if (typeof requestAnimationFrame === 'undefined') {\n measure()\n return\n }\n cancelAnimationFrame(frame)\n frame = requestAnimationFrame(measure)\n}\n\nonMounted(() => {\n if (typeof ResizeObserver !== 'undefined') {\n observer = new ResizeObserver(scheduleMeasure)\n // Observe the visible row for the available width, and the hidden measure\n // row for the natural tab widths. The latter catches changes the container\n // never sees — web fonts loading, or labels changing without the count\n // changing — which would otherwise leave the overflow logic stale.\n if (tabsRef.value) {\n observer.observe(tabsRef.value)\n }\n if (measureRef.value) {\n observer.observe(measureRef.value)\n }\n }\n measure()\n})\n\nonBeforeUnmount(() => {\n observer?.disconnect()\n if (typeof cancelAnimationFrame !== 'undefined') {\n cancelAnimationFrame(frame)\n }\n})\n</script>\n<template>\n <div v-if=\"sdks.length\">\n <div\n :id=\"headingId\"\n class=\"client-libraries-heading\">\n Client Libraries\n </div>\n\n <!-- Tabs -->\n <div class=\"client-libraries-content\">\n <div\n ref=\"tabsRef\"\n :aria-labelledby=\"headingId\"\n class=\"client-libraries-row\"\n role=\"tablist\">\n <button\n v-for=\"(sdk, index) in visibleSdks\"\n :id=\"`${baseId}-tab-${index}`\"\n :key=\"index\"\n :aria-controls=\"panelId\"\n :aria-selected=\"index === selectedIndex\"\n class=\"client-libraries\"\n :class=\"{ 'client-libraries__active': index === selectedIndex }\"\n role=\"tab\"\n :tabindex=\"index === tabStopIndex ? 0 : -1\"\n type=\"button\"\n @click=\"select(index)\"\n @keydown=\"onTabKeydown($event, index)\">\n <ScalarIcon\n v-if=\"sdk.icon\"\n class=\"client-libraries-icon\"\n :icon=\"sdk.icon\" />\n <span class=\"client-libraries-text\">{{ sdk.lang }}</span>\n </button>\n\n <!-- More dropdown -->\n <ScalarCombobox\n v-if=\"visibleCount < sdks.length\"\n :modelValue=\"selectedMoreOption\"\n :options=\"moreOptions\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectMore\">\n <button\n class=\"client-libraries client-libraries-more\"\n :class=\"{ 'client-libraries__active': isMoreActive }\"\n type=\"button\">\n <ScalarIcon\n class=\"client-libraries-icon\"\n :icon=\"\n isMoreActive && selected?.icon ? selected.icon : 'Ellipses'\n \" />\n <span class=\"client-libraries-text\">More</span>\n </button>\n </ScalarCombobox>\n </div>\n\n <!-- Hidden row used to measure the natural width of every tab. It is\n clipped to a zero-size box so it never contributes to the scrollable\n width of the (horizontally scrollable) row above. -->\n <div\n aria-hidden=\"true\"\n class=\"client-libraries-measure-clip\">\n <div\n ref=\"measureRef\"\n class=\"client-libraries-row client-libraries-row--measure\">\n <span\n v-for=\"(sdk, index) in sdks\"\n :key=\"index\"\n class=\"client-libraries\">\n <ScalarIcon\n v-if=\"sdk.icon\"\n class=\"client-libraries-icon\"\n :icon=\"sdk.icon\" />\n <span class=\"client-libraries-text\">{{ sdk.lang }}</span>\n </span>\n <span class=\"client-libraries\">\n <ScalarIcon\n class=\"client-libraries-icon\"\n icon=\"Ellipses\" />\n <span class=\"client-libraries-text\">More</span>\n </span>\n </div>\n </div>\n </div>\n\n <!-- Content: Markdown installation instructions (supports code blocks) -->\n <div\n v-if=\"selected?.description\"\n :id=\"panelId\"\n :aria-labelledby=\"activeTabId\"\n class=\"selected-client\"\n role=\"tabpanel\"\n tabindex=\"0\">\n <ScalarMarkdown :value=\"selected.description\" />\n </div>\n </div>\n</template>\n<style scoped>\n/* One panel holds the Markdown installation instructions */\n.selected-client {\n display: flex;\n flex-direction: column;\n gap: 9px;\n color: var(--scalar-color-1);\n font-size: var(--scalar-small);\n padding: 9px 12px;\n background: var(--scalar-background-1);\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-top: none;\n border-bottom-left-radius: var(--scalar-radius-xl);\n border-bottom-right-radius: var(--scalar-radius-xl);\n}\n.client-libraries-heading {\n font-size: var(--scalar-small);\n font-weight: var(--scalar-font-medium);\n color: var(--scalar-color-1);\n padding: 9px 12px;\n background-color: var(--scalar-background-2);\n display: flex;\n align-items: center;\n max-height: 32px;\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-top-left-radius: var(--scalar-radius-xl);\n border-top-right-radius: var(--scalar-radius-xl);\n}\n.client-libraries-content {\n position: relative;\n /*\n * Scroll horizontally rather than clip: before JS measures the tab widths\n * (and without JS at all) every tab is rendered, so overflowing tabs must\n * stay reachable. Once measured, the \"More\" dropdown absorbs the overflow and\n * no scrollbar is shown. The bar itself is hidden — keyboard focus and touch\n * still scroll clipped tabs into view.\n */\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n padding: 0 12px;\n background-color: var(--scalar-background-1);\n border-left: var(--scalar-border-width) solid var(--scalar-border-color);\n border-right: var(--scalar-border-width) solid var(--scalar-border-color);\n border-bottom: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n.client-libraries-content::-webkit-scrollbar {\n display: none;\n}\n.client-libraries-row {\n display: flex;\n justify-content: flex-start;\n}\n/* Zero-size clip so the measure row never adds to the scrollable width */\n.client-libraries-measure-clip {\n position: absolute;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n overflow: hidden;\n}\n/* Off-screen row used only to measure natural tab widths */\n.client-libraries-row--measure {\n width: max-content;\n visibility: hidden;\n pointer-events: none;\n}\n.client-libraries {\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n cursor: pointer;\n white-space: nowrap;\n /* Keep tabs at their natural (measured) width so they scroll rather than squish */\n flex-shrink: 0;\n padding: 8px 12px;\n gap: 6px;\n color: var(--scalar-color-3);\n border-bottom: 1px solid transparent;\n background: transparent;\n user-select: none;\n}\n.client-libraries:not(.client-libraries__active):hover:before {\n content: '';\n position: absolute;\n width: calc(100% - 4px);\n height: calc(100% - 4px);\n background: var(--scalar-background-2);\n left: 2px;\n top: 2px;\n z-index: 0;\n border-radius: var(--scalar-radius);\n}\n.client-libraries:active {\n color: var(--scalar-color-1);\n}\n.client-libraries:focus-visible {\n outline: none;\n box-shadow: inset 0 0 0 1px var(--scalar-color-accent);\n}\n.client-libraries__active {\n color: var(--scalar-color-1);\n border-bottom: 1px solid var(--scalar-color-1);\n}\n/* Always pin the \"More\" dropdown to the right edge */\n.client-libraries-more {\n margin-left: auto;\n}\n.client-libraries-icon {\n max-width: 14px;\n max-height: 14px;\n min-width: 14px;\n width: 100%;\n aspect-ratio: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n box-sizing: border-box;\n color: currentColor;\n}\n.client-libraries .client-libraries-text {\n font-size: var(--scalar-small);\n position: relative;\n display: flex;\n align-items: center;\n}\n.client-libraries__active .client-libraries-text {\n color: var(--scalar-color-1);\n font-weight: var(--scalar-semibold);\n}\n</style>\n"],"mappings":""}