@scalar/api-client 2.41.0 → 2.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/hooks/useClientConfig.d.ts +3 -3
  3. package/dist/libs/normalize-headers.d.ts.map +1 -1
  4. package/dist/libs/normalize-headers.js +1 -0
  5. package/dist/libs/normalize-headers.js.map +1 -1
  6. package/dist/style.css +124 -36
  7. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts +2 -0
  8. package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
  9. package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
  10. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +24 -10
  11. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
  12. package/dist/v2/blocks/operation-block/helpers/send-request.d.ts.map +1 -1
  13. package/dist/v2/blocks/operation-block/helpers/send-request.js +23 -2
  14. package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
  15. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.d.ts.map +1 -1
  16. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.js +18 -7
  17. package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.js.map +1 -1
  18. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.d.ts.map +1 -1
  19. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.js.map +1 -1
  20. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js +32 -9
  21. package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js.map +1 -1
  22. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
  23. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
  24. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js.map +1 -1
  25. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js +8 -1
  26. package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
  27. package/dist/v2/components/sidebar/Sidebar.vue.d.ts.map +1 -1
  28. package/dist/v2/components/sidebar/Sidebar.vue.js.map +1 -1
  29. package/dist/v2/components/sidebar/Sidebar.vue.script.js +9 -4
  30. package/dist/v2/components/sidebar/Sidebar.vue.script.js.map +1 -1
  31. package/dist/v2/constants.js +1 -1
  32. package/dist/v2/features/app/app-events.d.ts.map +1 -1
  33. package/dist/v2/features/app/app-events.js +8 -0
  34. package/dist/v2/features/app/app-events.js.map +1 -1
  35. package/dist/v2/features/app/components/AppSidebar.vue.d.ts.map +1 -1
  36. package/dist/v2/features/app/components/AppSidebar.vue.js +1 -1
  37. package/dist/v2/features/app/components/AppSidebar.vue.js.map +1 -1
  38. package/dist/v2/features/app/components/AppSidebar.vue.script.js +19 -10
  39. package/dist/v2/features/app/components/AppSidebar.vue.script.js.map +1 -1
  40. package/dist/v2/features/app/components/SidebarItemMenu.vue.d.ts +3 -0
  41. package/dist/v2/features/app/components/SidebarItemMenu.vue.d.ts.map +1 -1
  42. package/dist/v2/features/app/components/SidebarItemMenu.vue.js.map +1 -1
  43. package/dist/v2/features/app/components/SidebarItemMenu.vue.script.js +30 -30
  44. package/dist/v2/features/app/components/SidebarItemMenu.vue.script.js.map +1 -1
  45. package/dist/v2/features/app/helpers/create-temp-operation.d.ts +14 -0
  46. package/dist/v2/features/app/helpers/create-temp-operation.d.ts.map +1 -0
  47. package/dist/v2/features/app/helpers/create-temp-operation.js +52 -0
  48. package/dist/v2/features/app/helpers/create-temp-operation.js.map +1 -0
  49. package/dist/v2/features/app/helpers/routes.d.ts +5 -0
  50. package/dist/v2/features/app/helpers/routes.d.ts.map +1 -1
  51. package/dist/v2/features/app/helpers/routes.js +5 -0
  52. package/dist/v2/features/app/helpers/routes.js.map +1 -1
  53. package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.d.ts +12 -0
  54. package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.d.ts.map +1 -0
  55. package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.js +9 -0
  56. package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.js.map +1 -0
  57. package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.script.js +174 -0
  58. package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.script.js.map +1 -0
  59. package/dist/v2/features/collection/components/Scripts.vue.d.ts +16 -0
  60. package/dist/v2/features/collection/components/Scripts.vue.d.ts.map +1 -0
  61. package/dist/v2/features/collection/components/Scripts.vue.js +7 -0
  62. package/dist/v2/features/collection/components/Scripts.vue.js.map +1 -0
  63. package/dist/v2/features/collection/components/Scripts.vue.script.js +47 -0
  64. package/dist/v2/features/collection/components/Scripts.vue.script.js.map +1 -0
  65. package/dist/v2/features/collection/components/Tabs.vue.d.ts.map +1 -1
  66. package/dist/v2/features/collection/components/Tabs.vue.js.map +1 -1
  67. package/dist/v2/features/collection/components/Tabs.vue.script.js +2 -1
  68. package/dist/v2/features/collection/components/Tabs.vue.script.js.map +1 -1
  69. package/dist/v2/features/modal/index.d.ts +1 -0
  70. package/dist/v2/features/modal/index.d.ts.map +1 -1
  71. package/dist/v2/features/operation/Operation.vue.d.ts.map +1 -1
  72. package/dist/v2/features/operation/Operation.vue.js.map +1 -1
  73. package/dist/v2/features/operation/Operation.vue.script.js +3 -1
  74. package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
  75. package/dist/v2/workspace-events.d.ts.map +1 -1
  76. package/dist/v2/workspace-events.js +1 -0
  77. package/dist/v2/workspace-events.js.map +1 -1
  78. package/dist/views/Request/ResponseSection/ResponseEmpty.vue.script.js +1 -1
  79. package/package.json +13 -11
