vp-search.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. <script setup lang="ts">
  2. import '@docsearch/css'
  3. import { getCurrentInstance, onMounted, watch } from 'vue'
  4. import { useRoute, useRouter } from 'vitepress'
  5. import docsearch from '@docsearch/js'
  6. import { isClient } from '@vueuse/core'
  7. // import { useLang } from '../../composables/lang'
  8. // import type { DefaultTheme } from '../config'
  9. import type { DocSearchHit } from '@docsearch/react/dist/esm/types'
  10. const props = defineProps<{
  11. options: any
  12. multilang?: boolean
  13. }>()
  14. const vm = getCurrentInstance()
  15. const route = useRoute()
  16. const router = useRouter()
  17. watch(
  18. () => props.options,
  19. (value) => {
  20. update(value)
  21. }
  22. )
  23. onMounted(() => {
  24. initialize(props.options)
  25. })
  26. function isSpecialClick(event: MouseEvent) {
  27. return (
  28. event.button === 1 ||
  29. event.altKey ||
  30. event.ctrlKey ||
  31. event.metaKey ||
  32. event.shiftKey
  33. )
  34. }
  35. function getRelativePath(absoluteUrl: string) {
  36. const { pathname, hash } = new URL(absoluteUrl)
  37. return pathname + hash
  38. }
  39. function update(options: any) {
  40. if (vm && vm.vnode.el) {
  41. vm.vnode.el.innerHTML =
  42. '<div class="algolia-search-box" id="docsearch"></div>'
  43. initialize(options)
  44. }
  45. }
  46. // const lang = useLang()
  47. function initialize(userOptions: any) {
  48. // if the user has multiple locales, the search results should be filtered
  49. // based on the language
  50. // const facetFilters = props.multilang ? [`language:${lang.value}`] : []
  51. docsearch(
  52. Object.assign({}, userOptions, {
  53. container: '#docsearch',
  54. indexName: 'element-plus',
  55. // searchParameters: Object.assign({}, userOptions.searchParameters, {
  56. // // pass a custom lang facetFilter to allow multiple language search
  57. // // https://github.com/algolia/docsearch-configs/pull/3942
  58. // facetFilters: facetFilters.concat(
  59. // userOptions.searchParameters?.facetFilters || []
  60. // ),
  61. // }),
  62. navigator: {
  63. navigate: ({ itemUrl }: { itemUrl: string }) => {
  64. if (!isClient) return
  65. const { pathname: hitPathname } = new URL(
  66. window.location.origin + itemUrl
  67. )
  68. // Router doesn't handle same-page navigation so we use the native
  69. // browser location API for anchor navigation
  70. if (route.path === hitPathname) {
  71. window.location.assign(window.location.origin + itemUrl)
  72. } else {
  73. router.go(itemUrl)
  74. }
  75. },
  76. },
  77. transformItems: (items: DocSearchHit[]) => {
  78. return items.map((item) => {
  79. return Object.assign({}, item, {
  80. url: getRelativePath(item.url),
  81. })
  82. })
  83. },
  84. hitComponent: ({
  85. hit,
  86. children,
  87. }: {
  88. hit: DocSearchHit
  89. children: any
  90. }) => {
  91. const relativeHit = hit.url.startsWith('http')
  92. ? getRelativePath(hit.url as string)
  93. : hit.url
  94. return {
  95. type: 'a',
  96. ref: undefined,
  97. constructor: undefined,
  98. key: undefined,
  99. props: {
  100. href: hit.url,
  101. onClick: (event: MouseEvent) => {
  102. if (isSpecialClick(event)) {
  103. return
  104. }
  105. // we rely on the native link scrolling when user is already on
  106. // the right anchor because Router doesn't support duplicated
  107. // history entries
  108. if (route.path === relativeHit) {
  109. return
  110. }
  111. // if the hits goes to another page, we prevent the native link
  112. // behavior to leverage the Router loading feature
  113. if (route.path !== relativeHit) {
  114. event.preventDefault()
  115. }
  116. router.go(relativeHit)
  117. },
  118. children,
  119. },
  120. __v: null,
  121. }
  122. },
  123. })
  124. )
  125. }
  126. </script>
  127. <template>
  128. <div id="docsearch" class="algolia-search-box" />
  129. </template>
  130. <style lang="scss">
  131. @use '../../styles/mixins' as *;
  132. .algolia-search-box {
  133. // display: flex;
  134. // align-items: center;
  135. // line-height: var(--header-height);
  136. // padding-left: 0.5rem;
  137. // padding-top: 1px;
  138. // margin-right: 12px;
  139. // .search-box-placeholder,
  140. // .search-box-key {
  141. // display: flex;
  142. // }
  143. @include respond-to('md') {
  144. min-width: 176.3px;
  145. }
  146. }
  147. .DocSearch {
  148. --docsearch-primary-color: var(--brand-color);
  149. --docsearch-highlight-color: var(--brand-color);
  150. --docsearch-key-gradient: rgba(125, 125, 125, 0.1);
  151. // --docsearch-key-shadow: rgba(125, 125, 125, 0.3);
  152. --docsearch-footer-height: 44px;
  153. --docsearch-footer-background: var(--bg-color);
  154. --docsearch-footer-shadow: 0 -1px 0 0 #e0e3e8,
  155. 0 -3px 6px 0 rgba(69, 98, 155, 0.12);
  156. --docsearch-searchbox-background: rgba(var(--bg-color-rgb), 0.8);
  157. --docsearch-searchbox-focus-background: var(--bg-color-mute);
  158. --docsearch-searchbox-shadow: inset 0 0 0 2px var(--brand-color);
  159. --docsearch-muted-color: var(--text-color-lighter);
  160. --docsearch-text-color: var(--text-color-light);
  161. --docsearch-modal-background: var(--bg-color-soft);
  162. --docsearch-modal-shadow: var(--el-box-shadow);
  163. transition: background-color var(--el-transition-duration-fast);
  164. &.DocSearch-Container {
  165. z-index: 20000;
  166. }
  167. &.DocSearch-Button {
  168. margin-right: 8px;
  169. }
  170. @media (max-width: 749px) {
  171. &.DocSearch-Button {
  172. margin: 0 12px;
  173. padding: 0;
  174. }
  175. }
  176. .dark & {
  177. --docsearch-text-color: var(--text-color-light);
  178. --docsearch-key-shadow: none;
  179. --docsearch-modal-shadow: none;
  180. --docsearch-footer-shadow: none;
  181. --docsearch-hit-background: var(--bg-color-mute);
  182. --docsearch-hit-color: var(--text-color-lighter);
  183. --docsearch-hit-shadow: none;
  184. // --docsearch-searchbox-focus-background: var(--bg-color-mute);
  185. .DocSearch-Button {
  186. .DocSearch-Button-Key {
  187. box-shadow: unset;
  188. }
  189. }
  190. }
  191. background-color: transparent;
  192. @include respond-to('md') {
  193. background-color: var(--docsearch-searchbox-background);
  194. }
  195. }
  196. </style>