@scalar/api-reference
Version:
Generate beautiful API references from OpenAPI documents
121 lines (120 loc) • 5.01 kB
JavaScript
import { defineComponent, ref, watch, computed, createBlock, openBlock, unref, withCtx, createElementVNode, createVNode, withKeys, withModifiers, isRef, createElementBlock, Fragment, renderList, createTextVNode, toDisplayString } from "vue";
import { ScalarModal, ScalarSearchInput, ScalarSearchResultList } from "@scalar/components";
import { nanoid } from "nanoid";
import { useSearchIndex } from "../hooks/useSearchIndex.js";
import _sfc_main$1 from "./SearchResult.vue.js";
const _hoisted_1 = {
class: "mb-0 flex flex-col",
role: "search"
};
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "SearchModal",
props: {
modalState: {},
document: {},
eventBus: {}
},
setup(__props) {
const props = __props;
const id = nanoid();
const listboxId = `${id}-search-result`;
const instructionsId = `${id}-search-instructions`;
const { query, results } = useSearchIndex(() => props.document);
const selectedIndex = ref(void 0);
watch(
() => props.modalState.open,
(open) => {
if (open) {
query.value = "";
}
}
);
const navigateSearchResults = (direction) => {
const offset = direction === "up" ? -1 : 1;
const length = results.value.length;
if (typeof selectedIndex.value === "number") {
selectedIndex.value = (selectedIndex.value + offset + length) % length;
} else {
selectedIndex.value = offset === -1 ? length - 1 : 0;
}
};
function handleSelect(idx) {
if (typeof idx !== "number" || !results.value[idx]) {
return;
}
const result = results.value[idx];
props.modalState.hide();
props.eventBus.emit("scroll-to:nav-item", { id: result.item.id });
}
const activeDescendantId = computed(() => {
const selectedResult = results.value[selectedIndex.value ?? -1];
return selectedResult ? `search-result-${selectedResult.item.id}` : void 0;
});
return (_ctx, _cache) => {
return openBlock(), createBlock(unref(ScalarModal), {
"aria-label": "Reference Search",
state: __props.modalState,
variant: "search"
}, {
default: withCtx(() => [
createElementVNode("div", _hoisted_1, [
createVNode(unref(ScalarSearchInput), {
modelValue: unref(query),
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(query) ? query.value = $event : null),
"aria-activedescendant": activeDescendantId.value,
"aria-autocomplete": "list",
"aria-controls": listboxId,
"aria-describedby": instructionsId,
role: "combobox",
onBlur: _cache[1] || (_cache[1] = ($event) => selectedIndex.value = void 0),
onKeydown: [
_cache[2] || (_cache[2] = withKeys(withModifiers(($event) => navigateSearchResults("down"), ["stop", "prevent"]), ["down"])),
_cache[3] || (_cache[3] = withKeys(withModifiers(() => handleSelect(selectedIndex.value), ["stop", "prevent"]), ["enter"])),
_cache[4] || (_cache[4] = withKeys(withModifiers(($event) => navigateSearchResults("up"), ["stop", "prevent"]), ["up"]))
]
}, null, 8, ["modelValue", "aria-activedescendant"])
]),
createVNode(unref(ScalarSearchResultList), {
id: listboxId,
"aria-label": "Reference Search Results",
class: "custom-scroll p-1 pt-0",
noResults: !unref(results).length
}, {
query: withCtx(() => [
createTextVNode(toDisplayString(unref(query)), 1)
]),
default: withCtx(() => [
(openBlock(true), createElementBlock(Fragment, null, renderList(unref(results), (result, idx) => {
return openBlock(), createBlock(_sfc_main$1, {
id: `search-result-${result.item.id}`,
key: result.refIndex,
isSelected: selectedIndex.value === idx,
result,
onClick: withModifiers(() => handleSelect(idx), ["prevent"])
}, null, 8, ["id", "isSelected", "result", "onClick"]);
}), 128))
]),
_: 1
}, 8, ["noResults"]),
createElementVNode("div", {
id: instructionsId,
class: "ref-search-meta"
}, [..._cache[5] || (_cache[5] = [
createElementVNode("span", {
"aria-hidden": "true",
class: "contents"
}, [
createElementVNode("span", null, "↑↓ Navigate"),
createElementVNode("span", null, "⏎ Select")
], -1),
createElementVNode("span", { class: "sr-only" }, " Press up arrow / down arrow to navigate, enter to select, type to filter results ", -1)
])])
]),
_: 1
}, 8, ["state"]);
};
}
});
export {
_sfc_main as default
};