@scalar/sidebar 0.11.8 → 0.11.9
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SidebarItem.vue.d.ts","sourceRoot":"","sources":["../../src/components/SidebarItem.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SidebarItem.vue.d.ts","sourceRoot":"","sources":["../../src/components/SidebarItem.vue"],"names":[],"mappings":"AAqfA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAK3D,KAAK,WAAW,GAAG;IACjB;;OAEG;IACH,IAAI,EAAE,IAAI,CAAA;IACV;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAA;IACnC;;OAEG;IACH,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAA;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,CAAA;IAExB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,GAAG,SAAS,CAAA;IAE5C;;;;OAIG;IACH,WAAW,CAAC,EAAE,mBAAmB,CAAC,aAAa,CAAC,CAAA;IAChD;;;;OAIG;IACH,WAAW,CAAC,EAAE,mBAAmB,CAAC,aAAa,CAAC,CAAA;CACjD,CAAC;AAkCF,KAAK,WAAW,GAAG;IACjB;;;OAGG;IACH,SAAS,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAA;IAC1C;;;OAGG;IACH,KAAK,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAA;IACtC;;;OAGG;IACH,IAAI,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAA;CACrD,CAAC;AAiyBF,QAAA,MAAM,UAAU;;;;;;;;kFAGd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SidebarItem.vue.js","names":[],"sources":["../../src/components/SidebarItem.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport {\n ScalarSidebarButton,\n ScalarSidebarGroup,\n ScalarSidebarGroupToggle,\n ScalarSidebarGroupToggleButton,\n ScalarSidebarGroupToggleSpacer,\n ScalarSidebarIndent,\n ScalarSidebarItem,\n ScalarSidebarSection,\n} from '@scalar/components/sidebar'\nimport { isPlainLeftClick } from '@scalar/helpers/dom/is-plain-left-click'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport { computed } from 'vue'\n\nimport SidebarItemDecorator from '@/components/SidebarItemDecorator.vue'\nimport { filterItems } from '@/helpers/filter-items'\nimport { hasChildren } from '@/helpers/has-children'\nimport { isSidebarFolder } from '@/helpers/is-sidebar-folder'\nimport {\n useDraggable,\n type DraggingItem,\n type HoveredItem,\n type UseDraggableOptions,\n} from '@/hooks/use-draggable'\nimport type { Item, Layout, SidebarOptions } from '@/types'\n\nimport SidebarHttpBadge from './SidebarHttpBadge.vue'\nimport SidebarItemLabel from './SidebarItemLabel.vue'\n\nconst {\n item,\n layout,\n isSelected,\n isExpanded,\n isDraggable,\n isDroppable,\n options,\n getHref,\n} = defineProps<{\n /**\n * The sidebar item to render.\n */\n item: Item\n /**\n * The layout mode for the sidebar ('client' or 'reference').\n */\n layout: Layout\n /**\n * Function to determine if an item is currently selected by id.\n */\n isSelected: (id: string) => boolean\n /**\n * Function to determine if an item is currently expanded (showing its children) by id.\n */\n isExpanded: (id: string) => boolean\n /**\n * Sidebar configuration options.\n * - operationTitleSource: sets whether operations show their path or summary as the display title.\n */\n options?: SidebarOptions\n\n /**\n * Returns the URL for a sidebar item.\n *\n * When provided (and it returns a value) items render as anchor tags\n * instead of buttons, so search engines can crawl the navigation.\n */\n getHref?: (item: Item) => string | undefined\n\n /**\n * Prevents this item from being dragged.\n *\n * @default true\n */\n isDraggable?: UseDraggableOptions['isDraggable']\n /**\n * Prevents this item from being hovered and dropped into. Can be either a function or a boolean.\n *\n * @default true\n */\n isDroppable?: UseDraggableOptions['isDroppable']\n}>()\n\nconst emit = defineEmits<{\n /**\n * Emitted when the item is selected\n * @param id - The id of the selected item\n */\n (e: 'selectItem', id: string): void\n /**\n * Emitted when a drag operation ends for this item\n * @param draggingItem - The item being dragged\n * @param hoveredItem - The item currently being hovered over\n */\n (e: 'onDragEnd', draggingItem: DraggingItem, hoveredItem: HoveredItem): void\n\n /**\n * Emitted when the group is toggled\n * @param id - The id of the group\n */\n (e: 'toggleGroup', id: string): void\n}>()\n\nconst slots = defineSlots<{\n /**\n * Adds an optional decorator for each item, such as an edit menu.\n * The slot receives an object with the current item.\n */\n decorator?(props: { item: Item }): unknown\n /**\n * Adds an optional empty state for an item.\n * The slot receives an object with the current item.\n */\n empty?(props: { item: Item }): unknown\n /**\n * Adds an optional icon for each item.\n * The slot receives an object with the current item and the open state.\n */\n icon?(props: { item: Item; open: boolean }): unknown\n}>()\n\nconst isGroup = (\n currentItem: Item,\n): currentItem is Item & { isGroup: true } => {\n return 'isGroup' in currentItem && currentItem.isGroup\n}\n\nconst isDeprecated = (\n currentItem: Item,\n): currentItem is Item & { isDeprecated: true } => {\n return ('isDeprecated' in currentItem && currentItem.isDeprecated) ?? false\n}\n\n/**\n * Handle drag end event and bubble it up to parent.\n */\nconst onDragEnd = (draggingItem: DraggingItem, hoveredItem: HoveredItem) => {\n emit('onDragEnd', draggingItem, hoveredItem)\n}\nconst { draggableAttrs, draggableEvents } = useDraggable({\n id: item.id,\n isDraggable,\n isDroppable,\n onDragEnd,\n})\n\nconst children = computed(() =>\n hasChildren(item)\n ? filterItems(layout, item.children, options?.hideOperationDefaultExamples)\n : [],\n)\n\n/** The URL for this item, when the consumer provides one it renders as a link */\nconst href = computed(() => getHref?.(item) || undefined)\n\n/**\n * Whether the group renders its toggle separately from its label.\n *\n * A label that navigates cannot also own the open state, so a group that\n * renders as a link needs a toggle button of its own. Without one there is no\n * way to collapse the group from the keyboard, because pressing Enter on the\n * label follows the link instead.\n */\nconst isDiscrete = computed(\n () => Boolean(href.value) || (layout === 'reference' && item.type === 'text'),\n)\n\n/**\n * Builds the screen reader label for the discrete group toggle.\n *\n * The title of the group is appended so the toggles can be told apart. A page\n * can hold a lot of them, and a list of identical \"Open Group\" buttons gives a\n * screen reader user nothing to navigate by.\n */\nconst getToggleLabel = (open: boolean): string => {\n const label = open\n ? (options?.labels?.closeGroup ?? 'Close Group')\n : (options?.labels?.openGroup ?? 'Open Group')\n\n return item.title ? `${label} - ${item.title}` : label\n}\n\n/**\n * Emit the select event for a click on the item label.\n *\n * When the item renders as a link we only hijack plain left clicks on the\n * link itself for in-app navigation. Modified clicks (meta, ctrl, shift,\n * alt) and middle clicks keep the browser's default behavior so the link\n * can be opened in a new tab or window, and clicks on surrounding content\n * (like the decorator menu) keep their native behavior. A click whose\n * default is already prevented has been handled by someone else, so it is\n * left alone rather than navigated a second time.\n */\nconst handleSelect = (event: MouseEvent) => {\n if (href.value) {\n const anchor =\n event.target instanceof Element ? event.target.closest('a') : null\n if (anchor?.getAttribute('href') !== href.value) {\n return\n }\n if (event.defaultPrevented || !isPlainLeftClick(event)) {\n return\n }\n event.preventDefault()\n }\n emit('selectItem', item.id)\n}\n</script>\n<template>\n <!-- Sidebar section -->\n <ScalarSidebarSection\n v-if=\"children.length > 0 && isGroup(item)\"\n :data-sidebar-id=\"item.id\"\n v-bind=\"draggableAttrs\"\n v-on=\"draggableEvents\">\n {{ item.title }}\n <template #items>\n <SidebarItem\n v-for=\"child in children\"\n :key=\"child.id\"\n :getHref=\"getHref\"\n :isDraggable=\"isDraggable\"\n :isDroppable=\"isDroppable\"\n :isExpanded=\"isExpanded\"\n :isSelected=\"isSelected\"\n :item=\"child\"\n :layout=\"layout\"\n :options=\"options\"\n @onDragEnd=\"onDragEnd\"\n @selectItem=\"(id) => emit('selectItem', id)\"\n @toggleGroup=\"(id) => emit('toggleGroup', id)\">\n <template\n v-if=\"slots.decorator\"\n #decorator=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"decorator\" />\n </template>\n <template\n v-if=\"slots.empty\"\n #empty=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"empty\" />\n </template>\n <template\n v-if=\"slots.icon\"\n #icon=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"icon\" />\n </template>\n </SidebarItem>\n </template>\n </ScalarSidebarSection>\n\n <!-- Sidebar group (folder) -->\n <ScalarSidebarGroup\n v-else-if=\"\n isSidebarFolder(\n layout,\n item,\n slots.empty !== undefined,\n options?.hideOperationDefaultExamples ?? false,\n )\n \"\n :active=\"isSelected(item.id)\"\n class=\"relative\"\n controlled\n :data-sidebar-id=\"item.id\"\n v-bind=\"draggableAttrs\"\n :discrete=\"isDiscrete\"\n :open=\"isExpanded(item.id)\"\n v-on=\"draggableEvents\">\n <template #button=\"{ open, level }\">\n <ScalarSidebarButton\n :is=\"href ? 'a' : 'button'\"\n :active=\"isSelected(item.id)\"\n :aria-expanded=\"isDiscrete ? undefined : open\"\n :href=\"href\"\n :indent=\"level\"\n @click=\"handleSelect\">\n <template #indent>\n <ScalarSidebarIndent\n class=\"-my-2 mr-0\"\n :indent=\"level\" />\n </template>\n <template\n v-if=\"item.type === 'document'\"\n #icon>\n <slot\n :item=\"item\"\n name=\"icon\"\n :open=\"open\">\n <LibraryIcon\n class=\"block\"\n :src=\"\n ('icon' in item && item.icon) || 'interface-content-folder'\n \" />\n </slot>\n </template>\n <span\n v-if=\"isDeprecated(item)\"\n class=\"line-through\">\n <SidebarItemLabel\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n </span>\n <SidebarItemLabel\n v-else\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n <template #aside>\n <SidebarHttpBadge\n v-if=\"'method' in item\"\n :active=\"isSelected(item.id)\"\n class=\"ml-2 h-4 self-start\"\n :class=\"{\n // Hide the badge when we're showing the decorator\n 'group-hover/button:opacity-0 group-focus-visible/button:opacity-0 group-has-[~*_[aria-expanded=true]]/button:opacity-0 group-has-[~*:focus-within]/button:opacity-0 group-has-[~*:hover]/button:opacity-0':\n slots.decorator,\n }\"\n :label=\"options?.labels?.httpMethod\"\n :method=\"item.method\"\n :webhook=\"item.type === 'webhook'\" />\n <ScalarSidebarGroupToggleSpacer v-if=\"isDiscrete\" />\n <ScalarSidebarGroupToggle\n v-else-if=\"!('method' in item)\"\n class=\"text-sidebar-c-2\"\n :open>\n <template #label>\n {{\n open\n ? (options?.labels?.closeGroup ?? 'Close Group')\n : (options?.labels?.openGroup ?? 'Open Group')\n }}\n </template>\n </ScalarSidebarGroupToggle>\n </template>\n </ScalarSidebarButton>\n <ScalarSidebarGroupToggleButton\n v-if=\"isDiscrete\"\n :open\n @click=\"() => emit('toggleGroup', item.id)\">\n <template #label>{{ getToggleLabel(open) }}</template>\n </ScalarSidebarGroupToggleButton>\n </template>\n <template\n v-if=\"slots.decorator\"\n #after>\n <SidebarItemDecorator>\n <slot\n :item\n name=\"decorator\" />\n </SidebarItemDecorator>\n </template>\n <template #items>\n <SidebarItem\n v-for=\"child in children\"\n :key=\"child.id\"\n :getHref=\"getHref\"\n :isDraggable=\"isDraggable\"\n :isDroppable=\"isDroppable\"\n :isExpanded=\"isExpanded\"\n :isSelected=\"isSelected\"\n :item=\"child\"\n :layout=\"layout\"\n :options=\"options\"\n :parentIds=\"[]\"\n @onDragEnd=\"onDragEnd\"\n @selectItem=\"(id) => emit('selectItem', id)\"\n @toggleGroup=\"(id) => emit('toggleGroup', id)\">\n <template\n v-if=\"slots.decorator\"\n #decorator=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"decorator\" />\n </template>\n <template\n v-if=\"slots.empty\"\n #empty=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"empty\" />\n </template>\n <template\n v-if=\"slots.icon\"\n #icon=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"icon\" />\n </template>\n </SidebarItem>\n <template v-if=\"slots.empty && (item.children?.length ?? 0) === 0\">\n <slot\n :item\n name=\"empty\" />\n </template>\n </template>\n </ScalarSidebarGroup>\n\n <!-- Sidebar item (leaf node) -->\n <ScalarSidebarItem\n v-else\n v-bind=\"draggableAttrs\"\n class=\"relative\"\n :data-sidebar-id=\"item.id\"\n v-on=\"draggableEvents\"\n @click=\"handleSelect\">\n <template #button=\"{ level }\">\n <ScalarSidebarButton\n :is=\"href ? 'a' : 'button'\"\n :href=\"href\"\n :indent=\"level\"\n :selected=\"isSelected(item.id)\">\n <template\n v-if=\"slots.icon\"\n #icon>\n <slot\n :item=\"item\"\n name=\"icon\"\n :open=\"true\" />\n </template>\n <span\n v-if=\"isDeprecated(item)\"\n class=\"line-through\">\n <SidebarItemLabel\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n </span>\n <SidebarItemLabel\n v-else\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n <template\n v-if=\"'method' in item\"\n #aside>\n <SidebarHttpBadge\n :active=\"isSelected(item.id)\"\n class=\"ml-2 h-4 self-start\"\n :class=\"{\n // Hide the badge when we're showing the decorator\n 'group-hover/button:opacity-0 group-focus-visible/button:opacity-0 group-has-[~*_[aria-expanded=true]]/button:opacity-0 group-has-[~*:focus-within]/button:opacity-0 group-has-[~*:hover]/button:opacity-0':\n slots.decorator,\n }\"\n :label=\"options?.labels?.httpMethod\"\n :method=\"item.method\"\n :webhook=\"item.type === 'webhook'\" />\n </template>\n </ScalarSidebarButton>\n </template>\n <template\n v-if=\"slots.decorator\"\n #after>\n <SidebarItemDecorator>\n <slot\n :item\n name=\"decorator\" />\n </SidebarItemDecorator>\n </template>\n </ScalarSidebarItem>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"SidebarItem.vue.js","names":[],"sources":["../../src/components/SidebarItem.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport {\n ScalarSidebarButton,\n ScalarSidebarGroup,\n ScalarSidebarGroupToggle,\n ScalarSidebarGroupToggleButton,\n ScalarSidebarGroupToggleSpacer,\n ScalarSidebarIndent,\n ScalarSidebarItem,\n ScalarSidebarSection,\n} from '@scalar/components/sidebar'\nimport { isPlainLeftClick } from '@scalar/helpers/dom/is-plain-left-click'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport { computed } from 'vue'\n\nimport SidebarItemDecorator from '@/components/SidebarItemDecorator.vue'\nimport { filterItems } from '@/helpers/filter-items'\nimport { hasChildren } from '@/helpers/has-children'\nimport { isSidebarFolder } from '@/helpers/is-sidebar-folder'\nimport {\n useDraggable,\n type DraggingItem,\n type HoveredItem,\n type UseDraggableOptions,\n} from '@/hooks/use-draggable'\nimport type { Item, Layout, SidebarOptions } from '@/types'\n\nimport SidebarHttpBadge from './SidebarHttpBadge.vue'\nimport SidebarItemLabel from './SidebarItemLabel.vue'\n\nconst {\n item,\n layout,\n isSelected,\n isExpanded,\n isDraggable,\n isDroppable,\n options,\n getHref,\n} = defineProps<{\n /**\n * The sidebar item to render.\n */\n item: Item\n /**\n * The layout mode for the sidebar ('client' or 'reference').\n */\n layout: Layout\n /**\n * Function to determine if an item is currently selected by id.\n */\n isSelected: (id: string) => boolean\n /**\n * Function to determine if an item is currently expanded (showing its children) by id.\n */\n isExpanded: (id: string) => boolean\n /**\n * Sidebar configuration options.\n * - operationTitleSource: sets whether operations show their path or summary as the display title.\n */\n options?: SidebarOptions\n\n /**\n * Returns the URL for a sidebar item.\n *\n * When provided (and it returns a value) items render as anchor tags\n * instead of buttons, so search engines can crawl the navigation.\n */\n getHref?: (item: Item) => string | undefined\n\n /**\n * Prevents this item from being dragged.\n *\n * @default true\n */\n isDraggable?: UseDraggableOptions['isDraggable']\n /**\n * Prevents this item from being hovered and dropped into. Can be either a function or a boolean.\n *\n * @default true\n */\n isDroppable?: UseDraggableOptions['isDroppable']\n}>()\n\nconst emit = defineEmits<{\n /**\n * Emitted when the item is selected\n * @param id - The id of the selected item\n */\n (e: 'selectItem', id: string): void\n /**\n * Emitted when a drag operation ends for this item\n * @param draggingItem - The item being dragged\n * @param hoveredItem - The item currently being hovered over\n */\n (e: 'onDragEnd', draggingItem: DraggingItem, hoveredItem: HoveredItem): void\n\n /**\n * Emitted when the group is toggled\n * @param id - The id of the group\n */\n (e: 'toggleGroup', id: string): void\n}>()\n\nconst slots = defineSlots<{\n /**\n * Adds an optional decorator for each item, such as an edit menu.\n * The slot receives an object with the current item.\n */\n decorator?(props: { item: Item }): unknown\n /**\n * Adds an optional empty state for an item.\n * The slot receives an object with the current item.\n */\n empty?(props: { item: Item }): unknown\n /**\n * Adds an optional icon for each item.\n * The slot receives an object with the current item and the open state.\n */\n icon?(props: { item: Item; open: boolean }): unknown\n}>()\n\nconst isGroup = (\n currentItem: Item,\n): currentItem is Item & { isGroup: true } => {\n return 'isGroup' in currentItem && currentItem.isGroup\n}\n\nconst isDeprecated = (\n currentItem: Item,\n): currentItem is Item & { isDeprecated: true } => {\n return ('isDeprecated' in currentItem && currentItem.isDeprecated) ?? false\n}\n\n/**\n * Handle drag end event and bubble it up to parent.\n */\nconst onDragEnd = (draggingItem: DraggingItem, hoveredItem: HoveredItem) => {\n emit('onDragEnd', draggingItem, hoveredItem)\n}\nconst { draggableAttrs, draggableEvents } = useDraggable({\n id: item.id,\n isDraggable,\n isDroppable,\n onDragEnd,\n})\n\nconst children = computed(() =>\n hasChildren(item)\n ? filterItems(layout, item.children, options?.hideOperationDefaultExamples)\n : [],\n)\n\n/**\n * Whether this item is the one currently displayed on the page.\n *\n * `isSelected` also reports true for every ancestor of the displayed item,\n * which is what the active styling of a group needs. Only the deepest\n * selected node is the current page though, so a group counts as current when\n * none of its children are selected. Leaf items already get this from the\n * `selected` prop of ScalarSidebarButton.\n */\nconst isCurrent = computed(\n () =>\n isSelected(item.id) &&\n !(hasChildren(item) && item.children.some((child) => isSelected(child.id))),\n)\n\n/** The URL for this item, when the consumer provides one it renders as a link */\nconst href = computed(() => getHref?.(item) || undefined)\n\n/**\n * Whether the group renders its toggle separately from its label.\n *\n * A label that navigates cannot also own the open state, so a group that\n * renders as a link needs a toggle button of its own. Without one there is no\n * way to collapse the group from the keyboard, because pressing Enter on the\n * label follows the link instead.\n */\nconst isDiscrete = computed(\n () => Boolean(href.value) || (layout === 'reference' && item.type === 'text'),\n)\n\n/**\n * Builds the screen reader label for the discrete group toggle.\n *\n * The title of the group is appended so the toggles can be told apart. A page\n * can hold a lot of them, and a list of identical \"Open Group\" buttons gives a\n * screen reader user nothing to navigate by.\n */\nconst getToggleLabel = (open: boolean): string => {\n const label = open\n ? (options?.labels?.closeGroup ?? 'Close Group')\n : (options?.labels?.openGroup ?? 'Open Group')\n\n return item.title ? `${label} - ${item.title}` : label\n}\n\n/**\n * Emit the select event for a click on the item label.\n *\n * When the item renders as a link we only hijack plain left clicks on the\n * link itself for in-app navigation. Modified clicks (meta, ctrl, shift,\n * alt) and middle clicks keep the browser's default behavior so the link\n * can be opened in a new tab or window, and clicks on surrounding content\n * (like the decorator menu) keep their native behavior. A click whose\n * default is already prevented has been handled by someone else, so it is\n * left alone rather than navigated a second time.\n */\nconst handleSelect = (event: MouseEvent) => {\n if (href.value) {\n const anchor =\n event.target instanceof Element ? event.target.closest('a') : null\n if (anchor?.getAttribute('href') !== href.value) {\n return\n }\n if (event.defaultPrevented || !isPlainLeftClick(event)) {\n return\n }\n event.preventDefault()\n }\n emit('selectItem', item.id)\n}\n</script>\n<template>\n <!-- Sidebar section -->\n <ScalarSidebarSection\n v-if=\"children.length > 0 && isGroup(item)\"\n :data-sidebar-id=\"item.id\"\n v-bind=\"draggableAttrs\"\n v-on=\"draggableEvents\">\n {{ item.title }}\n <template #items>\n <SidebarItem\n v-for=\"child in children\"\n :key=\"child.id\"\n :getHref=\"getHref\"\n :isDraggable=\"isDraggable\"\n :isDroppable=\"isDroppable\"\n :isExpanded=\"isExpanded\"\n :isSelected=\"isSelected\"\n :item=\"child\"\n :layout=\"layout\"\n :options=\"options\"\n @onDragEnd=\"onDragEnd\"\n @selectItem=\"(id) => emit('selectItem', id)\"\n @toggleGroup=\"(id) => emit('toggleGroup', id)\">\n <template\n v-if=\"slots.decorator\"\n #decorator=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"decorator\" />\n </template>\n <template\n v-if=\"slots.empty\"\n #empty=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"empty\" />\n </template>\n <template\n v-if=\"slots.icon\"\n #icon=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"icon\" />\n </template>\n </SidebarItem>\n </template>\n </ScalarSidebarSection>\n\n <!-- Sidebar group (folder) -->\n <ScalarSidebarGroup\n v-else-if=\"\n isSidebarFolder(\n layout,\n item,\n slots.empty !== undefined,\n options?.hideOperationDefaultExamples ?? false,\n )\n \"\n :active=\"isSelected(item.id)\"\n class=\"relative\"\n controlled\n :data-sidebar-id=\"item.id\"\n v-bind=\"draggableAttrs\"\n :discrete=\"isDiscrete\"\n :open=\"isExpanded(item.id)\"\n v-on=\"draggableEvents\">\n <template #button=\"{ open, level }\">\n <ScalarSidebarButton\n :is=\"href ? 'a' : 'button'\"\n :active=\"isSelected(item.id)\"\n :aria-current=\"isCurrent ? 'page' : undefined\"\n :aria-expanded=\"isDiscrete ? undefined : open\"\n :href=\"href\"\n :indent=\"level\"\n @click=\"handleSelect\">\n <template #indent>\n <ScalarSidebarIndent\n class=\"-my-2 mr-0\"\n :indent=\"level\" />\n </template>\n <template\n v-if=\"item.type === 'document'\"\n #icon>\n <slot\n :item=\"item\"\n name=\"icon\"\n :open=\"open\">\n <LibraryIcon\n class=\"block\"\n :src=\"\n ('icon' in item && item.icon) || 'interface-content-folder'\n \" />\n </slot>\n </template>\n <span\n v-if=\"isDeprecated(item)\"\n class=\"line-through\">\n <SidebarItemLabel\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n </span>\n <SidebarItemLabel\n v-else\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n <template #aside>\n <SidebarHttpBadge\n v-if=\"'method' in item\"\n :active=\"isSelected(item.id)\"\n class=\"ml-2 h-4 self-start\"\n :class=\"{\n // Hide the badge when we're showing the decorator\n 'group-hover/button:opacity-0 group-focus-visible/button:opacity-0 group-has-[~*_[aria-expanded=true]]/button:opacity-0 group-has-[~*:focus-within]/button:opacity-0 group-has-[~*:hover]/button:opacity-0':\n slots.decorator,\n }\"\n :label=\"options?.labels?.httpMethod\"\n :method=\"item.method\"\n :webhook=\"item.type === 'webhook'\" />\n <ScalarSidebarGroupToggleSpacer v-if=\"isDiscrete\" />\n <ScalarSidebarGroupToggle\n v-else-if=\"!('method' in item)\"\n class=\"text-sidebar-c-2\"\n :open>\n <template #label>\n {{\n open\n ? (options?.labels?.closeGroup ?? 'Close Group')\n : (options?.labels?.openGroup ?? 'Open Group')\n }}\n </template>\n </ScalarSidebarGroupToggle>\n </template>\n </ScalarSidebarButton>\n <ScalarSidebarGroupToggleButton\n v-if=\"isDiscrete\"\n :open\n @click=\"() => emit('toggleGroup', item.id)\">\n <template #label>{{ getToggleLabel(open) }}</template>\n </ScalarSidebarGroupToggleButton>\n </template>\n <template\n v-if=\"slots.decorator\"\n #after>\n <SidebarItemDecorator>\n <slot\n :item\n name=\"decorator\" />\n </SidebarItemDecorator>\n </template>\n <template #items>\n <SidebarItem\n v-for=\"child in children\"\n :key=\"child.id\"\n :getHref=\"getHref\"\n :isDraggable=\"isDraggable\"\n :isDroppable=\"isDroppable\"\n :isExpanded=\"isExpanded\"\n :isSelected=\"isSelected\"\n :item=\"child\"\n :layout=\"layout\"\n :options=\"options\"\n :parentIds=\"[]\"\n @onDragEnd=\"onDragEnd\"\n @selectItem=\"(id) => emit('selectItem', id)\"\n @toggleGroup=\"(id) => emit('toggleGroup', id)\">\n <template\n v-if=\"slots.decorator\"\n #decorator=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"decorator\" />\n </template>\n <template\n v-if=\"slots.empty\"\n #empty=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"empty\" />\n </template>\n <template\n v-if=\"slots.icon\"\n #icon=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"icon\" />\n </template>\n </SidebarItem>\n <template v-if=\"slots.empty && (item.children?.length ?? 0) === 0\">\n <slot\n :item\n name=\"empty\" />\n </template>\n </template>\n </ScalarSidebarGroup>\n\n <!-- Sidebar item (leaf node) -->\n <ScalarSidebarItem\n v-else\n v-bind=\"draggableAttrs\"\n class=\"relative\"\n :data-sidebar-id=\"item.id\"\n v-on=\"draggableEvents\"\n @click=\"handleSelect\">\n <template #button=\"{ level }\">\n <ScalarSidebarButton\n :is=\"href ? 'a' : 'button'\"\n :href=\"href\"\n :indent=\"level\"\n :selected=\"isSelected(item.id)\">\n <template\n v-if=\"slots.icon\"\n #icon>\n <slot\n :item=\"item\"\n name=\"icon\"\n :open=\"true\" />\n </template>\n <span\n v-if=\"isDeprecated(item)\"\n class=\"line-through\">\n <SidebarItemLabel\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n </span>\n <SidebarItemLabel\n v-else\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n <template\n v-if=\"'method' in item\"\n #aside>\n <SidebarHttpBadge\n :active=\"isSelected(item.id)\"\n class=\"ml-2 h-4 self-start\"\n :class=\"{\n // Hide the badge when we're showing the decorator\n 'group-hover/button:opacity-0 group-focus-visible/button:opacity-0 group-has-[~*_[aria-expanded=true]]/button:opacity-0 group-has-[~*:focus-within]/button:opacity-0 group-has-[~*:hover]/button:opacity-0':\n slots.decorator,\n }\"\n :label=\"options?.labels?.httpMethod\"\n :method=\"item.method\"\n :webhook=\"item.type === 'webhook'\" />\n </template>\n </ScalarSidebarButton>\n </template>\n <template\n v-if=\"slots.decorator\"\n #after>\n <SidebarItemDecorator>\n <slot\n :item\n name=\"decorator\" />\n </SidebarItemDecorator>\n </template>\n </ScalarSidebarItem>\n</template>\n"],"mappings":""}
|
|
@@ -57,6 +57,16 @@ var SidebarItem_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
|
|
|
57
57
|
onDragEnd
|
|
58
58
|
});
|
|
59
59
|
const children = computed(() => hasChildren(__props.item) ? filterItems(__props.layout, __props.item.children, __props.options?.hideOperationDefaultExamples) : []);
|
|
60
|
+
/**
|
|
61
|
+
* Whether this item is the one currently displayed on the page.
|
|
62
|
+
*
|
|
63
|
+
* `isSelected` also reports true for every ancestor of the displayed item,
|
|
64
|
+
* which is what the active styling of a group needs. Only the deepest
|
|
65
|
+
* selected node is the current page though, so a group counts as current when
|
|
66
|
+
* none of its children are selected. Leaf items already get this from the
|
|
67
|
+
* `selected` prop of ScalarSidebarButton.
|
|
68
|
+
*/
|
|
69
|
+
const isCurrent = computed(() => __props.isSelected(__props.item.id) && !(hasChildren(__props.item) && __props.item.children.some((child) => __props.isSelected(child.id))));
|
|
60
70
|
/** The URL for this item, when the consumer provides one it renders as a link */
|
|
61
71
|
const href = computed(() => __props.getHref?.(__props.item) || void 0);
|
|
62
72
|
/**
|
|
@@ -160,6 +170,7 @@ var SidebarItem_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
|
|
|
160
170
|
button: withCtx(({ open, level }) => [createVNode(unref(ScalarSidebarButton), {
|
|
161
171
|
is: href.value ? "a" : "button",
|
|
162
172
|
active: __props.isSelected(__props.item.id),
|
|
173
|
+
"aria-current": isCurrent.value ? "page" : void 0,
|
|
163
174
|
"aria-expanded": isDiscrete.value ? void 0 : open,
|
|
164
175
|
href: href.value,
|
|
165
176
|
indent: level,
|
|
@@ -212,6 +223,7 @@ var SidebarItem_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
|
|
|
212
223
|
} : void 0]), 1032, [
|
|
213
224
|
"is",
|
|
214
225
|
"active",
|
|
226
|
+
"aria-current",
|
|
215
227
|
"aria-expanded",
|
|
216
228
|
"href",
|
|
217
229
|
"indent"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SidebarItem.vue.script.js","names":[],"sources":["../../src/components/SidebarItem.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport {\n ScalarSidebarButton,\n ScalarSidebarGroup,\n ScalarSidebarGroupToggle,\n ScalarSidebarGroupToggleButton,\n ScalarSidebarGroupToggleSpacer,\n ScalarSidebarIndent,\n ScalarSidebarItem,\n ScalarSidebarSection,\n} from '@scalar/components/sidebar'\nimport { isPlainLeftClick } from '@scalar/helpers/dom/is-plain-left-click'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport { computed } from 'vue'\n\nimport SidebarItemDecorator from '@/components/SidebarItemDecorator.vue'\nimport { filterItems } from '@/helpers/filter-items'\nimport { hasChildren } from '@/helpers/has-children'\nimport { isSidebarFolder } from '@/helpers/is-sidebar-folder'\nimport {\n useDraggable,\n type DraggingItem,\n type HoveredItem,\n type UseDraggableOptions,\n} from '@/hooks/use-draggable'\nimport type { Item, Layout, SidebarOptions } from '@/types'\n\nimport SidebarHttpBadge from './SidebarHttpBadge.vue'\nimport SidebarItemLabel from './SidebarItemLabel.vue'\n\nconst {\n item,\n layout,\n isSelected,\n isExpanded,\n isDraggable,\n isDroppable,\n options,\n getHref,\n} = defineProps<{\n /**\n * The sidebar item to render.\n */\n item: Item\n /**\n * The layout mode for the sidebar ('client' or 'reference').\n */\n layout: Layout\n /**\n * Function to determine if an item is currently selected by id.\n */\n isSelected: (id: string) => boolean\n /**\n * Function to determine if an item is currently expanded (showing its children) by id.\n */\n isExpanded: (id: string) => boolean\n /**\n * Sidebar configuration options.\n * - operationTitleSource: sets whether operations show their path or summary as the display title.\n */\n options?: SidebarOptions\n\n /**\n * Returns the URL for a sidebar item.\n *\n * When provided (and it returns a value) items render as anchor tags\n * instead of buttons, so search engines can crawl the navigation.\n */\n getHref?: (item: Item) => string | undefined\n\n /**\n * Prevents this item from being dragged.\n *\n * @default true\n */\n isDraggable?: UseDraggableOptions['isDraggable']\n /**\n * Prevents this item from being hovered and dropped into. Can be either a function or a boolean.\n *\n * @default true\n */\n isDroppable?: UseDraggableOptions['isDroppable']\n}>()\n\nconst emit = defineEmits<{\n /**\n * Emitted when the item is selected\n * @param id - The id of the selected item\n */\n (e: 'selectItem', id: string): void\n /**\n * Emitted when a drag operation ends for this item\n * @param draggingItem - The item being dragged\n * @param hoveredItem - The item currently being hovered over\n */\n (e: 'onDragEnd', draggingItem: DraggingItem, hoveredItem: HoveredItem): void\n\n /**\n * Emitted when the group is toggled\n * @param id - The id of the group\n */\n (e: 'toggleGroup', id: string): void\n}>()\n\nconst slots = defineSlots<{\n /**\n * Adds an optional decorator for each item, such as an edit menu.\n * The slot receives an object with the current item.\n */\n decorator?(props: { item: Item }): unknown\n /**\n * Adds an optional empty state for an item.\n * The slot receives an object with the current item.\n */\n empty?(props: { item: Item }): unknown\n /**\n * Adds an optional icon for each item.\n * The slot receives an object with the current item and the open state.\n */\n icon?(props: { item: Item; open: boolean }): unknown\n}>()\n\nconst isGroup = (\n currentItem: Item,\n): currentItem is Item & { isGroup: true } => {\n return 'isGroup' in currentItem && currentItem.isGroup\n}\n\nconst isDeprecated = (\n currentItem: Item,\n): currentItem is Item & { isDeprecated: true } => {\n return ('isDeprecated' in currentItem && currentItem.isDeprecated) ?? false\n}\n\n/**\n * Handle drag end event and bubble it up to parent.\n */\nconst onDragEnd = (draggingItem: DraggingItem, hoveredItem: HoveredItem) => {\n emit('onDragEnd', draggingItem, hoveredItem)\n}\nconst { draggableAttrs, draggableEvents } = useDraggable({\n id: item.id,\n isDraggable,\n isDroppable,\n onDragEnd,\n})\n\nconst children = computed(() =>\n hasChildren(item)\n ? filterItems(layout, item.children, options?.hideOperationDefaultExamples)\n : [],\n)\n\n/** The URL for this item, when the consumer provides one it renders as a link */\nconst href = computed(() => getHref?.(item) || undefined)\n\n/**\n * Whether the group renders its toggle separately from its label.\n *\n * A label that navigates cannot also own the open state, so a group that\n * renders as a link needs a toggle button of its own. Without one there is no\n * way to collapse the group from the keyboard, because pressing Enter on the\n * label follows the link instead.\n */\nconst isDiscrete = computed(\n () => Boolean(href.value) || (layout === 'reference' && item.type === 'text'),\n)\n\n/**\n * Builds the screen reader label for the discrete group toggle.\n *\n * The title of the group is appended so the toggles can be told apart. A page\n * can hold a lot of them, and a list of identical \"Open Group\" buttons gives a\n * screen reader user nothing to navigate by.\n */\nconst getToggleLabel = (open: boolean): string => {\n const label = open\n ? (options?.labels?.closeGroup ?? 'Close Group')\n : (options?.labels?.openGroup ?? 'Open Group')\n\n return item.title ? `${label} - ${item.title}` : label\n}\n\n/**\n * Emit the select event for a click on the item label.\n *\n * When the item renders as a link we only hijack plain left clicks on the\n * link itself for in-app navigation. Modified clicks (meta, ctrl, shift,\n * alt) and middle clicks keep the browser's default behavior so the link\n * can be opened in a new tab or window, and clicks on surrounding content\n * (like the decorator menu) keep their native behavior. A click whose\n * default is already prevented has been handled by someone else, so it is\n * left alone rather than navigated a second time.\n */\nconst handleSelect = (event: MouseEvent) => {\n if (href.value) {\n const anchor =\n event.target instanceof Element ? event.target.closest('a') : null\n if (anchor?.getAttribute('href') !== href.value) {\n return\n }\n if (event.defaultPrevented || !isPlainLeftClick(event)) {\n return\n }\n event.preventDefault()\n }\n emit('selectItem', item.id)\n}\n</script>\n<template>\n <!-- Sidebar section -->\n <ScalarSidebarSection\n v-if=\"children.length > 0 && isGroup(item)\"\n :data-sidebar-id=\"item.id\"\n v-bind=\"draggableAttrs\"\n v-on=\"draggableEvents\">\n {{ item.title }}\n <template #items>\n <SidebarItem\n v-for=\"child in children\"\n :key=\"child.id\"\n :getHref=\"getHref\"\n :isDraggable=\"isDraggable\"\n :isDroppable=\"isDroppable\"\n :isExpanded=\"isExpanded\"\n :isSelected=\"isSelected\"\n :item=\"child\"\n :layout=\"layout\"\n :options=\"options\"\n @onDragEnd=\"onDragEnd\"\n @selectItem=\"(id) => emit('selectItem', id)\"\n @toggleGroup=\"(id) => emit('toggleGroup', id)\">\n <template\n v-if=\"slots.decorator\"\n #decorator=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"decorator\" />\n </template>\n <template\n v-if=\"slots.empty\"\n #empty=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"empty\" />\n </template>\n <template\n v-if=\"slots.icon\"\n #icon=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"icon\" />\n </template>\n </SidebarItem>\n </template>\n </ScalarSidebarSection>\n\n <!-- Sidebar group (folder) -->\n <ScalarSidebarGroup\n v-else-if=\"\n isSidebarFolder(\n layout,\n item,\n slots.empty !== undefined,\n options?.hideOperationDefaultExamples ?? false,\n )\n \"\n :active=\"isSelected(item.id)\"\n class=\"relative\"\n controlled\n :data-sidebar-id=\"item.id\"\n v-bind=\"draggableAttrs\"\n :discrete=\"isDiscrete\"\n :open=\"isExpanded(item.id)\"\n v-on=\"draggableEvents\">\n <template #button=\"{ open, level }\">\n <ScalarSidebarButton\n :is=\"href ? 'a' : 'button'\"\n :active=\"isSelected(item.id)\"\n :aria-expanded=\"isDiscrete ? undefined : open\"\n :href=\"href\"\n :indent=\"level\"\n @click=\"handleSelect\">\n <template #indent>\n <ScalarSidebarIndent\n class=\"-my-2 mr-0\"\n :indent=\"level\" />\n </template>\n <template\n v-if=\"item.type === 'document'\"\n #icon>\n <slot\n :item=\"item\"\n name=\"icon\"\n :open=\"open\">\n <LibraryIcon\n class=\"block\"\n :src=\"\n ('icon' in item && item.icon) || 'interface-content-folder'\n \" />\n </slot>\n </template>\n <span\n v-if=\"isDeprecated(item)\"\n class=\"line-through\">\n <SidebarItemLabel\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n </span>\n <SidebarItemLabel\n v-else\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n <template #aside>\n <SidebarHttpBadge\n v-if=\"'method' in item\"\n :active=\"isSelected(item.id)\"\n class=\"ml-2 h-4 self-start\"\n :class=\"{\n // Hide the badge when we're showing the decorator\n 'group-hover/button:opacity-0 group-focus-visible/button:opacity-0 group-has-[~*_[aria-expanded=true]]/button:opacity-0 group-has-[~*:focus-within]/button:opacity-0 group-has-[~*:hover]/button:opacity-0':\n slots.decorator,\n }\"\n :label=\"options?.labels?.httpMethod\"\n :method=\"item.method\"\n :webhook=\"item.type === 'webhook'\" />\n <ScalarSidebarGroupToggleSpacer v-if=\"isDiscrete\" />\n <ScalarSidebarGroupToggle\n v-else-if=\"!('method' in item)\"\n class=\"text-sidebar-c-2\"\n :open>\n <template #label>\n {{\n open\n ? (options?.labels?.closeGroup ?? 'Close Group')\n : (options?.labels?.openGroup ?? 'Open Group')\n }}\n </template>\n </ScalarSidebarGroupToggle>\n </template>\n </ScalarSidebarButton>\n <ScalarSidebarGroupToggleButton\n v-if=\"isDiscrete\"\n :open\n @click=\"() => emit('toggleGroup', item.id)\">\n <template #label>{{ getToggleLabel(open) }}</template>\n </ScalarSidebarGroupToggleButton>\n </template>\n <template\n v-if=\"slots.decorator\"\n #after>\n <SidebarItemDecorator>\n <slot\n :item\n name=\"decorator\" />\n </SidebarItemDecorator>\n </template>\n <template #items>\n <SidebarItem\n v-for=\"child in children\"\n :key=\"child.id\"\n :getHref=\"getHref\"\n :isDraggable=\"isDraggable\"\n :isDroppable=\"isDroppable\"\n :isExpanded=\"isExpanded\"\n :isSelected=\"isSelected\"\n :item=\"child\"\n :layout=\"layout\"\n :options=\"options\"\n :parentIds=\"[]\"\n @onDragEnd=\"onDragEnd\"\n @selectItem=\"(id) => emit('selectItem', id)\"\n @toggleGroup=\"(id) => emit('toggleGroup', id)\">\n <template\n v-if=\"slots.decorator\"\n #decorator=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"decorator\" />\n </template>\n <template\n v-if=\"slots.empty\"\n #empty=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"empty\" />\n </template>\n <template\n v-if=\"slots.icon\"\n #icon=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"icon\" />\n </template>\n </SidebarItem>\n <template v-if=\"slots.empty && (item.children?.length ?? 0) === 0\">\n <slot\n :item\n name=\"empty\" />\n </template>\n </template>\n </ScalarSidebarGroup>\n\n <!-- Sidebar item (leaf node) -->\n <ScalarSidebarItem\n v-else\n v-bind=\"draggableAttrs\"\n class=\"relative\"\n :data-sidebar-id=\"item.id\"\n v-on=\"draggableEvents\"\n @click=\"handleSelect\">\n <template #button=\"{ level }\">\n <ScalarSidebarButton\n :is=\"href ? 'a' : 'button'\"\n :href=\"href\"\n :indent=\"level\"\n :selected=\"isSelected(item.id)\">\n <template\n v-if=\"slots.icon\"\n #icon>\n <slot\n :item=\"item\"\n name=\"icon\"\n :open=\"true\" />\n </template>\n <span\n v-if=\"isDeprecated(item)\"\n class=\"line-through\">\n <SidebarItemLabel\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n </span>\n <SidebarItemLabel\n v-else\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n <template\n v-if=\"'method' in item\"\n #aside>\n <SidebarHttpBadge\n :active=\"isSelected(item.id)\"\n class=\"ml-2 h-4 self-start\"\n :class=\"{\n // Hide the badge when we're showing the decorator\n 'group-hover/button:opacity-0 group-focus-visible/button:opacity-0 group-has-[~*_[aria-expanded=true]]/button:opacity-0 group-has-[~*:focus-within]/button:opacity-0 group-has-[~*:hover]/button:opacity-0':\n slots.decorator,\n }\"\n :label=\"options?.labels?.httpMethod\"\n :method=\"item.method\"\n :webhook=\"item.type === 'webhook'\" />\n </template>\n </ScalarSidebarButton>\n </template>\n <template\n v-if=\"slots.decorator\"\n #after>\n <SidebarItemDecorator>\n <slot\n :item\n name=\"decorator\" />\n </SidebarItemDecorator>\n </template>\n </ScalarSidebarItem>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SidebarItem.vue.script.js","names":[],"sources":["../../src/components/SidebarItem.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport {\n ScalarSidebarButton,\n ScalarSidebarGroup,\n ScalarSidebarGroupToggle,\n ScalarSidebarGroupToggleButton,\n ScalarSidebarGroupToggleSpacer,\n ScalarSidebarIndent,\n ScalarSidebarItem,\n ScalarSidebarSection,\n} from '@scalar/components/sidebar'\nimport { isPlainLeftClick } from '@scalar/helpers/dom/is-plain-left-click'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport { computed } from 'vue'\n\nimport SidebarItemDecorator from '@/components/SidebarItemDecorator.vue'\nimport { filterItems } from '@/helpers/filter-items'\nimport { hasChildren } from '@/helpers/has-children'\nimport { isSidebarFolder } from '@/helpers/is-sidebar-folder'\nimport {\n useDraggable,\n type DraggingItem,\n type HoveredItem,\n type UseDraggableOptions,\n} from '@/hooks/use-draggable'\nimport type { Item, Layout, SidebarOptions } from '@/types'\n\nimport SidebarHttpBadge from './SidebarHttpBadge.vue'\nimport SidebarItemLabel from './SidebarItemLabel.vue'\n\nconst {\n item,\n layout,\n isSelected,\n isExpanded,\n isDraggable,\n isDroppable,\n options,\n getHref,\n} = defineProps<{\n /**\n * The sidebar item to render.\n */\n item: Item\n /**\n * The layout mode for the sidebar ('client' or 'reference').\n */\n layout: Layout\n /**\n * Function to determine if an item is currently selected by id.\n */\n isSelected: (id: string) => boolean\n /**\n * Function to determine if an item is currently expanded (showing its children) by id.\n */\n isExpanded: (id: string) => boolean\n /**\n * Sidebar configuration options.\n * - operationTitleSource: sets whether operations show their path or summary as the display title.\n */\n options?: SidebarOptions\n\n /**\n * Returns the URL for a sidebar item.\n *\n * When provided (and it returns a value) items render as anchor tags\n * instead of buttons, so search engines can crawl the navigation.\n */\n getHref?: (item: Item) => string | undefined\n\n /**\n * Prevents this item from being dragged.\n *\n * @default true\n */\n isDraggable?: UseDraggableOptions['isDraggable']\n /**\n * Prevents this item from being hovered and dropped into. Can be either a function or a boolean.\n *\n * @default true\n */\n isDroppable?: UseDraggableOptions['isDroppable']\n}>()\n\nconst emit = defineEmits<{\n /**\n * Emitted when the item is selected\n * @param id - The id of the selected item\n */\n (e: 'selectItem', id: string): void\n /**\n * Emitted when a drag operation ends for this item\n * @param draggingItem - The item being dragged\n * @param hoveredItem - The item currently being hovered over\n */\n (e: 'onDragEnd', draggingItem: DraggingItem, hoveredItem: HoveredItem): void\n\n /**\n * Emitted when the group is toggled\n * @param id - The id of the group\n */\n (e: 'toggleGroup', id: string): void\n}>()\n\nconst slots = defineSlots<{\n /**\n * Adds an optional decorator for each item, such as an edit menu.\n * The slot receives an object with the current item.\n */\n decorator?(props: { item: Item }): unknown\n /**\n * Adds an optional empty state for an item.\n * The slot receives an object with the current item.\n */\n empty?(props: { item: Item }): unknown\n /**\n * Adds an optional icon for each item.\n * The slot receives an object with the current item and the open state.\n */\n icon?(props: { item: Item; open: boolean }): unknown\n}>()\n\nconst isGroup = (\n currentItem: Item,\n): currentItem is Item & { isGroup: true } => {\n return 'isGroup' in currentItem && currentItem.isGroup\n}\n\nconst isDeprecated = (\n currentItem: Item,\n): currentItem is Item & { isDeprecated: true } => {\n return ('isDeprecated' in currentItem && currentItem.isDeprecated) ?? false\n}\n\n/**\n * Handle drag end event and bubble it up to parent.\n */\nconst onDragEnd = (draggingItem: DraggingItem, hoveredItem: HoveredItem) => {\n emit('onDragEnd', draggingItem, hoveredItem)\n}\nconst { draggableAttrs, draggableEvents } = useDraggable({\n id: item.id,\n isDraggable,\n isDroppable,\n onDragEnd,\n})\n\nconst children = computed(() =>\n hasChildren(item)\n ? filterItems(layout, item.children, options?.hideOperationDefaultExamples)\n : [],\n)\n\n/**\n * Whether this item is the one currently displayed on the page.\n *\n * `isSelected` also reports true for every ancestor of the displayed item,\n * which is what the active styling of a group needs. Only the deepest\n * selected node is the current page though, so a group counts as current when\n * none of its children are selected. Leaf items already get this from the\n * `selected` prop of ScalarSidebarButton.\n */\nconst isCurrent = computed(\n () =>\n isSelected(item.id) &&\n !(hasChildren(item) && item.children.some((child) => isSelected(child.id))),\n)\n\n/** The URL for this item, when the consumer provides one it renders as a link */\nconst href = computed(() => getHref?.(item) || undefined)\n\n/**\n * Whether the group renders its toggle separately from its label.\n *\n * A label that navigates cannot also own the open state, so a group that\n * renders as a link needs a toggle button of its own. Without one there is no\n * way to collapse the group from the keyboard, because pressing Enter on the\n * label follows the link instead.\n */\nconst isDiscrete = computed(\n () => Boolean(href.value) || (layout === 'reference' && item.type === 'text'),\n)\n\n/**\n * Builds the screen reader label for the discrete group toggle.\n *\n * The title of the group is appended so the toggles can be told apart. A page\n * can hold a lot of them, and a list of identical \"Open Group\" buttons gives a\n * screen reader user nothing to navigate by.\n */\nconst getToggleLabel = (open: boolean): string => {\n const label = open\n ? (options?.labels?.closeGroup ?? 'Close Group')\n : (options?.labels?.openGroup ?? 'Open Group')\n\n return item.title ? `${label} - ${item.title}` : label\n}\n\n/**\n * Emit the select event for a click on the item label.\n *\n * When the item renders as a link we only hijack plain left clicks on the\n * link itself for in-app navigation. Modified clicks (meta, ctrl, shift,\n * alt) and middle clicks keep the browser's default behavior so the link\n * can be opened in a new tab or window, and clicks on surrounding content\n * (like the decorator menu) keep their native behavior. A click whose\n * default is already prevented has been handled by someone else, so it is\n * left alone rather than navigated a second time.\n */\nconst handleSelect = (event: MouseEvent) => {\n if (href.value) {\n const anchor =\n event.target instanceof Element ? event.target.closest('a') : null\n if (anchor?.getAttribute('href') !== href.value) {\n return\n }\n if (event.defaultPrevented || !isPlainLeftClick(event)) {\n return\n }\n event.preventDefault()\n }\n emit('selectItem', item.id)\n}\n</script>\n<template>\n <!-- Sidebar section -->\n <ScalarSidebarSection\n v-if=\"children.length > 0 && isGroup(item)\"\n :data-sidebar-id=\"item.id\"\n v-bind=\"draggableAttrs\"\n v-on=\"draggableEvents\">\n {{ item.title }}\n <template #items>\n <SidebarItem\n v-for=\"child in children\"\n :key=\"child.id\"\n :getHref=\"getHref\"\n :isDraggable=\"isDraggable\"\n :isDroppable=\"isDroppable\"\n :isExpanded=\"isExpanded\"\n :isSelected=\"isSelected\"\n :item=\"child\"\n :layout=\"layout\"\n :options=\"options\"\n @onDragEnd=\"onDragEnd\"\n @selectItem=\"(id) => emit('selectItem', id)\"\n @toggleGroup=\"(id) => emit('toggleGroup', id)\">\n <template\n v-if=\"slots.decorator\"\n #decorator=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"decorator\" />\n </template>\n <template\n v-if=\"slots.empty\"\n #empty=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"empty\" />\n </template>\n <template\n v-if=\"slots.icon\"\n #icon=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"icon\" />\n </template>\n </SidebarItem>\n </template>\n </ScalarSidebarSection>\n\n <!-- Sidebar group (folder) -->\n <ScalarSidebarGroup\n v-else-if=\"\n isSidebarFolder(\n layout,\n item,\n slots.empty !== undefined,\n options?.hideOperationDefaultExamples ?? false,\n )\n \"\n :active=\"isSelected(item.id)\"\n class=\"relative\"\n controlled\n :data-sidebar-id=\"item.id\"\n v-bind=\"draggableAttrs\"\n :discrete=\"isDiscrete\"\n :open=\"isExpanded(item.id)\"\n v-on=\"draggableEvents\">\n <template #button=\"{ open, level }\">\n <ScalarSidebarButton\n :is=\"href ? 'a' : 'button'\"\n :active=\"isSelected(item.id)\"\n :aria-current=\"isCurrent ? 'page' : undefined\"\n :aria-expanded=\"isDiscrete ? undefined : open\"\n :href=\"href\"\n :indent=\"level\"\n @click=\"handleSelect\">\n <template #indent>\n <ScalarSidebarIndent\n class=\"-my-2 mr-0\"\n :indent=\"level\" />\n </template>\n <template\n v-if=\"item.type === 'document'\"\n #icon>\n <slot\n :item=\"item\"\n name=\"icon\"\n :open=\"open\">\n <LibraryIcon\n class=\"block\"\n :src=\"\n ('icon' in item && item.icon) || 'interface-content-folder'\n \" />\n </slot>\n </template>\n <span\n v-if=\"isDeprecated(item)\"\n class=\"line-through\">\n <SidebarItemLabel\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n </span>\n <SidebarItemLabel\n v-else\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n <template #aside>\n <SidebarHttpBadge\n v-if=\"'method' in item\"\n :active=\"isSelected(item.id)\"\n class=\"ml-2 h-4 self-start\"\n :class=\"{\n // Hide the badge when we're showing the decorator\n 'group-hover/button:opacity-0 group-focus-visible/button:opacity-0 group-has-[~*_[aria-expanded=true]]/button:opacity-0 group-has-[~*:focus-within]/button:opacity-0 group-has-[~*:hover]/button:opacity-0':\n slots.decorator,\n }\"\n :label=\"options?.labels?.httpMethod\"\n :method=\"item.method\"\n :webhook=\"item.type === 'webhook'\" />\n <ScalarSidebarGroupToggleSpacer v-if=\"isDiscrete\" />\n <ScalarSidebarGroupToggle\n v-else-if=\"!('method' in item)\"\n class=\"text-sidebar-c-2\"\n :open>\n <template #label>\n {{\n open\n ? (options?.labels?.closeGroup ?? 'Close Group')\n : (options?.labels?.openGroup ?? 'Open Group')\n }}\n </template>\n </ScalarSidebarGroupToggle>\n </template>\n </ScalarSidebarButton>\n <ScalarSidebarGroupToggleButton\n v-if=\"isDiscrete\"\n :open\n @click=\"() => emit('toggleGroup', item.id)\">\n <template #label>{{ getToggleLabel(open) }}</template>\n </ScalarSidebarGroupToggleButton>\n </template>\n <template\n v-if=\"slots.decorator\"\n #after>\n <SidebarItemDecorator>\n <slot\n :item\n name=\"decorator\" />\n </SidebarItemDecorator>\n </template>\n <template #items>\n <SidebarItem\n v-for=\"child in children\"\n :key=\"child.id\"\n :getHref=\"getHref\"\n :isDraggable=\"isDraggable\"\n :isDroppable=\"isDroppable\"\n :isExpanded=\"isExpanded\"\n :isSelected=\"isSelected\"\n :item=\"child\"\n :layout=\"layout\"\n :options=\"options\"\n :parentIds=\"[]\"\n @onDragEnd=\"onDragEnd\"\n @selectItem=\"(id) => emit('selectItem', id)\"\n @toggleGroup=\"(id) => emit('toggleGroup', id)\">\n <template\n v-if=\"slots.decorator\"\n #decorator=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"decorator\" />\n </template>\n <template\n v-if=\"slots.empty\"\n #empty=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"empty\" />\n </template>\n <template\n v-if=\"slots.icon\"\n #icon=\"slotProps\">\n <slot\n v-bind=\"slotProps\"\n name=\"icon\" />\n </template>\n </SidebarItem>\n <template v-if=\"slots.empty && (item.children?.length ?? 0) === 0\">\n <slot\n :item\n name=\"empty\" />\n </template>\n </template>\n </ScalarSidebarGroup>\n\n <!-- Sidebar item (leaf node) -->\n <ScalarSidebarItem\n v-else\n v-bind=\"draggableAttrs\"\n class=\"relative\"\n :data-sidebar-id=\"item.id\"\n v-on=\"draggableEvents\"\n @click=\"handleSelect\">\n <template #button=\"{ level }\">\n <ScalarSidebarButton\n :is=\"href ? 'a' : 'button'\"\n :href=\"href\"\n :indent=\"level\"\n :selected=\"isSelected(item.id)\">\n <template\n v-if=\"slots.icon\"\n #icon>\n <slot\n :item=\"item\"\n name=\"icon\"\n :open=\"true\" />\n </template>\n <span\n v-if=\"isDeprecated(item)\"\n class=\"line-through\">\n <SidebarItemLabel\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n </span>\n <SidebarItemLabel\n v-else\n :item\n :operationTitleSource=\"options?.operationTitleSource\" />\n <template\n v-if=\"'method' in item\"\n #aside>\n <SidebarHttpBadge\n :active=\"isSelected(item.id)\"\n class=\"ml-2 h-4 self-start\"\n :class=\"{\n // Hide the badge when we're showing the decorator\n 'group-hover/button:opacity-0 group-focus-visible/button:opacity-0 group-has-[~*_[aria-expanded=true]]/button:opacity-0 group-has-[~*:focus-within]/button:opacity-0 group-has-[~*:hover]/button:opacity-0':\n slots.decorator,\n }\"\n :label=\"options?.labels?.httpMethod\"\n :method=\"item.method\"\n :webhook=\"item.type === 'webhook'\" />\n </template>\n </ScalarSidebarButton>\n </template>\n <template\n v-if=\"slots.decorator\"\n #after>\n <SidebarItemDecorator>\n <slot\n :item\n name=\"decorator\" />\n </SidebarItemDecorator>\n </template>\n </ScalarSidebarItem>\n</template>\n"],"mappings":"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"}
|
package/dist/style.css
CHANGED
|
@@ -213,7 +213,7 @@
|
|
|
213
213
|
--scalar-background-3: #e7e7e7;
|
|
214
214
|
--scalar-background-accent: #8ab4f81f;
|
|
215
215
|
--scalar-color-1: #1b1b1b;
|
|
216
|
-
--scalar-color-2: #
|
|
216
|
+
--scalar-color-2: #707070;
|
|
217
217
|
--scalar-color-3: #8e8e8e;
|
|
218
218
|
--scalar-color-accent: #09f;
|
|
219
219
|
--scalar-border-color: #dfdfdf;
|
|
@@ -261,7 +261,7 @@
|
|
|
261
261
|
--scalar-color-green: #069061;
|
|
262
262
|
--scalar-color-red: #ef0006;
|
|
263
263
|
--scalar-color-yellow: #edbe20;
|
|
264
|
-
--scalar-color-blue: #
|
|
264
|
+
--scalar-color-blue: #0072bd;
|
|
265
265
|
--scalar-color-orange: #ff5800;
|
|
266
266
|
--scalar-color-purple: #5203d1;
|
|
267
267
|
--scalar-color-query: #007b80;
|
|
@@ -379,7 +379,7 @@
|
|
|
379
379
|
--scalar-color-green: color(display-p3 .023529 .564706 .380392);
|
|
380
380
|
--scalar-color-red: color(display-p3 .937255 0 .023529);
|
|
381
381
|
--scalar-color-yellow: color(display-p3 .929412 .745098 .12549);
|
|
382
|
-
--scalar-color-blue: color(display-p3 0 .
|
|
382
|
+
--scalar-color-blue: color(display-p3 0 .447059 .741176);
|
|
383
383
|
--scalar-color-orange: color(display-p3 1 .4 .02);
|
|
384
384
|
--scalar-color-purple: color(display-p3 .321569 .011765 .819608);
|
|
385
385
|
}
|
|
@@ -411,9 +411,19 @@
|
|
|
411
411
|
:where(.scalar-app) {
|
|
412
412
|
font-family: var(--scalar-font);
|
|
413
413
|
color: var(--scalar-color-1);
|
|
414
|
+
--scalar-focus-color: var(--scalar-color-accent);
|
|
415
|
+
line-height: 1.15;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
419
|
+
:where(.scalar-app) {
|
|
420
|
+
--scalar-focus-color: color-mix(in srgb, var(--scalar-color-accent), var(--scalar-color-1) 20%);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
:where(.scalar-app) {
|
|
414
425
|
-webkit-text-size-adjust: 100%;
|
|
415
426
|
tab-size: 4;
|
|
416
|
-
line-height: 1.15;
|
|
417
427
|
}
|
|
418
428
|
|
|
419
429
|
:where(.scalar-app) *, :where(.scalar-app) :before, :where(.scalar-app) :after {
|
|
@@ -504,6 +514,10 @@
|
|
|
504
514
|
outline-offset: -1px;
|
|
505
515
|
}
|
|
506
516
|
|
|
517
|
+
:where(.scalar-app) a:focus-visible, :where(.scalar-app) button:focus-visible, :where(.scalar-app) [role="button"]:focus-visible {
|
|
518
|
+
outline-color: var(--scalar-focus-color);
|
|
519
|
+
}
|
|
520
|
+
|
|
507
521
|
:where(.scalar-app) button, :where(.scalar-app) [role="button"] {
|
|
508
522
|
cursor: pointer;
|
|
509
523
|
}
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"url": "git+https://github.com/scalar/scalar.git",
|
|
11
11
|
"directory": "packages/sidebar"
|
|
12
12
|
},
|
|
13
|
-
"version": "0.11.
|
|
13
|
+
"version": "0.11.9",
|
|
14
14
|
"engines": {
|
|
15
15
|
"node": ">=22"
|
|
16
16
|
},
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"dist"
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@scalar/components": "0.30.
|
|
36
|
-
"@scalar/helpers": "0.
|
|
35
|
+
"@scalar/components": "0.30.4",
|
|
36
|
+
"@scalar/helpers": "0.16.0",
|
|
37
37
|
"@scalar/icons": "0.7.6",
|
|
38
|
-
"@scalar/themes": "0.18.
|
|
39
|
-
"@scalar/use-hooks": "0.4.
|
|
40
|
-
"@scalar/workspace-store": "0.67.
|
|
38
|
+
"@scalar/themes": "0.18.1",
|
|
39
|
+
"@scalar/use-hooks": "0.4.16",
|
|
40
|
+
"@scalar/workspace-store": "0.67.1",
|
|
41
41
|
"vue": "^3.5.40"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|