-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSearch.tsx
135 lines (127 loc) · 3.23 KB
/
Search.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*/
import Head from 'next/head';
import Link from 'next/link';
import Router from 'next/router';
import {lazy, useEffect} from 'react';
import * as React from 'react';
import {createPortal} from 'react-dom';
import {siteConfig} from 'siteConfig';
export interface SearchProps {
appId?: string;
apiKey?: string;
indexName?: string;
searchParameters?: any;
isOpen: boolean;
onOpen: () => void;
onClose: () => void;
}
function Hit({hit, children}: any) {
return <Link href={hit.url.replace()}>{children}</Link>;
}
// Copy-pasted from @docsearch/react to avoid importing the whole bundle.
// Slightly trimmed to features we use.
// (c) Algolia, Inc.
function isEditingContent(event: any) {
var element = event.target;
var tagName = element.tagName;
return (
element.isContentEditable ||
tagName === 'INPUT' ||
tagName === 'SELECT' ||
tagName === 'TEXTAREA'
);
}
function useDocSearchKeyboardEvents({
isOpen,
onOpen,
onClose,
}: {
isOpen: boolean;
onOpen: () => void;
onClose: () => void;
}) {
useEffect(() => {
function onKeyDown(event: any) {
function open() {
// We check that no other DocSearch modal is showing before opening
// another one.
if (!document.body.classList.contains('DocSearch--active')) {
onOpen();
}
}
if (
(event.keyCode === 27 && isOpen) ||
(event.key === 'k' && (event.metaKey || event.ctrlKey)) ||
(!isEditingContent(event) && event.key === '/' && !isOpen)
) {
event.preventDefault();
if (isOpen) {
onClose();
} else if (!document.body.classList.contains('DocSearch--active')) {
open();
}
}
}
window.addEventListener('keydown', onKeyDown);
return function () {
window.removeEventListener('keydown', onKeyDown);
};
}, [isOpen, onOpen, onClose]);
}
const options = {
appId: siteConfig.algolia.appId,
apiKey: siteConfig.algolia.apiKey,
indexName: siteConfig.algolia.indexName,
};
const DocSearchModal: any = lazy(() =>
// @ts-ignore
import('@docsearch/react/modal').then((mod) => ({
default: mod.DocSearchModal,
}))
);
export function Search({
isOpen,
onOpen,
onClose,
searchParameters = {
hitsPerPage: 5,
},
}: SearchProps) {
useDocSearchKeyboardEvents({isOpen, onOpen, onClose});
return (
<>
<Head>
<link
rel="preconnect"
href={`https://${options.appId}-dsn.algolia.net`}
/>
</Head>
{isOpen &&
createPortal(
<DocSearchModal
{...options}
searchParameters={searchParameters}
onClose={onClose}
navigator={{
navigate({itemUrl}: any) {
Router.push(itemUrl);
},
}}
transformItems={(items: any[]) => {
return items.map((item) => {
const url = new URL(item.url);
return {
...item,
url: item.url.replace(url.origin, '').replace('#__next', ''),
};
});
}}
hitComponent={Hit}
/>,
document.body
)}
</>
);
}