@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.
- package/CHANGELOG.md +22 -0
- package/dist/hooks/useClientConfig.d.ts +3 -3
- package/dist/libs/normalize-headers.d.ts.map +1 -1
- package/dist/libs/normalize-headers.js +1 -0
- package/dist/libs/normalize-headers.js.map +1 -1
- package/dist/style.css +124 -36
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts +2 -0
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +24 -10
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.js +23 -2
- package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.js +18 -7
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseCookies.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseCookies.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js +32 -9
- package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js +8 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
- package/dist/v2/components/sidebar/Sidebar.vue.d.ts.map +1 -1
- package/dist/v2/components/sidebar/Sidebar.vue.js.map +1 -1
- package/dist/v2/components/sidebar/Sidebar.vue.script.js +9 -4
- package/dist/v2/components/sidebar/Sidebar.vue.script.js.map +1 -1
- package/dist/v2/constants.js +1 -1
- package/dist/v2/features/app/app-events.d.ts.map +1 -1
- package/dist/v2/features/app/app-events.js +8 -0
- package/dist/v2/features/app/app-events.js.map +1 -1
- package/dist/v2/features/app/components/AppSidebar.vue.d.ts.map +1 -1
- package/dist/v2/features/app/components/AppSidebar.vue.js +1 -1
- package/dist/v2/features/app/components/AppSidebar.vue.js.map +1 -1
- package/dist/v2/features/app/components/AppSidebar.vue.script.js +19 -10
- package/dist/v2/features/app/components/AppSidebar.vue.script.js.map +1 -1
- package/dist/v2/features/app/components/SidebarItemMenu.vue.d.ts +3 -0
- package/dist/v2/features/app/components/SidebarItemMenu.vue.d.ts.map +1 -1
- package/dist/v2/features/app/components/SidebarItemMenu.vue.js.map +1 -1
- package/dist/v2/features/app/components/SidebarItemMenu.vue.script.js +30 -30
- package/dist/v2/features/app/components/SidebarItemMenu.vue.script.js.map +1 -1
- package/dist/v2/features/app/helpers/create-temp-operation.d.ts +14 -0
- package/dist/v2/features/app/helpers/create-temp-operation.d.ts.map +1 -0
- package/dist/v2/features/app/helpers/create-temp-operation.js +52 -0
- package/dist/v2/features/app/helpers/create-temp-operation.js.map +1 -0
- package/dist/v2/features/app/helpers/routes.d.ts +5 -0
- package/dist/v2/features/app/helpers/routes.d.ts.map +1 -1
- package/dist/v2/features/app/helpers/routes.js +5 -0
- package/dist/v2/features/app/helpers/routes.js.map +1 -1
- package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.d.ts +12 -0
- package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.d.ts.map +1 -0
- package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.js +9 -0
- package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.js.map +1 -0
- package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.script.js +174 -0
- package/dist/v2/features/collection/components/DocumentScriptsEditors.vue.script.js.map +1 -0
- package/dist/v2/features/collection/components/Scripts.vue.d.ts +16 -0
- package/dist/v2/features/collection/components/Scripts.vue.d.ts.map +1 -0
- package/dist/v2/features/collection/components/Scripts.vue.js +7 -0
- package/dist/v2/features/collection/components/Scripts.vue.js.map +1 -0
- package/dist/v2/features/collection/components/Scripts.vue.script.js +47 -0
- package/dist/v2/features/collection/components/Scripts.vue.script.js.map +1 -0
- package/dist/v2/features/collection/components/Tabs.vue.d.ts.map +1 -1
- package/dist/v2/features/collection/components/Tabs.vue.js.map +1 -1
- package/dist/v2/features/collection/components/Tabs.vue.script.js +2 -1
- package/dist/v2/features/collection/components/Tabs.vue.script.js.map +1 -1
- package/dist/v2/features/modal/index.d.ts +1 -0
- package/dist/v2/features/modal/index.d.ts.map +1 -1
- package/dist/v2/features/operation/Operation.vue.d.ts.map +1 -1
- package/dist/v2/features/operation/Operation.vue.js.map +1 -1
- package/dist/v2/features/operation/Operation.vue.script.js +3 -1
- package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
- package/dist/v2/workspace-events.d.ts.map +1 -1
- package/dist/v2/workspace-events.js +1 -0
- package/dist/v2/workspace-events.js.map +1 -1
- package/dist/views/Request/ResponseSection/ResponseEmpty.vue.script.js +1 -1
- 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 \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 \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
|
-
/**
|
|
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
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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 \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 \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":"
|
|
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
|
|
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[
|
|
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:
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
133
|
+
onClick: _cache[1] || (_cache[1] = ($event) => handleEditTag())
|
|
134
134
|
}, {
|
|
135
|
-
default: withCtx(() => [createElementVNode("div", _hoisted_3, [createVNode(unref(ScalarIconPencil), { size: "sm" }), _cache[
|
|
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[
|
|
140
|
+
onClick: _cache[2] || (_cache[2] = ($event) => handleEditExample())
|
|
141
141
|
}, {
|
|
142
|
-
default: withCtx(() => [createElementVNode("div", _hoisted_4, [createVNode(unref(ScalarIconPencil), { size: "sm" }), _cache[
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
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
|