@@ -1 +1 @@
1
- {"version":3,"file":"AppSidebar.vue.js","names":[],"sources":["../../../../../src/v2/features/app/components/AppSidebar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarIconButton,\n ScalarModal,\n ScalarSidebarItem,\n useModal,\n type WorkspaceGroup,\n} from '@scalar/components'\nimport { isMacOS } from '@scalar/helpers/general/is-mac-os'\nimport {\n ScalarIconDotsThree,\n ScalarIconGearSix,\n ScalarIconPlus,\n} from '@scalar/icons'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport type { DraggingItem, HoveredItem, SidebarState } from '@scalar/sidebar'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport type {\n TraversedEntry,\n TraversedOperation,\n} from '@scalar/workspace-store/schemas/navigation'\nimport { capitalize, computed, nextTick, ref } from 'vue'\n\nimport Rabbit from '@/assets/rabbit.ascii?raw'\nimport RabbitJump from '@/assets/rabbitjump.ascii?raw'\nimport ScalarAsciiArt from '@/components/ScalarAsciiArt.vue'\nimport DeleteSidebarListElement from '@/components/Sidebar/Actions/DeleteSidebarListElement.vue'\nimport { Sidebar } from '@/v2/components/sidebar'\nimport DownloadAppButton from '@/v2/features/app/components/DownloadAppButton.vue'\nimport SidebarItemMenu from '@/v2/features/app/components/SidebarItemMenu.vue'\nimport { dragHandleFactory } from '@/v2/helpers/drag-handle-factory'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nconst { sidebarState, layout, activeWorkspace, workspaces, store, eventBus } =\n defineProps<{\n /**\n * The current layout of the app (e.g., 'desktop', 'web')\n */\n layout: ClientLayout\n\n /**\n * The sidebar state, holding navigation items and state\n */\n sidebarState: SidebarState<TraversedEntry>\n\n /**\n * Whether the workspace overview sidebar is currently open\n */\n isWorkspaceOpen?: boolean\n /**\n * The currently active workspace.\n * This represents the workspace that the user is currently working in.\n */\n activeWorkspace: { id: string; label: string }\n /**\n * The list of all available workspaces.\n * Used to render options for workspace switching and selection.\n */\n workspaces: WorkspaceGroup[]\n /**\n * The workspace event bus for handling workspace-level events.\n * Used for triggering and responding to workspace changes and actions.\n */\n eventBus: WorkspaceEventBus\n /**\n * The WorkspaceStore instance for managing workspace state and actions.\n * Provides methods and state for interacting with the current workspace.\n */\n store: WorkspaceStore\n }>()\n\nconst emit = defineEmits<{\n /** Emitted when the workspace button in the sidebar is clicked */\n (e: 'click:workspace'): void\n /** Emitted when a navigation or sidebar item is selected by ID */\n (e: 'selectItem', id: string): void\n /** Emitted when a workspace is selected by optional ID */\n (e: 'select:workspace', id?: string): void\n /** Emitted when the user requests to create a new workspace */\n (e: 'create:workspace'): void\n}>()\n\ndefineSlots<{\n /** Slot for customizing the actions section of the sidebar menu. */\n sidebarMenuActions?(): unknown\n}>()\n\n/** The label for the workspace button in the sidebar */\nconst workspaceLabel = computed(() => capitalize(activeWorkspace.label))\n\n/** Controls the visibility of the sidebar */\nconst isSidebarOpen = defineModel<boolean>('isSidebarOpen', {\n required: true,\n})\n\n/** Controls the width of the sidebar */\nconst sidebarWidth = defineModel<number>('sidebarWidth', {\n required: true,\n default: 288,\n})\n\n/** Calculate if we should show the getting started section */\nconst showGettingStarted = computed(() => sidebarState.items.value.length <= 1)\n\n/*\n * Setup drag and drop handlers for sidebar items.\n * The dragHandleFactory takes the current workspace store and sidebar state,\n * and returns the appropriate handlers for drag ending and droppability.\n *\n * We use computed to ensure the handlers are recreated when the store or sidebarState changes,\n * so they always have access to the latest values.\n */\nconst dragHandlers = computed(() =>\n dragHandleFactory({\n store,\n sidebarState,\n }),\n)\n\nconst handleDragEnd = (\n draggingItem: DraggingItem,\n hoveredItem: HoveredItem,\n): boolean => {\n return dragHandlers.value.handleDragEnd(draggingItem, hoveredItem)\n}\n\nconst isDroppable = (\n draggingItem: DraggingItem,\n hoveredItem: HoveredItem,\n): boolean => {\n return dragHandlers.value.isDroppable(draggingItem, hoveredItem)\n}\n\n/** The current target for the dropdown menu */\nconst menuTarget = ref<{\n /** The sidebar item that the menu is targeting */\n item: TraversedEntry\n /** A reference to the element that the menu is for */\n el: HTMLElement\n /** Whether or not to show the menu */\n showMenu: boolean\n} | null>(null)\n\nconst deleteModalState = useModal()\n\n/** Computes the message for the delete modal */\nconst deleteMessage = computed(() => {\n const item = menuTarget.value?.item\n\n if (item?.type === 'document') {\n return \"This cannot be undone. You're about to delete the document and all tags and operations inside it.\"\n }\n\n return `Are you sure you want to delete this ${item?.type ?? 'item'}? This action cannot be undone.`\n})\n\n/** Deletes an item from the sidebar by emitting the appropriate event */\nconst handleDelete = () => {\n const item = menuTarget.value?.item\n\n if (!item) {\n return\n }\n\n const result = sidebarState.getEntryById(item.id)\n\n const document = getParentEntry('document', result)\n const operation = getParentEntry('operation', result)\n\n if (!document) {\n return\n }\n\n if (item.type === 'document') {\n eventBus.emit('document:delete:document', { name: document.name })\n } else if (item.type === 'tag') {\n eventBus.emit('tag:delete:tag', {\n documentName: document.name,\n name: item.name,\n })\n } else if (item.type === 'operation') {\n if (!operation) {\n return\n }\n\n eventBus.emit('operation:delete:operation', {\n meta: {\n method: operation.method,\n path: operation.path,\n },\n documentName: document.name,\n })\n } else if (item.type === 'example') {\n if (!operation) {\n return\n }\n\n eventBus.emit('operation:delete:example', {\n meta: {\n method: operation.method,\n path: operation.path,\n exampleKey: item.name,\n },\n documentName: document.name,\n })\n }\n\n /** Clean up after deletion */\n deleteModalState.hide()\n menuTarget.value = null\n}\n\n/** Opens the dropdown menu for the given item */\nconst openMenu = async (\n event: MouseEvent | KeyboardEvent,\n item: TraversedEntry,\n) => {\n if (menuTarget.value?.showMenu) {\n return\n }\n\n const el = event.currentTarget as HTMLElement\n menuTarget.value = { item, el, showMenu: true }\n\n // Wait for the target to bind to the element\n await nextTick()\n\n // Re-dispatch the event on the target to open the menu\n const cloned =\n event instanceof MouseEvent\n ? new MouseEvent(event.type, event)\n : new KeyboardEvent(event.type, event)\n\n menuTarget.value?.el.dispatchEvent(cloned)\n}\n\n/** Closes the dropdown menu */\nconst closeMenu = () => {\n if (menuTarget.value) {\n menuTarget.value.showMenu = false\n }\n}\n\n/** Opens the command palette with the payload needed to create a request */\nconst handleAddEmptyFolder = (item: TraversedEntry) => {\n const itemWithParent = sidebarState.getEntryById(item.id)\n const documentEntry = getParentEntry('document', itemWithParent)\n const tag = getParentEntry('tag', itemWithParent)\n\n eventBus.emit('ui:open:command-palette', {\n action: 'create-request',\n payload: {\n documentName: documentEntry?.name,\n tagId: tag?.name,\n },\n })\n}\n\n/**\n * Navigates to the operations page for the provided operation item.\n * Emits a navigation event for the operation overview page.\n */\nconst navigateToOperationsPage = (item: TraversedOperation) => {\n const operationWithParent = sidebarState.getEntryById(item.id)\n const documentSlug = getParentEntry('document', operationWithParent)?.name\n\n eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'overview',\n operationPath: item.path,\n method: item.method,\n documentSlug: documentSlug,\n })\n}\n</script>\n\n<template>\n <div class=\"flex\">\n <Sidebar\n v-model:sidebarWidth=\"sidebarWidth\"\n :activeWorkspace=\"activeWorkspace\"\n :class=\"[\n 'max-md:inset-y-0 max-md:z-2 max-md:w-full!',\n isSidebarOpen ? 'max-md:fixed! max-md:flex!' : 'max-md:hidden!',\n ]\"\n :documents=\"Object.values(store.workspace.documents)\"\n :isDroppable=\"isDroppable\"\n :layout=\"layout\"\n :sidebarState=\"sidebarState\"\n :workspaces=\"workspaces\"\n @create:workspace=\"emit('create:workspace')\"\n @navigate:to:settings=\"\n eventBus.emit('ui:navigate', { page: 'workspace', path: 'settings' })\n \"\n @reorder=\"\n (draggingItem, hoveredItem) => handleDragEnd(draggingItem, hoveredItem)\n \"\n @select:workspace=\"(id) => emit('select:workspace', id)\"\n @selectItem=\"(id) => emit('selectItem', id)\">\n <template #sidebarMenuActions>\n <slot name=\"sidebarMenuActions\" />\n </template>\n <!-- Workspace Identifier -->\n <template #workspaceButton>\n <ScalarSidebarItem\n is=\"button\"\n :active=\"isWorkspaceOpen\"\n @click=\"emit('click:workspace')\">\n {{ workspaceLabel }}\n </ScalarSidebarItem>\n </template>\n\n <!-- Decorator dropdown menu -->\n <template #decorator=\"{ item }\">\n <div class=\"flex items-center gap-0.5\">\n <ScalarIconButton\n v-if=\"item.type === 'operation'\"\n :icon=\"ScalarIconGearSix\"\n label=\"Operation settings\"\n size=\"sm\"\n weight=\"bold\"\n @click.stop=\"navigateToOperationsPage(item)\"\n @keydown.enter.stop=\"navigateToOperationsPage(item)\"\n @keydown.space.stop=\"navigateToOperationsPage(item)\" />\n <ScalarIconButton\n aria-expanded=\"false\"\n aria-haspopup=\"menu\"\n :icon=\"ScalarIconDotsThree\"\n label=\"More options\"\n size=\"sm\"\n weight=\"bold\"\n @click.stop=\"(e: MouseEvent) => openMenu(e, item)\"\n @keydown.down.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.enter.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.space.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.up.stop=\"(e: KeyboardEvent) => openMenu(e, item)\" />\n </div>\n </template>\n\n <!-- Dirty document icon slot -->\n <template #icon=\"{ item }\">\n <template\n v-if=\"\n item.type === 'document' &&\n store.workspace.documents[item.name]?.['x-scalar-is-dirty'] === true\n \">\n <div class=\"relative flex items-center\">\n <LibraryIcon\n class=\"block\"\n :src=\"\n ('icon' in item && item.icon) || 'interface-content-folder'\n \" />\n <div\n class=\"bg-c-accent absolute -top-0.5 -right-0.5 size-1.5 rounded-full\">\n <span class=\"sr-only\">Unsaved changes</span>\n </div>\n </div>\n </template>\n </template>\n\n <!-- Empty folder slot -->\n <template #empty=\"{ item }\">\n <ScalarSidebarItem\n is=\"button\"\n @click=\"handleAddEmptyFolder(item)\">\n <template #icon>\n <ScalarIconPlus />\n </template>\n <template #default>Add operation</template>\n </ScalarSidebarItem>\n </template>\n\n <!-- Getting started section -->\n <template\n v-if=\"layout !== 'modal'\"\n #footer>\n <div\n :class=\"{\n 'empty-sidebar-item border-t': showGettingStarted,\n }\">\n <div\n v-if=\"showGettingStarted\"\n class=\"empty-sidebar-item-content overflow-hidden px-2.5 py-2.5\">\n <div class=\"rabbit-ascii relative m-auto mt-2 h-[68px] w-[60px]\">\n <ScalarAsciiArt\n :art=\"Rabbit\"\n class=\"rabbitsit font-bold\" />\n <ScalarAsciiArt\n :art=\"RabbitJump\"\n class=\"rabbitjump absolute top-0 left-0 font-bold\" />\n </div>\n <div class=\"mt-2 mb-2 text-center text-sm text-balance\">\n <b class=\"font-medium\">Let's Get Started</b>\n <p class=\"mt-2 leading-5\">\n Create request, folder, collection or import from\n OpenAPI/Postman\n </p>\n </div>\n </div>\n\n <div class=\"flex flex-col gap-1.5 p-2\">\n <ScalarButton\n v-if=\"showGettingStarted\"\n class=\"w-full\"\n size=\"sm\"\n @click=\"\n eventBus.emit('ui:open:command-palette', {\n action: 'import-from-openapi-swagger-postman-curl',\n payload: undefined,\n })\n \">\n Import Collection\n </ScalarButton>\n\n <ScalarButton\n class=\"w-full\"\n hotkey=\"K\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"eventBus.emit('ui:open:command-palette')\">\n Add Item &nbsp;\n\n <span\n class=\"text-sidebar-c-2 rounded border px-1.25 py-1 text-xs leading-none font-medium uppercase\">\n <template v-if=\"isMacOS()\">\n <span class=\"sr-only\">Command</span>\n <span aria-hidden=\"true\">⌘</span>\n </template>\n <template v-else>\n <span class=\"sr-only\">CTRL</span>\n <span aria-hidden=\"true\">⌃</span>\n </template>\n K\n </span>\n </ScalarButton>\n <DownloadAppButton v-if=\"layout === 'web'\" />\n </div>\n </div>\n </template>\n </Sidebar>\n <SidebarItemMenu\n v-if=\"menuTarget?.showMenu\"\n :eventBus=\"eventBus\"\n :item=\"menuTarget.item\"\n :sidebarState=\"sidebarState\"\n :target=\"menuTarget.el\"\n @closeMenu=\"closeMenu\"\n @showDeleteModal=\"deleteModalState.show()\" />\n\n <!-- Delete Modal -->\n <ScalarModal\n v-if=\"menuTarget\"\n size=\"xxs\"\n :state=\"deleteModalState\"\n :title=\"`Delete ${menuTarget.item.title}`\">\n <DeleteSidebarListElement\n :variableName=\"menuTarget.item.title\"\n :warningMessage=\"deleteMessage\"\n @close=\"deleteModalState.hide()\"\n @delete=\"handleDelete\" />\n </ScalarModal>\n </div>\n</template>\n\n<style scoped>\n.empty-sidebar-item-content {\n display: none;\n}\n.empty-sidebar-item .empty-sidebar-item-content {\n display: block;\n}\n.rabbitjump {\n opacity: 0;\n}\n.empty-sidebar-item:hover .rabbitjump {\n opacity: 1;\n animation: rabbitAnimation 0.5s steps(1) infinite;\n}\n.empty-sidebar-item:hover .rabbitsit {\n opacity: 0;\n animation: rabbitAnimation2 0.5s steps(1) infinite;\n}\n.empty-sidebar-item:hover .rabbit-ascii {\n animation: rabbitRun 8s infinite linear;\n}\n@keyframes rabbitRun {\n 0% {\n transform: translate3d(0, 0, 0);\n }\n 25% {\n transform: translate3d(250px, 0, 0);\n }\n 25.01% {\n transform: translate3d(-250px, 0, 0);\n }\n 75% {\n transform: translate3d(250px, 0, 0);\n }\n 75.01% {\n transform: translate3d(-250px, 0, 0);\n }\n 100% {\n transform: translate3d(0, 0, 0);\n }\n}\n@keyframes rabbitAnimation {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n }\n}\n@keyframes rabbitAnimation2 {\n 0%,\n 100% {\n opacity: 0;\n }\n 50% {\n opacity: 1;\n transform: translate3d(0, -8px, 0);\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"AppSidebar.vue.js","names":[],"sources":["../../../../../src/v2/features/app/components/AppSidebar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarIconButton,\n ScalarModal,\n ScalarSidebarItem,\n useModal,\n type WorkspaceGroup,\n} from '@scalar/components'\nimport { isMacOS } from '@scalar/helpers/general/is-mac-os'\nimport {\n ScalarIconDotsThree,\n ScalarIconGearSix,\n ScalarIconPlus,\n} from '@scalar/icons'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport type { DraggingItem, HoveredItem, SidebarState } from '@scalar/sidebar'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport type {\n TraversedEntry,\n TraversedOperation,\n} from '@scalar/workspace-store/schemas/navigation'\nimport { capitalize, computed, nextTick, ref } from 'vue'\n\nimport Rabbit from '@/assets/rabbit.ascii?raw'\nimport RabbitJump from '@/assets/rabbitjump.ascii?raw'\nimport ScalarAsciiArt from '@/components/ScalarAsciiArt.vue'\nimport DeleteSidebarListElement from '@/components/Sidebar/Actions/DeleteSidebarListElement.vue'\nimport { Sidebar } from '@/v2/components/sidebar'\nimport DownloadAppButton from '@/v2/features/app/components/DownloadAppButton.vue'\nimport SidebarItemMenu from '@/v2/features/app/components/SidebarItemMenu.vue'\nimport { createTempOperation } from '@/v2/features/app/helpers/create-temp-operation'\nimport { dragHandleFactory } from '@/v2/helpers/drag-handle-factory'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nconst { sidebarState, layout, activeWorkspace, workspaces, store, eventBus } =\n defineProps<{\n /**\n * The current layout of the app (e.g., 'desktop', 'web')\n */\n layout: ClientLayout\n\n /**\n * The sidebar state, holding navigation items and state\n */\n sidebarState: SidebarState<TraversedEntry>\n\n /**\n * Whether the workspace overview sidebar is currently open\n */\n isWorkspaceOpen?: boolean\n /**\n * The currently active workspace.\n * This represents the workspace that the user is currently working in.\n */\n activeWorkspace: { id: string; label: string }\n /**\n * The list of all available workspaces.\n * Used to render options for workspace switching and selection.\n */\n workspaces: WorkspaceGroup[]\n /**\n * The workspace event bus for handling workspace-level events.\n * Used for triggering and responding to workspace changes and actions.\n */\n eventBus: WorkspaceEventBus\n /**\n * The WorkspaceStore instance for managing workspace state and actions.\n * Provides methods and state for interacting with the current workspace.\n */\n store: WorkspaceStore\n }>()\n\nconst emit = defineEmits<{\n /** Emitted when the workspace button in the sidebar is clicked */\n (e: 'click:workspace'): void\n /** Emitted when a navigation or sidebar item is selected by ID */\n (e: 'selectItem', id: string): void\n /** Emitted when a workspace is selected by optional ID */\n (e: 'select:workspace', id?: string): void\n /** Emitted when the user requests to create a new workspace */\n (e: 'create:workspace'): void\n}>()\n\ndefineSlots<{\n /** Slot for customizing the actions section of the sidebar menu. */\n sidebarMenuActions?(): unknown\n}>()\n\n/** The label for the workspace button in the sidebar */\nconst workspaceLabel = computed(() => capitalize(activeWorkspace.label))\n\n/** Controls the visibility of the sidebar */\nconst isSidebarOpen = defineModel<boolean>('isSidebarOpen', {\n required: true,\n})\n\n/** Controls the width of the sidebar */\nconst sidebarWidth = defineModel<number>('sidebarWidth', {\n required: true,\n default: 288,\n})\n\n/** Calculate if we should show the getting started section */\nconst showGettingStarted = computed(() => sidebarState.items.value.length <= 1)\n\n/*\n * Setup drag and drop handlers for sidebar items.\n * The dragHandleFactory takes the current workspace store and sidebar state,\n * and returns the appropriate handlers for drag ending and droppability.\n *\n * We use computed to ensure the handlers are recreated when the store or sidebarState changes,\n * so they always have access to the latest values.\n */\nconst dragHandlers = computed(() =>\n dragHandleFactory({\n store,\n sidebarState,\n }),\n)\n\nconst handleDragEnd = (\n draggingItem: DraggingItem,\n hoveredItem: HoveredItem,\n): boolean => {\n return dragHandlers.value.handleDragEnd(draggingItem, hoveredItem)\n}\n\nconst isDroppable = (\n draggingItem: DraggingItem,\n hoveredItem: HoveredItem,\n): boolean => {\n return dragHandlers.value.isDroppable(draggingItem, hoveredItem)\n}\n\n/** The current target for the dropdown menu */\nconst menuTarget = ref<{\n /** The sidebar item that the menu is targeting */\n item: TraversedEntry\n /** A reference to the element that the menu is for */\n el: HTMLElement\n /** Whether or not to show the menu */\n showMenu: boolean\n} | null>(null)\n\nconst deleteModalState = useModal()\n\n/** Computes the message for the delete modal */\nconst deleteMessage = computed(() => {\n const item = menuTarget.value?.item\n\n if (item?.type === 'document') {\n return \"This cannot be undone. You're about to delete the document and all tags and operations inside it.\"\n }\n\n return `Are you sure you want to delete this ${item?.type ?? 'item'}? This action cannot be undone.`\n})\n\n/** Deletes an item from the sidebar by emitting the appropriate event */\nconst handleDelete = () => {\n const item = menuTarget.value?.item\n\n if (!item) {\n return\n }\n\n const result = sidebarState.getEntryById(item.id)\n\n const document = getParentEntry('document', result)\n const operation = getParentEntry('operation', result)\n\n if (!document) {\n return\n }\n\n if (item.type === 'document') {\n eventBus.emit('document:delete:document', { name: document.name })\n } else if (item.type === 'tag') {\n eventBus.emit('tag:delete:tag', {\n documentName: document.name,\n name: item.name,\n })\n } else if (item.type === 'operation') {\n if (!operation) {\n return\n }\n\n eventBus.emit('operation:delete:operation', {\n meta: {\n method: operation.method,\n path: operation.path,\n },\n documentName: document.name,\n })\n } else if (item.type === 'example') {\n if (!operation) {\n return\n }\n\n eventBus.emit('operation:delete:example', {\n meta: {\n method: operation.method,\n path: operation.path,\n exampleKey: item.name,\n },\n documentName: document.name,\n })\n }\n\n /** Clean up after deletion */\n deleteModalState.hide()\n menuTarget.value = null\n}\n\n/** Opens the dropdown menu for the given item */\nconst openMenu = async (\n event: MouseEvent | KeyboardEvent,\n item: TraversedEntry,\n) => {\n if (menuTarget.value?.showMenu) {\n return\n }\n\n const el = event.currentTarget as HTMLElement\n menuTarget.value = { item, el, showMenu: true }\n\n // Wait for the target to bind to the element\n await nextTick()\n\n // Re-dispatch the event on the target to open the menu\n const cloned =\n event instanceof MouseEvent\n ? new MouseEvent(event.type, event)\n : new KeyboardEvent(event.type, event)\n\n menuTarget.value?.el.dispatchEvent(cloned)\n}\n\n/** Closes the dropdown menu */\nconst closeMenu = () => {\n if (menuTarget.value) {\n menuTarget.value.showMenu = false\n }\n}\n\n/**\n * Creates a new operation directly from the empty folder slot.\n * Uses a unique temporary path to avoid conflicts, then navigates to the operation,\n * updates the path to `/`, and focuses the address bar so the user can immediately start typing.\n */\nconst handleAddEmptyFolder = (item: TraversedEntry) => {\n const itemWithParent = sidebarState.getEntryById(item.id)\n const documentName = getParentEntry('document', itemWithParent)?.name\n const tagName = getParentEntry('tag', itemWithParent)?.name\n\n if (!documentName) {\n console.error('Document name not found')\n return\n }\n createTempOperation(documentName, {\n existingPaths: new Set(\n Object.keys(store.workspace.documents[documentName]?.paths ?? {}),\n ),\n eventBus,\n tags: tagName ? [tagName] : undefined,\n })\n}\n\n/**\n * Navigates to the operations page for the provided operation item.\n * Emits a navigation event for the operation overview page.\n */\nconst navigateToOperationsPage = (item: TraversedOperation) => {\n const operationWithParent = sidebarState.getEntryById(item.id)\n const documentSlug = getParentEntry('document', operationWithParent)?.name\n\n eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'overview',\n operationPath: item.path,\n method: item.method,\n documentSlug: documentSlug,\n })\n}\n</script>\n\n<template>\n <div class=\"flex\">\n <Sidebar\n v-model:sidebarWidth=\"sidebarWidth\"\n :activeWorkspace=\"activeWorkspace\"\n :class=\"[\n 'max-md:inset-y-0 max-md:z-2 max-md:w-full!',\n isSidebarOpen ? 'max-md:fixed! max-md:flex!' : 'max-md:hidden!',\n ]\"\n :documents=\"Object.values(store.workspace.documents)\"\n :isDroppable=\"isDroppable\"\n :layout=\"layout\"\n :sidebarState=\"sidebarState\"\n :workspaces=\"workspaces\"\n @create:workspace=\"emit('create:workspace')\"\n @navigate:to:settings=\"\n eventBus.emit('ui:navigate', { page: 'workspace', path: 'settings' })\n \"\n @reorder=\"\n (draggingItem, hoveredItem) => handleDragEnd(draggingItem, hoveredItem)\n \"\n @select:workspace=\"(id) => emit('select:workspace', id)\"\n @selectItem=\"(id) => emit('selectItem', id)\">\n <template #sidebarMenuActions>\n <slot name=\"sidebarMenuActions\" />\n </template>\n <!-- Workspace Identifier -->\n <template #workspaceButton>\n <ScalarSidebarItem\n is=\"button\"\n :active=\"isWorkspaceOpen\"\n @click=\"emit('click:workspace')\">\n {{ workspaceLabel }}\n </ScalarSidebarItem>\n </template>\n\n <!-- Decorator dropdown menu -->\n <template #decorator=\"{ item }\">\n <div class=\"flex items-center gap-0.5\">\n <ScalarIconButton\n v-if=\"item.type === 'operation'\"\n :icon=\"ScalarIconGearSix\"\n label=\"Operation settings\"\n size=\"sm\"\n weight=\"bold\"\n @click.stop=\"navigateToOperationsPage(item)\"\n @keydown.enter.stop=\"navigateToOperationsPage(item)\"\n @keydown.space.stop=\"navigateToOperationsPage(item)\" />\n <ScalarIconButton\n aria-expanded=\"false\"\n aria-haspopup=\"menu\"\n :icon=\"ScalarIconDotsThree\"\n label=\"More options\"\n size=\"sm\"\n weight=\"bold\"\n @click.stop=\"(e: MouseEvent) => openMenu(e, item)\"\n @keydown.down.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.enter.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.space.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.up.stop=\"(e: KeyboardEvent) => openMenu(e, item)\" />\n </div>\n </template>\n\n <!-- Dirty document icon slot -->\n <template #icon=\"{ item }\">\n <template\n v-if=\"\n item.type === 'document' &&\n store.workspace.documents[item.name]?.['x-scalar-is-dirty'] === true\n \">\n <div class=\"relative flex items-center\">\n <LibraryIcon\n class=\"block\"\n :src=\"\n ('icon' in item && item.icon) || 'interface-content-folder'\n \" />\n <div\n class=\"bg-c-accent absolute -top-0.5 -right-0.5 size-1.5 rounded-full\">\n <span class=\"sr-only\">Unsaved changes</span>\n </div>\n </div>\n </template>\n </template>\n\n <!-- Empty folder slot -->\n <template #empty=\"{ item }\">\n <ScalarSidebarItem\n is=\"button\"\n @click=\"handleAddEmptyFolder(item)\">\n <template #icon>\n <ScalarIconPlus />\n </template>\n <template #default>Add operation</template>\n </ScalarSidebarItem>\n </template>\n\n <!-- Getting started section -->\n <template\n v-if=\"layout !== 'modal'\"\n #footer>\n <div\n :class=\"{\n 'empty-sidebar-item border-t': showGettingStarted,\n }\">\n <div\n v-if=\"showGettingStarted\"\n class=\"empty-sidebar-item-content overflow-hidden px-2.5 py-2.5\">\n <div class=\"rabbit-ascii relative m-auto mt-2 h-[68px] w-[60px]\">\n <ScalarAsciiArt\n :art=\"Rabbit\"\n class=\"rabbitsit font-bold\" />\n <ScalarAsciiArt\n :art=\"RabbitJump\"\n class=\"rabbitjump absolute top-0 left-0 font-bold\" />\n </div>\n <div class=\"mt-2 mb-2 text-center text-sm text-balance\">\n <b class=\"font-medium\">Let's Get Started</b>\n <p class=\"mt-2 leading-5\">\n Create request, folder, collection or import from\n OpenAPI/Postman\n </p>\n </div>\n </div>\n\n <div class=\"flex flex-col gap-1.5 p-2\">\n <ScalarButton\n v-if=\"showGettingStarted\"\n class=\"w-full\"\n size=\"sm\"\n @click=\"\n eventBus.emit('ui:open:command-palette', {\n action: 'import-from-openapi-swagger-postman-curl',\n payload: undefined,\n })\n \">\n Import Collection\n </ScalarButton>\n\n <ScalarButton\n class=\"w-full\"\n hotkey=\"K\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"eventBus.emit('ui:open:command-palette')\">\n Add Item &nbsp;\n\n <span\n class=\"text-sidebar-c-2 rounded border px-1.25 py-1 text-xs leading-none font-medium uppercase\">\n <template v-if=\"isMacOS()\">\n <span class=\"sr-only\">Command</span>\n <span aria-hidden=\"true\">⌘</span>\n </template>\n <template v-else>\n <span class=\"sr-only\">CTRL</span>\n <span aria-hidden=\"true\">⌃</span>\n </template>\n K\n </span>\n </ScalarButton>\n <DownloadAppButton v-if=\"layout === 'web'\" />\n </div>\n </div>\n </template>\n </Sidebar>\n <SidebarItemMenu\n v-if=\"menuTarget?.showMenu\"\n :eventBus=\"eventBus\"\n :item=\"menuTarget.item\"\n :sidebarState=\"sidebarState\"\n :target=\"menuTarget.el\"\n :workspaceStore=\"store\"\n @closeMenu=\"closeMenu\"\n @showDeleteModal=\"deleteModalState.show()\" />\n\n <!-- Delete Modal -->\n <ScalarModal\n v-if=\"menuTarget\"\n size=\"xxs\"\n :state=\"deleteModalState\"\n :title=\"`Delete ${menuTarget.item.title}`\">\n <DeleteSidebarListElement\n :variableName=\"menuTarget.item.title\"\n :warningMessage=\"deleteMessage\"\n @close=\"deleteModalState.hide()\"\n @delete=\"handleDelete\" />\n </ScalarModal>\n </div>\n</template>\n\n<style scoped>\n.empty-sidebar-item-content {\n display: none;\n}\n.empty-sidebar-item .empty-sidebar-item-content {\n display: block;\n}\n.rabbitjump {\n opacity: 0;\n}\n.empty-sidebar-item:hover .rabbitjump {\n opacity: 1;\n animation: rabbitAnimation 0.5s steps(1) infinite;\n}\n.empty-sidebar-item:hover .rabbitsit {\n opacity: 0;\n animation: rabbitAnimation2 0.5s steps(1) infinite;\n}\n.empty-sidebar-item:hover .rabbit-ascii {\n animation: rabbitRun 8s infinite linear;\n}\n@keyframes rabbitRun {\n 0% {\n transform: translate3d(0, 0, 0);\n }\n 25% {\n transform: translate3d(250px, 0, 0);\n }\n 25.01% {\n transform: translate3d(-250px, 0, 0);\n }\n 75% {\n transform: translate3d(250px, 0, 0);\n }\n 75.01% {\n transform: translate3d(-250px, 0, 0);\n }\n 100% {\n transform: translate3d(0, 0, 0);\n }\n}\n@keyframes rabbitAnimation {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n }\n}\n@keyframes rabbitAnimation2 {\n 0%,\n 100% {\n opacity: 0;\n }\n 50% {\n opacity: 1;\n transform: translate3d(0, -8px, 0);\n }\n}\n</style>\n"],"mappings":""}
@@ -4,6 +4,7 @@ import rabbit_default from "../../../../assets/rabbit.ascii.virtual.js";
4
4
  import rabbitjump_default from "../../../../assets/rabbitjump.ascii.virtual.js";
5
5
  import DeleteSidebarListElement_default from "../../../../components/Sidebar/Actions/DeleteSidebarListElement.vue.js";
6
6
  import DownloadAppButton_default from "./DownloadAppButton.vue.js";
7
+ import { createTempOperation } from "../helpers/create-temp-operation.js";
7
8
  import SidebarItemMenu_default from "./SidebarItemMenu.vue.js";
8
9
  import { dragHandleFactory } from "../../../helpers/drag-handle-factory.js";
9
10
  import { Fragment, capitalize, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, mergeModels, nextTick, normalizeClass, openBlock, ref, renderSlot, toDisplayString, unref, useModel, withCtx, withKeys, withModifiers } from "vue";
@@ -136,17 +137,23 @@ var AppSidebar_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
136
137
  const closeMenu = () => {
137
138
  if (menuTarget.value) menuTarget.value.showMenu = false;
138
139
  };
139
- /** Opens the command palette with the payload needed to create a request */
140
+ /**
141
+ * Creates a new operation directly from the empty folder slot.
142
+ * Uses a unique temporary path to avoid conflicts, then navigates to the operation,
143
+ * updates the path to `/`, and focuses the address bar so the user can immediately start typing.
144
+ */
140
145
  const handleAddEmptyFolder = (item) => {
141
146
  const itemWithParent = __props.sidebarState.getEntryById(item.id);
142
- const documentEntry = getParentEntry("document", itemWithParent);
143
- const tag = getParentEntry("tag", itemWithParent);
144
- __props.eventBus.emit("ui:open:command-palette", {
145
- action: "create-request",
146
- payload: {
147
- documentName: documentEntry?.name,
148
- tagId: tag?.name
149
- }
147
+ const documentName = getParentEntry("document", itemWithParent)?.name;
148
+ const tagName = getParentEntry("tag", itemWithParent)?.name;
149
+ if (!documentName) {
150
+ console.error("Document name not found");
151
+ return;
152
+ }
153
+ createTempOperation(documentName, {
154
+ existingPaths: new Set(Object.keys(__props.store.workspace.documents[documentName]?.paths ?? {})),
155
+ eventBus: __props.eventBus,
156
+ tags: tagName ? [tagName] : void 0
150
157
  });
151
158
  };
152
159
  /**
@@ -286,13 +293,15 @@ var AppSidebar_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ def
286
293
  item: menuTarget.value.item,
287
294
  sidebarState: __props.sidebarState,
288
295
  target: menuTarget.value.el,
296
+ workspaceStore: __props.store,
289
297
  onCloseMenu: closeMenu,
290
298
  onShowDeleteModal: _cache[9] || (_cache[9] = ($event) => unref(deleteModalState).show())
291
299
  }, null, 8, [
292
300
  "eventBus",
293
301
  "item",
294
302
  "sidebarState",
295
- "target"
303
+ "target",
304
+ "workspaceStore"
296
305
  ])) : createCommentVNode("", true),
297
306
  menuTarget.value ? (openBlock(), createBlock(unref(ScalarModal), {
298
307
  key: 1,
@@ -1 +1 @@
1
- {"version":3,"file":"AppSidebar.vue.script.js","names":[],"sources":["../../../../../src/v2/features/app/components/AppSidebar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarIconButton,\n ScalarModal,\n ScalarSidebarItem,\n useModal,\n type WorkspaceGroup,\n} from '@scalar/components'\nimport { isMacOS } from '@scalar/helpers/general/is-mac-os'\nimport {\n ScalarIconDotsThree,\n ScalarIconGearSix,\n ScalarIconPlus,\n} from '@scalar/icons'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport type { DraggingItem, HoveredItem, SidebarState } from '@scalar/sidebar'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport type {\n TraversedEntry,\n TraversedOperation,\n} from '@scalar/workspace-store/schemas/navigation'\nimport { capitalize, computed, nextTick, ref } from 'vue'\n\nimport Rabbit from '@/assets/rabbit.ascii?raw'\nimport RabbitJump from '@/assets/rabbitjump.ascii?raw'\nimport ScalarAsciiArt from '@/components/ScalarAsciiArt.vue'\nimport DeleteSidebarListElement from '@/components/Sidebar/Actions/DeleteSidebarListElement.vue'\nimport { Sidebar } from '@/v2/components/sidebar'\nimport DownloadAppButton from '@/v2/features/app/components/DownloadAppButton.vue'\nimport SidebarItemMenu from '@/v2/features/app/components/SidebarItemMenu.vue'\nimport { dragHandleFactory } from '@/v2/helpers/drag-handle-factory'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nconst { sidebarState, layout, activeWorkspace, workspaces, store, eventBus } =\n defineProps<{\n /**\n * The current layout of the app (e.g., 'desktop', 'web')\n */\n layout: ClientLayout\n\n /**\n * The sidebar state, holding navigation items and state\n */\n sidebarState: SidebarState<TraversedEntry>\n\n /**\n * Whether the workspace overview sidebar is currently open\n */\n isWorkspaceOpen?: boolean\n /**\n * The currently active workspace.\n * This represents the workspace that the user is currently working in.\n */\n activeWorkspace: { id: string; label: string }\n /**\n * The list of all available workspaces.\n * Used to render options for workspace switching and selection.\n */\n workspaces: WorkspaceGroup[]\n /**\n * The workspace event bus for handling workspace-level events.\n * Used for triggering and responding to workspace changes and actions.\n */\n eventBus: WorkspaceEventBus\n /**\n * The WorkspaceStore instance for managing workspace state and actions.\n * Provides methods and state for interacting with the current workspace.\n */\n store: WorkspaceStore\n }>()\n\nconst emit = defineEmits<{\n /** Emitted when the workspace button in the sidebar is clicked */\n (e: 'click:workspace'): void\n /** Emitted when a navigation or sidebar item is selected by ID */\n (e: 'selectItem', id: string): void\n /** Emitted when a workspace is selected by optional ID */\n (e: 'select:workspace', id?: string): void\n /** Emitted when the user requests to create a new workspace */\n (e: 'create:workspace'): void\n}>()\n\ndefineSlots<{\n /** Slot for customizing the actions section of the sidebar menu. */\n sidebarMenuActions?(): unknown\n}>()\n\n/** The label for the workspace button in the sidebar */\nconst workspaceLabel = computed(() => capitalize(activeWorkspace.label))\n\n/** Controls the visibility of the sidebar */\nconst isSidebarOpen = defineModel<boolean>('isSidebarOpen', {\n required: true,\n})\n\n/** Controls the width of the sidebar */\nconst sidebarWidth = defineModel<number>('sidebarWidth', {\n required: true,\n default: 288,\n})\n\n/** Calculate if we should show the getting started section */\nconst showGettingStarted = computed(() => sidebarState.items.value.length <= 1)\n\n/*\n * Setup drag and drop handlers for sidebar items.\n * The dragHandleFactory takes the current workspace store and sidebar state,\n * and returns the appropriate handlers for drag ending and droppability.\n *\n * We use computed to ensure the handlers are recreated when the store or sidebarState changes,\n * so they always have access to the latest values.\n */\nconst dragHandlers = computed(() =>\n dragHandleFactory({\n store,\n sidebarState,\n }),\n)\n\nconst handleDragEnd = (\n draggingItem: DraggingItem,\n hoveredItem: HoveredItem,\n): boolean => {\n return dragHandlers.value.handleDragEnd(draggingItem, hoveredItem)\n}\n\nconst isDroppable = (\n draggingItem: DraggingItem,\n hoveredItem: HoveredItem,\n): boolean => {\n return dragHandlers.value.isDroppable(draggingItem, hoveredItem)\n}\n\n/** The current target for the dropdown menu */\nconst menuTarget = ref<{\n /** The sidebar item that the menu is targeting */\n item: TraversedEntry\n /** A reference to the element that the menu is for */\n el: HTMLElement\n /** Whether or not to show the menu */\n showMenu: boolean\n} | null>(null)\n\nconst deleteModalState = useModal()\n\n/** Computes the message for the delete modal */\nconst deleteMessage = computed(() => {\n const item = menuTarget.value?.item\n\n if (item?.type === 'document') {\n return \"This cannot be undone. You're about to delete the document and all tags and operations inside it.\"\n }\n\n return `Are you sure you want to delete this ${item?.type ?? 'item'}? This action cannot be undone.`\n})\n\n/** Deletes an item from the sidebar by emitting the appropriate event */\nconst handleDelete = () => {\n const item = menuTarget.value?.item\n\n if (!item) {\n return\n }\n\n const result = sidebarState.getEntryById(item.id)\n\n const document = getParentEntry('document', result)\n const operation = getParentEntry('operation', result)\n\n if (!document) {\n return\n }\n\n if (item.type === 'document') {\n eventBus.emit('document:delete:document', { name: document.name })\n } else if (item.type === 'tag') {\n eventBus.emit('tag:delete:tag', {\n documentName: document.name,\n name: item.name,\n })\n } else if (item.type === 'operation') {\n if (!operation) {\n return\n }\n\n eventBus.emit('operation:delete:operation', {\n meta: {\n method: operation.method,\n path: operation.path,\n },\n documentName: document.name,\n })\n } else if (item.type === 'example') {\n if (!operation) {\n return\n }\n\n eventBus.emit('operation:delete:example', {\n meta: {\n method: operation.method,\n path: operation.path,\n exampleKey: item.name,\n },\n documentName: document.name,\n })\n }\n\n /** Clean up after deletion */\n deleteModalState.hide()\n menuTarget.value = null\n}\n\n/** Opens the dropdown menu for the given item */\nconst openMenu = async (\n event: MouseEvent | KeyboardEvent,\n item: TraversedEntry,\n) => {\n if (menuTarget.value?.showMenu) {\n return\n }\n\n const el = event.currentTarget as HTMLElement\n menuTarget.value = { item, el, showMenu: true }\n\n // Wait for the target to bind to the element\n await nextTick()\n\n // Re-dispatch the event on the target to open the menu\n const cloned =\n event instanceof MouseEvent\n ? new MouseEvent(event.type, event)\n : new KeyboardEvent(event.type, event)\n\n menuTarget.value?.el.dispatchEvent(cloned)\n}\n\n/** Closes the dropdown menu */\nconst closeMenu = () => {\n if (menuTarget.value) {\n menuTarget.value.showMenu = false\n }\n}\n\n/** Opens the command palette with the payload needed to create a request */\nconst handleAddEmptyFolder = (item: TraversedEntry) => {\n const itemWithParent = sidebarState.getEntryById(item.id)\n const documentEntry = getParentEntry('document', itemWithParent)\n const tag = getParentEntry('tag', itemWithParent)\n\n eventBus.emit('ui:open:command-palette', {\n action: 'create-request',\n payload: {\n documentName: documentEntry?.name,\n tagId: tag?.name,\n },\n })\n}\n\n/**\n * Navigates to the operations page for the provided operation item.\n * Emits a navigation event for the operation overview page.\n */\nconst navigateToOperationsPage = (item: TraversedOperation) => {\n const operationWithParent = sidebarState.getEntryById(item.id)\n const documentSlug = getParentEntry('document', operationWithParent)?.name\n\n eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'overview',\n operationPath: item.path,\n method: item.method,\n documentSlug: documentSlug,\n })\n}\n</script>\n\n<template>\n <div class=\"flex\">\n <Sidebar\n v-model:sidebarWidth=\"sidebarWidth\"\n :activeWorkspace=\"activeWorkspace\"\n :class=\"[\n 'max-md:inset-y-0 max-md:z-2 max-md:w-full!',\n isSidebarOpen ? 'max-md:fixed! max-md:flex!' : 'max-md:hidden!',\n ]\"\n :documents=\"Object.values(store.workspace.documents)\"\n :isDroppable=\"isDroppable\"\n :layout=\"layout\"\n :sidebarState=\"sidebarState\"\n :workspaces=\"workspaces\"\n @create:workspace=\"emit('create:workspace')\"\n @navigate:to:settings=\"\n eventBus.emit('ui:navigate', { page: 'workspace', path: 'settings' })\n \"\n @reorder=\"\n (draggingItem, hoveredItem) => handleDragEnd(draggingItem, hoveredItem)\n \"\n @select:workspace=\"(id) => emit('select:workspace', id)\"\n @selectItem=\"(id) => emit('selectItem', id)\">\n <template #sidebarMenuActions>\n <slot name=\"sidebarMenuActions\" />\n </template>\n <!-- Workspace Identifier -->\n <template #workspaceButton>\n <ScalarSidebarItem\n is=\"button\"\n :active=\"isWorkspaceOpen\"\n @click=\"emit('click:workspace')\">\n {{ workspaceLabel }}\n </ScalarSidebarItem>\n </template>\n\n <!-- Decorator dropdown menu -->\n <template #decorator=\"{ item }\">\n <div class=\"flex items-center gap-0.5\">\n <ScalarIconButton\n v-if=\"item.type === 'operation'\"\n :icon=\"ScalarIconGearSix\"\n label=\"Operation settings\"\n size=\"sm\"\n weight=\"bold\"\n @click.stop=\"navigateToOperationsPage(item)\"\n @keydown.enter.stop=\"navigateToOperationsPage(item)\"\n @keydown.space.stop=\"navigateToOperationsPage(item)\" />\n <ScalarIconButton\n aria-expanded=\"false\"\n aria-haspopup=\"menu\"\n :icon=\"ScalarIconDotsThree\"\n label=\"More options\"\n size=\"sm\"\n weight=\"bold\"\n @click.stop=\"(e: MouseEvent) => openMenu(e, item)\"\n @keydown.down.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.enter.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.space.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.up.stop=\"(e: KeyboardEvent) => openMenu(e, item)\" />\n </div>\n </template>\n\n <!-- Dirty document icon slot -->\n <template #icon=\"{ item }\">\n <template\n v-if=\"\n item.type === 'document' &&\n store.workspace.documents[item.name]?.['x-scalar-is-dirty'] === true\n \">\n <div class=\"relative flex items-center\">\n <LibraryIcon\n class=\"block\"\n :src=\"\n ('icon' in item && item.icon) || 'interface-content-folder'\n \" />\n <div\n class=\"bg-c-accent absolute -top-0.5 -right-0.5 size-1.5 rounded-full\">\n <span class=\"sr-only\">Unsaved changes</span>\n </div>\n </div>\n </template>\n </template>\n\n <!-- Empty folder slot -->\n <template #empty=\"{ item }\">\n <ScalarSidebarItem\n is=\"button\"\n @click=\"handleAddEmptyFolder(item)\">\n <template #icon>\n <ScalarIconPlus />\n </template>\n <template #default>Add operation</template>\n </ScalarSidebarItem>\n </template>\n\n <!-- Getting started section -->\n <template\n v-if=\"layout !== 'modal'\"\n #footer>\n <div\n :class=\"{\n 'empty-sidebar-item border-t': showGettingStarted,\n }\">\n <div\n v-if=\"showGettingStarted\"\n class=\"empty-sidebar-item-content overflow-hidden px-2.5 py-2.5\">\n <div class=\"rabbit-ascii relative m-auto mt-2 h-[68px] w-[60px]\">\n <ScalarAsciiArt\n :art=\"Rabbit\"\n class=\"rabbitsit font-bold\" />\n <ScalarAsciiArt\n :art=\"RabbitJump\"\n class=\"rabbitjump absolute top-0 left-0 font-bold\" />\n </div>\n <div class=\"mt-2 mb-2 text-center text-sm text-balance\">\n <b class=\"font-medium\">Let's Get Started</b>\n <p class=\"mt-2 leading-5\">\n Create request, folder, collection or import from\n OpenAPI/Postman\n </p>\n </div>\n </div>\n\n <div class=\"flex flex-col gap-1.5 p-2\">\n <ScalarButton\n v-if=\"showGettingStarted\"\n class=\"w-full\"\n size=\"sm\"\n @click=\"\n eventBus.emit('ui:open:command-palette', {\n action: 'import-from-openapi-swagger-postman-curl',\n payload: undefined,\n })\n \">\n Import Collection\n </ScalarButton>\n\n <ScalarButton\n class=\"w-full\"\n hotkey=\"K\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"eventBus.emit('ui:open:command-palette')\">\n Add Item &nbsp;\n\n <span\n class=\"text-sidebar-c-2 rounded border px-1.25 py-1 text-xs leading-none font-medium uppercase\">\n <template v-if=\"isMacOS()\">\n <span class=\"sr-only\">Command</span>\n <span aria-hidden=\"true\">⌘</span>\n </template>\n <template v-else>\n <span class=\"sr-only\">CTRL</span>\n <span aria-hidden=\"true\">⌃</span>\n </template>\n K\n </span>\n </ScalarButton>\n <DownloadAppButton v-if=\"layout === 'web'\" />\n </div>\n </div>\n </template>\n </Sidebar>\n <SidebarItemMenu\n v-if=\"menuTarget?.showMenu\"\n :eventBus=\"eventBus\"\n :item=\"menuTarget.item\"\n :sidebarState=\"sidebarState\"\n :target=\"menuTarget.el\"\n @closeMenu=\"closeMenu\"\n @showDeleteModal=\"deleteModalState.show()\" />\n\n <!-- Delete Modal -->\n <ScalarModal\n v-if=\"menuTarget\"\n size=\"xxs\"\n :state=\"deleteModalState\"\n :title=\"`Delete ${menuTarget.item.title}`\">\n <DeleteSidebarListElement\n :variableName=\"menuTarget.item.title\"\n :warningMessage=\"deleteMessage\"\n @close=\"deleteModalState.hide()\"\n @delete=\"handleDelete\" />\n </ScalarModal>\n </div>\n</template>\n\n<style scoped>\n.empty-sidebar-item-content {\n display: none;\n}\n.empty-sidebar-item .empty-sidebar-item-content {\n display: block;\n}\n.rabbitjump {\n opacity: 0;\n}\n.empty-sidebar-item:hover .rabbitjump {\n opacity: 1;\n animation: rabbitAnimation 0.5s steps(1) infinite;\n}\n.empty-sidebar-item:hover .rabbitsit {\n opacity: 0;\n animation: rabbitAnimation2 0.5s steps(1) infinite;\n}\n.empty-sidebar-item:hover .rabbit-ascii {\n animation: rabbitRun 8s infinite linear;\n}\n@keyframes rabbitRun {\n 0% {\n transform: translate3d(0, 0, 0);\n }\n 25% {\n transform: translate3d(250px, 0, 0);\n }\n 25.01% {\n transform: translate3d(-250px, 0, 0);\n }\n 75% {\n transform: translate3d(250px, 0, 0);\n }\n 75.01% {\n transform: translate3d(-250px, 0, 0);\n }\n 100% {\n transform: translate3d(0, 0, 0);\n }\n}\n@keyframes rabbitAnimation {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n }\n}\n@keyframes rabbitAnimation2 {\n 0%,\n 100% {\n opacity: 0;\n }\n 50% {\n opacity: 1;\n transform: translate3d(0, -8px, 0);\n }\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"AppSidebar.vue.script.js","names":[],"sources":["../../../../../src/v2/features/app/components/AppSidebar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarIconButton,\n ScalarModal,\n ScalarSidebarItem,\n useModal,\n type WorkspaceGroup,\n} from '@scalar/components'\nimport { isMacOS } from '@scalar/helpers/general/is-mac-os'\nimport {\n ScalarIconDotsThree,\n ScalarIconGearSix,\n ScalarIconPlus,\n} from '@scalar/icons'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport type { DraggingItem, HoveredItem, SidebarState } from '@scalar/sidebar'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport type {\n TraversedEntry,\n TraversedOperation,\n} from '@scalar/workspace-store/schemas/navigation'\nimport { capitalize, computed, nextTick, ref } from 'vue'\n\nimport Rabbit from '@/assets/rabbit.ascii?raw'\nimport RabbitJump from '@/assets/rabbitjump.ascii?raw'\nimport ScalarAsciiArt from '@/components/ScalarAsciiArt.vue'\nimport DeleteSidebarListElement from '@/components/Sidebar/Actions/DeleteSidebarListElement.vue'\nimport { Sidebar } from '@/v2/components/sidebar'\nimport DownloadAppButton from '@/v2/features/app/components/DownloadAppButton.vue'\nimport SidebarItemMenu from '@/v2/features/app/components/SidebarItemMenu.vue'\nimport { createTempOperation } from '@/v2/features/app/helpers/create-temp-operation'\nimport { dragHandleFactory } from '@/v2/helpers/drag-handle-factory'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nconst { sidebarState, layout, activeWorkspace, workspaces, store, eventBus } =\n defineProps<{\n /**\n * The current layout of the app (e.g., 'desktop', 'web')\n */\n layout: ClientLayout\n\n /**\n * The sidebar state, holding navigation items and state\n */\n sidebarState: SidebarState<TraversedEntry>\n\n /**\n * Whether the workspace overview sidebar is currently open\n */\n isWorkspaceOpen?: boolean\n /**\n * The currently active workspace.\n * This represents the workspace that the user is currently working in.\n */\n activeWorkspace: { id: string; label: string }\n /**\n * The list of all available workspaces.\n * Used to render options for workspace switching and selection.\n */\n workspaces: WorkspaceGroup[]\n /**\n * The workspace event bus for handling workspace-level events.\n * Used for triggering and responding to workspace changes and actions.\n */\n eventBus: WorkspaceEventBus\n /**\n * The WorkspaceStore instance for managing workspace state and actions.\n * Provides methods and state for interacting with the current workspace.\n */\n store: WorkspaceStore\n }>()\n\nconst emit = defineEmits<{\n /** Emitted when the workspace button in the sidebar is clicked */\n (e: 'click:workspace'): void\n /** Emitted when a navigation or sidebar item is selected by ID */\n (e: 'selectItem', id: string): void\n /** Emitted when a workspace is selected by optional ID */\n (e: 'select:workspace', id?: string): void\n /** Emitted when the user requests to create a new workspace */\n (e: 'create:workspace'): void\n}>()\n\ndefineSlots<{\n /** Slot for customizing the actions section of the sidebar menu. */\n sidebarMenuActions?(): unknown\n}>()\n\n/** The label for the workspace button in the sidebar */\nconst workspaceLabel = computed(() => capitalize(activeWorkspace.label))\n\n/** Controls the visibility of the sidebar */\nconst isSidebarOpen = defineModel<boolean>('isSidebarOpen', {\n required: true,\n})\n\n/** Controls the width of the sidebar */\nconst sidebarWidth = defineModel<number>('sidebarWidth', {\n required: true,\n default: 288,\n})\n\n/** Calculate if we should show the getting started section */\nconst showGettingStarted = computed(() => sidebarState.items.value.length <= 1)\n\n/*\n * Setup drag and drop handlers for sidebar items.\n * The dragHandleFactory takes the current workspace store and sidebar state,\n * and returns the appropriate handlers for drag ending and droppability.\n *\n * We use computed to ensure the handlers are recreated when the store or sidebarState changes,\n * so they always have access to the latest values.\n */\nconst dragHandlers = computed(() =>\n dragHandleFactory({\n store,\n sidebarState,\n }),\n)\n\nconst handleDragEnd = (\n draggingItem: DraggingItem,\n hoveredItem: HoveredItem,\n): boolean => {\n return dragHandlers.value.handleDragEnd(draggingItem, hoveredItem)\n}\n\nconst isDroppable = (\n draggingItem: DraggingItem,\n hoveredItem: HoveredItem,\n): boolean => {\n return dragHandlers.value.isDroppable(draggingItem, hoveredItem)\n}\n\n/** The current target for the dropdown menu */\nconst menuTarget = ref<{\n /** The sidebar item that the menu is targeting */\n item: TraversedEntry\n /** A reference to the element that the menu is for */\n el: HTMLElement\n /** Whether or not to show the menu */\n showMenu: boolean\n} | null>(null)\n\nconst deleteModalState = useModal()\n\n/** Computes the message for the delete modal */\nconst deleteMessage = computed(() => {\n const item = menuTarget.value?.item\n\n if (item?.type === 'document') {\n return \"This cannot be undone. You're about to delete the document and all tags and operations inside it.\"\n }\n\n return `Are you sure you want to delete this ${item?.type ?? 'item'}? This action cannot be undone.`\n})\n\n/** Deletes an item from the sidebar by emitting the appropriate event */\nconst handleDelete = () => {\n const item = menuTarget.value?.item\n\n if (!item) {\n return\n }\n\n const result = sidebarState.getEntryById(item.id)\n\n const document = getParentEntry('document', result)\n const operation = getParentEntry('operation', result)\n\n if (!document) {\n return\n }\n\n if (item.type === 'document') {\n eventBus.emit('document:delete:document', { name: document.name })\n } else if (item.type === 'tag') {\n eventBus.emit('tag:delete:tag', {\n documentName: document.name,\n name: item.name,\n })\n } else if (item.type === 'operation') {\n if (!operation) {\n return\n }\n\n eventBus.emit('operation:delete:operation', {\n meta: {\n method: operation.method,\n path: operation.path,\n },\n documentName: document.name,\n })\n } else if (item.type === 'example') {\n if (!operation) {\n return\n }\n\n eventBus.emit('operation:delete:example', {\n meta: {\n method: operation.method,\n path: operation.path,\n exampleKey: item.name,\n },\n documentName: document.name,\n })\n }\n\n /** Clean up after deletion */\n deleteModalState.hide()\n menuTarget.value = null\n}\n\n/** Opens the dropdown menu for the given item */\nconst openMenu = async (\n event: MouseEvent | KeyboardEvent,\n item: TraversedEntry,\n) => {\n if (menuTarget.value?.showMenu) {\n return\n }\n\n const el = event.currentTarget as HTMLElement\n menuTarget.value = { item, el, showMenu: true }\n\n // Wait for the target to bind to the element\n await nextTick()\n\n // Re-dispatch the event on the target to open the menu\n const cloned =\n event instanceof MouseEvent\n ? new MouseEvent(event.type, event)\n : new KeyboardEvent(event.type, event)\n\n menuTarget.value?.el.dispatchEvent(cloned)\n}\n\n/** Closes the dropdown menu */\nconst closeMenu = () => {\n if (menuTarget.value) {\n menuTarget.value.showMenu = false\n }\n}\n\n/**\n * Creates a new operation directly from the empty folder slot.\n * Uses a unique temporary path to avoid conflicts, then navigates to the operation,\n * updates the path to `/`, and focuses the address bar so the user can immediately start typing.\n */\nconst handleAddEmptyFolder = (item: TraversedEntry) => {\n const itemWithParent = sidebarState.getEntryById(item.id)\n const documentName = getParentEntry('document', itemWithParent)?.name\n const tagName = getParentEntry('tag', itemWithParent)?.name\n\n if (!documentName) {\n console.error('Document name not found')\n return\n }\n createTempOperation(documentName, {\n existingPaths: new Set(\n Object.keys(store.workspace.documents[documentName]?.paths ?? {}),\n ),\n eventBus,\n tags: tagName ? [tagName] : undefined,\n })\n}\n\n/**\n * Navigates to the operations page for the provided operation item.\n * Emits a navigation event for the operation overview page.\n */\nconst navigateToOperationsPage = (item: TraversedOperation) => {\n const operationWithParent = sidebarState.getEntryById(item.id)\n const documentSlug = getParentEntry('document', operationWithParent)?.name\n\n eventBus.emit('ui:navigate', {\n page: 'operation',\n path: 'overview',\n operationPath: item.path,\n method: item.method,\n documentSlug: documentSlug,\n })\n}\n</script>\n\n<template>\n <div class=\"flex\">\n <Sidebar\n v-model:sidebarWidth=\"sidebarWidth\"\n :activeWorkspace=\"activeWorkspace\"\n :class=\"[\n 'max-md:inset-y-0 max-md:z-2 max-md:w-full!',\n isSidebarOpen ? 'max-md:fixed! max-md:flex!' : 'max-md:hidden!',\n ]\"\n :documents=\"Object.values(store.workspace.documents)\"\n :isDroppable=\"isDroppable\"\n :layout=\"layout\"\n :sidebarState=\"sidebarState\"\n :workspaces=\"workspaces\"\n @create:workspace=\"emit('create:workspace')\"\n @navigate:to:settings=\"\n eventBus.emit('ui:navigate', { page: 'workspace', path: 'settings' })\n \"\n @reorder=\"\n (draggingItem, hoveredItem) => handleDragEnd(draggingItem, hoveredItem)\n \"\n @select:workspace=\"(id) => emit('select:workspace', id)\"\n @selectItem=\"(id) => emit('selectItem', id)\">\n <template #sidebarMenuActions>\n <slot name=\"sidebarMenuActions\" />\n </template>\n <!-- Workspace Identifier -->\n <template #workspaceButton>\n <ScalarSidebarItem\n is=\"button\"\n :active=\"isWorkspaceOpen\"\n @click=\"emit('click:workspace')\">\n {{ workspaceLabel }}\n </ScalarSidebarItem>\n </template>\n\n <!-- Decorator dropdown menu -->\n <template #decorator=\"{ item }\">\n <div class=\"flex items-center gap-0.5\">\n <ScalarIconButton\n v-if=\"item.type === 'operation'\"\n :icon=\"ScalarIconGearSix\"\n label=\"Operation settings\"\n size=\"sm\"\n weight=\"bold\"\n @click.stop=\"navigateToOperationsPage(item)\"\n @keydown.enter.stop=\"navigateToOperationsPage(item)\"\n @keydown.space.stop=\"navigateToOperationsPage(item)\" />\n <ScalarIconButton\n aria-expanded=\"false\"\n aria-haspopup=\"menu\"\n :icon=\"ScalarIconDotsThree\"\n label=\"More options\"\n size=\"sm\"\n weight=\"bold\"\n @click.stop=\"(e: MouseEvent) => openMenu(e, item)\"\n @keydown.down.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.enter.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.space.stop=\"(e: KeyboardEvent) => openMenu(e, item)\"\n @keydown.up.stop=\"(e: KeyboardEvent) => openMenu(e, item)\" />\n </div>\n </template>\n\n <!-- Dirty document icon slot -->\n <template #icon=\"{ item }\">\n <template\n v-if=\"\n item.type === 'document' &&\n store.workspace.documents[item.name]?.['x-scalar-is-dirty'] === true\n \">\n <div class=\"relative flex items-center\">\n <LibraryIcon\n class=\"block\"\n :src=\"\n ('icon' in item && item.icon) || 'interface-content-folder'\n \" />\n <div\n class=\"bg-c-accent absolute -top-0.5 -right-0.5 size-1.5 rounded-full\">\n <span class=\"sr-only\">Unsaved changes</span>\n </div>\n </div>\n </template>\n </template>\n\n <!-- Empty folder slot -->\n <template #empty=\"{ item }\">\n <ScalarSidebarItem\n is=\"button\"\n @click=\"handleAddEmptyFolder(item)\">\n <template #icon>\n <ScalarIconPlus />\n </template>\n <template #default>Add operation</template>\n </ScalarSidebarItem>\n </template>\n\n <!-- Getting started section -->\n <template\n v-if=\"layout !== 'modal'\"\n #footer>\n <div\n :class=\"{\n 'empty-sidebar-item border-t': showGettingStarted,\n }\">\n <div\n v-if=\"showGettingStarted\"\n class=\"empty-sidebar-item-content overflow-hidden px-2.5 py-2.5\">\n <div class=\"rabbit-ascii relative m-auto mt-2 h-[68px] w-[60px]\">\n <ScalarAsciiArt\n :art=\"Rabbit\"\n class=\"rabbitsit font-bold\" />\n <ScalarAsciiArt\n :art=\"RabbitJump\"\n class=\"rabbitjump absolute top-0 left-0 font-bold\" />\n </div>\n <div class=\"mt-2 mb-2 text-center text-sm text-balance\">\n <b class=\"font-medium\">Let's Get Started</b>\n <p class=\"mt-2 leading-5\">\n Create request, folder, collection or import from\n OpenAPI/Postman\n </p>\n </div>\n </div>\n\n <div class=\"flex flex-col gap-1.5 p-2\">\n <ScalarButton\n v-if=\"showGettingStarted\"\n class=\"w-full\"\n size=\"sm\"\n @click=\"\n eventBus.emit('ui:open:command-palette', {\n action: 'import-from-openapi-swagger-postman-curl',\n payload: undefined,\n })\n \">\n Import Collection\n </ScalarButton>\n\n <ScalarButton\n class=\"w-full\"\n hotkey=\"K\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"eventBus.emit('ui:open:command-palette')\">\n Add Item &nbsp;\n\n <span\n class=\"text-sidebar-c-2 rounded border px-1.25 py-1 text-xs leading-none font-medium uppercase\">\n <template v-if=\"isMacOS()\">\n <span class=\"sr-only\">Command</span>\n <span aria-hidden=\"true\">⌘</span>\n </template>\n <template v-else>\n <span class=\"sr-only\">CTRL</span>\n <span aria-hidden=\"true\">⌃</span>\n </template>\n K\n </span>\n </ScalarButton>\n <DownloadAppButton v-if=\"layout === 'web'\" />\n </div>\n </div>\n </template>\n </Sidebar>\n <SidebarItemMenu\n v-if=\"menuTarget?.showMenu\"\n :eventBus=\"eventBus\"\n :item=\"menuTarget.item\"\n :sidebarState=\"sidebarState\"\n :target=\"menuTarget.el\"\n :workspaceStore=\"store\"\n @closeMenu=\"closeMenu\"\n @showDeleteModal=\"deleteModalState.show()\" />\n\n <!-- Delete Modal -->\n <ScalarModal\n v-if=\"menuTarget\"\n size=\"xxs\"\n :state=\"deleteModalState\"\n :title=\"`Delete ${menuTarget.item.title}`\">\n <DeleteSidebarListElement\n :variableName=\"menuTarget.item.title\"\n :warningMessage=\"deleteMessage\"\n @close=\"deleteModalState.hide()\"\n @delete=\"handleDelete\" />\n </ScalarModal>\n </div>\n</template>\n\n<style scoped>\n.empty-sidebar-item-content {\n display: none;\n}\n.empty-sidebar-item .empty-sidebar-item-content {\n display: block;\n}\n.rabbitjump {\n opacity: 0;\n}\n.empty-sidebar-item:hover .rabbitjump {\n opacity: 1;\n animation: rabbitAnimation 0.5s steps(1) infinite;\n}\n.empty-sidebar-item:hover .rabbitsit {\n opacity: 0;\n animation: rabbitAnimation2 0.5s steps(1) infinite;\n}\n.empty-sidebar-item:hover .rabbit-ascii {\n animation: rabbitRun 8s infinite linear;\n}\n@keyframes rabbitRun {\n 0% {\n transform: translate3d(0, 0, 0);\n }\n 25% {\n transform: translate3d(250px, 0, 0);\n }\n 25.01% {\n transform: translate3d(-250px, 0, 0);\n }\n 75% {\n transform: translate3d(250px, 0, 0);\n }\n 75.01% {\n transform: translate3d(-250px, 0, 0);\n }\n 100% {\n transform: translate3d(0, 0, 0);\n }\n}\n@keyframes rabbitAnimation {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n }\n}\n@keyframes rabbitAnimation2 {\n 0%,\n 100% {\n opacity: 0;\n }\n 50% {\n opacity: 1;\n transform: translate3d(0, -8px, 0);\n }\n}\n</style>\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { SidebarState } from '@scalar/sidebar';
2
+ import type { WorkspaceStore } from '@scalar/workspace-store/client';
2
3
  import type { WorkspaceEventBus } from '@scalar/workspace-store/events';
3
4
  import type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation';
4
5
  type __VLS_Props = {
@@ -10,6 +11,8 @@ type __VLS_Props = {
10
11
  sidebarState: SidebarState<TraversedEntry>;
11
12
  /** The target to position the dropdown relative to */
12
13
  target: HTMLElement;
14
+ /** The workspace store for accessing documents */
15
+ workspaceStore: WorkspaceStore;
13
16
  };
14
17
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
15
18
  closeMenu: () => any;
@@ -1 +1 @@
1
- {"version":3,"file":"SidebarItemMenu.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/components/SidebarItemMenu.vue"],"names":[],"mappings":"AA+OA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAA;AAGhF,KAAK,WAAW,GAAG;IACjB,4CAA4C;IAC5C,IAAI,EAAE,cAAc,CAAA;IACpB,sCAAsC;IACtC,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,qDAAqD;IACrD,YAAY,EAAE,YAAY,CAAC,cAAc,CAAC,CAAA;IAC1C,sDAAsD;IACtD,MAAM,EAAE,WAAW,CAAA;CACpB,CAAC;AAqdF,QAAA,MAAM,YAAY;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"SidebarItemMenu.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/components/SidebarItemMenu.vue"],"names":[],"mappings":"AAiPA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAA;AAKhF,KAAK,WAAW,GAAG;IACjB,4CAA4C;IAC5C,IAAI,EAAE,cAAc,CAAA;IACpB,sCAAsC;IACtC,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,qDAAqD;IACrD,YAAY,EAAE,YAAY,CAAC,cAAc,CAAC,CAAA;IAC1C,sDAAsD;IACtD,MAAM,EAAE,WAAW,CAAA;IACnB,kDAAkD;IAClD,cAAc,EAAE,cAAc,CAAA;CAC/B,CAAC;AA6cF,QAAA,MAAM,YAAY;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1 +1 @@
1
- {"version":3,"file":"SidebarItemMenu.vue.js","names":[],"sources":["../../../../../src/v2/features/app/components/SidebarItemMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarDropdown,\n ScalarDropdownDivider,\n ScalarDropdownItem,\n ScalarIcon,\n} from '@scalar/components'\nimport { ScalarIconPencil } from '@scalar/icons'\nimport type { SidebarState } from '@scalar/sidebar'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\nimport { nextTick, ref, watch } from 'vue'\n\nconst { item, eventBus, sidebarState, target } = defineProps<{\n /** The item to display the decorator for */\n item: TraversedEntry\n /** The event bus to emit events to */\n eventBus: WorkspaceEventBus\n /** The sidebar state to get the parent entry from */\n sidebarState: SidebarState<TraversedEntry>\n /** The target to position the dropdown relative to */\n target: HTMLElement\n}>()\n\nconst emit = defineEmits<{\n (e: 'closeMenu'): void\n (e: 'showDeleteModal'): void\n}>()\n\nconst open = ref(false)\n\nwatch(open, async (newValue, oldValue) => {\n // Close the menu if it was open and is now closed\n if (!newValue && oldValue) {\n // Wait to let the menu close and clean up the aria attributes\n await nextTick()\n emit('closeMenu')\n }\n})\n\n/** Returns whether the item supports adding operations */\nconst canAddOperation = (): boolean =>\n item.type === 'document' || item.type === 'tag'\n\n/** Returns whether the item supports adding tags */\nconst canAddTag = (): boolean => item.type === 'document'\n\n/** Returns whether the item supports editing tags */\nconst canEditTag = (): boolean => item.type === 'tag'\n\n/** Returns whether the item supports editing examples */\nconst canEditExample = (): boolean => item.type === 'example'\n\n/** Returns whether the item supports adding examples */\nconst canAddExample = (): boolean => item.type === 'operation'\n\n/** Returns whether the item supports deletion */\nconst canDelete = (): boolean =>\n (item.type === 'document' && item.id !== 'drafts') ||\n item.type === 'tag' ||\n item.type === 'operation' ||\n item.type === 'example'\n\nconst handleAddOperation = () => {\n if (item.type === 'document') {\n eventBus.emit('ui:open:command-palette', {\n action: 'create-request',\n payload: {\n documentName: item.name,\n },\n })\n }\n\n if (item.type === 'tag') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n eventBus.emit('ui:open:command-palette', {\n action: 'create-request',\n payload: {\n documentName: getParentEntry('document', itemWithParent)?.name,\n tagId: item.name,\n },\n })\n }\n}\n\nconst handleAddTag = () => {\n if (item.type === 'document') {\n eventBus.emit('ui:open:command-palette', {\n action: 'add-tag',\n payload: {\n documentName: item.name,\n },\n })\n }\n}\n\nconst handleEditTag = () => {\n if (item.type === 'tag') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n eventBus.emit(\n 'ui:open:command-palette',\n {\n action: 'edit-tag',\n payload: {\n tag: item,\n documentName: getParentEntry('document', itemWithParent)?.name ?? '',\n },\n },\n { skipUnpackProxy: true },\n )\n }\n}\n\nconst handleAddExample = () => {\n if (item.type === 'operation') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n eventBus.emit('ui:open:command-palette', {\n action: 'add-example',\n payload: {\n documentName: getParentEntry('document', itemWithParent)?.name,\n operationId: item.id,\n },\n })\n }\n}\n\nconst handleEditExample = () => {\n if (item.type === 'example') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n const parentOperation = getParentEntry('operation', itemWithParent)\n eventBus.emit(\n 'ui:open:command-palette',\n {\n action: 'edit-example',\n payload: {\n example: item,\n documentName: getParentEntry('document', itemWithParent)?.name ?? '',\n operationId: parentOperation?.id ?? '',\n },\n } as any,\n { skipUnpackProxy: true },\n )\n }\n}\n</script>\n<template>\n <ScalarDropdown\n v-model:open=\"open\"\n placement=\"bottom-end\"\n :target=\"target\"\n teleport>\n <template #items>\n <!-- Add operation option for documents and tags -->\n <ScalarDropdownItem\n v-if=\"canAddOperation()\"\n @click=\"handleAddOperation()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Operation\n </div>\n </ScalarDropdownItem>\n\n <!-- Add tag option for documents only -->\n <ScalarDropdownItem\n v-if=\"canAddTag()\"\n @click=\"handleAddTag()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Tag\n </div>\n </ScalarDropdownItem>\n\n <!-- Edit tag option for tags only -->\n <ScalarDropdownItem\n v-if=\"canEditTag()\"\n @click=\"handleEditTag()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIconPencil size=\"sm\" />\n Rename Tag\n </div>\n </ScalarDropdownItem>\n\n <!-- Edit example option for examples only -->\n <ScalarDropdownItem\n v-if=\"canEditExample()\"\n @click=\"handleEditExample()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIconPencil size=\"sm\" />\n Rename Example\n </div>\n </ScalarDropdownItem>\n\n <!-- Add example option for operations -->\n <ScalarDropdownItem\n v-if=\"canAddExample()\"\n @click=\"handleAddExample()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Example\n </div>\n </ScalarDropdownItem>\n <ScalarDropdownDivider\n v-if=\"\n (canAddExample() ||\n canAddOperation() ||\n canAddTag() ||\n canEditExample()) &&\n canDelete()\n \" />\n <ScalarDropdownItem\n v-if=\"canDelete()\"\n @click=\"emit('showDeleteModal')\">\n <div class=\"text-red flex items-center gap-2\">\n <ScalarIcon\n icon=\"Delete\"\n size=\"sm\" />\n Delete\n </div>\n </ScalarDropdownItem>\n </template>\n </ScalarDropdown>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"SidebarItemMenu.vue.js","names":[],"sources":["../../../../../src/v2/features/app/components/SidebarItemMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarDropdown,\n ScalarDropdownDivider,\n ScalarDropdownItem,\n ScalarIcon,\n} from '@scalar/components'\nimport { ScalarIconPencil } from '@scalar/icons'\nimport type { SidebarState } from '@scalar/sidebar'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\nimport { nextTick, ref, watch } from 'vue'\n\nimport { createTempOperation } from '@/v2/features/app/helpers/create-temp-operation'\n\nconst { item, eventBus, sidebarState, target, workspaceStore } = defineProps<{\n /** The item to display the decorator for */\n item: TraversedEntry\n /** The event bus to emit events to */\n eventBus: WorkspaceEventBus\n /** The sidebar state to get the parent entry from */\n sidebarState: SidebarState<TraversedEntry>\n /** The target to position the dropdown relative to */\n target: HTMLElement\n /** The workspace store for accessing documents */\n workspaceStore: WorkspaceStore\n}>()\n\nconst emit = defineEmits<{\n (e: 'closeMenu'): void\n (e: 'showDeleteModal'): void\n}>()\n\nconst open = ref(false)\n\nwatch(open, async (newValue, oldValue) => {\n // Close the menu if it was open and is now closed\n if (!newValue && oldValue) {\n // Wait to let the menu close and clean up the aria attributes\n await nextTick()\n emit('closeMenu')\n }\n})\n\n/** Returns whether the item supports adding operations */\nconst canAddOperation = (): boolean =>\n item.type === 'document' || item.type === 'tag'\n\n/** Returns whether the item supports adding tags */\nconst canAddTag = (): boolean => item.type === 'document'\n\n/** Returns whether the item supports editing tags */\nconst canEditTag = (): boolean => item.type === 'tag'\n\n/** Returns whether the item supports editing examples */\nconst canEditExample = (): boolean => item.type === 'example'\n\n/** Returns whether the item supports adding examples */\nconst canAddExample = (): boolean => item.type === 'operation'\n\n/** Returns whether the item supports deletion */\nconst canDelete = (): boolean =>\n (item.type === 'document' && item.id !== 'drafts') ||\n item.type === 'tag' ||\n item.type === 'operation' ||\n item.type === 'example'\n\nconst handleAddTag = () => {\n if (item.type === 'document') {\n eventBus.emit('ui:open:command-palette', {\n action: 'add-tag',\n payload: {\n documentName: item.name,\n },\n })\n }\n}\n\nconst handleEditTag = () => {\n if (item.type === 'tag') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n eventBus.emit(\n 'ui:open:command-palette',\n {\n action: 'edit-tag',\n payload: {\n tag: item,\n documentName: getParentEntry('document', itemWithParent)?.name ?? '',\n },\n },\n { skipUnpackProxy: true },\n )\n }\n}\n\nconst handleAddExample = () => {\n if (item.type === 'operation') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n eventBus.emit('ui:open:command-palette', {\n action: 'add-example',\n payload: {\n documentName: getParentEntry('document', itemWithParent)?.name,\n operationId: item.id,\n },\n })\n }\n}\n\nconst handleEditExample = () => {\n if (item.type === 'example') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n const parentOperation = getParentEntry('operation', itemWithParent)\n eventBus.emit(\n 'ui:open:command-palette',\n {\n action: 'edit-example',\n payload: {\n example: item,\n documentName: getParentEntry('document', itemWithParent)?.name ?? '',\n operationId: parentOperation?.id ?? '',\n },\n } as any,\n { skipUnpackProxy: true },\n )\n }\n}\n\nconst handleAddOperation = () => {\n const itemWithParent = sidebarState.getEntryById(item.id)\n const documentName = getParentEntry('document', itemWithParent)?.name\n const tagName = getParentEntry('tag', itemWithParent)?.name\n if (!documentName) {\n console.error('Document name not found')\n return\n }\n createTempOperation(documentName, {\n existingPaths: new Set(\n Object.keys(\n workspaceStore.workspace.documents[documentName]?.paths ?? {},\n ),\n ),\n eventBus,\n tags: tagName ? [tagName] : undefined,\n })\n}\n</script>\n<template>\n <ScalarDropdown\n v-model:open=\"open\"\n placement=\"bottom-end\"\n :target=\"target\"\n teleport>\n <template #items>\n <!-- Add operation option for documents and tags -->\n <ScalarDropdownItem\n v-if=\"canAddOperation()\"\n @click=\"handleAddOperation\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Operation\n </div>\n </ScalarDropdownItem>\n\n <!-- Add tag option for documents only -->\n <ScalarDropdownItem\n v-if=\"canAddTag()\"\n @click=\"handleAddTag()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Tag\n </div>\n </ScalarDropdownItem>\n\n <!-- Edit tag option for tags only -->\n <ScalarDropdownItem\n v-if=\"canEditTag()\"\n @click=\"handleEditTag()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIconPencil size=\"sm\" />\n Rename Tag\n </div>\n </ScalarDropdownItem>\n\n <!-- Edit example option for examples only -->\n <ScalarDropdownItem\n v-if=\"canEditExample()\"\n @click=\"handleEditExample()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIconPencil size=\"sm\" />\n Rename Example\n </div>\n </ScalarDropdownItem>\n\n <!-- Add example option for operations -->\n <ScalarDropdownItem\n v-if=\"canAddExample()\"\n @click=\"handleAddExample()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Example\n </div>\n </ScalarDropdownItem>\n <ScalarDropdownDivider\n v-if=\"\n (canAddExample() ||\n canAddOperation() ||\n canAddTag() ||\n canEditExample()) &&\n canDelete()\n \" />\n <ScalarDropdownItem\n v-if=\"canDelete()\"\n @click=\"emit('showDeleteModal')\">\n <div class=\"text-red flex items-center gap-2\">\n <ScalarIcon\n icon=\"Delete\"\n size=\"sm\" />\n Delete\n </div>\n </ScalarDropdownItem>\n </template>\n </ScalarDropdown>\n</template>\n"],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import { createTempOperation } from "../helpers/create-temp-operation.js";
1
2
  import { createBlock, createCommentVNode, createElementVNode, createTextVNode, createVNode, defineComponent, nextTick, openBlock, ref, unref, watch, withCtx } from "vue";
2
3
  import { ScalarDropdown, ScalarDropdownDivider, ScalarDropdownItem, ScalarIcon } from "@scalar/components";
3
4
  import { ScalarIconPencil } from "@scalar/icons";
@@ -15,7 +16,8 @@ var SidebarItemMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
15
16
  item: {},
16
17
  eventBus: {},
17
18
  sidebarState: {},
18
- target: {}
19
+ target: {},
20
+ workspaceStore: {}
19
21
  },
20
22
  emits: ["closeMenu", "showDeleteModal"],
21
23
  setup(__props, { emit: __emit }) {
@@ -39,22 +41,6 @@ var SidebarItemMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
39
41
  const canAddExample = () => __props.item.type === "operation";
40
42
  /** Returns whether the item supports deletion */
41
43
  const canDelete = () => __props.item.type === "document" && __props.item.id !== "drafts" || __props.item.type === "tag" || __props.item.type === "operation" || __props.item.type === "example";
42
- const handleAddOperation = () => {
43
- if (__props.item.type === "document") __props.eventBus.emit("ui:open:command-palette", {
44
- action: "create-request",
45
- payload: { documentName: __props.item.name }
46
- });
47
- if (__props.item.type === "tag") {
48
- const itemWithParent = __props.sidebarState.getEntryById(__props.item.id);
49
- __props.eventBus.emit("ui:open:command-palette", {
50
- action: "create-request",
51
- payload: {
52
- documentName: getParentEntry("document", itemWithParent)?.name,
53
- tagId: __props.item.name
54
- }
55
- });
56
- }
57
- };
58
44
  const handleAddTag = () => {
59
45
  if (__props.item.type === "document") __props.eventBus.emit("ui:open:command-palette", {
60
46
  action: "add-tag",
@@ -99,10 +85,24 @@ var SidebarItemMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
99
85
  }, { skipUnpackProxy: true });
100
86
  }
101
87
  };
88
+ const handleAddOperation = () => {
89
+ const itemWithParent = __props.sidebarState.getEntryById(__props.item.id);
90
+ const documentName = getParentEntry("document", itemWithParent)?.name;
91
+ const tagName = getParentEntry("tag", itemWithParent)?.name;
92
+ if (!documentName) {
93
+ console.error("Document name not found");
94
+ return;
95
+ }
96
+ createTempOperation(documentName, {
97
+ existingPaths: new Set(Object.keys(__props.workspaceStore.workspace.documents[documentName]?.paths ?? {})),
98
+ eventBus: __props.eventBus,
99
+ tags: tagName ? [tagName] : void 0
100
+ });
101
+ };
102
102
  return (_ctx, _cache) => {
103
103
  return openBlock(), createBlock(unref(ScalarDropdown), {
104
104
  open: open.value,
105
- "onUpdate:open": _cache[6] || (_cache[6] = ($event) => open.value = $event),
105
+ "onUpdate:open": _cache[5] || (_cache[5] = ($event) => open.value = $event),
106
106
  placement: "bottom-end",
107
107
  target: __props.target,
108
108
  teleport: ""
@@ -110,57 +110,57 @@ var SidebarItemMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
110
110
  items: withCtx(() => [
111
111
  canAddOperation() ? (openBlock(), createBlock(unref(ScalarDropdownItem), {
112
112
  key: 0,
113
- onClick: _cache[0] || (_cache[0] = ($event) => handleAddOperation())
113
+ onClick: handleAddOperation
114
114
  }, {
115
115
  default: withCtx(() => [createElementVNode("div", _hoisted_1, [createVNode(unref(ScalarIcon), {
116
116
  icon: "Add",
117
117
  size: "sm"
118
- }), _cache[7] || (_cache[7] = createTextVNode(" Add Operation ", -1))])]),
118
+ }), _cache[6] || (_cache[6] = createTextVNode(" Add Operation ", -1))])]),
119
119
  _: 1
120
120
  })) : createCommentVNode("", true),
121
121
  canAddTag() ? (openBlock(), createBlock(unref(ScalarDropdownItem), {
122
122
  key: 1,
123
- onClick: _cache[1] || (_cache[1] = ($event) => handleAddTag())
123
+ onClick: _cache[0] || (_cache[0] = ($event) => handleAddTag())
124
124
  }, {
125
125
  default: withCtx(() => [createElementVNode("div", _hoisted_2, [createVNode(unref(ScalarIcon), {
126
126
  icon: "Add",
127
127
  size: "sm"
128
- }), _cache[8] || (_cache[8] = createTextVNode(" Add Tag ", -1))])]),
128
+ }), _cache[7] || (_cache[7] = createTextVNode(" Add Tag ", -1))])]),
129
129
  _: 1
130
130
  })) : createCommentVNode("", true),
131
131
  canEditTag() ? (openBlock(), createBlock(unref(ScalarDropdownItem), {
132
132
  key: 2,
133
- onClick: _cache[2] || (_cache[2] = ($event) => handleEditTag())
133
+ onClick: _cache[1] || (_cache[1] = ($event) => handleEditTag())
134
134
  }, {
135
- default: withCtx(() => [createElementVNode("div", _hoisted_3, [createVNode(unref(ScalarIconPencil), { size: "sm" }), _cache[9] || (_cache[9] = createTextVNode(" Rename Tag ", -1))])]),
135
+ default: withCtx(() => [createElementVNode("div", _hoisted_3, [createVNode(unref(ScalarIconPencil), { size: "sm" }), _cache[8] || (_cache[8] = createTextVNode(" Rename Tag ", -1))])]),
136
136
  _: 1
137
137
  })) : createCommentVNode("", true),
138
138
  canEditExample() ? (openBlock(), createBlock(unref(ScalarDropdownItem), {
139
139
  key: 3,
140
- onClick: _cache[3] || (_cache[3] = ($event) => handleEditExample())
140
+ onClick: _cache[2] || (_cache[2] = ($event) => handleEditExample())
141
141
  }, {
142
- default: withCtx(() => [createElementVNode("div", _hoisted_4, [createVNode(unref(ScalarIconPencil), { size: "sm" }), _cache[10] || (_cache[10] = createTextVNode(" Rename Example ", -1))])]),
142
+ default: withCtx(() => [createElementVNode("div", _hoisted_4, [createVNode(unref(ScalarIconPencil), { size: "sm" }), _cache[9] || (_cache[9] = createTextVNode(" Rename Example ", -1))])]),
143
143
  _: 1
144
144
  })) : createCommentVNode("", true),
145
145
  canAddExample() ? (openBlock(), createBlock(unref(ScalarDropdownItem), {
146
146
  key: 4,
147
- onClick: _cache[4] || (_cache[4] = ($event) => handleAddExample())
147
+ onClick: _cache[3] || (_cache[3] = ($event) => handleAddExample())
148
148
  }, {
149
149
  default: withCtx(() => [createElementVNode("div", _hoisted_5, [createVNode(unref(ScalarIcon), {
150
150
  icon: "Add",
151
151
  size: "sm"
152
- }), _cache[11] || (_cache[11] = createTextVNode(" Add Example ", -1))])]),
152
+ }), _cache[10] || (_cache[10] = createTextVNode(" Add Example ", -1))])]),
153
153
  _: 1
154
154
  })) : createCommentVNode("", true),
