@scalar/api-client 3.16.1 → 3.17.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.
- package/CHANGELOG.md +46 -0
- package/README.md +18 -0
- package/dist/style.css +27 -38
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts +2 -0
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +36 -10
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.d.ts +4 -0
- package/dist/v2/blocks/operation-block/components/Header.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.js +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.script.js +14 -9
- package/dist/v2/blocks/operation-block/components/Header.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +15 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js +13 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js +5 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts +4 -0
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js +61 -24
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.d.ts.map +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.js +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.js.map +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.script.js +7 -0
- package/dist/v2/components/code-input/CodeInputLite.vue.script.js.map +1 -1
- package/dist/v2/constants.js +1 -1
- package/dist/v2/features/modal/Modal.vue.d.ts +2 -0
- package/dist/v2/features/modal/Modal.vue.d.ts.map +1 -1
- package/dist/v2/features/modal/Modal.vue.js.map +1 -1
- package/dist/v2/features/modal/Modal.vue.script.js +3 -0
- package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
- package/dist/v2/features/modal/helpers/create-api-client-modal.d.ts.map +1 -1
- package/dist/v2/features/modal/helpers/create-api-client-modal.js +6 -6
- package/dist/v2/features/modal/helpers/create-api-client-modal.js.map +1 -1
- package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts +12 -3
- package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts.map +1 -1
- package/dist/v2/features/modal/helpers/resolve-route-parameters.js +13 -9
- package/dist/v2/features/modal/helpers/resolve-route-parameters.js.map +1 -1
- package/dist/v2/features/modal/hooks/use-modal-sidebar.d.ts +3 -1
- package/dist/v2/features/modal/hooks/use-modal-sidebar.d.ts.map +1 -1
- package/dist/v2/features/modal/hooks/use-modal-sidebar.js +28 -7
- package/dist/v2/features/modal/hooks/use-modal-sidebar.js.map +1 -1
- package/dist/v2/features/modal/modal-events.d.ts.map +1 -1
- package/dist/v2/features/modal/modal-events.js +5 -2
- package/dist/v2/features/modal/modal-events.js.map +1 -1
- package/dist/v2/features/operation/Operation.vue.d.ts +2 -0
- package/dist/v2/features/operation/Operation.vue.d.ts.map +1 -1
- package/dist/v2/features/operation/Operation.vue.js.map +1 -1
- package/dist/v2/features/operation/Operation.vue.script.js +8 -1
- package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
- package/dist/v2/features/search/helpers/create-search-index.js +2 -2
- package/dist/v2/features/search/helpers/create-search-index.js.map +1 -1
- package/dist/v2/helpers/generate-location-id.d.ts +3 -1
- package/dist/v2/helpers/generate-location-id.d.ts.map +1 -1
- package/dist/v2/helpers/generate-location-id.js +2 -1
- package/dist/v2/helpers/generate-location-id.js.map +1 -1
- package/dist/vue-styles.css +26 -26
- package/package.json +18 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.vue.script.js","names":[],"sources":["../../../../src/v2/features/modal/Modal.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type ModalProps = {\n /** The workspace store must be initialized and passed in */\n workspaceStore: WorkspaceStore\n /** The document must be initialized and passed in. OpenAPI-only — the modal has no AsyncAPI path. */\n document: ComputedRef<OpenApiDocument | null>\n /** The path must be initialized and passed in */\n path: ComputedRef<string | undefined>\n /** The event bus for handling all events */\n eventBus: WorkspaceEventBus\n /** The method must be initialized and passed in */\n method: ComputedRef<HttpMethod | undefined>\n /** The example name must be initialized and passed in */\n exampleName: ComputedRef<string | undefined>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection: Ref<Record<string, number>>\n /** Controls the visibility of the modal */\n modalState: ModalState\n /** The sidebar state must be initialized and passed in */\n sidebarState: UseModalSidebarReturn\n /** Api client plugins to include in the modal */\n plugins: ClientPlugin[]\n /** Subset of the configuration options for the modal */\n options: MaybeRefOrGetter<ApiClientOptions>\n}\n\n/**\n * Scalar Api Client Modal\n *\n * This component is used to render the API Client Modal\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport type { ScalarListboxOption } from '@scalar/components/listbox'\nimport type { ModalState } from '@scalar/components/modal'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport { ScalarToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getActiveEnvironment } from '@scalar/workspace-store/request-example'\nimport type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport {\n computed,\n onBeforeUnmount,\n ref,\n watch,\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n} from 'vue'\n\nimport ModalClientContainer from '@/v2/components/modals/ModalClientContainer.vue'\nimport { Sidebar, SidebarToggle } from '@/v2/components/sidebar'\nimport { type UseModalSidebarReturn } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport { initializeModalEvents } from '@/v2/features/modal/modal-events'\nimport Operation from '@/v2/features/operation/Operation.vue'\nimport { useGlobalHotKeys } from '@/v2/hooks/use-global-hot-keys'\nimport { useScrollLock } from '@/v2/hooks/use-scroll-lock'\nimport type { ApiClientOptions, ApiClientOptionsRef } from '@/v2/types/options'\n\nconst {\n document,\n eventBus,\n modalState,\n options,\n plugins,\n requestBodyCompositionSelection,\n sidebarState,\n workspaceStore,\n} = defineProps<\n Omit<ModalProps, 'options'> & { options: ApiClientOptionsRef }\n>()\n\nconst activeWorkspace: ScalarListboxOption = {\n label: 'default',\n id: 'default',\n}\n\n/** Controls the visibility of the sidebar. */\nconst isSidebarOpen = ref(false)\n\n/** Initialize modal events */\ninitializeModalEvents({\n eventBus,\n isSidebarOpen,\n requestBodyCompositionSelection,\n sidebarState,\n modalState,\n store: workspaceStore,\n})\n\n/** Register global hotkeys for the app, passing the workspace event bus and layout state */\nuseGlobalHotKeys(eventBus, 'modal', () => !modalState.open)\n\n/** Clean up on close */\nconst cleanUp = () => {\n eventBus.emit('operation:cancel:request')\n}\n\nconst isLocked = useScrollLock(() => {\n if (typeof window !== 'undefined') {\n return window.document.body\n }\n return null\n})\n\nwatch(\n () => modalState.open,\n (open) => {\n // Make sure scrolling is locked or unlocked when the modal is opened or closed\n isLocked.value = open\n\n if (!open) {\n cleanUp()\n }\n },\n)\n\n// Ensure we add our scalar wrapper class to the headless ui root\nonBeforeUnmount(() => cleanUp())\n\n/** Default sidebar width in pixels. */\nconst DEFAULT_SIDEBAR_WIDTH = 288\n\n/** Width of the sidebar, with fallback to default. */\nconst sidebarWidth = computed(\n () =>\n workspaceStore?.workspace?.['x-scalar-sidebar-width'] ??\n DEFAULT_SIDEBAR_WIDTH,\n)\n\n/** Handler for sidebar width changes. */\nconst handleSidebarWidthUpdate = (width: number) =>\n workspaceStore?.update('x-scalar-sidebar-width', width)\n\n/**\n * Merged environment variables from workspace and document levels.\n * Variables from both sources are combined, with document variables\n * taking precedence in case of naming conflicts.\n */\nconst environment = computed(\n () => getActiveEnvironment(workspaceStore, document.value).environment,\n)\n\ndefineExpose({\n sidebarWidth,\n environment,\n})\n</script>\n\n<template>\n <ModalClientContainer :modalState>\n <!-- Toasts -->\n <ScalarToasts />\n\n <!-- If we have a document, path and method, render the operation -->\n <main\n v-if=\"document.value && path?.value && method?.value\"\n class=\"relative flex h-full min-h-0 w-full flex-1\">\n <SidebarToggle\n v-model=\"isSidebarOpen\"\n class=\"absolute top-2 left-4 z-10 max-md:top-4\" />\n <Sidebar\n v-show=\"isSidebarOpen\"\n v-model:sidebarWidth=\"sidebarWidth\"\n :activeWorkspace=\"activeWorkspace\"\n class=\"h-full max-md:absolute! max-md:z-5 max-md:w-full!\"\n :documents=\"[document.value]\"\n :eventBus\n :isDroppable=\"() => false\"\n layout=\"modal\"\n :sidebarState=\"sidebarState.state\"\n :workspaces=\"[]\"\n @selectItem=\"sidebarState.handleSelectItem\"\n @update:sidebarWidth=\"handleSidebarWidthUpdate\" />\n <Operation\n :activeWorkspace=\"activeWorkspace\"\n class=\"flex-1\"\n :document=\"document.value\"\n :documentSlug=\"document.value['x-scalar-navigation']?.name ?? ''\"\n :environment\n :eventBus\n :exampleName=\"exampleName?.value\"\n layout=\"modal\"\n :method=\"method?.value\"\n :options\n :path=\"path?.value\"\n :plugins\n :requestBodyCompositionSelection=\"requestBodyCompositionSelection.value\"\n :workspaceStore />\n </main>\n <!-- Empty state -->\n <div\n v-else\n class=\"flex h-full w-full items-center justify-center\">\n <span class=\"text-c-3\">No document selected</span>\n </div>\n </ModalClientContainer>\n</template>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Modal.vue.script.js","names":[],"sources":["../../../../src/v2/features/modal/Modal.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type ModalProps = {\n /** The workspace store must be initialized and passed in */\n workspaceStore: WorkspaceStore\n /** The document must be initialized and passed in. OpenAPI-only — the modal has no AsyncAPI path. */\n document: ComputedRef<OpenApiDocument | null>\n /** The path must be initialized and passed in */\n path: ComputedRef<string | undefined>\n /** The event bus for handling all events */\n eventBus: WorkspaceEventBus\n /** The method must be initialized and passed in */\n method: ComputedRef<HttpMethod | undefined>\n /** The example name must be initialized and passed in */\n exampleName: ComputedRef<string | undefined>\n /** Whether the active route resolves from `document.webhooks`. */\n isWebhook: ComputedRef<boolean>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection: Ref<Record<string, number>>\n /** Controls the visibility of the modal */\n modalState: ModalState\n /** The sidebar state must be initialized and passed in */\n sidebarState: UseModalSidebarReturn\n /** Api client plugins to include in the modal */\n plugins: ClientPlugin[]\n /** Subset of the configuration options for the modal */\n options: MaybeRefOrGetter<ApiClientOptions>\n}\n\n/**\n * Scalar Api Client Modal\n *\n * This component is used to render the API Client Modal\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport type { ScalarListboxOption } from '@scalar/components/listbox'\nimport type { ModalState } from '@scalar/components/modal'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport { ScalarToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getActiveEnvironment } from '@scalar/workspace-store/request-example'\nimport type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport {\n computed,\n onBeforeUnmount,\n ref,\n watch,\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n} from 'vue'\n\nimport ModalClientContainer from '@/v2/components/modals/ModalClientContainer.vue'\nimport { Sidebar, SidebarToggle } from '@/v2/components/sidebar'\nimport { type UseModalSidebarReturn } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport { initializeModalEvents } from '@/v2/features/modal/modal-events'\nimport Operation from '@/v2/features/operation/Operation.vue'\nimport { useGlobalHotKeys } from '@/v2/hooks/use-global-hot-keys'\nimport { useScrollLock } from '@/v2/hooks/use-scroll-lock'\nimport type { ApiClientOptions, ApiClientOptionsRef } from '@/v2/types/options'\n\nconst {\n document,\n eventBus,\n modalState,\n options,\n plugins,\n requestBodyCompositionSelection,\n sidebarState,\n workspaceStore,\n} = defineProps<\n Omit<ModalProps, 'options'> & { options: ApiClientOptionsRef }\n>()\n\nconst activeWorkspace: ScalarListboxOption = {\n label: 'default',\n id: 'default',\n}\n\n/** Controls the visibility of the sidebar. */\nconst isSidebarOpen = ref(false)\n\n/** Initialize modal events */\ninitializeModalEvents({\n eventBus,\n isSidebarOpen,\n requestBodyCompositionSelection,\n sidebarState,\n modalState,\n store: workspaceStore,\n})\n\n/** Register global hotkeys for the app, passing the workspace event bus and layout state */\nuseGlobalHotKeys(eventBus, 'modal', () => !modalState.open)\n\n/** Clean up on close */\nconst cleanUp = () => {\n eventBus.emit('operation:cancel:request')\n}\n\nconst isLocked = useScrollLock(() => {\n if (typeof window !== 'undefined') {\n return window.document.body\n }\n return null\n})\n\nwatch(\n () => modalState.open,\n (open) => {\n // Make sure scrolling is locked or unlocked when the modal is opened or closed\n isLocked.value = open\n\n if (!open) {\n cleanUp()\n }\n },\n)\n\n// Ensure we add our scalar wrapper class to the headless ui root\nonBeforeUnmount(() => cleanUp())\n\n/** Default sidebar width in pixels. */\nconst DEFAULT_SIDEBAR_WIDTH = 288\n\n/** Width of the sidebar, with fallback to default. */\nconst sidebarWidth = computed(\n () =>\n workspaceStore?.workspace?.['x-scalar-sidebar-width'] ??\n DEFAULT_SIDEBAR_WIDTH,\n)\n\n/** Handler for sidebar width changes. */\nconst handleSidebarWidthUpdate = (width: number) =>\n workspaceStore?.update('x-scalar-sidebar-width', width)\n\n/**\n * Merged environment variables from workspace and document levels.\n * Variables from both sources are combined, with document variables\n * taking precedence in case of naming conflicts.\n */\nconst environment = computed(\n () => getActiveEnvironment(workspaceStore, document.value).environment,\n)\n\ndefineExpose({\n sidebarWidth,\n environment,\n})\n</script>\n\n<template>\n <ModalClientContainer :modalState>\n <!-- Toasts -->\n <ScalarToasts />\n\n <!-- If we have a document, path and method, render the operation -->\n <main\n v-if=\"document.value && path?.value && method?.value\"\n class=\"relative flex h-full min-h-0 w-full flex-1\">\n <SidebarToggle\n v-model=\"isSidebarOpen\"\n class=\"absolute top-2 left-4 z-10 max-md:top-4\" />\n <Sidebar\n v-show=\"isSidebarOpen\"\n v-model:sidebarWidth=\"sidebarWidth\"\n :activeWorkspace=\"activeWorkspace\"\n class=\"h-full max-md:absolute! max-md:z-5 max-md:w-full!\"\n :documents=\"[document.value]\"\n :eventBus\n :isDroppable=\"() => false\"\n layout=\"modal\"\n :sidebarState=\"sidebarState.state\"\n :workspaces=\"[]\"\n @selectItem=\"sidebarState.handleSelectItem\"\n @update:sidebarWidth=\"handleSidebarWidthUpdate\" />\n <Operation\n :activeWorkspace=\"activeWorkspace\"\n class=\"flex-1\"\n :document=\"document.value\"\n :documentSlug=\"document.value['x-scalar-navigation']?.name ?? ''\"\n :environment\n :eventBus\n :exampleName=\"exampleName?.value\"\n :isWebhook=\"isWebhook.value\"\n layout=\"modal\"\n :method=\"method?.value\"\n :options\n :path=\"path?.value\"\n :plugins\n :requestBodyCompositionSelection=\"requestBodyCompositionSelection.value\"\n :workspaceStore />\n </main>\n <!-- Empty state -->\n <div\n v-else\n class=\"flex h-full w-full items-center justify-center\">\n <span class=\"text-c-3\">No document selected</span>\n </div>\n </ModalClientContainer>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8EA,MAAM,kBAAuC;GAC3C,OAAO;GACP,IAAI;EACN;;EAGA,MAAM,gBAAgB,IAAI,KAAK;;EAG/B,sBAAsB;GACpB,UAAO,QAAA;GACP;GACA,iCAA8B,QAAA;GAC9B,cAAW,QAAA;GACX,YAAS,QAAA;GACT,OAAO,QAAA;EACT,CAAC;;EAGD,iBAAiB,QAAA,UAAU,eAAe,CAAC,QAAA,WAAW,IAAI;;EAG1D,MAAM,gBAAgB;GACpB,QAAA,SAAS,KAAK,0BAA0B;EAC1C;EAEA,MAAM,WAAW,oBAAoB;GACnC,IAAI,OAAO,WAAW,aACpB,OAAO,OAAO,SAAS;GAEzB,OAAO;EACT,CAAC;EAED,YACQ,QAAA,WAAW,OAChB,SAAS;GAER,SAAS,QAAQ;GAEjB,IAAI,CAAC,MACH,QAAQ;EAEZ,CACF;EAGA,sBAAsB,QAAQ,CAAC;;EAG/B,MAAM,wBAAwB;;EAG9B,MAAM,eAAe,eAEjB,QAAA,gBAAgB,YAAY,6BAC5B,qBACJ;;EAGA,MAAM,4BAA4B,UAChC,QAAA,gBAAgB,OAAO,0BAA0B,KAAK;;;;;;EAOxD,MAAM,cAAc,eACZ,qBAAqB,QAAA,gBAAgB,QAAA,SAAS,KAAK,CAAC,CAAC,WAC7D;EAEA,SAAa;GACX;GACA;EACF,CAAC;;uBAIC,YA+CuB,8BAAA,EA/CA,YAAA,QAAA,WAAU,GAAA;2BAEf,CAAhB,YAAgB,MAAA,YAAA,CAAA,GAIR,QAAA,SAAS,SAAS,QAAA,MAAM,SAAS,QAAA,QAAQ,SAAA,UAAA,GADjD,mBAmCO,QAnCP,YAmCO;KAhCL,YAEoD,MAAA,qBAAA,GAAA;kBADzC,cAAA;iFAAa,QAAA;MACtB,OAAM;;oBACR,YAYoD,MAAA,eAAA,GAAA;MAV1C,cAAc,aAAA;mFAAY,QAAA,SAUZ,wBAAA;MATJ;MAClB,OAAM;MACL,WAAS,CAAG,QAAA,SAAS,KAAK;MAC1B,UAAA,QAAA;MACA,mBAAa;MACd,QAAO;MACN,cAAc,QAAA,aAAa;MAC3B,YAAY,CAAA;MACZ,cAAY,QAAA,aAAa;;;;;;;kBAVlB,cAAA,KAAa,CAAA,CAAA;KAYvB,YAeoB,mBAAA;MAdA;MAClB,OAAM;MACL,UAAU,QAAA,SAAS;MACnB,cAAc,QAAA,SAAS,MAAK,sBAAA,EAAyB,QAAI;MACzD,aAAA,YAAA;MACA,UAAA,QAAA;MACA,aAAa,QAAA,aAAa;MAC1B,WAAW,QAAA,UAAU;MACtB,QAAO;MACN,QAAQ,QAAA,QAAQ;MAChB,SAAA,QAAA;MACA,MAAM,QAAA,MAAM;MACZ,SAAA,QAAA;MACA,iCAAiC,QAAA,gCAAgC;MACjE,gBAAA,QAAA;;;;;;;;;;;;;;;wBAGL,mBAIM,OAJN,YAIM,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CADJ,mBAAkD,QAAA,EAA5C,OAAM,WAAU,GAAC,wBAAoB,EAAA,CAAA,EAAA,CAAA,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-api-client-modal.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/modal/helpers/create-api-client-modal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAY,MAAM,0BAA0B,CAAA;AACpE,OAAO,EAAE,KAAK,YAAY,EAAyB,MAAM,2BAA2B,CAAA;AACpF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,KAAK,iBAAiB,EAA2B,MAAM,gCAAgC,CAAA;AAEhG,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,gBAAgB,EAA6D,MAAM,KAAK,CAAA;AAEhH,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,sDAAsD,CAAA;AAG7D,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,oBAAoB,CAAA;AAE/E,KAAK,sBAAsB,GAAG;IAC5B,4CAA4C;IAC5C,EAAE,EAAE,WAAW,GAAG,IAAI,CAAA;IACtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,6DAA6D;IAC7D,cAAc,EAAE,cAAc,CAAA;IAC9B,iDAAiD;IACjD,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,wGAAwG;IACxG,OAAO,CAAC,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,IAAI,CAAA;IACtC,KAAK,EAAE,CAAC,UAAU,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;IAC/C,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAA;IACtC,aAAa,EAAE,CAAC,WAAW,EAAE,gBAAgB,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3E,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAcD;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,wEASlC,sBAAsB,KAAG,
|
|
1
|
+
{"version":3,"file":"create-api-client-modal.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/modal/helpers/create-api-client-modal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAY,MAAM,0BAA0B,CAAA;AACpE,OAAO,EAAE,KAAK,YAAY,EAAyB,MAAM,2BAA2B,CAAA;AACpF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,KAAK,iBAAiB,EAA2B,MAAM,gCAAgC,CAAA;AAEhG,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,gBAAgB,EAA6D,MAAM,KAAK,CAAA;AAEhH,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,sDAAsD,CAAA;AAG7D,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,oBAAoB,CAAA;AAE/E,KAAK,sBAAsB,GAAG;IAC5B,4CAA4C;IAC5C,EAAE,EAAE,WAAW,GAAG,IAAI,CAAA;IACtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,6DAA6D;IAC7D,cAAc,EAAE,cAAc,CAAA;IAC9B,iDAAiD;IACjD,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,wGAAwG;IACxG,OAAO,CAAC,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,IAAI,CAAA;IACtC,KAAK,EAAE,CAAC,UAAU,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;IAC/C,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAA;IACtC,aAAa,EAAE,CAAC,WAAW,EAAE,gBAAgB,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3E,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAcD;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,wEASlC,sBAAsB,KAAG,cA8I3B,CAAA"}
|
|
@@ -32,7 +32,8 @@ var createApiClientModal = ({ el, eventBus = createWorkspaceEventBus({ debug: fa
|
|
|
32
32
|
path: "default",
|
|
33
33
|
method: "default",
|
|
34
34
|
example: "default",
|
|
35
|
-
documentSlug: workspaceStore.workspace["x-scalar-active-document"] || "default"
|
|
35
|
+
documentSlug: workspaceStore.workspace["x-scalar-active-document"] || "default",
|
|
36
|
+
isWebhook: false
|
|
36
37
|
};
|
|
37
38
|
const parameters = reactive({ ...defaultEntities });
|
|
38
39
|
/** Navigate to the specified path, method, and example. */
|
|
@@ -45,6 +46,7 @@ var createApiClientModal = ({ el, eventBus = createWorkspaceEventBus({ debug: fa
|
|
|
45
46
|
const path = computed(() => resolvedParameters.value.path);
|
|
46
47
|
const method = computed(() => resolvedParameters.value.method);
|
|
47
48
|
const exampleName = computed(() => resolvedParameters.value.example);
|
|
49
|
+
const isWebhook = computed(() => resolvedParameters.value.isWebhook ?? false);
|
|
48
50
|
/** The document from the workspace store. Modal is OpenAPI-only; AsyncAPI docs surface as null. */
|
|
49
51
|
const document = computed(() => {
|
|
50
52
|
const doc = workspaceStore.workspace.documents[documentSlug.value ?? ""];
|
|
@@ -57,6 +59,7 @@ var createApiClientModal = ({ el, eventBus = createWorkspaceEventBus({ debug: fa
|
|
|
57
59
|
path,
|
|
58
60
|
method,
|
|
59
61
|
exampleName,
|
|
62
|
+
isWebhook,
|
|
60
63
|
route
|
|
61
64
|
});
|
|
62
65
|
const modalState = useModal();
|
|
@@ -64,6 +67,7 @@ var createApiClientModal = ({ el, eventBus = createWorkspaceEventBus({ debug: fa
|
|
|
64
67
|
document,
|
|
65
68
|
eventBus,
|
|
66
69
|
exampleName,
|
|
70
|
+
isWebhook,
|
|
67
71
|
method,
|
|
68
72
|
modalState,
|
|
69
73
|
path,
|
|
@@ -73,10 +77,6 @@ var createApiClientModal = ({ el, eventBus = createWorkspaceEventBus({ debug: fa
|
|
|
73
77
|
workspaceStore,
|
|
74
78
|
options: optionsRef
|
|
75
79
|
});
|
|
76
|
-
/** Restore the workspace store when the modal is closed. */
|
|
77
|
-
const handleModalClose = () => {
|
|
78
|
-
requestBodyCompositionSelection.value = {};
|
|
79
|
-
};
|
|
80
80
|
/** Initialize plugins and subscribe to event bus events */
|
|
81
81
|
const pluginUnsubscribes = [];
|
|
82
82
|
for (const plugin of plugins) {
|
|
@@ -88,7 +88,6 @@ var createApiClientModal = ({ el, eventBus = createWorkspaceEventBus({ debug: fa
|
|
|
88
88
|
for (const unsub of pluginUnsubscribes) unsub();
|
|
89
89
|
for (const plugin of plugins) plugin.lifecycle?.onDestroy?.();
|
|
90
90
|
});
|
|
91
|
-
watch(() => modalState.open, (open) => open ? null : handleModalClose());
|
|
92
91
|
watch(() => toValue(optionsRef).proxyUrl, (newProxyUrl) => workspaceStore.update("x-scalar-active-proxy", newProxyUrl), { immediate: true });
|
|
93
92
|
app.config.idPrefix = `scalar-client-${modalAppCount++}`;
|
|
94
93
|
/** Mount the modal to a given element. */
|
|
@@ -105,6 +104,7 @@ var createApiClientModal = ({ el, eventBus = createWorkspaceEventBus({ debug: fa
|
|
|
105
104
|
app,
|
|
106
105
|
/** Open the modal and optionally navigate to a specific route. */
|
|
107
106
|
open: (payload) => {
|
|
107
|
+
requestBodyCompositionSelection.value = {};
|
|
108
108
|
modalState.open = true;
|
|
109
109
|
if (payload) route(payload);
|
|
110
110
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-api-client-modal.js","names":[],"sources":["../../../../../src/v2/features/modal/helpers/create-api-client-modal.ts"],"sourcesContent":["import { type ModalState, useModal } from '@scalar/components/modal'\nimport { type ClientPlugin, subscribePluginEvents } from '@scalar/oas-utils/helpers'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { type WorkspaceEventBus, createWorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { isOpenApiDocument } from '@scalar/workspace-store/schemas/type-guards'\nimport { type App, type MaybeRefOrGetter, computed, createApp, isRef, reactive, ref, toValue, watch } from 'vue'\n\nimport {\n type DefaultEntities,\n type RoutePayload,\n resolveRouteParameters,\n} from '@/v2/features/modal/helpers/resolve-route-parameters'\nimport { useModalSidebar } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport Modal, { type ModalProps } from '@/v2/features/modal/Modal.vue'\nimport type { ApiClientOptions, ApiClientOptionsRef } from '@/v2/types/options'\n\ntype CreateApiClientOptions = {\n /** Element to mount the client modal to. */\n el: HTMLElement | null\n /**\n * Will attempt to mount the references immediately.\n * For SSR this may need to be disabled and handled manually on the client side.\n */\n mountOnInitialize?: boolean\n /** You can pass in an event bus if you have one already, or we will create one */\n eventBus?: WorkspaceEventBus\n /** The workspace store must be initialized and passed in. */\n workspaceStore: WorkspaceStore\n /** Api client plugins to include in the modal */\n plugins?: ClientPlugin[]\n /** Subset of the configuration options for the modal, if you want it to be reactive ensure its a ref */\n options?: MaybeRefOrGetter<ApiClientOptions>\n}\n\nexport type ApiClientModal = {\n app: App\n open: (payload?: RoutePayload) => void\n mount: (mountingEl: HTMLElement | null) => void\n route: (payload: RoutePayload) => void\n updateOptions: (nextOptions: ApiClientOptions, overwrite?: boolean) => void\n modalState: ModalState\n}\n\n/**\n * Monotonic counter used to give every modal Vue app a unique `idPrefix`.\n *\n * Vue derives `useId()` values (and therefore our teleport target ids) from the app's\n * `idPrefix`. When more than one client app mounts on the same page — for example, the\n * API reference embeds this modal alongside another client instance — a shared prefix\n * makes both apps emit identical ids. A teleported popover then resolves to the first\n * matching target in the DOM, which can be a hidden app, so the popover never appears.\n * A per-app suffix keeps the ids unique across instances.\n */\nlet modalAppCount = 0\n\n/**\n * Creates the API Client Modal.\n *\n * The modal does not require a router. Instead, navigation is handled by setting\n * active entities directly through the returned `route` function.\n */\nexport const createApiClientModal = ({\n el,\n eventBus = createWorkspaceEventBus({\n debug: import.meta.env.DEV,\n }),\n mountOnInitialize = true,\n plugins = [],\n workspaceStore,\n options = {},\n}: CreateApiClientOptions): ApiClientModal => {\n const requestBodyCompositionSelection = ref<Record<string, number>>({})\n\n /** This is to ensure that the options are a ref if they are not already, useful for react */\n const optionsRef = (isRef(options) ? options : ref(toValue(options))) as ApiClientOptionsRef\n\n const defaultEntities: DefaultEntities = {\n path: 'default',\n method: 'default',\n example: 'default',\n documentSlug: workspaceStore.workspace['x-scalar-active-document'] || 'default',\n }\n\n const parameters = reactive<DefaultEntities>({ ...defaultEntities })\n\n /** Navigate to the specified path, method, and example. */\n const route = (payload: RoutePayload): void => {\n Object.assign(parameters, defaultEntities, payload)\n }\n\n /** Resolved parameters from the workspace store. */\n const resolvedParameters = computed(() => resolveRouteParameters(workspaceStore, parameters))\n const documentSlug = computed(() => resolvedParameters.value.documentSlug)\n const path = computed(() => resolvedParameters.value.path)\n const method = computed(() => resolvedParameters.value.method)\n const exampleName = computed(() => resolvedParameters.value.example)\n /** The document from the workspace store. Modal is OpenAPI-only; AsyncAPI docs surface as null. */\n const document = computed(() => {\n const doc = workspaceStore.workspace.documents[documentSlug.value ?? '']\n return isOpenApiDocument(doc) ? doc : null\n })\n\n /** Sidebar state and selection handling. */\n const sidebarState = useModalSidebar({\n workspaceStore,\n documentSlug: documentSlug,\n path: path,\n method: method,\n exampleName: exampleName,\n route,\n })\n\n const modalState = useModal()\n\n const app = createApp(Modal, {\n document,\n eventBus,\n exampleName,\n method,\n modalState,\n path,\n plugins,\n requestBodyCompositionSelection,\n sidebarState,\n workspaceStore,\n options: optionsRef,\n } satisfies ModalProps)\n\n /**
|
|
1
|
+
{"version":3,"file":"create-api-client-modal.js","names":[],"sources":["../../../../../src/v2/features/modal/helpers/create-api-client-modal.ts"],"sourcesContent":["import { type ModalState, useModal } from '@scalar/components/modal'\nimport { type ClientPlugin, subscribePluginEvents } from '@scalar/oas-utils/helpers'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { type WorkspaceEventBus, createWorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { isOpenApiDocument } from '@scalar/workspace-store/schemas/type-guards'\nimport { type App, type MaybeRefOrGetter, computed, createApp, isRef, reactive, ref, toValue, watch } from 'vue'\n\nimport {\n type DefaultEntities,\n type RoutePayload,\n resolveRouteParameters,\n} from '@/v2/features/modal/helpers/resolve-route-parameters'\nimport { useModalSidebar } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport Modal, { type ModalProps } from '@/v2/features/modal/Modal.vue'\nimport type { ApiClientOptions, ApiClientOptionsRef } from '@/v2/types/options'\n\ntype CreateApiClientOptions = {\n /** Element to mount the client modal to. */\n el: HTMLElement | null\n /**\n * Will attempt to mount the references immediately.\n * For SSR this may need to be disabled and handled manually on the client side.\n */\n mountOnInitialize?: boolean\n /** You can pass in an event bus if you have one already, or we will create one */\n eventBus?: WorkspaceEventBus\n /** The workspace store must be initialized and passed in. */\n workspaceStore: WorkspaceStore\n /** Api client plugins to include in the modal */\n plugins?: ClientPlugin[]\n /** Subset of the configuration options for the modal, if you want it to be reactive ensure its a ref */\n options?: MaybeRefOrGetter<ApiClientOptions>\n}\n\nexport type ApiClientModal = {\n app: App\n open: (payload?: RoutePayload) => void\n mount: (mountingEl: HTMLElement | null) => void\n route: (payload: RoutePayload) => void\n updateOptions: (nextOptions: ApiClientOptions, overwrite?: boolean) => void\n modalState: ModalState\n}\n\n/**\n * Monotonic counter used to give every modal Vue app a unique `idPrefix`.\n *\n * Vue derives `useId()` values (and therefore our teleport target ids) from the app's\n * `idPrefix`. When more than one client app mounts on the same page — for example, the\n * API reference embeds this modal alongside another client instance — a shared prefix\n * makes both apps emit identical ids. A teleported popover then resolves to the first\n * matching target in the DOM, which can be a hidden app, so the popover never appears.\n * A per-app suffix keeps the ids unique across instances.\n */\nlet modalAppCount = 0\n\n/**\n * Creates the API Client Modal.\n *\n * The modal does not require a router. Instead, navigation is handled by setting\n * active entities directly through the returned `route` function.\n */\nexport const createApiClientModal = ({\n el,\n eventBus = createWorkspaceEventBus({\n debug: import.meta.env.DEV,\n }),\n mountOnInitialize = true,\n plugins = [],\n workspaceStore,\n options = {},\n}: CreateApiClientOptions): ApiClientModal => {\n const requestBodyCompositionSelection = ref<Record<string, number>>({})\n\n /** This is to ensure that the options are a ref if they are not already, useful for react */\n const optionsRef = (isRef(options) ? options : ref(toValue(options))) as ApiClientOptionsRef\n\n const defaultEntities: DefaultEntities = {\n path: 'default',\n method: 'default',\n example: 'default',\n documentSlug: workspaceStore.workspace['x-scalar-active-document'] || 'default',\n isWebhook: false,\n }\n\n const parameters = reactive<DefaultEntities>({ ...defaultEntities })\n\n /** Navigate to the specified path, method, and example. */\n const route = (payload: RoutePayload): void => {\n Object.assign(parameters, defaultEntities, payload)\n }\n\n /** Resolved parameters from the workspace store. */\n const resolvedParameters = computed(() => resolveRouteParameters(workspaceStore, parameters))\n const documentSlug = computed(() => resolvedParameters.value.documentSlug)\n const path = computed(() => resolvedParameters.value.path)\n const method = computed(() => resolvedParameters.value.method)\n const exampleName = computed(() => resolvedParameters.value.example)\n const isWebhook = computed(() => resolvedParameters.value.isWebhook ?? false)\n /** The document from the workspace store. Modal is OpenAPI-only; AsyncAPI docs surface as null. */\n const document = computed(() => {\n const doc = workspaceStore.workspace.documents[documentSlug.value ?? '']\n return isOpenApiDocument(doc) ? doc : null\n })\n\n /** Sidebar state and selection handling. */\n const sidebarState = useModalSidebar({\n workspaceStore,\n documentSlug: documentSlug,\n path: path,\n method: method,\n exampleName: exampleName,\n isWebhook,\n route,\n })\n\n const modalState = useModal()\n\n const app = createApp(Modal, {\n document,\n eventBus,\n exampleName,\n isWebhook,\n method,\n modalState,\n path,\n plugins,\n requestBodyCompositionSelection,\n sidebarState,\n workspaceStore,\n options: optionsRef,\n } satisfies ModalProps)\n\n /** Initialize plugins and subscribe to event bus events */\n const pluginUnsubscribes: (() => void)[] = []\n for (const plugin of plugins) {\n plugin.lifecycle?.onInit?.()\n\n pluginUnsubscribes.push(subscribePluginEvents(eventBus, plugin))\n }\n\n /** Clean up plugin lifecycle and event bus subscriptions when the app is unmounted */\n app.onUnmount(() => {\n for (const unsub of pluginUnsubscribes) {\n unsub()\n }\n for (const plugin of plugins) {\n plugin.lifecycle?.onDestroy?.()\n }\n })\n\n // Update the active proxy when the proxyUrl changes\n watch(\n () => toValue(optionsRef).proxyUrl,\n (newProxyUrl) => workspaceStore.update('x-scalar-active-proxy', newProxyUrl),\n { immediate: true },\n )\n\n // Use a unique id prefix to prevent collisions with other Vue apps on the page.\n // The suffix keeps the prefix unique even when several client apps mount together.\n app.config.idPrefix = `scalar-client-${modalAppCount++}`\n\n /** Mount the modal to a given element. */\n const mount = (mountingEl: HTMLElement | null = el): void => {\n if (!mountingEl) {\n console.error(\n '[@scalar/api-client] Could not create the API client Modal.',\n 'Invalid HTML element provided.',\n 'Read more: https://github.com/scalar/scalar/tree/main/packages/api-client',\n )\n return\n }\n app.mount(mountingEl)\n }\n\n if (mountOnInitialize) {\n mount()\n }\n\n return {\n /** The Vue app instance for the modal. Use with caution. */\n app,\n /** Open the modal and optionally navigate to a specific route. */\n open: (payload?: RoutePayload): void => {\n // This path does not carry a composition selection, so clear any selection left over from a\n // previously opened operation. (The event-driven open path re-establishes it from its payload.)\n requestBodyCompositionSelection.value = {}\n modalState.open = true\n if (payload) {\n route(payload)\n }\n },\n /** Mount the modal to a given element. */\n mount,\n /** Navigate to the specified path, method, and example. */\n route,\n /** Controls the visibility of the modal. */\n modalState,\n /**\n * Merge new options into the current modal options.\n *\n * @param newOptions - The new options to merge into the current modal options.\n * @param overwrite - Whether to overwrite the current modal options with the new options. If false, the new options will be merged with the current options.\n */\n updateOptions: (newOptions: ApiClientOptions, overwrite = false): void => {\n optionsRef.value = overwrite\n ? newOptions\n : {\n ...optionsRef.value,\n ...newOptions,\n }\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqDA,IAAI,gBAAgB;;;;;;;AAQpB,IAAa,wBAAwB,EACnC,IACA,WAAW,wBAAwB,EACjC,OAAA,MACF,CAAC,GACD,oBAAoB,MACpB,UAAU,CAAC,GACX,gBACA,UAAU,CAAC,QACiC;CAC5C,MAAM,kCAAkC,IAA4B,CAAC,CAAC;;CAGtE,MAAM,aAAc,MAAM,OAAO,IAAI,UAAU,IAAI,QAAQ,OAAO,CAAC;CAEnE,MAAM,kBAAmC;EACvC,MAAM;EACN,QAAQ;EACR,SAAS;EACT,cAAc,eAAe,UAAU,+BAA+B;EACtE,WAAW;CACb;CAEA,MAAM,aAAa,SAA0B,EAAE,GAAG,gBAAgB,CAAC;;CAGnE,MAAM,SAAS,YAAgC;EAC7C,OAAO,OAAO,YAAY,iBAAiB,OAAO;CACpD;;CAGA,MAAM,qBAAqB,eAAe,uBAAuB,gBAAgB,UAAU,CAAC;CAC5F,MAAM,eAAe,eAAe,mBAAmB,MAAM,YAAY;CACzE,MAAM,OAAO,eAAe,mBAAmB,MAAM,IAAI;CACzD,MAAM,SAAS,eAAe,mBAAmB,MAAM,MAAM;CAC7D,MAAM,cAAc,eAAe,mBAAmB,MAAM,OAAO;CACnE,MAAM,YAAY,eAAe,mBAAmB,MAAM,aAAa,KAAK;;CAE5E,MAAM,WAAW,eAAe;EAC9B,MAAM,MAAM,eAAe,UAAU,UAAU,aAAa,SAAS;EACrE,OAAO,kBAAkB,GAAG,IAAI,MAAM;CACxC,CAAC;;CAGD,MAAM,eAAe,gBAAgB;EACnC;EACc;EACR;EACE;EACK;EACb;EACA;CACF,CAAC;CAED,MAAM,aAAa,SAAS;CAE5B,MAAM,MAAM,UAAU,eAAO;EAC3B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,SAAS;CACX,CAAsB;;CAGtB,MAAM,qBAAqC,CAAC;CAC5C,KAAK,MAAM,UAAU,SAAS;EAC5B,OAAO,WAAW,SAAS;EAE3B,mBAAmB,KAAK,sBAAsB,UAAU,MAAM,CAAC;CACjE;;CAGA,IAAI,gBAAgB;EAClB,KAAK,MAAM,SAAS,oBAClB,MAAM;EAER,KAAK,MAAM,UAAU,SACnB,OAAO,WAAW,YAAY;CAElC,CAAC;CAGD,YACQ,QAAQ,UAAU,CAAC,CAAC,WACzB,gBAAgB,eAAe,OAAO,yBAAyB,WAAW,GAC3E,EAAE,WAAW,KAAK,CACpB;CAIA,IAAI,OAAO,WAAW,iBAAiB;;CAGvC,MAAM,SAAS,aAAiC,OAAa;EAC3D,IAAI,CAAC,YAAY;GACf,QAAQ,MACN,+DACA,kCACA,2EACF;GACA;EACF;EACA,IAAI,MAAM,UAAU;CACtB;CAEA,IAAI,mBACF,MAAM;CAGR,OAAO;;EAEL;;EAEA,OAAO,YAAiC;GAGtC,gCAAgC,QAAQ,CAAC;GACzC,WAAW,OAAO;GAClB,IAAI,SACF,MAAM,OAAO;EAEjB;;EAEA;;EAEA;;EAEA;;;;;;;EAOA,gBAAgB,YAA8B,YAAY,UAAgB;GACxE,WAAW,QAAQ,YACf,aACA;IACE,GAAG,WAAW;IACd,GAAG;GACL;EACN;CACF;AACF"}
|
|
@@ -3,13 +3,22 @@ import type { WorkspaceStore } from '@scalar/workspace-store/client';
|
|
|
3
3
|
import type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation';
|
|
4
4
|
/** Payload for routing and opening the API client modal. */
|
|
5
5
|
export type RoutePayload = {
|
|
6
|
+
/** API path, or webhook name when `isWebhook` is true. */
|
|
6
7
|
path: string;
|
|
7
8
|
method: HttpMethod;
|
|
8
9
|
example?: string;
|
|
9
10
|
documentSlug?: string;
|
|
11
|
+
/** Resolve `path` from the OpenAPI webhooks map. */
|
|
12
|
+
isWebhook?: boolean;
|
|
10
13
|
};
|
|
11
14
|
/** Raw input values that may contain "default" placeholders. */
|
|
12
|
-
export type DefaultEntities =
|
|
15
|
+
export type DefaultEntities = {
|
|
16
|
+
path: string;
|
|
17
|
+
method: string;
|
|
18
|
+
example: string;
|
|
19
|
+
documentSlug: string;
|
|
20
|
+
isWebhook?: boolean;
|
|
21
|
+
};
|
|
13
22
|
/** Context for resolving route parameters from the workspace store. */
|
|
14
23
|
type ResolverContext = {
|
|
15
24
|
store: WorkspaceStore;
|
|
@@ -33,14 +42,14 @@ export declare const resolveDocumentSlug: (store: WorkspaceStore, slug: string |
|
|
|
33
42
|
* When "default" is specified, returns the first available path in the document.
|
|
34
43
|
* This is useful for initial navigation when no specific path is requested.
|
|
35
44
|
*/
|
|
36
|
-
export declare const resolvePath: (ctx: ResolverContext, path: string | undefined) => string | undefined;
|
|
45
|
+
export declare const resolvePath: (ctx: ResolverContext, path: string | undefined, isWebhook?: boolean) => string | undefined;
|
|
37
46
|
/**
|
|
38
47
|
* Resolves the HTTP method from a raw input value.
|
|
39
48
|
*
|
|
40
49
|
* When "default" is specified, returns the first valid HTTP method for the given path.
|
|
41
50
|
* This ensures we select a real method rather than metadata keys like "parameters" or "summary".
|
|
42
51
|
*/
|
|
43
|
-
export declare const resolveMethod: (ctx: ResolverContext, path: string | undefined, method: string | undefined) => HttpMethod | undefined;
|
|
52
|
+
export declare const resolveMethod: (ctx: ResolverContext, path: string | undefined, method: string | undefined, isWebhook?: boolean) => HttpMethod | undefined;
|
|
44
53
|
/**
|
|
45
54
|
* Resolves the example name from a raw input value.
|
|
46
55
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-route-parameters.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/modal/helpers/resolve-route-parameters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAGpE,OAAO,KAAK,EAAE,cAAc,EAAoB,MAAM,4CAA4C,CAAA;AAGlG,4DAA4D;AAC5D,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,UAAU,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"resolve-route-parameters.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/modal/helpers/resolve-route-parameters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAGpE,OAAO,KAAK,EAAE,cAAc,EAAoB,MAAM,4CAA4C,CAAA;AAGlG,4DAA4D;AAC5D,MAAM,MAAM,YAAY,GAAG;IACzB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,UAAU,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oDAAoD;IACpD,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,gEAAgE;AAChE,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,uEAAuE;AACvE,KAAK,eAAe,GAAG;IACrB,KAAK,EAAE,cAAc,CAAA;IACrB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;CACjC,CAAA;AAeD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,cAAc,EAAE,MAAM,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAe9F,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,eAAe,EAAE,MAAM,MAAM,GAAG,SAAS,EAAE,mBAAiB,KAAG,MAAM,GAAG,SAYxG,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,eAAe,EACpB,MAAM,MAAM,GAAG,SAAS,EACxB,QAAQ,MAAM,GAAG,SAAS,EAC1B,mBAAiB,KAChB,UAAU,GAAG,SAiBf,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,KAAK,eAAe,EACpB,WAAW,cAAc,GAAG,SAAS,EACrC,YAAY,MAAM,GAAG,SAAS,KAC7B,MAmBF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,cAAc,EAAE,QAAQ,eAAe,KAAG,OAAO,CAAC,YAAY,CAsB3G,CAAA"}
|
|
@@ -37,10 +37,10 @@ var resolveDocumentSlug = (store, slug) => {
|
|
|
37
37
|
* When "default" is specified, returns the first available path in the document.
|
|
38
38
|
* This is useful for initial navigation when no specific path is requested.
|
|
39
39
|
*/
|
|
40
|
-
var resolvePath = (ctx, path) => {
|
|
40
|
+
var resolvePath = (ctx, path, isWebhook = false) => {
|
|
41
41
|
const document = getDocument(ctx);
|
|
42
42
|
if (!document) return;
|
|
43
|
-
if (path === "default") return Object.keys(document.paths ?? {})[0];
|
|
43
|
+
if (path === "default") return Object.keys(isWebhook ? document.webhooks ?? {} : document.paths ?? {})[0];
|
|
44
44
|
return path;
|
|
45
45
|
};
|
|
46
46
|
/**
|
|
@@ -49,11 +49,11 @@ var resolvePath = (ctx, path) => {
|
|
|
49
49
|
* When "default" is specified, returns the first valid HTTP method for the given path.
|
|
50
50
|
* This ensures we select a real method rather than metadata keys like "parameters" or "summary".
|
|
51
51
|
*/
|
|
52
|
-
var resolveMethod = (ctx, path, method) => {
|
|
52
|
+
var resolveMethod = (ctx, path, method, isWebhook = false) => {
|
|
53
53
|
const document = getDocument(ctx);
|
|
54
54
|
if (!document || !path) return;
|
|
55
55
|
if (method === "default") {
|
|
56
|
-
const pathItem = getResolvedPathItem(document.paths?.[path]);
|
|
56
|
+
const pathItem = getResolvedPathItem(isWebhook ? document.webhooks?.[path] : document.paths?.[path]);
|
|
57
57
|
if (!pathItem) return;
|
|
58
58
|
return Object.keys(pathItem).filter(isHttpMethod)[0];
|
|
59
59
|
}
|
|
@@ -85,21 +85,25 @@ var resolveRouteParameters = (store, params) => {
|
|
|
85
85
|
store,
|
|
86
86
|
documentSlug
|
|
87
87
|
};
|
|
88
|
-
const
|
|
89
|
-
const
|
|
88
|
+
const isWebhook = params.isWebhook ?? false;
|
|
89
|
+
const path = resolvePath(ctx, params.path, isWebhook);
|
|
90
|
+
const method = resolveMethod(ctx, path, params.method, isWebhook);
|
|
91
|
+
const routeType = isWebhook ? { isWebhook: true } : {};
|
|
90
92
|
const traversedDocument = getDocument(ctx)?.["x-scalar-navigation"];
|
|
91
93
|
if (!traversedDocument) return {
|
|
92
94
|
documentSlug,
|
|
93
95
|
path,
|
|
94
96
|
method,
|
|
95
|
-
example: "default"
|
|
97
|
+
example: "default",
|
|
98
|
+
...routeType
|
|
96
99
|
};
|
|
97
|
-
const operation = getOperationEntries(traversedDocument).get(`${path}|${method}`)?.find((entry) => entry.type === "operation");
|
|
100
|
+
const operation = getOperationEntries(traversedDocument).get(`${path}|${method}`)?.find((entry) => entry.type === (isWebhook ? "webhook" : "operation"));
|
|
98
101
|
return {
|
|
99
102
|
documentSlug,
|
|
100
103
|
path,
|
|
101
104
|
method,
|
|
102
|
-
example: resolveExampleName(ctx, operation, params.example)
|
|
105
|
+
example: resolveExampleName(ctx, operation, params.example),
|
|
106
|
+
...routeType
|
|
103
107
|
};
|
|
104
108
|
};
|
|
105
109
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-route-parameters.js","names":[],"sources":["../../../../../src/v2/features/modal/helpers/resolve-route-parameters.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { getResolvedPathItem } from '@scalar/workspace-store/helpers/for-each-path-item-operation'\nimport { getOperationEntries } from '@scalar/workspace-store/navigation'\nimport type { TraversedEntry, TraversedExample } from '@scalar/workspace-store/schemas/navigation'\nimport { isOpenApiDocument } from '@scalar/workspace-store/schemas/type-guards'\n\n/** Payload for routing and opening the API client modal. */\nexport type RoutePayload = {\n path: string\n method: HttpMethod\n example?: string\n documentSlug?: string\n}\n\n/** Raw input values that may contain \"default\" placeholders. */\nexport type DefaultEntities =
|
|
1
|
+
{"version":3,"file":"resolve-route-parameters.js","names":[],"sources":["../../../../../src/v2/features/modal/helpers/resolve-route-parameters.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { getResolvedPathItem } from '@scalar/workspace-store/helpers/for-each-path-item-operation'\nimport { getOperationEntries } from '@scalar/workspace-store/navigation'\nimport type { TraversedEntry, TraversedExample } from '@scalar/workspace-store/schemas/navigation'\nimport { isOpenApiDocument } from '@scalar/workspace-store/schemas/type-guards'\n\n/** Payload for routing and opening the API client modal. */\nexport type RoutePayload = {\n /** API path, or webhook name when `isWebhook` is true. */\n path: string\n method: HttpMethod\n example?: string\n documentSlug?: string\n /** Resolve `path` from the OpenAPI webhooks map. */\n isWebhook?: boolean\n}\n\n/** Raw input values that may contain \"default\" placeholders. */\nexport type DefaultEntities = {\n path: string\n method: string\n example: string\n documentSlug: string\n isWebhook?: boolean\n}\n\n/** Context for resolving route parameters from the workspace store. */\ntype ResolverContext = {\n store: WorkspaceStore\n documentSlug: string | undefined\n}\n\n/** Type guard to check if an entry is an example. */\nconst isExample = (entry: TraversedEntry): entry is TraversedExample => entry.type === 'example'\n\n/**\n * Gets the document from the workspace store.\n * Returns undefined if the document slug is not provided or the document does not exist.\n * Modal routing is OpenAPI-only — AsyncAPI docs surface as undefined here.\n */\nconst getDocument = (ctx: ResolverContext) => {\n const doc = ctx.store.workspace.documents[ctx.documentSlug ?? '']\n return isOpenApiDocument(doc) ? doc : undefined\n}\n\n/**\n * Resolves the document slug from a raw input value.\n *\n * When \"default\" is specified and no document exists with that slug,\n * we fall back to the active document or the first available document.\n * Modal routing is OpenAPI-only, so the fallback skips AsyncAPI documents —\n * otherwise opening the modal with default params on a workspace that has\n * an AsyncAPI active or first document would hand a slug back that\n * `getDocument` then resolves to undefined, rendering the modal with\n * `document: null` even when OpenAPI documents exist.\n */\nexport const resolveDocumentSlug = (store: WorkspaceStore, slug: string | undefined): string | undefined => {\n const hasMatchingDocument = slug !== 'default' || store.workspace.documents[slug] !== undefined\n\n if (hasMatchingDocument) {\n return slug\n }\n\n // Prefer the active document when it is OpenAPI; otherwise pick the first\n // OpenAPI document in the workspace.\n const activeSlug = store.workspace['x-scalar-active-document']\n if (activeSlug && isOpenApiDocument(store.workspace.documents[activeSlug])) {\n return activeSlug\n }\n\n return Object.entries(store.workspace.documents).find(([, document]) => isOpenApiDocument(document))?.[0]\n}\n\n/**\n * Resolves the path from a raw input value.\n *\n * When \"default\" is specified, returns the first available path in the document.\n * This is useful for initial navigation when no specific path is requested.\n */\nexport const resolvePath = (ctx: ResolverContext, path: string | undefined, isWebhook = false): string | undefined => {\n const document = getDocument(ctx)\n\n if (!document) {\n return undefined\n }\n\n if (path === 'default') {\n return Object.keys(isWebhook ? (document.webhooks ?? {}) : (document.paths ?? {}))[0]\n }\n\n return path\n}\n\n/**\n * Resolves the HTTP method from a raw input value.\n *\n * When \"default\" is specified, returns the first valid HTTP method for the given path.\n * This ensures we select a real method rather than metadata keys like \"parameters\" or \"summary\".\n */\nexport const resolveMethod = (\n ctx: ResolverContext,\n path: string | undefined,\n method: string | undefined,\n isWebhook = false,\n): HttpMethod | undefined => {\n const document = getDocument(ctx)\n\n if (!document || !path) {\n return undefined\n }\n\n if (method === 'default') {\n const pathItem = getResolvedPathItem(isWebhook ? document.webhooks?.[path] : document.paths?.[path])\n if (!pathItem) {\n return undefined\n }\n const pathMethods = Object.keys(pathItem).filter(isHttpMethod)\n return pathMethods[0]\n }\n\n return isHttpMethod(method) ? method : undefined\n}\n\n/**\n * Resolves the example name from a raw input value.\n *\n * When \"default\" is specified, returns the first available example name.\n * Falls back to \"default\" when no examples exist, which signals to use the default request body.\n */\nexport const resolveExampleName = (\n ctx: ResolverContext,\n operation: TraversedEntry | undefined,\n exampleKey: string | undefined,\n): string => {\n const document = getDocument(ctx)\n\n if (!document || operation?.type !== 'operation') {\n return 'default'\n }\n\n const examples = operation.children?.filter(isExample) ?? []\n const matchingExample = examples.find((child) => child.name === exampleKey)\n\n if (matchingExample) {\n return matchingExample.name\n }\n\n if (exampleKey === 'default') {\n return examples[0]?.name ?? 'default'\n }\n\n return 'default'\n}\n\n/**\n * Resolves all route parameters from raw input values to their actual values.\n *\n * This function handles \"default\" placeholders by looking up actual values from the workspace store.\n * It ensures the modal can be opened even when the caller does not know specific paths, methods, or examples.\n */\nexport const resolveRouteParameters = (store: WorkspaceStore, params: DefaultEntities): Partial<RoutePayload> => {\n const documentSlug = resolveDocumentSlug(store, params.documentSlug)\n const ctx: ResolverContext = { store, documentSlug }\n const isWebhook = params.isWebhook ?? false\n\n const path = resolvePath(ctx, params.path, isWebhook)\n const method = resolveMethod(ctx, path, params.method, isWebhook)\n const routeType = isWebhook ? { isWebhook: true as const } : {}\n\n const traversedDocument = getDocument(ctx)?.['x-scalar-navigation']\n\n if (!traversedDocument) {\n return { documentSlug, path, method, example: 'default', ...routeType }\n }\n\n const operations = getOperationEntries(traversedDocument)\n const operation = operations\n .get(`${path}|${method}`)\n ?.find((entry) => entry.type === (isWebhook ? 'webhook' : 'operation'))\n const example = resolveExampleName(ctx, operation, params.example)\n\n return { documentSlug, path, method, example, ...routeType }\n}\n"],"mappings":";;;;;;AAmCA,IAAM,aAAa,UAAqD,MAAM,SAAS;;;;;;AAOvF,IAAM,eAAe,QAAyB;CAC5C,MAAM,MAAM,IAAI,MAAM,UAAU,UAAU,IAAI,gBAAgB;CAC9D,OAAO,kBAAkB,GAAG,IAAI,MAAM,KAAA;AACxC;;;;;;;;;;;;AAaA,IAAa,uBAAuB,OAAuB,SAAiD;CAG1G,IAF4B,SAAS,aAAa,MAAM,UAAU,UAAU,UAAU,KAAA,GAGpF,OAAO;CAKT,MAAM,aAAa,MAAM,UAAU;CACnC,IAAI,cAAc,kBAAkB,MAAM,UAAU,UAAU,WAAW,GACvE,OAAO;CAGT,OAAO,OAAO,QAAQ,MAAM,UAAU,SAAS,CAAC,CAAC,MAAM,GAAG,cAAc,kBAAkB,QAAQ,CAAC,CAAC,GAAG;AACzG;;;;;;;AAQA,IAAa,eAAe,KAAsB,MAA0B,YAAY,UAA8B;CACpH,MAAM,WAAW,YAAY,GAAG;CAEhC,IAAI,CAAC,UACH;CAGF,IAAI,SAAS,WACX,OAAO,OAAO,KAAK,YAAa,SAAS,YAAY,CAAC,IAAM,SAAS,SAAS,CAAC,CAAE,CAAC,CAAC;CAGrF,OAAO;AACT;;;;;;;AAQA,IAAa,iBACX,KACA,MACA,QACA,YAAY,UACe;CAC3B,MAAM,WAAW,YAAY,GAAG;CAEhC,IAAI,CAAC,YAAY,CAAC,MAChB;CAGF,IAAI,WAAW,WAAW;EACxB,MAAM,WAAW,oBAAoB,YAAY,SAAS,WAAW,QAAQ,SAAS,QAAQ,KAAK;EACnG,IAAI,CAAC,UACH;EAGF,OADoB,OAAO,KAAK,QAAQ,CAAC,CAAC,OAAO,YAC1C,CAAA,CAAY;CACrB;CAEA,OAAO,aAAa,MAAM,IAAI,SAAS,KAAA;AACzC;;;;;;;AAQA,IAAa,sBACX,KACA,WACA,eACW;CAGX,IAAI,CAFa,YAAY,GAExB,KAAY,WAAW,SAAS,aACnC,OAAO;CAGT,MAAM,WAAW,UAAU,UAAU,OAAO,SAAS,KAAK,CAAC;CAC3D,MAAM,kBAAkB,SAAS,MAAM,UAAU,MAAM,SAAS,UAAU;CAE1E,IAAI,iBACF,OAAO,gBAAgB;CAGzB,IAAI,eAAe,WACjB,OAAO,SAAS,EAAE,EAAE,QAAQ;CAG9B,OAAO;AACT;;;;;;;AAQA,IAAa,0BAA0B,OAAuB,WAAmD;CAC/G,MAAM,eAAe,oBAAoB,OAAO,OAAO,YAAY;CACnE,MAAM,MAAuB;EAAE;EAAO;CAAa;CACnD,MAAM,YAAY,OAAO,aAAa;CAEtC,MAAM,OAAO,YAAY,KAAK,OAAO,MAAM,SAAS;CACpD,MAAM,SAAS,cAAc,KAAK,MAAM,OAAO,QAAQ,SAAS;CAChE,MAAM,YAAY,YAAY,EAAE,WAAW,KAAc,IAAI,CAAC;CAE9D,MAAM,oBAAoB,YAAY,GAAG,CAAC,GAAG;CAE7C,IAAI,CAAC,mBACH,OAAO;EAAE;EAAc;EAAM;EAAQ,SAAS;EAAW,GAAG;CAAU;CAIxE,MAAM,YADa,oBAAoB,iBACrB,CAAA,CACf,IAAI,GAAG,KAAK,GAAG,QAAQ,CAAC,EACvB,MAAM,UAAU,MAAM,UAAU,YAAY,YAAY,YAAY;CAGxE,OAAO;EAAE;EAAc;EAAM;EAAQ,SAFrB,mBAAmB,KAAK,WAAW,OAAO,OAErB;EAAS,GAAG;CAAU;AAC7D"}
|
|
@@ -12,6 +12,7 @@ export type UseModalSidebarReturn = {
|
|
|
12
12
|
path?: string;
|
|
13
13
|
method?: HttpMethod;
|
|
14
14
|
example?: string;
|
|
15
|
+
isWebhook?: boolean;
|
|
15
16
|
}) => TraversedEntry | undefined;
|
|
16
17
|
};
|
|
17
18
|
/**
|
|
@@ -31,12 +32,13 @@ export type UseModalSidebarReturn = {
|
|
|
31
32
|
* exampleName,
|
|
32
33
|
* })
|
|
33
34
|
*/
|
|
34
|
-
export declare const useModalSidebar: ({ workspaceStore, documentSlug, path, method, exampleName, route, }: {
|
|
35
|
+
export declare const useModalSidebar: ({ workspaceStore, documentSlug, path, method, exampleName, isWebhook, route, }: {
|
|
35
36
|
workspaceStore: WorkspaceStore | null;
|
|
36
37
|
documentSlug: ComputedRef<string | undefined>;
|
|
37
38
|
path: ComputedRef<string | undefined>;
|
|
38
39
|
method: ComputedRef<HttpMethod | undefined>;
|
|
39
40
|
exampleName: ComputedRef<string | undefined>;
|
|
41
|
+
isWebhook?: ComputedRef<boolean>;
|
|
40
42
|
route: (payload: RoutePayload) => void;
|
|
41
43
|
}) => UseModalSidebarReturn;
|
|
42
44
|
//# sourceMappingURL=use-modal-sidebar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-modal-sidebar.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/modal/hooks/use-modal-sidebar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAuC,MAAM,iBAAiB,CAAA;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAEpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAA;AAEhF,OAAO,EAAE,KAAK,WAAW,EAA4B,MAAM,KAAK,CAAA;AAEhE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sDAAsD,CAAA;AAGxF,MAAM,MAAM,qBAAqB,GAAG;IAClC,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,KAAK,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,cAAc,CAAC,CAAC,CAAA;IAC5D,kBAAkB,EAAE,CAAC,QAAQ,EAAE;QAC7B,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,MAAM,CAAC,EAAE,UAAU,CAAA;QACnB,OAAO,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"use-modal-sidebar.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/modal/hooks/use-modal-sidebar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,EAAE,kBAAkB,EAAuC,MAAM,iBAAiB,CAAA;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAEpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAA;AAEhF,OAAO,EAAE,KAAK,WAAW,EAA4B,MAAM,KAAK,CAAA;AAEhE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sDAAsD,CAAA;AAGxF,MAAM,MAAM,qBAAqB,GAAG;IAClC,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,KAAK,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,cAAc,CAAC,CAAC,CAAA;IAC5D,kBAAkB,EAAE,CAAC,QAAQ,EAAE;QAC7B,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,MAAM,CAAC,EAAE,UAAU,CAAA;QACnB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,SAAS,CAAC,EAAE,OAAO,CAAA;KACpB,KAAK,cAAc,GAAG,SAAS,CAAA;CACjC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,eAAe,GAAI,gFAQ7B;IACD,cAAc,EAAE,cAAc,GAAG,IAAI,CAAA;IACrC,YAAY,EAAE,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAC7C,IAAI,EAAE,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IACrC,MAAM,EAAE,WAAW,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;IAC3C,WAAW,EAAE,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAC5C,SAAS,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IAChC,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAA;CACvC,KAAG,qBAiLH,CAAA"}
|
|
@@ -21,7 +21,8 @@ import { getParentEntry } from "@scalar/workspace-store/navigation";
|
|
|
21
21
|
* exampleName,
|
|
22
22
|
* })
|
|
23
23
|
*/
|
|
24
|
-
var useModalSidebar = ({ workspaceStore, documentSlug, path, method, exampleName, route }) => {
|
|
24
|
+
var useModalSidebar = ({ workspaceStore, documentSlug, path, method, exampleName, isWebhook, route }) => {
|
|
25
|
+
const activeIsWebhook = isWebhook ?? computed(() => false);
|
|
25
26
|
const entries = computed(() => {
|
|
26
27
|
const doc = workspaceStore?.workspace.documents[toValue(documentSlug) ?? ""];
|
|
27
28
|
return isOpenApiDocument(doc) ? doc["x-scalar-navigation"]?.children ?? [] : [];
|
|
@@ -37,8 +38,14 @@ var useModalSidebar = ({ workspaceStore, documentSlug, path, method, exampleName
|
|
|
37
38
|
const locationIndex = computed(() => generateReverseIndex({
|
|
38
39
|
items: entries.value,
|
|
39
40
|
nestedKey: "children",
|
|
40
|
-
filter: (node) => node.type === "operation" || node.type === "example",
|
|
41
|
+
filter: (node) => node.type === "operation" || node.type === "example" || node.type === "webhook",
|
|
41
42
|
getId: (node) => {
|
|
43
|
+
if (node.type === "webhook") return generateLocationId({
|
|
44
|
+
document: toValue(documentSlug) ?? "",
|
|
45
|
+
path: node.name,
|
|
46
|
+
method: node.method,
|
|
47
|
+
isWebhook: true
|
|
48
|
+
});
|
|
42
49
|
const operation = getParentEntry("operation", node);
|
|
43
50
|
return generateLocationId({
|
|
44
51
|
document: toValue(documentSlug) ?? "",
|
|
@@ -70,13 +77,15 @@ var useModalSidebar = ({ workspaceStore, documentSlug, path, method, exampleName
|
|
|
70
77
|
document: location.document,
|
|
71
78
|
path: location.path,
|
|
72
79
|
method: location.method,
|
|
73
|
-
example: location.example
|
|
80
|
+
example: location.example,
|
|
81
|
+
isWebhook: location.isWebhook
|
|
74
82
|
}));
|
|
75
83
|
if (entryWithExample) return entryWithExample;
|
|
76
84
|
return locationIndex.value.get(generateLocationId({
|
|
77
85
|
document: location.document,
|
|
78
86
|
path: location.path,
|
|
79
|
-
method: location.method
|
|
87
|
+
method: location.method,
|
|
88
|
+
isWebhook: location.isWebhook
|
|
80
89
|
}));
|
|
81
90
|
};
|
|
82
91
|
/**
|
|
@@ -110,6 +119,16 @@ var useModalSidebar = ({ workspaceStore, documentSlug, path, method, exampleName
|
|
|
110
119
|
example: example?.name ?? "default"
|
|
111
120
|
});
|
|
112
121
|
}
|
|
122
|
+
if (entry.type === "webhook") {
|
|
123
|
+
state.setSelected(id);
|
|
124
|
+
return route({
|
|
125
|
+
documentSlug: toValue(documentSlug),
|
|
126
|
+
path: entry.name,
|
|
127
|
+
method: entry.method,
|
|
128
|
+
example: "default",
|
|
129
|
+
isWebhook: true
|
|
130
|
+
});
|
|
131
|
+
}
|
|
113
132
|
state.setExpanded(id, !state.isExpanded(id));
|
|
114
133
|
};
|
|
115
134
|
/** Keep the sidebar state in sync with the modal parameters */
|
|
@@ -117,8 +136,9 @@ var useModalSidebar = ({ workspaceStore, documentSlug, path, method, exampleName
|
|
|
117
136
|
documentSlug,
|
|
118
137
|
path,
|
|
119
138
|
method,
|
|
120
|
-
exampleName
|
|
121
|
-
|
|
139
|
+
exampleName,
|
|
140
|
+
activeIsWebhook
|
|
141
|
+
], ([newDocument, newPath, newMethod, newExample, newIsWebhook]) => {
|
|
122
142
|
if (!newDocument) {
|
|
123
143
|
state.setSelected(null);
|
|
124
144
|
return;
|
|
@@ -127,7 +147,8 @@ var useModalSidebar = ({ workspaceStore, documentSlug, path, method, exampleName
|
|
|
127
147
|
document: newDocument,
|
|
128
148
|
path: newPath,
|
|
129
149
|
method: newMethod,
|
|
130
|
-
example: newExample
|
|
150
|
+
example: newExample,
|
|
151
|
+
isWebhook: newIsWebhook
|
|
131
152
|
});
|
|
132
153
|
if (entry) {
|
|
133
154
|
state.setSelected(entry.id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-modal-sidebar.js","names":[],"sources":["../../../../../src/v2/features/modal/hooks/use-modal-sidebar.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { createSidebarState, generateReverseIndex, getChildEntry } from '@scalar/sidebar'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\nimport { isOpenApiDocument } from '@scalar/workspace-store/schemas/type-guards'\nimport { type ComputedRef, computed, toValue, watch } from 'vue'\n\nimport type { RoutePayload } from '@/v2/features/modal/helpers/resolve-route-parameters'\nimport { generateLocationId } from '@/v2/helpers/generate-location-id'\n\nexport type UseModalSidebarReturn = {\n handleSelectItem: (id: string) => void\n state: ReturnType<typeof createSidebarState<TraversedEntry>>\n getEntryByLocation: (location: {\n document: string\n path?: string\n method?: HttpMethod\n example?: string\n }) => TraversedEntry | undefined\n}\n\n/**\n * useSidebarState - Custom hook to manage the sidebar state and navigation logic in the Scalar API client\n *\n * This composable manages the sidebar structure, synchronizes selection state\n * with the current route, and provides a handler for selecting sidebar items.\n *\n * Example usage:\n *\n * const { handleSelectItem, sidebarState } = useSidebarState({\n * workspaceStore,\n * workspaceSlug,\n * documentSlug,\n * path,\n * method,\n * exampleName,\n * })\n */\nexport const useModalSidebar = ({\n workspaceStore,\n documentSlug,\n path,\n method,\n exampleName,\n route,\n}: {\n workspaceStore: WorkspaceStore | null\n documentSlug: ComputedRef<string | undefined>\n path: ComputedRef<string | undefined>\n method: ComputedRef<HttpMethod | undefined>\n exampleName: ComputedRef<string | undefined>\n route: (payload: RoutePayload) => void\n}): UseModalSidebarReturn => {\n const entries = computed<TraversedEntry[]>(() => {\n const doc = workspaceStore?.workspace.documents[toValue(documentSlug) ?? '']\n return isOpenApiDocument(doc) ? (doc['x-scalar-navigation']?.children ?? []) : []\n })\n const state = createSidebarState(entries)\n\n /**\n * Computed index for fast lookup of sidebar nodes by their unique API location.\n *\n * - Only indexes nodes of type 'operation', or 'example'.\n * - The lookup key is a serialized array of: [operationPath, operationMethod, exampleName?].\n * - Supports precise resolution of sidebar entries given an API \"location\".\n */\n const locationIndex = computed(() =>\n generateReverseIndex({\n items: entries.value,\n nestedKey: 'children',\n filter: (node) => node.type === 'operation' || node.type === 'example',\n getId: (node) => {\n const operation = getParentEntry('operation', node)\n return generateLocationId({\n document: toValue(documentSlug) ?? '',\n path: operation?.path,\n method: operation?.method,\n example: node.type === 'example' ? node.name : undefined,\n })\n },\n }),\n )\n\n /**\n * Looks up a sidebar entry by its unique API location.\n * - First tries to find an entry matching all provided properties (including example).\n * - If not found, falls back to matching only the operation (ignores example field).\n * This allows resolving either examples, operations, or documents as appropriate.\n *\n * @param location - Object specifying the document name, path, method, and optional example name.\n * @returns The matching sidebar entry, or undefined if none found.\n *\n * Example:\n * const entry = getEntryByLocation({\n * document: 'pets',\n * path: '/pets',\n * method: 'get',\n * example: 'default',\n * })\n */\n const getEntryByLocation: UseModalSidebarReturn['getEntryByLocation'] = (location) => {\n // Try to find an entry with the most-specific location (including example)\n const entryWithExample = locationIndex.value.get(\n generateLocationId({\n document: location.document,\n path: location.path,\n method: location.method,\n example: location.example,\n }),\n )\n\n if (entryWithExample) {\n return entryWithExample\n }\n\n // Fallback to the operation (ignoring example) if an example wasn't found or specified\n return locationIndex.value.get(\n generateLocationId({\n document: location.document,\n path: location.path,\n method: location.method,\n }),\n )\n }\n\n /**\n * Handles item selection from the sidebar and routes navigation accordingly.\n *\n * Example:\n * handleSelectItem('id-of-entry')\n */\n const handleSelectItem = (id: string) => {\n const entry = state.getEntryById(id)\n\n if (!entry) {\n console.warn(`Could not find sidebar entry with id ${id} to select`)\n return\n }\n\n // Navigate to the example page\n if (entry.type === 'operation' || entry.type === 'example') {\n // If we are already in the operation, just toggle expansion\n if (state.isSelected(id)) {\n state.setExpanded(id, !state.isExpanded(id))\n return\n }\n\n const operation = getParentEntry('operation', entry)\n const example = getChildEntry('example', entry)\n\n if (example) {\n state.setSelected(example.id)\n state.setExpanded(example.id, true)\n } else {\n state.setSelected(id)\n }\n\n if (!operation) {\n return\n }\n\n return route({\n documentSlug: toValue(documentSlug),\n path: operation.path,\n method: operation.method,\n example: example?.name ?? 'default',\n })\n }\n\n state.setExpanded(id, !state.isExpanded(id))\n return\n }\n\n /** Keep the sidebar state in sync with the modal parameters */\n watch(\n [documentSlug, path, method, exampleName],\n ([newDocument, newPath, newMethod, newExample]) => {\n if (!newDocument) {\n // Reset selection if no document is selected\n state.setSelected(null)\n return\n }\n\n const entry = getEntryByLocation({\n document: newDocument,\n path: newPath,\n method: newMethod,\n example: newExample,\n })\n\n if (entry) {\n state.setSelected(entry.id)\n state.setExpanded(entry.id, true)\n }\n },\n {\n immediate: true,\n },\n )\n\n return {\n handleSelectItem,\n state,\n getEntryByLocation,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"use-modal-sidebar.js","names":[],"sources":["../../../../../src/v2/features/modal/hooks/use-modal-sidebar.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { createSidebarState, generateReverseIndex, getChildEntry } from '@scalar/sidebar'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\nimport { isOpenApiDocument } from '@scalar/workspace-store/schemas/type-guards'\nimport { type ComputedRef, computed, toValue, watch } from 'vue'\n\nimport type { RoutePayload } from '@/v2/features/modal/helpers/resolve-route-parameters'\nimport { generateLocationId } from '@/v2/helpers/generate-location-id'\n\nexport type UseModalSidebarReturn = {\n handleSelectItem: (id: string) => void\n state: ReturnType<typeof createSidebarState<TraversedEntry>>\n getEntryByLocation: (location: {\n document: string\n path?: string\n method?: HttpMethod\n example?: string\n isWebhook?: boolean\n }) => TraversedEntry | undefined\n}\n\n/**\n * useSidebarState - Custom hook to manage the sidebar state and navigation logic in the Scalar API client\n *\n * This composable manages the sidebar structure, synchronizes selection state\n * with the current route, and provides a handler for selecting sidebar items.\n *\n * Example usage:\n *\n * const { handleSelectItem, sidebarState } = useSidebarState({\n * workspaceStore,\n * workspaceSlug,\n * documentSlug,\n * path,\n * method,\n * exampleName,\n * })\n */\nexport const useModalSidebar = ({\n workspaceStore,\n documentSlug,\n path,\n method,\n exampleName,\n isWebhook,\n route,\n}: {\n workspaceStore: WorkspaceStore | null\n documentSlug: ComputedRef<string | undefined>\n path: ComputedRef<string | undefined>\n method: ComputedRef<HttpMethod | undefined>\n exampleName: ComputedRef<string | undefined>\n isWebhook?: ComputedRef<boolean>\n route: (payload: RoutePayload) => void\n}): UseModalSidebarReturn => {\n const activeIsWebhook = isWebhook ?? computed(() => false)\n const entries = computed<TraversedEntry[]>(() => {\n const doc = workspaceStore?.workspace.documents[toValue(documentSlug) ?? '']\n return isOpenApiDocument(doc) ? (doc['x-scalar-navigation']?.children ?? []) : []\n })\n const state = createSidebarState(entries)\n\n /**\n * Computed index for fast lookup of sidebar nodes by their unique API location.\n *\n * - Only indexes nodes of type 'operation', or 'example'.\n * - The lookup key is a serialized array of: [operationPath, operationMethod, exampleName?].\n * - Supports precise resolution of sidebar entries given an API \"location\".\n */\n const locationIndex = computed(() =>\n generateReverseIndex({\n items: entries.value,\n nestedKey: 'children',\n filter: (node) => node.type === 'operation' || node.type === 'example' || node.type === 'webhook',\n getId: (node) => {\n if (node.type === 'webhook') {\n return generateLocationId({\n document: toValue(documentSlug) ?? '',\n path: node.name,\n method: node.method,\n isWebhook: true,\n })\n }\n\n const operation = getParentEntry('operation', node)\n return generateLocationId({\n document: toValue(documentSlug) ?? '',\n path: operation?.path,\n method: operation?.method,\n example: node.type === 'example' ? node.name : undefined,\n })\n },\n }),\n )\n\n /**\n * Looks up a sidebar entry by its unique API location.\n * - First tries to find an entry matching all provided properties (including example).\n * - If not found, falls back to matching only the operation (ignores example field).\n * This allows resolving either examples, operations, or documents as appropriate.\n *\n * @param location - Object specifying the document name, path, method, and optional example name.\n * @returns The matching sidebar entry, or undefined if none found.\n *\n * Example:\n * const entry = getEntryByLocation({\n * document: 'pets',\n * path: '/pets',\n * method: 'get',\n * example: 'default',\n * })\n */\n const getEntryByLocation: UseModalSidebarReturn['getEntryByLocation'] = (location) => {\n // Try to find an entry with the most-specific location (including example)\n const entryWithExample = locationIndex.value.get(\n generateLocationId({\n document: location.document,\n path: location.path,\n method: location.method,\n example: location.example,\n isWebhook: location.isWebhook,\n }),\n )\n\n if (entryWithExample) {\n return entryWithExample\n }\n\n // Fallback to the operation (ignoring example) if an example wasn't found or specified\n return locationIndex.value.get(\n generateLocationId({\n document: location.document,\n path: location.path,\n method: location.method,\n isWebhook: location.isWebhook,\n }),\n )\n }\n\n /**\n * Handles item selection from the sidebar and routes navigation accordingly.\n *\n * Example:\n * handleSelectItem('id-of-entry')\n */\n const handleSelectItem = (id: string) => {\n const entry = state.getEntryById(id)\n\n if (!entry) {\n console.warn(`Could not find sidebar entry with id ${id} to select`)\n return\n }\n\n // Navigate to the example page\n if (entry.type === 'operation' || entry.type === 'example') {\n // If we are already in the operation, just toggle expansion\n if (state.isSelected(id)) {\n state.setExpanded(id, !state.isExpanded(id))\n return\n }\n\n const operation = getParentEntry('operation', entry)\n const example = getChildEntry('example', entry)\n\n if (example) {\n state.setSelected(example.id)\n state.setExpanded(example.id, true)\n } else {\n state.setSelected(id)\n }\n\n if (!operation) {\n return\n }\n\n return route({\n documentSlug: toValue(documentSlug),\n path: operation.path,\n method: operation.method,\n example: example?.name ?? 'default',\n })\n }\n\n if (entry.type === 'webhook') {\n state.setSelected(id)\n return route({\n documentSlug: toValue(documentSlug),\n path: entry.name,\n method: entry.method,\n example: 'default',\n isWebhook: true,\n })\n }\n\n state.setExpanded(id, !state.isExpanded(id))\n return\n }\n\n /** Keep the sidebar state in sync with the modal parameters */\n watch(\n [documentSlug, path, method, exampleName, activeIsWebhook],\n ([newDocument, newPath, newMethod, newExample, newIsWebhook]) => {\n if (!newDocument) {\n // Reset selection if no document is selected\n state.setSelected(null)\n return\n }\n\n const entry = getEntryByLocation({\n document: newDocument,\n path: newPath,\n method: newMethod,\n example: newExample,\n isWebhook: newIsWebhook,\n })\n\n if (entry) {\n state.setSelected(entry.id)\n state.setExpanded(entry.id, true)\n }\n },\n {\n immediate: true,\n },\n )\n\n return {\n handleSelectItem,\n state,\n getEntryByLocation,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAwCA,IAAa,mBAAmB,EAC9B,gBACA,cACA,MACA,QACA,aACA,WACA,YAS2B;CAC3B,MAAM,kBAAkB,aAAa,eAAe,KAAK;CACzD,MAAM,UAAU,eAAiC;EAC/C,MAAM,MAAM,gBAAgB,UAAU,UAAU,QAAQ,YAAY,KAAK;EACzE,OAAO,kBAAkB,GAAG,IAAK,IAAI,sBAAsB,EAAE,YAAY,CAAC,IAAK,CAAC;CAClF,CAAC;CACD,MAAM,QAAQ,mBAAmB,OAAO;;;;;;;;CASxC,MAAM,gBAAgB,eACpB,qBAAqB;EACnB,OAAO,QAAQ;EACf,WAAW;EACX,SAAS,SAAS,KAAK,SAAS,eAAe,KAAK,SAAS,aAAa,KAAK,SAAS;EACxF,QAAQ,SAAS;GACf,IAAI,KAAK,SAAS,WAChB,OAAO,mBAAmB;IACxB,UAAU,QAAQ,YAAY,KAAK;IACnC,MAAM,KAAK;IACX,QAAQ,KAAK;IACb,WAAW;GACb,CAAC;GAGH,MAAM,YAAY,eAAe,aAAa,IAAI;GAClD,OAAO,mBAAmB;IACxB,UAAU,QAAQ,YAAY,KAAK;IACnC,MAAM,WAAW;IACjB,QAAQ,WAAW;IACnB,SAAS,KAAK,SAAS,YAAY,KAAK,OAAO,KAAA;GACjD,CAAC;EACH;CACF,CAAC,CACH;;;;;;;;;;;;;;;;;;CAmBA,MAAM,sBAAmE,aAAa;EAEpF,MAAM,mBAAmB,cAAc,MAAM,IAC3C,mBAAmB;GACjB,UAAU,SAAS;GACnB,MAAM,SAAS;GACf,QAAQ,SAAS;GACjB,SAAS,SAAS;GAClB,WAAW,SAAS;EACtB,CAAC,CACH;EAEA,IAAI,kBACF,OAAO;EAIT,OAAO,cAAc,MAAM,IACzB,mBAAmB;GACjB,UAAU,SAAS;GACnB,MAAM,SAAS;GACf,QAAQ,SAAS;GACjB,WAAW,SAAS;EACtB,CAAC,CACH;CACF;;;;;;;CAQA,MAAM,oBAAoB,OAAe;EACvC,MAAM,QAAQ,MAAM,aAAa,EAAE;EAEnC,IAAI,CAAC,OAAO;GACV,QAAQ,KAAK,wCAAwC,GAAG,WAAW;GACnE;EACF;EAGA,IAAI,MAAM,SAAS,eAAe,MAAM,SAAS,WAAW;GAE1D,IAAI,MAAM,WAAW,EAAE,GAAG;IACxB,MAAM,YAAY,IAAI,CAAC,MAAM,WAAW,EAAE,CAAC;IAC3C;GACF;GAEA,MAAM,YAAY,eAAe,aAAa,KAAK;GACnD,MAAM,UAAU,cAAc,WAAW,KAAK;GAE9C,IAAI,SAAS;IACX,MAAM,YAAY,QAAQ,EAAE;IAC5B,MAAM,YAAY,QAAQ,IAAI,IAAI;GACpC,OACE,MAAM,YAAY,EAAE;GAGtB,IAAI,CAAC,WACH;GAGF,OAAO,MAAM;IACX,cAAc,QAAQ,YAAY;IAClC,MAAM,UAAU;IAChB,QAAQ,UAAU;IAClB,SAAS,SAAS,QAAQ;GAC5B,CAAC;EACH;EAEA,IAAI,MAAM,SAAS,WAAW;GAC5B,MAAM,YAAY,EAAE;GACpB,OAAO,MAAM;IACX,cAAc,QAAQ,YAAY;IAClC,MAAM,MAAM;IACZ,QAAQ,MAAM;IACd,SAAS;IACT,WAAW;GACb,CAAC;EACH;EAEA,MAAM,YAAY,IAAI,CAAC,MAAM,WAAW,EAAE,CAAC;CAE7C;;CAGA,MACE;EAAC;EAAc;EAAM;EAAQ;EAAa;CAAe,IACxD,CAAC,aAAa,SAAS,WAAW,YAAY,kBAAkB;EAC/D,IAAI,CAAC,aAAa;GAEhB,MAAM,YAAY,IAAI;GACtB;EACF;EAEA,MAAM,QAAQ,mBAAmB;GAC/B,UAAU;GACV,MAAM;GACN,QAAQ;GACR,SAAS;GACT,WAAW;EACb,CAAC;EAED,IAAI,OAAO;GACT,MAAM,YAAY,MAAM,EAAE;GAC1B,MAAM,YAAY,MAAM,IAAI,IAAI;EAClC;CACF,GACA,EACE,WAAW,KACb,CACF;CAEA,OAAO;EACL;EACA;EACA;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-events.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/modal/modal-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAGvE,OAAO,EAAE,KAAK,GAAG,EAAO,MAAM,KAAK,CAAA;AAEnC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAA;
|
|
1
|
+
{"version":3,"file":"modal-events.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/modal/modal-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAGvE,OAAO,EAAE,KAAK,GAAG,EAAO,MAAM,KAAK,CAAA;AAEnC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAA;AAOxF,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,aAAa,EACb,+BAA+B,EAC/B,YAAY,EACZ,UAAU,EACV,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAC3B,+BAA+B,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC5D,YAAY,EAAE,qBAAqB,CAAA;IACnC,UAAU,EAAE,UAAU,CAAA;IACtB,KAAK,EAAE,cAAc,CAAA;CACtB,QAkFA"}
|
|
@@ -2,7 +2,7 @@ import { initializeWorkspaceEventHandlers } from "../../workspace-events.js";
|
|
|
2
2
|
import { ref } from "vue";
|
|
3
3
|
import { isOpenApiDocument } from "@scalar/workspace-store/schemas/type-guards";
|
|
4
4
|
//#region src/v2/features/modal/modal-events.ts
|
|
5
|
-
var EMPTY_REQUEST_BODY_COMPOSITION_SELECTION = {};
|
|
5
|
+
var EMPTY_REQUEST_BODY_COMPOSITION_SELECTION = Object.freeze({});
|
|
6
6
|
function initializeModalEvents({ eventBus, isSidebarOpen, requestBodyCompositionSelection, sidebarState, modalState, store }) {
|
|
7
7
|
/** Initialize workspace event handlers */
|
|
8
8
|
initializeWorkspaceEventHandlers({
|
|
@@ -14,11 +14,13 @@ function initializeModalEvents({ eventBus, isSidebarOpen, requestBodyComposition
|
|
|
14
14
|
eventBus.on("ui:toggle:sidebar", () => isSidebarOpen.value = !isSidebarOpen.value);
|
|
15
15
|
eventBus.on("ui:close:client-modal", () => modalState.hide());
|
|
16
16
|
eventBus.on("ui:open:client-modal", (payload) => {
|
|
17
|
-
|
|
17
|
+
const nextRequestBodyCompositionSelection = payload && "requestBodyCompositionSelection" in payload && payload.requestBodyCompositionSelection ? payload.requestBodyCompositionSelection : EMPTY_REQUEST_BODY_COMPOSITION_SELECTION;
|
|
18
18
|
if (!payload) {
|
|
19
|
+
requestBodyCompositionSelection.value = nextRequestBodyCompositionSelection;
|
|
19
20
|
modalState.show();
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
23
|
+
const previousSelectedId = sidebarState.state.selectedItem.value;
|
|
22
24
|
if ("id" in payload && payload.id) {
|
|
23
25
|
let targetId = payload.id;
|
|
24
26
|
if ("exampleName" in payload && payload.exampleName) {
|
|
@@ -38,6 +40,7 @@ function initializeModalEvents({ eventBus, isSidebarOpen, requestBodyComposition
|
|
|
38
40
|
example: payload.exampleName
|
|
39
41
|
})?.id ?? "");
|
|
40
42
|
}
|
|
43
|
+
if (!(modalState.open && sidebarState.state.selectedItem.value === previousSelectedId)) requestBodyCompositionSelection.value = nextRequestBodyCompositionSelection;
|
|
41
44
|
modalState.show();
|
|
42
45
|
});
|
|
43
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-events.js","names":[],"sources":["../../../../src/v2/features/modal/modal-events.ts"],"sourcesContent":["import type { ModalState } from '@scalar/components/modal'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\nimport { isOpenApiDocument } from '@scalar/workspace-store/schemas/type-guards'\nimport { type Ref, ref } from 'vue'\n\nimport type { UseModalSidebarReturn } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport { initializeWorkspaceEventHandlers } from '@/v2/workspace-events'\n\nconst EMPTY_REQUEST_BODY_COMPOSITION_SELECTION = {} as Record<string, number>\n\nexport function initializeModalEvents({\n eventBus,\n isSidebarOpen,\n requestBodyCompositionSelection,\n sidebarState,\n modalState,\n store,\n}: {\n eventBus: WorkspaceEventBus\n isSidebarOpen: Ref<boolean>\n requestBodyCompositionSelection: Ref<Record<string, number>>\n sidebarState: UseModalSidebarReturn\n modalState: ModalState\n store: WorkspaceStore\n}) {\n /** Initialize workspace event handlers */\n initializeWorkspaceEventHandlers({\n eventBus,\n store: ref(store),\n hooks: {},\n })\n\n //------------------------------------------------------------------------------------\n // Navigation Event Handlers\n //------------------------------------------------------------------------------------\n eventBus.on('scroll-to:nav-item', ({ id }) => sidebarState.handleSelectItem(id))\n\n //------------------------------------------------------------------------------------\n // UI Related Event Handlers\n //------------------------------------------------------------------------------------\n eventBus.on('ui:toggle:sidebar', () => (isSidebarOpen.value = !isSidebarOpen.value))\n eventBus.on('ui:close:client-modal', () => modalState.hide())\n eventBus.on('ui:open:client-modal', (payload) => {\n const nextRequestBodyCompositionSelection = (\n payload && 'requestBodyCompositionSelection' in payload && payload.requestBodyCompositionSelection\n ? payload.requestBodyCompositionSelection\n : EMPTY_REQUEST_BODY_COMPOSITION_SELECTION\n ) as Record<string, number>\n\n
|
|
1
|
+
{"version":3,"file":"modal-events.js","names":[],"sources":["../../../../src/v2/features/modal/modal-events.ts"],"sourcesContent":["import type { ModalState } from '@scalar/components/modal'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\nimport { isOpenApiDocument } from '@scalar/workspace-store/schemas/type-guards'\nimport { type Ref, ref } from 'vue'\n\nimport type { UseModalSidebarReturn } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport { initializeWorkspaceEventHandlers } from '@/v2/workspace-events'\n\n// Frozen so this shared fallback cannot be mutated in place, which would leak a stale selection into\n// every future open that falls back to empty. Callers only ever reassign the ref, never mutate it.\nconst EMPTY_REQUEST_BODY_COMPOSITION_SELECTION = Object.freeze({}) as Record<string, number>\n\nexport function initializeModalEvents({\n eventBus,\n isSidebarOpen,\n requestBodyCompositionSelection,\n sidebarState,\n modalState,\n store,\n}: {\n eventBus: WorkspaceEventBus\n isSidebarOpen: Ref<boolean>\n requestBodyCompositionSelection: Ref<Record<string, number>>\n sidebarState: UseModalSidebarReturn\n modalState: ModalState\n store: WorkspaceStore\n}) {\n /** Initialize workspace event handlers */\n initializeWorkspaceEventHandlers({\n eventBus,\n store: ref(store),\n hooks: {},\n })\n\n //------------------------------------------------------------------------------------\n // Navigation Event Handlers\n //------------------------------------------------------------------------------------\n eventBus.on('scroll-to:nav-item', ({ id }) => sidebarState.handleSelectItem(id))\n\n //------------------------------------------------------------------------------------\n // UI Related Event Handlers\n //------------------------------------------------------------------------------------\n eventBus.on('ui:toggle:sidebar', () => (isSidebarOpen.value = !isSidebarOpen.value))\n eventBus.on('ui:close:client-modal', () => modalState.hide())\n eventBus.on('ui:open:client-modal', (payload) => {\n // Every open re-establishes the selection (falling back to empty), so the modal no longer needs\n // to reset it on close.\n const nextRequestBodyCompositionSelection = (\n payload && 'requestBodyCompositionSelection' in payload && payload.requestBodyCompositionSelection\n ? payload.requestBodyCompositionSelection\n : EMPTY_REQUEST_BODY_COMPOSITION_SELECTION\n ) as Record<string, number>\n\n // Just open the modal\n if (!payload) {\n requestBodyCompositionSelection.value = nextRequestBodyCompositionSelection\n modalState.show()\n return\n }\n\n const previousSelectedId = sidebarState.state.selectedItem.value\n\n // We route to the exact ID\n if ('id' in payload && payload.id) {\n let targetId = payload.id\n\n // If exampleName is provided, try to find the specific example entry\n if ('exampleName' in payload && payload.exampleName) {\n const operationEntry = sidebarState.state.getEntryById(payload.id)\n\n // Try to find the specific example in the operation's children\n if (operationEntry && 'children' in operationEntry && operationEntry.children) {\n const exampleEntry = operationEntry.children.find(\n (child: TraversedEntry) => child.type === 'example' && child.name === payload.exampleName,\n )\n if (exampleEntry) {\n targetId = exampleEntry.id\n }\n }\n }\n\n sidebarState.handleSelectItem(targetId)\n }\n // We must find the ID first from the entries\n else if ('method' in payload && 'path' in payload) {\n const activeDoc = store.workspace.activeDocument\n sidebarState.handleSelectItem(\n sidebarState.getEntryByLocation({\n document: isOpenApiDocument(activeDoc) ? (activeDoc['x-scalar-navigation']?.id ?? '') : '',\n path: payload.path,\n method: payload.method,\n example: payload.exampleName,\n })?.id ?? '',\n )\n }\n\n // Apply the selection after routing so the request body compares it with the selection used\n // for this operation, rather than briefly resetting the operation that was previously open.\n // Reopening the entry already on screen routes nowhere, so a new selection would read as a\n // manual branch switch and discard the edited body.\n const isReopeningVisibleEntry = modalState.open && sidebarState.state.selectedItem.value === previousSelectedId\n\n if (!isReopeningVisibleEntry) {\n requestBodyCompositionSelection.value = nextRequestBodyCompositionSelection\n }\n\n modalState.show()\n })\n}\n"],"mappings":";;;;AAYA,IAAM,2CAA2C,OAAO,OAAO,CAAC,CAAC;AAEjE,SAAgB,sBAAsB,EACpC,UACA,eACA,iCACA,cACA,YACA,SAQC;;CAED,iCAAiC;EAC/B;EACA,OAAO,IAAI,KAAK;EAChB,OAAO,CAAC;CACV,CAAC;CAKD,SAAS,GAAG,uBAAuB,EAAE,SAAS,aAAa,iBAAiB,EAAE,CAAC;CAK/E,SAAS,GAAG,2BAA4B,cAAc,QAAQ,CAAC,cAAc,KAAM;CACnF,SAAS,GAAG,+BAA+B,WAAW,KAAK,CAAC;CAC5D,SAAS,GAAG,yBAAyB,YAAY;EAG/C,MAAM,sCACJ,WAAW,qCAAqC,WAAW,QAAQ,kCAC/D,QAAQ,kCACR;EAIN,IAAI,CAAC,SAAS;GACZ,gCAAgC,QAAQ;GACxC,WAAW,KAAK;GAChB;EACF;EAEA,MAAM,qBAAqB,aAAa,MAAM,aAAa;EAG3D,IAAI,QAAQ,WAAW,QAAQ,IAAI;GACjC,IAAI,WAAW,QAAQ;GAGvB,IAAI,iBAAiB,WAAW,QAAQ,aAAa;IACnD,MAAM,iBAAiB,aAAa,MAAM,aAAa,QAAQ,EAAE;IAGjE,IAAI,kBAAkB,cAAc,kBAAkB,eAAe,UAAU;KAC7E,MAAM,eAAe,eAAe,SAAS,MAC1C,UAA0B,MAAM,SAAS,aAAa,MAAM,SAAS,QAAQ,WAChF;KACA,IAAI,cACF,WAAW,aAAa;IAE5B;GACF;GAEA,aAAa,iBAAiB,QAAQ;EACxC,OAEK,IAAI,YAAY,WAAW,UAAU,SAAS;GACjD,MAAM,YAAY,MAAM,UAAU;GAClC,aAAa,iBACX,aAAa,mBAAmB;IAC9B,UAAU,kBAAkB,SAAS,IAAK,UAAU,sBAAsB,EAAE,MAAM,KAAM;IACxF,MAAM,QAAQ;IACd,QAAQ,QAAQ;IAChB,SAAS,QAAQ;GACnB,CAAC,CAAC,EAAE,MAAM,EACZ;EACF;EAQA,IAAI,EAF4B,WAAW,QAAQ,aAAa,MAAM,aAAa,UAAU,qBAG3F,gCAAgC,QAAQ;EAG1C,WAAW,KAAK;CAClB,CAAC;AACH"}
|
|
@@ -32,6 +32,8 @@ export type OperationProps = {
|
|
|
32
32
|
method?: HttpMethod;
|
|
33
33
|
/** The name of the currently selected example (for examples within an endpoint) */
|
|
34
34
|
exampleName?: string;
|
|
35
|
+
/** Resolve the selected entry from the OpenAPI webhooks map. */
|
|
36
|
+
isWebhook?: boolean;
|
|
35
37
|
/** The currently active environment */
|
|
36
38
|
environment: XScalarEnvironment;
|
|
37
39
|
/** The workspace store */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Operation.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/operation/Operation.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Operation.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/operation/Operation.vue"],"names":[],"mappings":"AA8NA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAKvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AACnH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AACnG,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,KAAK,CAAA;AAK9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAG1D;;;;;;;GAOG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAIzC,MAAM,MAAM,cAAc,GAAG;IAC3B,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAA;IACpB,4FAA4F;IAC5F,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAA;IAChC,8BAA8B;IAC9B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,+BAA+B;IAC/B,MAAM,EAAE,YAAY,CAAA;IACpB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2EAA2E;IAC3E,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,uCAAuC;IACvC,WAAW,EAAE,kBAAkB,CAAA;IAC/B,0BAA0B;IAC1B,cAAc,EAAE,cAAc,CAAA;IAC9B,qBAAqB;IACrB,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;CAC7C,CAAA;AACD,QAAA,MAAM,YAAY;IAEd,sEAAsE;sCACpC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;IADxD,sEAAsE;sCACpC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;iGA8PxD,CAAC"}
|