@scalar/api-client 3.2.2 → 3.3.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 +11 -0
- package/dist/style.css +102 -130
- 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 +9 -0
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.d.ts +2 -0
- package/dist/v2/blocks/operation-block/components/Header.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.js +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.script.js +20 -10
- package/dist/v2/blocks/operation-block/components/Header.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts +2 -2
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts +2 -2
- package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.d.ts +2 -2
- package/dist/v2/components/server/ServerDropdown.vue.d.ts +2 -2
- package/dist/v2/components/sidebar/Sidebar.vue.script.js +2 -2
- 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.vue.d.ts +22 -4
- package/dist/v2/features/app/App.vue.d.ts.map +1 -1
- package/dist/v2/features/app/App.vue.js.map +1 -1
- package/dist/v2/features/app/App.vue.script.js +57 -54
- package/dist/v2/features/app/App.vue.script.js.map +1 -1
- package/dist/v2/features/app/app-events.d.ts.map +1 -1
- package/dist/v2/features/app/app-events.js +4 -0
- package/dist/v2/features/app/app-events.js.map +1 -1
- package/dist/v2/features/app/app-state.d.ts +6 -0
- package/dist/v2/features/app/app-state.d.ts.map +1 -1
- package/dist/v2/features/app/app-state.js +15 -1
- package/dist/v2/features/app/app-state.js.map +1 -1
- package/dist/v2/features/app/components/AppHeader.vue.d.ts +20 -0
- package/dist/v2/features/app/components/AppHeader.vue.d.ts.map +1 -0
- package/dist/v2/features/app/components/AppHeader.vue.js +7 -0
- package/dist/v2/features/app/components/AppHeader.vue.js.map +1 -0
- package/dist/v2/features/app/components/AppHeader.vue.script.js +43 -0
- package/dist/v2/features/app/components/AppHeader.vue.script.js.map +1 -0
- package/dist/v2/features/app/components/AppSidebar.vue.d.ts +17 -56
- 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 +437 -271
- package/dist/v2/features/app/components/AppSidebar.vue.script.js.map +1 -1
- package/dist/v2/features/app/helpers/load-registry-document.d.ts +18 -0
- package/dist/v2/features/app/helpers/load-registry-document.d.ts.map +1 -0
- package/dist/v2/features/app/helpers/load-registry-document.js +45 -0
- package/dist/v2/features/app/helpers/load-registry-document.js.map +1 -0
- package/dist/v2/features/app/helpers/routes.d.ts +6 -1
- package/dist/v2/features/app/helpers/routes.d.ts.map +1 -1
- package/dist/v2/features/app/helpers/routes.js +84 -75
- package/dist/v2/features/app/helpers/routes.js.map +1 -1
- package/dist/v2/features/app/hooks/use-document-filter.d.ts +38 -0
- package/dist/v2/features/app/hooks/use-document-filter.d.ts.map +1 -0
- package/dist/v2/features/app/hooks/use-document-filter.js +63 -0
- package/dist/v2/features/app/hooks/use-document-filter.js.map +1 -0
- package/dist/v2/features/app/hooks/use-sidebar-context-menu.d.ts +17258 -0
- package/dist/v2/features/app/hooks/use-sidebar-context-menu.d.ts.map +1 -0
- package/dist/v2/features/app/hooks/use-sidebar-context-menu.js +107 -0
- package/dist/v2/features/app/hooks/use-sidebar-context-menu.js.map +1 -0
- package/dist/v2/features/app/hooks/use-sidebar-documents.d.ts +95 -0
- package/dist/v2/features/app/hooks/use-sidebar-documents.d.ts.map +1 -0
- package/dist/v2/features/app/hooks/use-sidebar-documents.js +97 -0
- package/dist/v2/features/app/hooks/use-sidebar-documents.js.map +1 -0
- package/dist/v2/features/app/index.d.ts +1 -0
- package/dist/v2/features/app/index.d.ts.map +1 -1
- package/dist/v2/features/collection/components/GetStarted.vue.d.ts +13 -0
- package/dist/v2/features/collection/components/GetStarted.vue.d.ts.map +1 -0
- package/dist/v2/features/collection/components/GetStarted.vue.js +7 -0
- package/dist/v2/features/collection/components/GetStarted.vue.js.map +1 -0
- package/dist/v2/features/collection/components/GetStarted.vue.script.js +101 -0
- package/dist/v2/features/collection/components/GetStarted.vue.script.js.map +1 -0
- package/dist/v2/features/command-palette/helpers/generate-unique-slug.d.ts +4 -0
- package/dist/v2/features/command-palette/helpers/generate-unique-slug.d.ts.map +1 -1
- package/dist/v2/features/command-palette/helpers/generate-unique-slug.js +5 -1
- package/dist/v2/features/command-palette/helpers/generate-unique-slug.js.map +1 -1
- package/dist/v2/features/search/components/DocumentSearchModal.vue.d.ts +16 -0
- package/dist/v2/features/search/components/DocumentSearchModal.vue.d.ts.map +1 -0
- package/dist/v2/features/search/components/DocumentSearchModal.vue.js +9 -0
- package/dist/v2/features/search/components/DocumentSearchModal.vue.js.map +1 -0
- package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js +123 -0
- package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js.map +1 -0
- package/dist/v2/features/search/components/SearchResult.vue.d.ts +11 -0
- package/dist/v2/features/search/components/SearchResult.vue.d.ts.map +1 -0
- package/dist/v2/features/search/components/SearchResult.vue.js +7 -0
- package/dist/v2/features/search/components/SearchResult.vue.js.map +1 -0
- package/dist/v2/features/search/components/SearchResult.vue.script.js +71 -0
- package/dist/v2/features/search/components/SearchResult.vue.script.js.map +1 -0
- package/dist/v2/features/search/hooks/use-document-search.d.ts +19 -0
- package/dist/v2/features/search/hooks/use-document-search.d.ts.map +1 -0
- package/dist/v2/features/search/hooks/use-document-search.js +42 -0
- package/dist/v2/features/search/hooks/use-document-search.js.map +1 -0
- package/dist/v2/features/search/index.d.ts +2 -0
- package/dist/v2/features/search/index.d.ts.map +1 -1
- package/dist/v2/features/search/index.js +3 -1
- package/dist/v2/helpers/handle-hotkeys.d.ts.map +1 -1
- package/dist/v2/helpers/handle-hotkeys.js +8 -4
- package/dist/v2/helpers/handle-hotkeys.js.map +1 -1
- package/dist/v2/types/configuration.d.ts +1 -0
- package/dist/v2/types/configuration.d.ts.map +1 -1
- package/package.json +11 -10
- package/dist/assets/rabbit.ascii.virtual.js +0 -6
- package/dist/assets/rabbit.ascii.virtual.js.map +0 -1
- package/dist/assets/rabbitjump.ascii.virtual.js +0 -6
- package/dist/assets/rabbitjump.ascii.virtual.js.map +0 -1
- package/dist/v2/features/app/components/DownloadAppButton.vue.d.ts +0 -4
- package/dist/v2/features/app/components/DownloadAppButton.vue.d.ts.map +0 -1
- package/dist/v2/features/app/components/DownloadAppButton.vue.js +0 -9
- package/dist/v2/features/app/components/DownloadAppButton.vue.js.map +0 -1
- package/dist/v2/features/app/components/DownloadAppButton.vue.script.js +0 -21
- package/dist/v2/features/app/components/DownloadAppButton.vue.script.js.map +0 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import _plugin_vue_export_helper_default from "../../../../_virtual/_plugin-vue_export-helper.js";
|
|
2
|
+
import DocumentSearchModal_vue_vue_type_script_setup_true_lang_default from "./DocumentSearchModal.vue.script.js";
|
|
3
|
+
/* empty css */
|
|
4
|
+
//#region src/v2/features/search/components/DocumentSearchModal.vue
|
|
5
|
+
var DocumentSearchModal_default = /* @__PURE__ */ _plugin_vue_export_helper_default(DocumentSearchModal_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-a00657cc"]]);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { DocumentSearchModal_default as default };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=DocumentSearchModal.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DocumentSearchModal.vue.js","names":[],"sources":["../../../../../src/v2/features/search/components/DocumentSearchModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarModal,\n ScalarSearchInput,\n ScalarSearchResultList,\n type ModalState,\n} from '@scalar/components'\nimport type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { nanoid } from 'nanoid'\nimport { computed, ref, watch } from 'vue'\n\nimport { useDocumentSearch } from '@/v2/features/search/hooks/use-document-search'\n\nimport SearchResult from './SearchResult.vue'\n\nconst props = defineProps<{\n /** Controls the visibility of the search modal. */\n modalState: ModalState\n /** The document whose entries should be searched. */\n document: OpenApiDocument | undefined\n}>()\n\nconst emit = defineEmits<{\n /** Emitted when the user picks a result, passing the navigation id. */\n (e: 'select', id: string): void\n}>()\n\n/** Base id for the search form. */\nconst id = nanoid()\nconst listboxId = `${id}-search-result`\nconst instructionsId = `${id}-search-instructions`\n\nconst { query, results } = useDocumentSearch(() => props.document)\n\nconst selectedIndex = ref<number | undefined>(undefined)\n\n/**\n * Reset the query every time the modal is opened so users always start from a\n * clean state. Matches the reference search modal behaviour.\n */\nwatch(\n () => props.modalState.open,\n (open) => {\n if (open) {\n query.value = ''\n selectedIndex.value = undefined\n }\n },\n)\n\n/** Keyboard navigation, wrapping around the ends of the result list. */\nconst navigateSearchResults = (direction: 'up' | 'down') => {\n const offset = direction === 'up' ? -1 : 1\n const length = results.value.length\n if (length === 0) {\n return\n }\n\n if (typeof selectedIndex.value === 'number') {\n selectedIndex.value = (selectedIndex.value + offset + length) % length\n return\n }\n\n selectedIndex.value = offset === -1 ? length - 1 : 0\n}\n\nfunction handleSelect(idx: number | undefined) {\n if (typeof idx !== 'number' || !results.value[idx]) {\n return\n }\n\n const result = results.value[idx]\n props.modalState.hide()\n emit('select', result.item.id)\n}\n\n/**\n * aria-activedescendant for the combobox. Each result item must render the\n * matching id for assistive tech to announce the selection correctly.\n */\nconst activeDescendantId = computed(() => {\n const selectedResult = results.value[selectedIndex.value ?? -1]\n return selectedResult ? `search-result-${selectedResult.item.id}` : undefined\n})\n</script>\n\n<template>\n <ScalarModal\n aria-label=\"Document Search\"\n :state=\"modalState\"\n variant=\"search\">\n <div\n class=\"mb-0 flex flex-col\"\n role=\"search\">\n <ScalarSearchInput\n v-model=\"query\"\n :aria-activedescendant=\"activeDescendantId\"\n aria-autocomplete=\"list\"\n :aria-controls=\"listboxId\"\n :aria-describedby=\"instructionsId\"\n role=\"combobox\"\n @blur=\"selectedIndex = undefined\"\n @keydown.down.stop.prevent=\"navigateSearchResults('down')\"\n @keydown.enter.stop.prevent=\"() => handleSelect(selectedIndex)\"\n @keydown.up.stop.prevent=\"navigateSearchResults('up')\" />\n </div>\n <ScalarSearchResultList\n :id=\"listboxId\"\n aria-label=\"Document Search Results\"\n class=\"custom-scroll px-1 pb-1\"\n :noResults=\"!results.length\">\n <template #query>\n {{ query }}\n </template>\n <SearchResult\n v-for=\"(result, idx) in results\"\n :id=\"`search-result-${result.item.id}`\"\n :key=\"result.refIndex\"\n :isSelected=\"selectedIndex === idx\"\n :result=\"result\"\n @click.prevent=\"() => handleSelect(idx)\" />\n </ScalarSearchResultList>\n <div\n :id=\"instructionsId\"\n class=\"ref-search-meta\">\n <span\n aria-hidden=\"true\"\n class=\"contents\">\n <span>↑↓ Navigate</span>\n <span>⏎ Select</span>\n </span>\n <span class=\"sr-only\">\n Press up arrow / down arrow to navigate, enter to select, type to filter\n results\n </span>\n </div>\n </ScalarModal>\n</template>\n\n<style scoped>\n.ref-search-meta {\n background: var(--scalar-background-1);\n border-bottom-left-radius: var(--scalar-radius-lg);\n border-bottom-right-radius: var(--scalar-radius-lg);\n padding: 6px 12px;\n font-size: var(--scalar-font-size-4);\n color: var(--scalar-color-3);\n font-weight: var(--scalar-semibold);\n display: flex;\n gap: 12px;\n border-top: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n</style>\n"],"mappings":""}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { useDocumentSearch } from "../hooks/use-document-search.js";
|
|
2
|
+
import SearchResult_default from "./SearchResult.vue.js";
|
|
3
|
+
import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, isRef, openBlock, ref, renderList, toDisplayString, unref, watch, withCtx, withKeys, withModifiers } from "vue";
|
|
4
|
+
import { ScalarModal, ScalarSearchInput, ScalarSearchResultList } from "@scalar/components";
|
|
5
|
+
import { nanoid } from "nanoid";
|
|
6
|
+
//#region src/v2/features/search/components/DocumentSearchModal.vue?vue&type=script&setup=true&lang.ts
|
|
7
|
+
var _hoisted_1 = {
|
|
8
|
+
class: "mb-0 flex flex-col",
|
|
9
|
+
role: "search"
|
|
10
|
+
};
|
|
11
|
+
var DocumentSearchModal_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
12
|
+
__name: "DocumentSearchModal",
|
|
13
|
+
props: {
|
|
14
|
+
modalState: {},
|
|
15
|
+
document: {}
|
|
16
|
+
},
|
|
17
|
+
emits: ["select"],
|
|
18
|
+
setup(__props, { emit: __emit }) {
|
|
19
|
+
const props = __props;
|
|
20
|
+
const emit = __emit;
|
|
21
|
+
/** Base id for the search form. */
|
|
22
|
+
const id = nanoid();
|
|
23
|
+
const listboxId = `${id}-search-result`;
|
|
24
|
+
const instructionsId = `${id}-search-instructions`;
|
|
25
|
+
const { query, results } = useDocumentSearch(() => props.document);
|
|
26
|
+
const selectedIndex = ref(void 0);
|
|
27
|
+
/**
|
|
28
|
+
* Reset the query every time the modal is opened so users always start from a
|
|
29
|
+
* clean state. Matches the reference search modal behaviour.
|
|
30
|
+
*/
|
|
31
|
+
watch(() => props.modalState.open, (open) => {
|
|
32
|
+
if (open) {
|
|
33
|
+
query.value = "";
|
|
34
|
+
selectedIndex.value = void 0;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
/** Keyboard navigation, wrapping around the ends of the result list. */
|
|
38
|
+
const navigateSearchResults = (direction) => {
|
|
39
|
+
const offset = direction === "up" ? -1 : 1;
|
|
40
|
+
const length = results.value.length;
|
|
41
|
+
if (length === 0) return;
|
|
42
|
+
if (typeof selectedIndex.value === "number") {
|
|
43
|
+
selectedIndex.value = (selectedIndex.value + offset + length) % length;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
selectedIndex.value = offset === -1 ? length - 1 : 0;
|
|
47
|
+
};
|
|
48
|
+
function handleSelect(idx) {
|
|
49
|
+
if (typeof idx !== "number" || !results.value[idx]) return;
|
|
50
|
+
const result = results.value[idx];
|
|
51
|
+
props.modalState.hide();
|
|
52
|
+
emit("select", result.item.id);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* aria-activedescendant for the combobox. Each result item must render the
|
|
56
|
+
* matching id for assistive tech to announce the selection correctly.
|
|
57
|
+
*/
|
|
58
|
+
const activeDescendantId = computed(() => {
|
|
59
|
+
const selectedResult = results.value[selectedIndex.value ?? -1];
|
|
60
|
+
return selectedResult ? `search-result-${selectedResult.item.id}` : void 0;
|
|
61
|
+
});
|
|
62
|
+
return (_ctx, _cache) => {
|
|
63
|
+
return openBlock(), createBlock(unref(ScalarModal), {
|
|
64
|
+
"aria-label": "Document Search",
|
|
65
|
+
state: __props.modalState,
|
|
66
|
+
variant: "search"
|
|
67
|
+
}, {
|
|
68
|
+
default: withCtx(() => [
|
|
69
|
+
createElementVNode("div", _hoisted_1, [createVNode(unref(ScalarSearchInput), {
|
|
70
|
+
modelValue: unref(query),
|
|
71
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(query) ? query.value = $event : null),
|
|
72
|
+
"aria-activedescendant": activeDescendantId.value,
|
|
73
|
+
"aria-autocomplete": "list",
|
|
74
|
+
"aria-controls": listboxId,
|
|
75
|
+
"aria-describedby": instructionsId,
|
|
76
|
+
role: "combobox",
|
|
77
|
+
onBlur: _cache[1] || (_cache[1] = ($event) => selectedIndex.value = void 0),
|
|
78
|
+
onKeydown: [
|
|
79
|
+
_cache[2] || (_cache[2] = withKeys(withModifiers(($event) => navigateSearchResults("down"), ["stop", "prevent"]), ["down"])),
|
|
80
|
+
_cache[3] || (_cache[3] = withKeys(withModifiers(() => handleSelect(selectedIndex.value), ["stop", "prevent"]), ["enter"])),
|
|
81
|
+
_cache[4] || (_cache[4] = withKeys(withModifiers(($event) => navigateSearchResults("up"), ["stop", "prevent"]), ["up"]))
|
|
82
|
+
]
|
|
83
|
+
}, null, 8, ["modelValue", "aria-activedescendant"])]),
|
|
84
|
+
createVNode(unref(ScalarSearchResultList), {
|
|
85
|
+
id: listboxId,
|
|
86
|
+
"aria-label": "Document Search Results",
|
|
87
|
+
class: "custom-scroll px-1 pb-1",
|
|
88
|
+
noResults: !unref(results).length
|
|
89
|
+
}, {
|
|
90
|
+
query: withCtx(() => [createTextVNode(toDisplayString(unref(query)), 1)]),
|
|
91
|
+
default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(results), (result, idx) => {
|
|
92
|
+
return openBlock(), createBlock(SearchResult_default, {
|
|
93
|
+
id: `search-result-${result.item.id}`,
|
|
94
|
+
key: result.refIndex,
|
|
95
|
+
isSelected: selectedIndex.value === idx,
|
|
96
|
+
result,
|
|
97
|
+
onClick: withModifiers(() => handleSelect(idx), ["prevent"])
|
|
98
|
+
}, null, 8, [
|
|
99
|
+
"id",
|
|
100
|
+
"isSelected",
|
|
101
|
+
"result",
|
|
102
|
+
"onClick"
|
|
103
|
+
]);
|
|
104
|
+
}), 128))]),
|
|
105
|
+
_: 1
|
|
106
|
+
}, 8, ["noResults"]),
|
|
107
|
+
createElementVNode("div", {
|
|
108
|
+
id: instructionsId,
|
|
109
|
+
class: "ref-search-meta"
|
|
110
|
+
}, [..._cache[5] || (_cache[5] = [createElementVNode("span", {
|
|
111
|
+
"aria-hidden": "true",
|
|
112
|
+
class: "contents"
|
|
113
|
+
}, [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)])])
|
|
114
|
+
]),
|
|
115
|
+
_: 1
|
|
116
|
+
}, 8, ["state"]);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
//#endregion
|
|
121
|
+
export { DocumentSearchModal_vue_vue_type_script_setup_true_lang_default as default };
|
|
122
|
+
|
|
123
|
+
//# sourceMappingURL=DocumentSearchModal.vue.script.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DocumentSearchModal.vue.script.js","names":[],"sources":["../../../../../src/v2/features/search/components/DocumentSearchModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarModal,\n ScalarSearchInput,\n ScalarSearchResultList,\n type ModalState,\n} from '@scalar/components'\nimport type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { nanoid } from 'nanoid'\nimport { computed, ref, watch } from 'vue'\n\nimport { useDocumentSearch } from '@/v2/features/search/hooks/use-document-search'\n\nimport SearchResult from './SearchResult.vue'\n\nconst props = defineProps<{\n /** Controls the visibility of the search modal. */\n modalState: ModalState\n /** The document whose entries should be searched. */\n document: OpenApiDocument | undefined\n}>()\n\nconst emit = defineEmits<{\n /** Emitted when the user picks a result, passing the navigation id. */\n (e: 'select', id: string): void\n}>()\n\n/** Base id for the search form. */\nconst id = nanoid()\nconst listboxId = `${id}-search-result`\nconst instructionsId = `${id}-search-instructions`\n\nconst { query, results } = useDocumentSearch(() => props.document)\n\nconst selectedIndex = ref<number | undefined>(undefined)\n\n/**\n * Reset the query every time the modal is opened so users always start from a\n * clean state. Matches the reference search modal behaviour.\n */\nwatch(\n () => props.modalState.open,\n (open) => {\n if (open) {\n query.value = ''\n selectedIndex.value = undefined\n }\n },\n)\n\n/** Keyboard navigation, wrapping around the ends of the result list. */\nconst navigateSearchResults = (direction: 'up' | 'down') => {\n const offset = direction === 'up' ? -1 : 1\n const length = results.value.length\n if (length === 0) {\n return\n }\n\n if (typeof selectedIndex.value === 'number') {\n selectedIndex.value = (selectedIndex.value + offset + length) % length\n return\n }\n\n selectedIndex.value = offset === -1 ? length - 1 : 0\n}\n\nfunction handleSelect(idx: number | undefined) {\n if (typeof idx !== 'number' || !results.value[idx]) {\n return\n }\n\n const result = results.value[idx]\n props.modalState.hide()\n emit('select', result.item.id)\n}\n\n/**\n * aria-activedescendant for the combobox. Each result item must render the\n * matching id for assistive tech to announce the selection correctly.\n */\nconst activeDescendantId = computed(() => {\n const selectedResult = results.value[selectedIndex.value ?? -1]\n return selectedResult ? `search-result-${selectedResult.item.id}` : undefined\n})\n</script>\n\n<template>\n <ScalarModal\n aria-label=\"Document Search\"\n :state=\"modalState\"\n variant=\"search\">\n <div\n class=\"mb-0 flex flex-col\"\n role=\"search\">\n <ScalarSearchInput\n v-model=\"query\"\n :aria-activedescendant=\"activeDescendantId\"\n aria-autocomplete=\"list\"\n :aria-controls=\"listboxId\"\n :aria-describedby=\"instructionsId\"\n role=\"combobox\"\n @blur=\"selectedIndex = undefined\"\n @keydown.down.stop.prevent=\"navigateSearchResults('down')\"\n @keydown.enter.stop.prevent=\"() => handleSelect(selectedIndex)\"\n @keydown.up.stop.prevent=\"navigateSearchResults('up')\" />\n </div>\n <ScalarSearchResultList\n :id=\"listboxId\"\n aria-label=\"Document Search Results\"\n class=\"custom-scroll px-1 pb-1\"\n :noResults=\"!results.length\">\n <template #query>\n {{ query }}\n </template>\n <SearchResult\n v-for=\"(result, idx) in results\"\n :id=\"`search-result-${result.item.id}`\"\n :key=\"result.refIndex\"\n :isSelected=\"selectedIndex === idx\"\n :result=\"result\"\n @click.prevent=\"() => handleSelect(idx)\" />\n </ScalarSearchResultList>\n <div\n :id=\"instructionsId\"\n class=\"ref-search-meta\">\n <span\n aria-hidden=\"true\"\n class=\"contents\">\n <span>↑↓ Navigate</span>\n <span>⏎ Select</span>\n </span>\n <span class=\"sr-only\">\n Press up arrow / down arrow to navigate, enter to select, type to filter\n results\n </span>\n </div>\n </ScalarModal>\n</template>\n\n<style scoped>\n.ref-search-meta {\n background: var(--scalar-background-1);\n border-bottom-left-radius: var(--scalar-radius-lg);\n border-bottom-right-radius: var(--scalar-radius-lg);\n padding: 6px 12px;\n font-size: var(--scalar-font-size-4);\n color: var(--scalar-color-3);\n font-weight: var(--scalar-semibold);\n display: flex;\n gap: 12px;\n border-top: var(--scalar-border-width) solid var(--scalar-border-color);\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAeA,MAAM,QAAQ;EAOd,MAAM,OAAO;;EAMb,MAAM,KAAK,QAAO;EAClB,MAAM,YAAY,GAAG,GAAG;EACxB,MAAM,iBAAiB,GAAG,GAAG;EAE7B,MAAM,EAAE,OAAO,YAAY,wBAAwB,MAAM,SAAQ;EAEjE,MAAM,gBAAgB,IAAwB,KAAA,EAAS;;;;;AAMvD,cACQ,MAAM,WAAW,OACtB,SAAS;AACR,OAAI,MAAM;AACR,UAAM,QAAQ;AACd,kBAAc,QAAQ,KAAA;;IAG5B;;EAGA,MAAM,yBAAyB,cAA6B;GAC1D,MAAM,SAAS,cAAc,OAAO,KAAK;GACzC,MAAM,SAAS,QAAQ,MAAM;AAC7B,OAAI,WAAW,EACb;AAGF,OAAI,OAAO,cAAc,UAAU,UAAU;AAC3C,kBAAc,SAAS,cAAc,QAAQ,SAAS,UAAU;AAChE;;AAGF,iBAAc,QAAQ,WAAW,KAAK,SAAS,IAAI;;EAGrD,SAAS,aAAa,KAAyB;AAC7C,OAAI,OAAO,QAAQ,YAAY,CAAC,QAAQ,MAAM,KAC5C;GAGF,MAAM,SAAS,QAAQ,MAAM;AAC7B,SAAM,WAAW,MAAK;AACtB,QAAK,UAAU,OAAO,KAAK,GAAE;;;;;;EAO/B,MAAM,qBAAqB,eAAe;GACxC,MAAM,iBAAiB,QAAQ,MAAM,cAAc,SAAS;AAC5D,UAAO,iBAAiB,iBAAiB,eAAe,KAAK,OAAO,KAAA;IACrE;;uBAIC,YAiDc,MAAA,YAAA,EAAA;IAhDZ,cAAW;IACV,OAAO,QAAA;IACR,SAAQ;;2BAeF;KAdN,mBAcM,OAdN,YAcM,CAXJ,YAU2D,MAAA,kBAAA,EAAA;kBAThD,MAAA,MAAK;wFAAA,QAAA,SAAA;MACb,yBAAuB,mBAAA;MACxB,qBAAkB;MACjB,iBAAe;MACf,oBAAkB;MACnB,MAAK;MACJ,QAAI,OAAA,OAAA,OAAA,MAAA,WAAE,cAAA,QAAgB,KAAA;MACtB,WAAO;oEAAoB,sBAAqB,OAAA,EAAA,CAAA,QAAA,UAAA,CAAA,EAAA,CAAA,OAAA,CAAA;8DACd,aAAa,cAAA,MAAa,EAAA,CAAA,QAAA,UAAA,CAAA,EAAA,CAAA,QAAA,CAAA;oEACnC,sBAAqB,KAAA,EAAA,CAAA,QAAA,UAAA,CAAA,EAAA,CAAA,KAAA,CAAA;;;KAEnD,YAeyB,MAAA,uBAAA,EAAA;MAdtB,IAAI;MACL,cAAW;MACX,OAAM;MACL,WAAS,CAAG,MAAA,QAAO,CAAC;;MACV,OAAK,cACH,CAAA,gBAAA,gBAAR,MAAA,MAAK,CAAA,EAAA,EAAA,CAAA,CAAA;6BAGwB,EAAA,UAAA,KAAA,EADlC,mBAM6C,UAAA,MAAA,WALnB,MAAA,QAAO,GAAvB,QAAQ,QAAG;2BADrB,YAM6C,sBAAA;QAJ1C,IAAE,iBAAmB,OAAO,KAAK;QACjC,KAAK,OAAO;QACZ,YAAY,cAAA,UAAkB;QACtB;QACR,SAAK,oBAAgB,aAAa,IAAG,EAAA,CAAA,UAAA,CAAA;;;;;;;;;;KAE1C,mBAaM,OAAA;MAZH,IAAI;MACL,OAAM;uCACN,mBAKO,QAAA;MAJL,eAAY;MACZ,OAAM;SACN,mBAAwB,QAAA,MAAlB,cAAW,EACjB,mBAAqB,QAAA,MAAf,WAAQ,CAAA,EAAA,GAAA,EAEhB,mBAGO,QAAA,EAHD,OAAM,WAAS,EAAC,sFAGtB,GAAA,CAAA,EAAA,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FuseResult } from 'fuse.js';
|
|
2
|
+
import type { FuseData } from '../../../../v2/features/search/types';
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
id: string;
|
|
5
|
+
isSelected: boolean;
|
|
6
|
+
result: FuseResult<FuseData>;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
11
|
+
//# sourceMappingURL=SearchResult.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchResult.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/search/components/SearchResult.vue"],"names":[],"mappings":"AAoFA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAE1D,KAAK,WAAW,GAAG;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;CAC7B,CAAC;AAyHF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import SearchResult_vue_vue_type_script_setup_true_lang_default from "./SearchResult.vue.script.js";
|
|
2
|
+
//#region src/v2/features/search/components/SearchResult.vue
|
|
3
|
+
var SearchResult_default = SearchResult_vue_vue_type_script_setup_true_lang_default;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { SearchResult_default as default };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=SearchResult.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchResult.vue.js","names":[],"sources":["../../../../../src/v2/features/search/components/SearchResult.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarSearchResultItem } from '@scalar/components'\nimport {\n ScalarIconTag,\n ScalarIconTerminalWindow,\n ScalarIconTextAlignLeft,\n} from '@scalar/icons'\nimport type { ScalarIconComponent } from '@scalar/icons/types'\nimport { HttpMethod } from '@scalar/sidebar'\nimport type { FuseResult } from 'fuse.js'\n\nimport type { FuseData } from '@/v2/features/search/types'\n\ndefineProps<{\n id: string\n isSelected: boolean\n result: FuseResult<FuseData>\n}>()\n\n/**\n * Icon used for each search result type. Operations use the terminal glyph to\n * match the sidebar's operation indicator, tags and headings use their closest\n * semantic equivalents.\n */\nconst ENTRY_ICONS: { [x in FuseData['type']]: ScalarIconComponent } = {\n heading: ScalarIconTextAlignLeft,\n operation: ScalarIconTerminalWindow,\n tag: ScalarIconTag,\n}\n\nconst ENTRY_LABELS: { [x in FuseData['type']]: string } = {\n heading: 'Heading',\n operation: 'Operation',\n tag: 'Tag',\n}\n</script>\n\n<template>\n <ScalarSearchResultItem\n :id=\"id\"\n :icon=\"ENTRY_ICONS[result.item.type]\"\n :selected=\"isSelected\">\n <span>\n <span class=\"sr-only\">{{ ENTRY_LABELS[result.item.type] }}: </span>\n {{ result.item.title }}\n <span class=\"sr-only\">,</span>\n </span>\n <template\n v-if=\"\n result.item.type === 'operation' &&\n (result.item.method || result.item.path) &&\n result.item.path !== result.item.title\n \"\n #description>\n <span class=\"inline-flex items-center gap-1\">\n <HttpMethod\n aria-hidden=\"true\"\n :method=\"result.item.method ?? 'get'\" />\n <span class=\"sr-only\">\n HTTP Method: {{ result.item.method ?? 'get' }}\n </span>\n <span class=\"sr-only\">Path: </span>\n {{ result.item.path }}\n </span>\n </template>\n <template\n v-else-if=\"result.item.description\"\n #description>\n <span class=\"sr-only\">Description: </span>\n {{ result.item.description }}\n </template>\n </ScalarSearchResultItem>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, openBlock, toDisplayString, unref, withCtx } from "vue";
|
|
2
|
+
import { ScalarSearchResultItem } from "@scalar/components";
|
|
3
|
+
import { ScalarIconTag, ScalarIconTerminalWindow, ScalarIconTextAlignLeft } from "@scalar/icons";
|
|
4
|
+
import { HttpMethod } from "@scalar/sidebar";
|
|
5
|
+
//#region src/v2/features/search/components/SearchResult.vue?vue&type=script&setup=true&lang.ts
|
|
6
|
+
var _hoisted_1 = { class: "sr-only" };
|
|
7
|
+
var _hoisted_2 = { class: "inline-flex items-center gap-1" };
|
|
8
|
+
var _hoisted_3 = { class: "sr-only" };
|
|
9
|
+
var SearchResult_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
10
|
+
__name: "SearchResult",
|
|
11
|
+
props: {
|
|
12
|
+
id: {},
|
|
13
|
+
isSelected: { type: Boolean },
|
|
14
|
+
result: {}
|
|
15
|
+
},
|
|
16
|
+
setup(__props) {
|
|
17
|
+
/**
|
|
18
|
+
* Icon used for each search result type. Operations use the terminal glyph to
|
|
19
|
+
* match the sidebar's operation indicator, tags and headings use their closest
|
|
20
|
+
* semantic equivalents.
|
|
21
|
+
*/
|
|
22
|
+
const ENTRY_ICONS = {
|
|
23
|
+
heading: ScalarIconTextAlignLeft,
|
|
24
|
+
operation: ScalarIconTerminalWindow,
|
|
25
|
+
tag: ScalarIconTag
|
|
26
|
+
};
|
|
27
|
+
const ENTRY_LABELS = {
|
|
28
|
+
heading: "Heading",
|
|
29
|
+
operation: "Operation",
|
|
30
|
+
tag: "Tag"
|
|
31
|
+
};
|
|
32
|
+
return (_ctx, _cache) => {
|
|
33
|
+
return openBlock(), createBlock(unref(ScalarSearchResultItem), {
|
|
34
|
+
id: __props.id,
|
|
35
|
+
icon: ENTRY_ICONS[__props.result.item.type],
|
|
36
|
+
selected: __props.isSelected
|
|
37
|
+
}, createSlots({
|
|
38
|
+
default: withCtx(() => [createElementVNode("span", null, [
|
|
39
|
+
createElementVNode("span", _hoisted_1, toDisplayString(ENTRY_LABELS[__props.result.item.type]) + ":\xA0", 1),
|
|
40
|
+
createTextVNode(" " + toDisplayString(__props.result.item.title) + " ", 1),
|
|
41
|
+
_cache[0] || (_cache[0] = createElementVNode("span", { class: "sr-only" }, ",", -1))
|
|
42
|
+
])]),
|
|
43
|
+
_: 2
|
|
44
|
+
}, [__props.result.item.type === "operation" && (__props.result.item.method || __props.result.item.path) && __props.result.item.path !== __props.result.item.title ? {
|
|
45
|
+
name: "description",
|
|
46
|
+
fn: withCtx(() => [createElementVNode("span", _hoisted_2, [
|
|
47
|
+
createVNode(unref(HttpMethod), {
|
|
48
|
+
"aria-hidden": "true",
|
|
49
|
+
method: __props.result.item.method ?? "get"
|
|
50
|
+
}, null, 8, ["method"]),
|
|
51
|
+
createElementVNode("span", _hoisted_3, " HTTP Method: " + toDisplayString(__props.result.item.method ?? "get"), 1),
|
|
52
|
+
_cache[1] || (_cache[1] = createElementVNode("span", { class: "sr-only" }, "Path:\xA0", -1)),
|
|
53
|
+
createTextVNode(" " + toDisplayString(__props.result.item.path), 1)
|
|
54
|
+
])]),
|
|
55
|
+
key: "0"
|
|
56
|
+
} : __props.result.item.description ? {
|
|
57
|
+
name: "description",
|
|
58
|
+
fn: withCtx(() => [_cache[2] || (_cache[2] = createElementVNode("span", { class: "sr-only" }, "Description:\xA0", -1)), createTextVNode(" " + toDisplayString(__props.result.item.description), 1)]),
|
|
59
|
+
key: "1"
|
|
60
|
+
} : void 0]), 1032, [
|
|
61
|
+
"id",
|
|
62
|
+
"icon",
|
|
63
|
+
"selected"
|
|
64
|
+
]);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
//#endregion
|
|
69
|
+
export { SearchResult_vue_vue_type_script_setup_true_lang_default as default };
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=SearchResult.vue.script.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchResult.vue.script.js","names":[],"sources":["../../../../../src/v2/features/search/components/SearchResult.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarSearchResultItem } from '@scalar/components'\nimport {\n ScalarIconTag,\n ScalarIconTerminalWindow,\n ScalarIconTextAlignLeft,\n} from '@scalar/icons'\nimport type { ScalarIconComponent } from '@scalar/icons/types'\nimport { HttpMethod } from '@scalar/sidebar'\nimport type { FuseResult } from 'fuse.js'\n\nimport type { FuseData } from '@/v2/features/search/types'\n\ndefineProps<{\n id: string\n isSelected: boolean\n result: FuseResult<FuseData>\n}>()\n\n/**\n * Icon used for each search result type. Operations use the terminal glyph to\n * match the sidebar's operation indicator, tags and headings use their closest\n * semantic equivalents.\n */\nconst ENTRY_ICONS: { [x in FuseData['type']]: ScalarIconComponent } = {\n heading: ScalarIconTextAlignLeft,\n operation: ScalarIconTerminalWindow,\n tag: ScalarIconTag,\n}\n\nconst ENTRY_LABELS: { [x in FuseData['type']]: string } = {\n heading: 'Heading',\n operation: 'Operation',\n tag: 'Tag',\n}\n</script>\n\n<template>\n <ScalarSearchResultItem\n :id=\"id\"\n :icon=\"ENTRY_ICONS[result.item.type]\"\n :selected=\"isSelected\">\n <span>\n <span class=\"sr-only\">{{ ENTRY_LABELS[result.item.type] }}: </span>\n {{ result.item.title }}\n <span class=\"sr-only\">,</span>\n </span>\n <template\n v-if=\"\n result.item.type === 'operation' &&\n (result.item.method || result.item.path) &&\n result.item.path !== result.item.title\n \"\n #description>\n <span class=\"inline-flex items-center gap-1\">\n <HttpMethod\n aria-hidden=\"true\"\n :method=\"result.item.method ?? 'get'\" />\n <span class=\"sr-only\">\n HTTP Method: {{ result.item.method ?? 'get' }}\n </span>\n <span class=\"sr-only\">Path: </span>\n {{ result.item.path }}\n </span>\n </template>\n <template\n v-else-if=\"result.item.description\"\n #description>\n <span class=\"sr-only\">Description: </span>\n {{ result.item.description }}\n </template>\n </ScalarSearchResultItem>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAwBA,MAAM,cAAgE;GACpE,SAAS;GACT,WAAW;GACX,KAAK;GACP;EAEA,MAAM,eAAoD;GACxD,SAAS;GACT,WAAW;GACX,KAAK;GACP;;uBAIE,YAiCyB,MAAA,uBAAA,EAAA;IAhCtB,IAAI,QAAA;IACJ,MAAM,YAAY,QAAA,OAAO,KAAK;IAC9B,UAAU,QAAA;;2BAKJ,CAJP,mBAIO,QAAA,MAAA;KAHL,mBAAwE,QAAxE,YAAwE,gBAA/C,aAAa,QAAA,OAAO,KAAK,MAAI,GAAI,SAAO,EAAA;qBAAO,MACxE,gBAAG,QAAA,OAAO,KAAK,MAAK,GAAG,KACvB,EAAA;+BAAA,mBAA8B,QAAA,EAAxB,OAAM,WAAS,EAAC,KAAC,GAAA;;;OAGR,QAAA,OAAO,KAAK,SAAI,gBAA6B,QAAA,OAAO,KAAK,UAAU,QAAA,OAAO,KAAK,SAAiB,QAAA,OAAO,KAAK,SAAS,QAAA,OAAO,KAAK,QAAA;UAK/I;sBAUM,CATP,mBASO,QATP,YASO;KARL,YAE0C,MAAA,WAAA,EAAA;MADxC,eAAY;MACX,QAAQ,QAAA,OAAO,KAAK,UAAM;;KAC7B,mBAEO,QAFP,YAAsB,mBACP,gBAAG,QAAA,OAAO,KAAK,UAAM,MAAA,EAAA,EAAA;+BAEpC,mBAAwC,QAAA,EAAlC,OAAM,WAAS,EAAC,aAAW,GAAA;qBAAO,MACxC,gBAAG,QAAA,OAAO,KAAK,KAAI,EAAA,EAAA;;;OAIV,QAAA,OAAO,KAAK,cAAA;UACtB;sBAC8C,CAAA,OAAA,OAAA,OAAA,KAA/C,mBAA+C,QAAA,EAAzC,OAAM,WAAS,EAAC,oBAAkB,GAAA,GAAA,gBAAO,MAC/C,gBAAG,QAAA,OAAO,KAAK,YAAW,EAAA,EAAA,CAAA,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document';
|
|
2
|
+
import type { FuseResult } from 'fuse.js';
|
|
3
|
+
import { type MaybeRefOrGetter } from 'vue';
|
|
4
|
+
import type { FuseData } from '../types';
|
|
5
|
+
/**
|
|
6
|
+
* Fuzzy search scoped to a single OpenAPI document.
|
|
7
|
+
*
|
|
8
|
+
* Mirrors the behaviour of the reference search modal (`@scalar/api-reference`)
|
|
9
|
+
* but stays local to api-client so the two packages do not have a circular
|
|
10
|
+
* dependency. The index is rebuilt whenever the source document changes.
|
|
11
|
+
*
|
|
12
|
+
* When the query is empty we surface the first `MAX_SEARCH_RESULTS` entries of
|
|
13
|
+
* the index as a zero-state list, matching the reference UX.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useDocumentSearch(document: MaybeRefOrGetter<OpenApiDocument | undefined>): {
|
|
16
|
+
results: import("vue").ComputedRef<FuseResult<FuseData>[]>;
|
|
17
|
+
query: import("vue").Ref<string, string>;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=use-document-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-document-search.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/search/hooks/use-document-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8DAA8D,CAAA;AACnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACzC,OAAO,EAAE,KAAK,gBAAgB,EAA0B,MAAM,KAAK,CAAA;AAInE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAIxC;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,CAAC,eAAe,GAAG,SAAS,CAAC;;;EAiCxF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createFuseInstance } from "../helpers/create-fuse-instance.js";
|
|
2
|
+
import { createSearchIndex } from "../helpers/create-search-index.js";
|
|
3
|
+
import { computed, ref, toValue } from "vue";
|
|
4
|
+
//#region src/v2/features/search/hooks/use-document-search.ts
|
|
5
|
+
var MAX_SEARCH_RESULTS = 25;
|
|
6
|
+
/**
|
|
7
|
+
* Fuzzy search scoped to a single OpenAPI document.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors the behaviour of the reference search modal (`@scalar/api-reference`)
|
|
10
|
+
* but stays local to api-client so the two packages do not have a circular
|
|
11
|
+
* dependency. The index is rebuilt whenever the source document changes.
|
|
12
|
+
*
|
|
13
|
+
* When the query is empty we surface the first `MAX_SEARCH_RESULTS` entries of
|
|
14
|
+
* the index as a zero-state list, matching the reference UX.
|
|
15
|
+
*/
|
|
16
|
+
function useDocumentSearch(document) {
|
|
17
|
+
const searchIndex = computed(() => {
|
|
18
|
+
const doc = toValue(document);
|
|
19
|
+
return doc ? createSearchIndex([doc]) : [];
|
|
20
|
+
});
|
|
21
|
+
const fuse = computed(() => {
|
|
22
|
+
const instance = createFuseInstance();
|
|
23
|
+
instance.setCollection(searchIndex.value);
|
|
24
|
+
return instance;
|
|
25
|
+
});
|
|
26
|
+
const query = ref("");
|
|
27
|
+
return {
|
|
28
|
+
results: computed(() => {
|
|
29
|
+
const trimmed = query.value.trim();
|
|
30
|
+
if (trimmed) return fuse.value.search(trimmed, { limit: MAX_SEARCH_RESULTS });
|
|
31
|
+
return searchIndex.value.slice(0, MAX_SEARCH_RESULTS).map((item, index) => ({
|
|
32
|
+
item,
|
|
33
|
+
refIndex: index
|
|
34
|
+
}));
|
|
35
|
+
}),
|
|
36
|
+
query
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { useDocumentSearch };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=use-document-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-document-search.js","names":[],"sources":["../../../../../src/v2/features/search/hooks/use-document-search.ts"],"sourcesContent":["import type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { FuseResult } from 'fuse.js'\nimport { type MaybeRefOrGetter, computed, ref, toValue } from 'vue'\n\nimport { createFuseInstance } from '../helpers/create-fuse-instance'\nimport { createSearchIndex } from '../helpers/create-search-index'\nimport type { FuseData } from '../types'\n\nconst MAX_SEARCH_RESULTS = 25\n\n/**\n * Fuzzy search scoped to a single OpenAPI document.\n *\n * Mirrors the behaviour of the reference search modal (`@scalar/api-reference`)\n * but stays local to api-client so the two packages do not have a circular\n * dependency. The index is rebuilt whenever the source document changes.\n *\n * When the query is empty we surface the first `MAX_SEARCH_RESULTS` entries of\n * the index as a zero-state list, matching the reference UX.\n */\nexport function useDocumentSearch(document: MaybeRefOrGetter<OpenApiDocument | undefined>) {\n const searchIndex = computed<FuseData[]>(() => {\n const doc = toValue(document)\n return doc ? createSearchIndex([doc]) : []\n })\n\n const fuse = computed(() => {\n const instance = createFuseInstance()\n instance.setCollection(searchIndex.value)\n return instance\n })\n\n const query = ref<string>('')\n\n const results = computed<FuseResult<FuseData>[]>(() => {\n const trimmed = query.value.trim()\n if (trimmed) {\n return fuse.value.search(trimmed, { limit: MAX_SEARCH_RESULTS })\n }\n\n return searchIndex.value.slice(0, MAX_SEARCH_RESULTS).map(\n (item, index) =>\n ({\n item,\n refIndex: index,\n }) satisfies FuseResult<FuseData>,\n )\n })\n\n return {\n results,\n query,\n }\n}\n"],"mappings":";;;;AAQA,IAAM,qBAAqB;;;;;;;;;;;AAY3B,SAAgB,kBAAkB,UAAyD;CACzF,MAAM,cAAc,eAA2B;EAC7C,MAAM,MAAM,QAAQ,SAAS;AAC7B,SAAO,MAAM,kBAAkB,CAAC,IAAI,CAAC,GAAG,EAAE;GAC1C;CAEF,MAAM,OAAO,eAAe;EAC1B,MAAM,WAAW,oBAAoB;AACrC,WAAS,cAAc,YAAY,MAAM;AACzC,SAAO;GACP;CAEF,MAAM,QAAQ,IAAY,GAAG;AAiB7B,QAAO;EACL,SAhBc,eAAuC;GACrD,MAAM,UAAU,MAAM,MAAM,MAAM;AAClC,OAAI,QACF,QAAO,KAAK,MAAM,OAAO,SAAS,EAAE,OAAO,oBAAoB,CAAC;AAGlE,UAAO,YAAY,MAAM,MAAM,GAAG,mBAAmB,CAAC,KACnD,MAAM,WACJ;IACC;IACA,UAAU;IACX,EACJ;IACD;EAIA;EACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/search/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/search/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,sCAAsC,CAAA;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA"}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
import { useDocumentSearch } from "./hooks/use-document-search.js";
|
|
2
|
+
import DocumentSearchModal_default from "./components/DocumentSearchModal.vue.js";
|
|
1
3
|
import { useSearchIndex } from "./hooks/use-search-index.js";
|
|
2
|
-
export { useSearchIndex };
|
|
4
|
+
export { DocumentSearchModal_default as DocumentSearchModal, useDocumentSearch, useSearchIndex };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handle-hotkeys.d.ts","sourceRoot":"","sources":["../../../src/v2/helpers/handle-hotkeys.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAE3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"handle-hotkeys.d.ts","sourceRoot":"","sources":["../../../src/v2/helpers/handle-hotkeys.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAE3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AA+ErD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,aAAa,EAAE,UAAU,iBAAiB,EAAE,QAAQ,YAAY,KAAG,IAkCvG,CAAA"}
|
|
@@ -17,6 +17,14 @@ var DEFAULT_HOTKEYS = {
|
|
|
17
17
|
l: {
|
|
18
18
|
event: "ui:focus:address-bar",
|
|
19
19
|
modifiers: ["default"]
|
|
20
|
+
},
|
|
21
|
+
j: {
|
|
22
|
+
event: "ui:focus:search",
|
|
23
|
+
modifiers: ["default"]
|
|
24
|
+
},
|
|
25
|
+
i: {
|
|
26
|
+
event: "ui:open:settings",
|
|
27
|
+
modifiers: ["default"]
|
|
20
28
|
}
|
|
21
29
|
};
|
|
22
30
|
/** Hotkey map by layout, we can allow the user to override this later */
|
|
@@ -35,10 +43,6 @@ var HOTKEYS = {
|
|
|
35
43
|
},
|
|
36
44
|
desktop: {
|
|
37
45
|
...DEFAULT_HOTKEYS,
|
|
38
|
-
f: {
|
|
39
|
-
event: "ui:focus:search",
|
|
40
|
-
modifiers: ["default"]
|
|
41
|
-
},
|
|
42
46
|
n: {
|
|
43
47
|
event: "ui:open:command-palette",
|
|
44
48
|
modifiers: ["default"]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handle-hotkeys.js","names":[],"sources":["../../../src/v2/helpers/handle-hotkeys.ts"],"sourcesContent":["import { isMacOS } from '@scalar/helpers/general/is-mac-os'\nimport type { ApiReferenceEvents, WorkspaceEventBus } from '@scalar/workspace-store/events'\n\nimport type { ClientLayout } from '@/v2/types/layout'\n\ntype HotKeyModifiers = ('altKey' | 'ctrlKey' | 'shiftKey' | 'metaKey' | 'default')[]\n\n/** Hotkey configuration */\ntype HotKeyConfig = Record<string | number, { event: keyof ApiReferenceEvents; modifiers: HotKeyModifiers }>\n\n/** Default hotkeys available in most contexts */\nconst DEFAULT_HOTKEYS: HotKeyConfig = {\n Enter: { event: 'operation:send:request:hotkey', modifiers: ['default'] },\n b: { event: 'ui:toggle:sidebar', modifiers: ['default'] },\n k: { event: 'ui:open:command-palette', modifiers: ['default'] },\n l: { event: 'ui:focus:address-bar', modifiers: ['default'] },\n}\n\n/** Hotkey map by layout, we can allow the user to override this later */\nconst HOTKEYS: Record<ClientLayout, HotKeyConfig> = {\n web: DEFAULT_HOTKEYS,\n\n modal: {\n ...DEFAULT_HOTKEYS,\n Escape: { event: 'ui:close:client-modal', modifiers: [] },\n l: { event: 'ui:focus:send-button', modifiers: ['default'] },\n },\n\n desktop: {\n ...DEFAULT_HOTKEYS,\n
|
|
1
|
+
{"version":3,"file":"handle-hotkeys.js","names":[],"sources":["../../../src/v2/helpers/handle-hotkeys.ts"],"sourcesContent":["import { isMacOS } from '@scalar/helpers/general/is-mac-os'\nimport type { ApiReferenceEvents, WorkspaceEventBus } from '@scalar/workspace-store/events'\n\nimport type { ClientLayout } from '@/v2/types/layout'\n\ntype HotKeyModifiers = ('altKey' | 'ctrlKey' | 'shiftKey' | 'metaKey' | 'default')[]\n\n/** Hotkey configuration */\ntype HotKeyConfig = Record<string | number, { event: keyof ApiReferenceEvents; modifiers: HotKeyModifiers }>\n\n/** Default hotkeys available in most contexts */\nconst DEFAULT_HOTKEYS: HotKeyConfig = {\n Enter: { event: 'operation:send:request:hotkey', modifiers: ['default'] },\n b: { event: 'ui:toggle:sidebar', modifiers: ['default'] },\n k: { event: 'ui:open:command-palette', modifiers: ['default'] },\n l: { event: 'ui:focus:address-bar', modifiers: ['default'] },\n j: { event: 'ui:focus:search', modifiers: ['default'] },\n i: { event: 'ui:open:settings', modifiers: ['default'] },\n}\n\n/** Hotkey map by layout, we can allow the user to override this later */\nconst HOTKEYS: Record<ClientLayout, HotKeyConfig> = {\n web: DEFAULT_HOTKEYS,\n\n modal: {\n ...DEFAULT_HOTKEYS,\n Escape: { event: 'ui:close:client-modal', modifiers: [] },\n l: { event: 'ui:focus:send-button', modifiers: ['default'] },\n },\n\n desktop: {\n ...DEFAULT_HOTKEYS,\n n: { event: 'ui:open:command-palette', modifiers: ['default'] },\n t: { event: 'tabs:add:tab', modifiers: ['default'] },\n w: { event: 'tabs:close:tab', modifiers: ['default'] },\n ArrowLeft: { event: 'tabs:navigate:previous', modifiers: ['default', 'altKey'] },\n ArrowRight: { event: 'tabs:navigate:next', modifiers: ['default', 'altKey'] },\n 1: { event: 'tabs:focus:tab', modifiers: ['default'] },\n 2: { event: 'tabs:focus:tab', modifiers: ['default'] },\n 3: { event: 'tabs:focus:tab', modifiers: ['default'] },\n 4: { event: 'tabs:focus:tab', modifiers: ['default'] },\n 5: { event: 'tabs:focus:tab', modifiers: ['default'] },\n 6: { event: 'tabs:focus:tab', modifiers: ['default'] },\n 7: { event: 'tabs:focus:tab', modifiers: ['default'] },\n 8: { event: 'tabs:focus:tab', modifiers: ['default'] },\n 9: { event: 'tabs:focus:tab-last', modifiers: ['default'] },\n },\n}\n\n/** Keys that should work in input fields when the modifier is pressed */\nconst INPUT_ALLOWED_KEYS = new Set(['Escape', 'ArrowDown', 'ArrowUp', 'Enter'])\n\n/**\n * Checks if all required modifiers are pressed.\n * Resolves 'default' to metaKey (macOS) or ctrlKey (Windows/Linux).\n */\nconst areModifiersPressed = (event: KeyboardEvent, modifiers: HotKeyModifiers): boolean =>\n modifiers.length > 0 &&\n modifiers\n .map((modifier) => (modifier === 'default' ? (isMacOS() ? 'metaKey' : 'ctrlKey') : modifier))\n .every((key) => event[key] === true)\n\n/**\n * Determines if the event target is an editable element where hotkeys should be blocked.\n * Returns true if we should block the hotkey, false otherwise.\n */\nconst isEditableElement = (event: KeyboardEvent, key: string): boolean => {\n if (!(event.target instanceof HTMLElement)) {\n return false\n }\n\n const target = event.target\n\n // Allow certain functional keys in INPUT fields\n if (target.tagName === 'INPUT') {\n return !INPUT_ALLOWED_KEYS.has(key)\n }\n\n // Block all hotkeys in textareas and contenteditable elements\n return target.tagName === 'TEXTAREA' || target.contentEditable === 'true' || target.hasAttribute('contenteditable')\n}\n\n/**\n * Handles global keyboard shortcuts.\n * Checks modifier keys and input context before emitting events.\n *\n * @param event - the keyboard event\n * @param eventBus - event bus for emitting hotkey actions\n * @param layout - client layout\n */\nexport const handleHotkeys = (event: KeyboardEvent, eventBus: WorkspaceEventBus, layout: ClientLayout): void => {\n /** Special case for space */\n const key = event.key === ' ' ? 'Space' : event.key\n /** Get the discriminated hotkey event with payload */\n const hotkeyEvent = HOTKEYS[layout][key]\n\n if (!hotkeyEvent) {\n return\n }\n\n // Default to sending the keyboard event as the payload\n const payload = { event }\n\n // Escape always fires, regardless of context\n if (key === 'Escape') {\n eventBus.emit(hotkeyEvent.event, payload, { skipUnpackProxy: true })\n return\n }\n\n // If modifiers are pressed, fire the hotkey (even in input fields)\n if (areModifiersPressed(event, hotkeyEvent.modifiers)) {\n eventBus.emit(hotkeyEvent.event, payload, { skipUnpackProxy: true })\n return\n }\n\n // If modifiers are required but missing, do not fire the hotkey.\n if (hotkeyEvent.modifiers.length > 0) {\n return\n }\n\n // Without modifiers, only fire if not in an editable element\n if (!isEditableElement(event, key)) {\n eventBus.emit(hotkeyEvent.event, payload, { skipUnpackProxy: true })\n }\n}\n"],"mappings":";;;AAWA,IAAM,kBAAgC;CACpC,OAAO;EAAE,OAAO;EAAiC,WAAW,CAAC,UAAU;EAAE;CACzE,GAAG;EAAE,OAAO;EAAqB,WAAW,CAAC,UAAU;EAAE;CACzD,GAAG;EAAE,OAAO;EAA2B,WAAW,CAAC,UAAU;EAAE;CAC/D,GAAG;EAAE,OAAO;EAAwB,WAAW,CAAC,UAAU;EAAE;CAC5D,GAAG;EAAE,OAAO;EAAmB,WAAW,CAAC,UAAU;EAAE;CACvD,GAAG;EAAE,OAAO;EAAoB,WAAW,CAAC,UAAU;EAAE;CACzD;;AAGD,IAAM,UAA8C;CAClD,KAAK;CAEL,OAAO;EACL,GAAG;EACH,QAAQ;GAAE,OAAO;GAAyB,WAAW,EAAE;GAAE;EACzD,GAAG;GAAE,OAAO;GAAwB,WAAW,CAAC,UAAU;GAAE;EAC7D;CAED,SAAS;EACP,GAAG;EACH,GAAG;GAAE,OAAO;GAA2B,WAAW,CAAC,UAAU;GAAE;EAC/D,GAAG;GAAE,OAAO;GAAgB,WAAW,CAAC,UAAU;GAAE;EACpD,GAAG;GAAE,OAAO;GAAkB,WAAW,CAAC,UAAU;GAAE;EACtD,WAAW;GAAE,OAAO;GAA0B,WAAW,CAAC,WAAW,SAAS;GAAE;EAChF,YAAY;GAAE,OAAO;GAAsB,WAAW,CAAC,WAAW,SAAS;GAAE;EAC7E,GAAG;GAAE,OAAO;GAAkB,WAAW,CAAC,UAAU;GAAE;EACtD,GAAG;GAAE,OAAO;GAAkB,WAAW,CAAC,UAAU;GAAE;EACtD,GAAG;GAAE,OAAO;GAAkB,WAAW,CAAC,UAAU;GAAE;EACtD,GAAG;GAAE,OAAO;GAAkB,WAAW,CAAC,UAAU;GAAE;EACtD,GAAG;GAAE,OAAO;GAAkB,WAAW,CAAC,UAAU;GAAE;EACtD,GAAG;GAAE,OAAO;GAAkB,WAAW,CAAC,UAAU;GAAE;EACtD,GAAG;GAAE,OAAO;GAAkB,WAAW,CAAC,UAAU;GAAE;EACtD,GAAG;GAAE,OAAO;GAAkB,WAAW,CAAC,UAAU;GAAE;EACtD,GAAG;GAAE,OAAO;GAAuB,WAAW,CAAC,UAAU;GAAE;EAC5D;CACF;;AAGD,IAAM,qBAAqB,IAAI,IAAI;CAAC;CAAU;CAAa;CAAW;CAAQ,CAAC;;;;;AAM/E,IAAM,uBAAuB,OAAsB,cACjD,UAAU,SAAS,KACnB,UACG,KAAK,aAAc,aAAa,YAAa,SAAS,GAAG,YAAY,YAAa,SAAU,CAC5F,OAAO,QAAQ,MAAM,SAAS,KAAK;;;;;AAMxC,IAAM,qBAAqB,OAAsB,QAAyB;AACxE,KAAI,EAAE,MAAM,kBAAkB,aAC5B,QAAO;CAGT,MAAM,SAAS,MAAM;AAGrB,KAAI,OAAO,YAAY,QACrB,QAAO,CAAC,mBAAmB,IAAI,IAAI;AAIrC,QAAO,OAAO,YAAY,cAAc,OAAO,oBAAoB,UAAU,OAAO,aAAa,kBAAkB;;;;;;;;;;AAWrH,IAAa,iBAAiB,OAAsB,UAA6B,WAA+B;;CAE9G,MAAM,MAAM,MAAM,QAAQ,MAAM,UAAU,MAAM;;CAEhD,MAAM,cAAc,QAAQ,QAAQ;AAEpC,KAAI,CAAC,YACH;CAIF,MAAM,UAAU,EAAE,OAAO;AAGzB,KAAI,QAAQ,UAAU;AACpB,WAAS,KAAK,YAAY,OAAO,SAAS,EAAE,iBAAiB,MAAM,CAAC;AACpE;;AAIF,KAAI,oBAAoB,OAAO,YAAY,UAAU,EAAE;AACrD,WAAS,KAAK,YAAY,OAAO,SAAS,EAAE,iBAAiB,MAAM,CAAC;AACpE;;AAIF,KAAI,YAAY,UAAU,SAAS,EACjC;AAIF,KAAI,CAAC,kBAAkB,OAAO,IAAI,CAChC,UAAS,KAAK,YAAY,OAAO,SAAS,EAAE,iBAAiB,MAAM,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../../src/v2/types/configuration.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,0BAA0B,GAAG,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,
|
|
1
|
+
{"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../../src/v2/types/configuration.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,0BAA0B,GAAG,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAC7G;IACE,EAAE,EAAE,IAAI,CAAA;IACR,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B,GACD;IACE,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;CACd,CACJ,CAAA"}
|
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"rest",
|
|
19
19
|
"testing"
|
|
20
20
|
],
|
|
21
|
-
"version": "3.
|
|
21
|
+
"version": "3.3.0",
|
|
22
22
|
"engines": {
|
|
23
23
|
"node": ">=22"
|
|
24
24
|
},
|
|
@@ -332,21 +332,22 @@
|
|
|
332
332
|
"vue-router": "5.0.4",
|
|
333
333
|
"yaml": "^2.8.0",
|
|
334
334
|
"zod": "^4.3.5",
|
|
335
|
-
"@scalar/components": "0.22.
|
|
335
|
+
"@scalar/components": "0.22.4",
|
|
336
336
|
"@scalar/helpers": "0.5.2",
|
|
337
|
-
"@scalar/
|
|
337
|
+
"@scalar/oas-utils": "0.13.3",
|
|
338
338
|
"@scalar/icons": "0.7.2",
|
|
339
|
-
"@scalar/
|
|
339
|
+
"@scalar/json-magic": "0.12.8",
|
|
340
340
|
"@scalar/openapi-types": "0.8.0",
|
|
341
|
-
"@scalar/sidebar": "0.9.4",
|
|
342
341
|
"@scalar/postman-to-openapi": "0.7.1",
|
|
343
|
-
"@scalar/
|
|
342
|
+
"@scalar/sidebar": "0.9.5",
|
|
344
343
|
"@scalar/snippetz": "0.9.2",
|
|
345
344
|
"@scalar/types": "0.9.2",
|
|
346
|
-
"@scalar/
|
|
347
|
-
"@scalar/
|
|
345
|
+
"@scalar/use-codemirror": "0.14.11",
|
|
346
|
+
"@scalar/themes": "0.15.3",
|
|
348
347
|
"@scalar/use-toasts": "0.10.2",
|
|
349
|
-
"@scalar/use-
|
|
348
|
+
"@scalar/use-hooks": "0.4.3",
|
|
349
|
+
"@scalar/workspace-store": "0.47.0",
|
|
350
|
+
"@scalar/validation": "0.3.0"
|
|
350
351
|
},
|
|
351
352
|
"devDependencies": {
|
|
352
353
|
"@tailwindcss/vite": "^4.2.0",
|
|
@@ -361,7 +362,7 @@
|
|
|
361
362
|
"vite": "8.0.0",
|
|
362
363
|
"vite-svg-loader": "5.1.1",
|
|
363
364
|
"vitest": "4.1.0",
|
|
364
|
-
"@scalar/pre-post-request-scripts": "0.4.
|
|
365
|
+
"@scalar/pre-post-request-scripts": "0.4.6"
|
|
365
366
|
},
|
|
366
367
|
"scripts": {
|
|
367
368
|
"build": "vite build && vue-tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rabbit.ascii.virtual.js","names":[],"sources":["../../src/assets/rabbit.ascii?raw"],"sourcesContent":["export default \" ,\\\\\\n \\\\\\\\\\\\,_\\n \\\\` ,\\\\\\n __,.-\\\" =__)\\n .\\\" )\\n,_/ , \\\\/\\\\_\\n\\\\_| )_-\\\\ \\\\_-`\\n `-----` `--`\""],"mappings":";AAAA,IAAA,iBAAe"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
//#region src/assets/rabbitjump.ascii?raw
|
|
2
|
-
var rabbitjump_default = " __\n // \\,_\n \\` ,\\\n __,.-\" =__)\n .\" )\n,_/ , \\/\\ \n\\_| // / / /\n / / ";
|
|
3
|
-
//#endregion
|
|
4
|
-
export { rabbitjump_default as default };
|
|
5
|
-
|
|
6
|
-
//# sourceMappingURL=rabbitjump.ascii.virtual.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rabbitjump.ascii.virtual.js","names":[],"sources":["../../src/assets/rabbitjump.ascii?raw"],"sourcesContent":["export default \" __\\n // \\\\,_\\n \\\\` ,\\\\\\n __,.-\\\" =__)\\n .\\\" )\\n,_/ , \\\\/\\\\ \\n\\\\_| // / / /\\n / / \""],"mappings":";AAAA,IAAA,qBAAe"}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
declare const _default: typeof __VLS_export;
|
|
3
|
-
export default _default;
|
|
4
|
-
//# sourceMappingURL=DownloadAppButton.vue.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DownloadAppButton.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/components/DownloadAppButton.vue"],"names":[],"mappings":"AAiGA,QAAA,MAAM,YAAY,+QAChB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import _plugin_vue_export_helper_default from "../../../../_virtual/_plugin-vue_export-helper.js";
|
|
2
|
-
import DownloadAppButton_vue_vue_type_script_setup_true_lang_default from "./DownloadAppButton.vue.script.js";
|
|
3
|
-
/* empty css */
|
|
4
|
-
//#region src/v2/features/app/components/DownloadAppButton.vue
|
|
5
|
-
var DownloadAppButton_default = /* @__PURE__ */ _plugin_vue_export_helper_default(DownloadAppButton_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-9b609275"]]);
|
|
6
|
-
//#endregion
|
|
7
|
-
export { DownloadAppButton_default as default };
|
|
8
|
-
|
|
9
|
-
//# sourceMappingURL=DownloadAppButton.vue.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DownloadAppButton.vue.js","names":[],"sources":["../../../../../src/v2/features/app/components/DownloadAppButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIconDownloadSimple } from '@scalar/icons'\n</script>\n<template>\n <a\n class=\"download-app-button flex w-full flex-row items-center justify-center gap-2 rounded px-3.5 py-2 text-sm leading-4 font-medium\"\n href=\"https://scalar.com/download?utm_source=web_client&utm_medium=download_button&utm_campaign=topnav\"\n target=\"_blank\"\n type=\"button\">\n <ScalarIconDownloadSimple size=\"sm\" />\n <span class=\"sr-only text-sm font-medium sm:not-sr-only\">\n Download App\n </span>\n </a>\n</template>\n<style scoped>\n.download-app-button {\n box-shadow: 0 0 0 0.5px var(--scalar-border-color);\n background: linear-gradient(rgba(255, 255, 255, 0.75), rgba(0, 0, 0, 0.035));\n}\n\n.dark-mode .download-app-button {\n background: linear-gradient(rgba(255, 255, 255, 0.1), rgba(0, 0, 0, 0.15));\n}\n\n.download-app-button:hover {\n background: linear-gradient(rgba(0, 0, 0, 0.035), rgba(255, 255, 255, 0.75));\n}\n\n.dark-mode .download-app-button:hover {\n background: linear-gradient(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.1));\n}\n</style>\n"],"mappings":""}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { createElementBlock, createElementVNode, createVNode, defineComponent, openBlock, unref } from "vue";
|
|
2
|
-
import { ScalarIconDownloadSimple } from "@scalar/icons";
|
|
3
|
-
//#region src/v2/features/app/components/DownloadAppButton.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
-
var _hoisted_1 = {
|
|
5
|
-
class: "download-app-button flex w-full flex-row items-center justify-center gap-2 rounded px-3.5 py-2 text-sm leading-4 font-medium",
|
|
6
|
-
href: "https://scalar.com/download?utm_source=web_client&utm_medium=download_button&utm_campaign=topnav",
|
|
7
|
-
target: "_blank",
|
|
8
|
-
type: "button"
|
|
9
|
-
};
|
|
10
|
-
var DownloadAppButton_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
11
|
-
__name: "DownloadAppButton",
|
|
12
|
-
setup(__props) {
|
|
13
|
-
return (_ctx, _cache) => {
|
|
14
|
-
return openBlock(), createElementBlock("a", _hoisted_1, [createVNode(unref(ScalarIconDownloadSimple), { size: "sm" }), _cache[0] || (_cache[0] = createElementVNode("span", { class: "sr-only text-sm font-medium sm:not-sr-only" }, " Download App ", -1))]);
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
//#endregion
|
|
19
|
-
export { DownloadAppButton_vue_vue_type_script_setup_true_lang_default as default };
|
|
20
|
-
|
|
21
|
-
//# sourceMappingURL=DownloadAppButton.vue.script.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DownloadAppButton.vue.script.js","names":[],"sources":["../../../../../src/v2/features/app/components/DownloadAppButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIconDownloadSimple } from '@scalar/icons'\n</script>\n<template>\n <a\n class=\"download-app-button flex w-full flex-row items-center justify-center gap-2 rounded px-3.5 py-2 text-sm leading-4 font-medium\"\n href=\"https://scalar.com/download?utm_source=web_client&utm_medium=download_button&utm_campaign=topnav\"\n target=\"_blank\"\n type=\"button\">\n <ScalarIconDownloadSimple size=\"sm\" />\n <span class=\"sr-only text-sm font-medium sm:not-sr-only\">\n Download App\n </span>\n </a>\n</template>\n<style scoped>\n.download-app-button {\n box-shadow: 0 0 0 0.5px var(--scalar-border-color);\n background: linear-gradient(rgba(255, 255, 255, 0.75), rgba(0, 0, 0, 0.035));\n}\n\n.dark-mode .download-app-button {\n background: linear-gradient(rgba(255, 255, 255, 0.1), rgba(0, 0, 0, 0.15));\n}\n\n.download-app-button:hover {\n background: linear-gradient(rgba(0, 0, 0, 0.035), rgba(255, 255, 255, 0.75));\n}\n\n.dark-mode .download-app-button:hover {\n background: linear-gradient(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.1));\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;uBAIE,mBASI,KATJ,YASI,CAJF,YAAsC,MAAA,yBAAA,EAAA,EAAZ,MAAK,MAAI,CAAA,EAAA,OAAA,OAAA,OAAA,KACnC,mBAEO,QAAA,EAFD,OAAM,8CAA4C,EAAC,kBAEzD,GAAA,EAAA,CAAA"}
|