155
155
  (canAddExample() || canAddOperation() || canAddTag() || canEditExample()) && canDelete() ? (openBlock(), createBlock(unref(ScalarDropdownDivider), { key: 5 })) : createCommentVNode("", true),
156
156
  canDelete() ? (openBlock(), createBlock(unref(ScalarDropdownItem), {
157
157
  key: 6,
158
- onClick: _cache[5] || (_cache[5] = ($event) => emit("showDeleteModal"))
158
+ onClick: _cache[4] || (_cache[4] = ($event) => emit("showDeleteModal"))
159
159
  }, {
160
160
  default: withCtx(() => [createElementVNode("div", _hoisted_6, [createVNode(unref(ScalarIcon), {
161
161
  icon: "Delete",
162
162
  size: "sm"
163
- }), _cache[12] || (_cache[12] = createTextVNode(" Delete ", -1))])]),
163
+ }), _cache[11] || (_cache[11] = createTextVNode(" Delete ", -1))])]),
164
164
  _: 1
165
165
  })) : createCommentVNode("", true)
166
166
  ]),
@@ -1 +1 @@
1
- {"version":3,"file":"SidebarItemMenu.vue.script.js","names":[],"sources":["../../../../../src/v2/features/app/components/SidebarItemMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarDropdown,\n ScalarDropdownDivider,\n ScalarDropdownItem,\n ScalarIcon,\n} from '@scalar/components'\nimport { ScalarIconPencil } from '@scalar/icons'\nimport type { SidebarState } from '@scalar/sidebar'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\nimport { nextTick, ref, watch } from 'vue'\n\nconst { item, eventBus, sidebarState, target } = defineProps<{\n /** The item to display the decorator for */\n item: TraversedEntry\n /** The event bus to emit events to */\n eventBus: WorkspaceEventBus\n /** The sidebar state to get the parent entry from */\n sidebarState: SidebarState<TraversedEntry>\n /** The target to position the dropdown relative to */\n target: HTMLElement\n}>()\n\nconst emit = defineEmits<{\n (e: 'closeMenu'): void\n (e: 'showDeleteModal'): void\n}>()\n\nconst open = ref(false)\n\nwatch(open, async (newValue, oldValue) => {\n // Close the menu if it was open and is now closed\n if (!newValue && oldValue) {\n // Wait to let the menu close and clean up the aria attributes\n await nextTick()\n emit('closeMenu')\n }\n})\n\n/** Returns whether the item supports adding operations */\nconst canAddOperation = (): boolean =>\n item.type === 'document' || item.type === 'tag'\n\n/** Returns whether the item supports adding tags */\nconst canAddTag = (): boolean => item.type === 'document'\n\n/** Returns whether the item supports editing tags */\nconst canEditTag = (): boolean => item.type === 'tag'\n\n/** Returns whether the item supports editing examples */\nconst canEditExample = (): boolean => item.type === 'example'\n\n/** Returns whether the item supports adding examples */\nconst canAddExample = (): boolean => item.type === 'operation'\n\n/** Returns whether the item supports deletion */\nconst canDelete = (): boolean =>\n (item.type === 'document' && item.id !== 'drafts') ||\n item.type === 'tag' ||\n item.type === 'operation' ||\n item.type === 'example'\n\nconst handleAddOperation = () => {\n if (item.type === 'document') {\n eventBus.emit('ui:open:command-palette', {\n action: 'create-request',\n payload: {\n documentName: item.name,\n },\n })\n }\n\n if (item.type === 'tag') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n eventBus.emit('ui:open:command-palette', {\n action: 'create-request',\n payload: {\n documentName: getParentEntry('document', itemWithParent)?.name,\n tagId: item.name,\n },\n })\n }\n}\n\nconst handleAddTag = () => {\n if (item.type === 'document') {\n eventBus.emit('ui:open:command-palette', {\n action: 'add-tag',\n payload: {\n documentName: item.name,\n },\n })\n }\n}\n\nconst handleEditTag = () => {\n if (item.type === 'tag') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n eventBus.emit(\n 'ui:open:command-palette',\n {\n action: 'edit-tag',\n payload: {\n tag: item,\n documentName: getParentEntry('document', itemWithParent)?.name ?? '',\n },\n },\n { skipUnpackProxy: true },\n )\n }\n}\n\nconst handleAddExample = () => {\n if (item.type === 'operation') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n eventBus.emit('ui:open:command-palette', {\n action: 'add-example',\n payload: {\n documentName: getParentEntry('document', itemWithParent)?.name,\n operationId: item.id,\n },\n })\n }\n}\n\nconst handleEditExample = () => {\n if (item.type === 'example') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n const parentOperation = getParentEntry('operation', itemWithParent)\n eventBus.emit(\n 'ui:open:command-palette',\n {\n action: 'edit-example',\n payload: {\n example: item,\n documentName: getParentEntry('document', itemWithParent)?.name ?? '',\n operationId: parentOperation?.id ?? '',\n },\n } as any,\n { skipUnpackProxy: true },\n )\n }\n}\n</script>\n<template>\n <ScalarDropdown\n v-model:open=\"open\"\n placement=\"bottom-end\"\n :target=\"target\"\n teleport>\n <template #items>\n <!-- Add operation option for documents and tags -->\n <ScalarDropdownItem\n v-if=\"canAddOperation()\"\n @click=\"handleAddOperation()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Operation\n </div>\n </ScalarDropdownItem>\n\n <!-- Add tag option for documents only -->\n <ScalarDropdownItem\n v-if=\"canAddTag()\"\n @click=\"handleAddTag()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Tag\n </div>\n </ScalarDropdownItem>\n\n <!-- Edit tag option for tags only -->\n <ScalarDropdownItem\n v-if=\"canEditTag()\"\n @click=\"handleEditTag()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIconPencil size=\"sm\" />\n Rename Tag\n </div>\n </ScalarDropdownItem>\n\n <!-- Edit example option for examples only -->\n <ScalarDropdownItem\n v-if=\"canEditExample()\"\n @click=\"handleEditExample()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIconPencil size=\"sm\" />\n Rename Example\n </div>\n </ScalarDropdownItem>\n\n <!-- Add example option for operations -->\n <ScalarDropdownItem\n v-if=\"canAddExample()\"\n @click=\"handleAddExample()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Example\n </div>\n </ScalarDropdownItem>\n <ScalarDropdownDivider\n v-if=\"\n (canAddExample() ||\n canAddOperation() ||\n canAddTag() ||\n canEditExample()) &&\n canDelete()\n \" />\n <ScalarDropdownItem\n v-if=\"canDelete()\"\n @click=\"emit('showDeleteModal')\">\n <div class=\"text-red flex items-center gap-2\">\n <ScalarIcon\n icon=\"Delete\"\n size=\"sm\" />\n Delete\n </div>\n </ScalarDropdownItem>\n </template>\n </ScalarDropdown>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"SidebarItemMenu.vue.script.js","names":[],"sources":["../../../../../src/v2/features/app/components/SidebarItemMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarDropdown,\n ScalarDropdownDivider,\n ScalarDropdownItem,\n ScalarIcon,\n} from '@scalar/components'\nimport { ScalarIconPencil } from '@scalar/icons'\nimport type { SidebarState } from '@scalar/sidebar'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\nimport { nextTick, ref, watch } from 'vue'\n\nimport { createTempOperation } from '@/v2/features/app/helpers/create-temp-operation'\n\nconst { item, eventBus, sidebarState, target, workspaceStore } = defineProps<{\n /** The item to display the decorator for */\n item: TraversedEntry\n /** The event bus to emit events to */\n eventBus: WorkspaceEventBus\n /** The sidebar state to get the parent entry from */\n sidebarState: SidebarState<TraversedEntry>\n /** The target to position the dropdown relative to */\n target: HTMLElement\n /** The workspace store for accessing documents */\n workspaceStore: WorkspaceStore\n}>()\n\nconst emit = defineEmits<{\n (e: 'closeMenu'): void\n (e: 'showDeleteModal'): void\n}>()\n\nconst open = ref(false)\n\nwatch(open, async (newValue, oldValue) => {\n // Close the menu if it was open and is now closed\n if (!newValue && oldValue) {\n // Wait to let the menu close and clean up the aria attributes\n await nextTick()\n emit('closeMenu')\n }\n})\n\n/** Returns whether the item supports adding operations */\nconst canAddOperation = (): boolean =>\n item.type === 'document' || item.type === 'tag'\n\n/** Returns whether the item supports adding tags */\nconst canAddTag = (): boolean => item.type === 'document'\n\n/** Returns whether the item supports editing tags */\nconst canEditTag = (): boolean => item.type === 'tag'\n\n/** Returns whether the item supports editing examples */\nconst canEditExample = (): boolean => item.type === 'example'\n\n/** Returns whether the item supports adding examples */\nconst canAddExample = (): boolean => item.type === 'operation'\n\n/** Returns whether the item supports deletion */\nconst canDelete = (): boolean =>\n (item.type === 'document' && item.id !== 'drafts') ||\n item.type === 'tag' ||\n item.type === 'operation' ||\n item.type === 'example'\n\nconst handleAddTag = () => {\n if (item.type === 'document') {\n eventBus.emit('ui:open:command-palette', {\n action: 'add-tag',\n payload: {\n documentName: item.name,\n },\n })\n }\n}\n\nconst handleEditTag = () => {\n if (item.type === 'tag') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n eventBus.emit(\n 'ui:open:command-palette',\n {\n action: 'edit-tag',\n payload: {\n tag: item,\n documentName: getParentEntry('document', itemWithParent)?.name ?? '',\n },\n },\n { skipUnpackProxy: true },\n )\n }\n}\n\nconst handleAddExample = () => {\n if (item.type === 'operation') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n eventBus.emit('ui:open:command-palette', {\n action: 'add-example',\n payload: {\n documentName: getParentEntry('document', itemWithParent)?.name,\n operationId: item.id,\n },\n })\n }\n}\n\nconst handleEditExample = () => {\n if (item.type === 'example') {\n const itemWithParent = sidebarState.getEntryById(item.id)\n const parentOperation = getParentEntry('operation', itemWithParent)\n eventBus.emit(\n 'ui:open:command-palette',\n {\n action: 'edit-example',\n payload: {\n example: item,\n documentName: getParentEntry('document', itemWithParent)?.name ?? '',\n operationId: parentOperation?.id ?? '',\n },\n } as any,\n { skipUnpackProxy: true },\n )\n }\n}\n\nconst handleAddOperation = () => {\n const itemWithParent = sidebarState.getEntryById(item.id)\n const documentName = getParentEntry('document', itemWithParent)?.name\n const tagName = getParentEntry('tag', itemWithParent)?.name\n if (!documentName) {\n console.error('Document name not found')\n return\n }\n createTempOperation(documentName, {\n existingPaths: new Set(\n Object.keys(\n workspaceStore.workspace.documents[documentName]?.paths ?? {},\n ),\n ),\n eventBus,\n tags: tagName ? [tagName] : undefined,\n })\n}\n</script>\n<template>\n <ScalarDropdown\n v-model:open=\"open\"\n placement=\"bottom-end\"\n :target=\"target\"\n teleport>\n <template #items>\n <!-- Add operation option for documents and tags -->\n <ScalarDropdownItem\n v-if=\"canAddOperation()\"\n @click=\"handleAddOperation\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Operation\n </div>\n </ScalarDropdownItem>\n\n <!-- Add tag option for documents only -->\n <ScalarDropdownItem\n v-if=\"canAddTag()\"\n @click=\"handleAddTag()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Tag\n </div>\n </ScalarDropdownItem>\n\n <!-- Edit tag option for tags only -->\n <ScalarDropdownItem\n v-if=\"canEditTag()\"\n @click=\"handleEditTag()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIconPencil size=\"sm\" />\n Rename Tag\n </div>\n </ScalarDropdownItem>\n\n <!-- Edit example option for examples only -->\n <ScalarDropdownItem\n v-if=\"canEditExample()\"\n @click=\"handleEditExample()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIconPencil size=\"sm\" />\n Rename Example\n </div>\n </ScalarDropdownItem>\n\n <!-- Add example option for operations -->\n <ScalarDropdownItem\n v-if=\"canAddExample()\"\n @click=\"handleAddExample()\">\n <div class=\"flex items-center gap-2\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n Add Example\n </div>\n </ScalarDropdownItem>\n <ScalarDropdownDivider\n v-if=\"\n (canAddExample() ||\n canAddOperation() ||\n canAddTag() ||\n canEditExample()) &&\n canDelete()\n \" />\n <ScalarDropdownItem\n v-if=\"canDelete()\"\n @click=\"emit('showDeleteModal')\">\n <div class=\"text-red flex items-center gap-2\">\n <ScalarIcon\n icon=\"Delete\"\n size=\"sm\" />\n Delete\n </div>\n </ScalarDropdownItem>\n </template>\n </ScalarDropdown>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { WorkspaceEventBus } from '@scalar/workspace-store/events';
2
+ /**
3
+ * Creates a temporary operation with a unique path, emits its creation on the event bus,
4
+ * then navigates to the operation and focuses the address bar if successful.
5
+ * @param documentName - The name of the document to add the operation to
6
+ * @param existingPaths - Set of existing operation paths for uniqueness checking
7
+ * @param eventBus - The workspace event bus to emit events on
8
+ */
9
+ export declare const createTempOperation: (documentName: string, options: {
10
+ existingPaths: Set<string>;
11
+ eventBus: WorkspaceEventBus;
12
+ tags?: string[];
13
+ }) => void;
14
+ //# sourceMappingURL=create-temp-operation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-temp-operation.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/create-temp-operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AA+BvE;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,cAAc,MAAM,EACpB,SAAS;IACP,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB,SA8BF,CAAA"}
@@ -0,0 +1,52 @@
1
+ //#region src/v2/features/app/helpers/create-temp-operation.ts
2
+ /**
3
+ * Generates a unique temporary operation path for a new operation.
4
+ * Tries up to 10 times to generate a non-colliding path, then falls back to a static path.
5
+ *
6
+ * Example:
7
+ * const existingPaths = new Set(['/tempabcd1234', '/tempdeadbeef']);
8
+ * const newPath = generateUniquePath('my-doc', existingPaths); // e.g. "/tempa1b2c3d4"
9
+ *
10
+ * @param existingPaths - Set of paths already present in the document to avoid collisions
11
+ * @param attempts - Used internally to limit recursion (default: 0)
12
+ * @returns A unique operation path (e.g., "/temp1234abcd")
13
+ */
14
+ var generateUniquePath = (existingPaths, attempts = 0) => {
15
+ if (attempts > 10) return "/temp-path";
16
+ const path = `/temp${crypto.randomUUID().slice(0, 8)}`;
17
+ if (existingPaths.has(path)) return generateUniquePath(existingPaths, attempts + 1);
18
+ return path;
19
+ };
20
+ /**
21
+ * Creates a temporary operation with a unique path, emits its creation on the event bus,
22
+ * then navigates to the operation and focuses the address bar if successful.
23
+ * @param documentName - The name of the document to add the operation to
24
+ * @param existingPaths - Set of existing operation paths for uniqueness checking
25
+ * @param eventBus - The workspace event bus to emit events on
26
+ */
27
+ var createTempOperation = (documentName, options) => {
28
+ const uniquePath = generateUniquePath(options.existingPaths);
29
+ options.eventBus.emit("operation:create:operation", {
30
+ documentName,
31
+ path: uniquePath,
32
+ method: "get",
33
+ operation: { tags: options.tags ?? [] },
34
+ callback: (success) => {
35
+ if (success) options.eventBus.emit("ui:navigate", {
36
+ page: "example",
37
+ documentSlug: documentName,
38
+ path: uniquePath,
39
+ method: "get",
40
+ exampleName: "default",
41
+ callback: async () => {
42
+ await new Promise((resolve) => requestAnimationFrame(resolve));
43
+ options.eventBus.emit("ui:focus:address-bar", { clear: true });
44
+ }
45
+ });
46
+ }
47
+ });
48
+ };
49
+ //#endregion
50
+ export { createTempOperation };
51
+
52
+ //# sourceMappingURL=create-temp-operation.js.map