hds-web 1.15.9 → 1.16.1
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/.env +2 -1
- package/dist/index.css +3 -3
- package/dist/index.es.css +3 -3
- package/dist/index.es.js +5 -5
- package/dist/index.js +5 -5
- package/package.json +1 -5
- package/src/HDS/components/Headers/v3Header.js +0 -2
- package/src/HDS/helpers/index.js +0 -1
- package/src/styles/tailwind.css +107 -669
- package/src/HDS/helpers/AlgoliaSearch/constants.js +0 -48
- package/src/HDS/helpers/AlgoliaSearch/index.js +0 -1
- package/src/HDS/helpers/AlgoliaSearch/search.js +0 -38
- package/src/HDS/helpers/AlgoliaSearch/search.scss +0 -38
- package/src/HDS/helpers/AlgoliaSearch/searchbox.js +0 -88
- package/src/HDS/helpers/AlgoliaSearch/searchfooter.js +0 -30
- package/src/HDS/helpers/AlgoliaSearch/searchoverlay.js +0 -36
- package/src/HDS/helpers/AlgoliaSearch/searchresults.js +0 -98
- package/src/HDS/helpers/AlgoliaSearch/searchwrapper.js +0 -126
@@ -1,48 +0,0 @@
|
|
1
|
-
export const INDEX_TYPES = Object.freeze({
|
2
|
-
blog: "blog",
|
3
|
-
docs: "docs",
|
4
|
-
learn: "learn",
|
5
|
-
});
|
6
|
-
|
7
|
-
export const SEARCH_INDICES = [
|
8
|
-
{ name: `blog-production`, title: `Hasura Blog`, type: INDEX_TYPES.blog },
|
9
|
-
{ name: `graphql-docs-prod`, title: `Hasura GraphQL Engine Docs`, type: INDEX_TYPES.docs },
|
10
|
-
{ name: `learn-intro-graphql`, title: `Learn Intro GraphQL`, type: INDEX_TYPES.learn },
|
11
|
-
{ name: `learn-intro-graphql-zh`, title: `Learn Intro GraphQL`, type: INDEX_TYPES.learn },
|
12
|
-
{ name: `learn-elm-graphql`, title: `Learn ELM GraphQl`, type: INDEX_TYPES.learn },
|
13
|
-
{ name: `learn-flutter-graphql`, title: `Learn Flutter GraphQL`, type: INDEX_TYPES.learn },
|
14
|
-
{ name: `learn-database-mysql`, title: `Learn Database MySQL`, type: INDEX_TYPES.learn },
|
15
|
-
{
|
16
|
-
name: `learn-database-postgresql`,
|
17
|
-
title: `Learn Database PostgreSQL`,
|
18
|
-
type: INDEX_TYPES.learn,
|
19
|
-
},
|
20
|
-
{ name: `learn-hasura-backend`, title: `Learn Hasura Backend`, type: INDEX_TYPES.learn },
|
21
|
-
{ name: `learn-hasura-backend-ja`, title: `Learn Hasura Backend`, type: INDEX_TYPES.learn },
|
22
|
-
{ name: `learn-hasura-backend-zh`, title: `Learn Hasura Backend`, type: INDEX_TYPES.learn },
|
23
|
-
{ name: `learn-hasura-backend-advanced`, title: `Learn Hasura Backend Advanced`, type: INDEX_TYPES.learn },
|
24
|
-
{ name: `learn-hasura-auth-slack`, title: `Learn Hasura Auth Slack`, type: INDEX_TYPES.learn },
|
25
|
-
{ name: `learn-react-apollo-hooks`, title: `Learn React Apollo Hooks`, type: INDEX_TYPES.learn },
|
26
|
-
{ name: `learn-react-apollo`, title: `Learn React Apollo`, type: INDEX_TYPES.learn },
|
27
|
-
{
|
28
|
-
name: `learn-typescript-react-apollo`,
|
29
|
-
title: `Learn TypeScript React Apollo`,
|
30
|
-
type: INDEX_TYPES.learn,
|
31
|
-
},
|
32
|
-
{ name: `learn-angular-apollo`, title: `Learn Angular Apollo`, type: INDEX_TYPES.learn },
|
33
|
-
{ name: `learn-vue-apollo`, title: `Learn Vue Apollo`, type: INDEX_TYPES.learn },
|
34
|
-
{ name: `learn-ios-apollo`, title: `Learn IOS Apollo`, type: INDEX_TYPES.learn },
|
35
|
-
{ name: `learn-svelte-apollo`, title: `Learn Svelte Apollo`, type: INDEX_TYPES.learn },
|
36
|
-
{ name: `learn-android-apollo`, title: `Learn Android Apollo`, type: INDEX_TYPES.learn },
|
37
|
-
{
|
38
|
-
name: `learn-react-native-apollo`,
|
39
|
-
title: `Learn React Native Apollo`,
|
40
|
-
type: INDEX_TYPES.learn,
|
41
|
-
},
|
42
|
-
{
|
43
|
-
name: `learn-reason-react-apollo`,
|
44
|
-
title: `Learn Reason React Apollo`,
|
45
|
-
type: INDEX_TYPES.learn,
|
46
|
-
},
|
47
|
-
{ name: `learn-database-mssql`, title: `Learn MicrosoftSQL`, type: INDEX_TYPES.learn },
|
48
|
-
];
|
@@ -1 +0,0 @@
|
|
1
|
-
export {default as AlgoliaSearch } from './search';
|
@@ -1,38 +0,0 @@
|
|
1
|
-
import { useEffect, useState } from "react";
|
2
|
-
import SearchOverlay from "./searchoverlay";
|
3
|
-
export default function Search() {
|
4
|
-
const [showSearch, setShowSearch] = useState(false);
|
5
|
-
|
6
|
-
const handleSearchWithKeyboard = e => {
|
7
|
-
if (e.key === "/" || e.key === "Escape") {
|
8
|
-
e.preventDefault();
|
9
|
-
if (e.key === "/") return setShowSearch(true);
|
10
|
-
if (e.key === "Escape") return onCloseSearch();
|
11
|
-
}
|
12
|
-
|
13
|
-
return null;
|
14
|
-
};
|
15
|
-
|
16
|
-
useEffect(() => {
|
17
|
-
document.addEventListener("keydown", handleSearchWithKeyboard);
|
18
|
-
|
19
|
-
return () => {
|
20
|
-
document.removeEventListener("keydown", handleSearchWithKeyboard);
|
21
|
-
};
|
22
|
-
}, []);
|
23
|
-
|
24
|
-
const onCloseSearch = () => setShowSearch(false);
|
25
|
-
|
26
|
-
return (
|
27
|
-
<>
|
28
|
-
<div className="pt-10">
|
29
|
-
<div className="max-w-7xl mx-auto">
|
30
|
-
<div className="w-full" onClick={() => {setShowSearch(preShowSearch => !preShowSearch);}}>
|
31
|
-
Search
|
32
|
-
</div>
|
33
|
-
</div>
|
34
|
-
</div>
|
35
|
-
<SearchOverlay showSearch={showSearch} onCloseSearch={onCloseSearch} />
|
36
|
-
</>
|
37
|
-
);
|
38
|
-
}
|
@@ -1,38 +0,0 @@
|
|
1
|
-
.search-results {
|
2
|
-
width: calc(100% - 150px);
|
3
|
-
.ais-Hits, .Hits {
|
4
|
-
.ais-Hits-list {
|
5
|
-
display: grid;
|
6
|
-
grid-template-columns: repeat(3, 1fr);
|
7
|
-
grid-gap: 40px;
|
8
|
-
.ais-Hits-item {
|
9
|
-
border-bottom: 1px solid transparent;
|
10
|
-
&:hover {
|
11
|
-
border-bottom: 1px solid #E5E7EB;
|
12
|
-
}
|
13
|
-
.hit-slug {
|
14
|
-
word-break: break-word;
|
15
|
-
}
|
16
|
-
}
|
17
|
-
}
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
@media (max-width: 799px) {
|
22
|
-
.search-results {
|
23
|
-
.ais-Hits, .Hits {
|
24
|
-
.ais-Hits-list {
|
25
|
-
grid-template-columns: 1fr;
|
26
|
-
}
|
27
|
-
}
|
28
|
-
}
|
29
|
-
}
|
30
|
-
@media (min-width: 800px) and (max-width: 905px) {
|
31
|
-
.search-results {
|
32
|
-
.ais-Hits, .Hits {
|
33
|
-
.ais-Hits-list {
|
34
|
-
grid-template-columns: 1fr 1fr;
|
35
|
-
}
|
36
|
-
}
|
37
|
-
}
|
38
|
-
}
|
@@ -1,88 +0,0 @@
|
|
1
|
-
import React, { useEffect, useRef, useState } from "react";
|
2
|
-
import { connectSearchBox } from "react-instantsearch-dom";
|
3
|
-
import { Icon } from '../../components/common-components/Icon'
|
4
|
-
import { Typography } from '../../foundation/Typography'
|
5
|
-
const searchSuggestions = [
|
6
|
-
"GraphQL",
|
7
|
-
"Actions",
|
8
|
-
"Authentication",
|
9
|
-
"React",
|
10
|
-
"Remote Joins",
|
11
|
-
"Postgres",
|
12
|
-
];
|
13
|
-
|
14
|
-
const DebouncedSearchBox = ({
|
15
|
-
refine,
|
16
|
-
currentRefinement,
|
17
|
-
className,
|
18
|
-
delay = 500,
|
19
|
-
isSearchStalled,
|
20
|
-
}) => {
|
21
|
-
const [value, setValue] = useState(currentRefinement);
|
22
|
-
const timerId = useRef();
|
23
|
-
const searchInputRef = useRef();
|
24
|
-
useEffect(() => {
|
25
|
-
searchInputRef.current?.focus();
|
26
|
-
}, []);
|
27
|
-
|
28
|
-
const trySuggestion = inputValue => {
|
29
|
-
refine(inputValue);
|
30
|
-
setValue(inputValue);
|
31
|
-
};
|
32
|
-
|
33
|
-
const resetInput = () => {
|
34
|
-
refine("");
|
35
|
-
setValue("");
|
36
|
-
};
|
37
|
-
|
38
|
-
const onChangeDebounced = event => {
|
39
|
-
const value = event.target.value;
|
40
|
-
|
41
|
-
clearTimeout(timerId.current);
|
42
|
-
timerId.current = setTimeout(() => refine(value), delay);
|
43
|
-
|
44
|
-
setValue(value);
|
45
|
-
};
|
46
|
-
return (
|
47
|
-
<div className=" sticky -top-20 tb-m:-top-20 z-10 py-8 pt-16 tb-m:pt-16 tb-m:py-9 bg-neutral-50">
|
48
|
-
<div className="flex relative items-center w-full">
|
49
|
-
<div className="absolute left-2">
|
50
|
-
{isSearchStalled ? (
|
51
|
-
<div className="loader-spin border-[3px] border-neutral-400 border-t-blue-500 w-5 h-5 rounded-full" />
|
52
|
-
) : (
|
53
|
-
<Icon height={'w-5 h-5 stroke-[1.5px]'} variant="searchsm" strokeClass="stroke-neutral-800" />
|
54
|
-
)}
|
55
|
-
</div>
|
56
|
-
<form className={`${className} w-full`} onSubmit={e => e.preventDefault()}>
|
57
|
-
<input
|
58
|
-
id="search-input"
|
59
|
-
ref={searchInputRef}
|
60
|
-
className="w-full indent-5 rounded-xl border-neutral-400 h-12"
|
61
|
-
type="text"
|
62
|
-
placeholder="Search for tutorials, articles or docs"
|
63
|
-
aria-label="Search"
|
64
|
-
onChange={onChangeDebounced}
|
65
|
-
value={value}
|
66
|
-
/>
|
67
|
-
</form>
|
68
|
-
<div onClick={resetInput} className="absolute right-2 cursor-pointer bg-neutral-200 rounded-md">
|
69
|
-
<Icon height={'w-6 h-6 stroke-[1.5px]'} variant="xclose" strokeClass="stroke-neutral-800" />
|
70
|
-
</div>
|
71
|
-
</div>
|
72
|
-
<div className="hidden tb:flex flex-wrap items-center mt-4">
|
73
|
-
<Typography textStyle="body2c-bold" className="uppercase text-neutral-500 mr-4">POPULAR</Typography>
|
74
|
-
{searchSuggestions.map(suggestion => (
|
75
|
-
<button
|
76
|
-
key={suggestion}
|
77
|
-
className={`px-3 py-1 border rounded-md m-1 ${currentRefinement === suggestion ? "border-neutral-300 hover:bg-neutral-300 bg-neutral-300" : "bg-neutral-150 hover:bg-neutral-200 border-neutral-150"}`}
|
78
|
-
onClick={() => trySuggestion(suggestion)}
|
79
|
-
>
|
80
|
-
{suggestion}
|
81
|
-
</button>
|
82
|
-
))}
|
83
|
-
</div>
|
84
|
-
</div>
|
85
|
-
);
|
86
|
-
};
|
87
|
-
|
88
|
-
export default connectSearchBox(DebouncedSearchBox);
|
@@ -1,30 +0,0 @@
|
|
1
|
-
import React, { Fragment } from "react";
|
2
|
-
import { PoweredBy } from "react-instantsearch-dom";
|
3
|
-
|
4
|
-
const SearchFooter = () => (
|
5
|
-
<Fragment>
|
6
|
-
<hr className="my-5 border-t-neutral-200" />
|
7
|
-
<div className="mt-12 flex flex-wrap justify-between">
|
8
|
-
<div className="community-links-wrapper">
|
9
|
-
<p>Unable to find what you're looking for?</p>
|
10
|
-
<p>
|
11
|
-
Reach out to our{" "}
|
12
|
-
<a className="text-blue-500 hover:text-blue-700" href="https://discord.com/invite/hasura" target="_blank" rel="noopener noreferrer">
|
13
|
-
Discord Community
|
14
|
-
</a>{" "}
|
15
|
-
or start a{" "}
|
16
|
-
<a className="text-blue-500 hover:text-blue-700"
|
17
|
-
href="https://github.com/hasura/graphql-engine/discussions"
|
18
|
-
target="_blank"
|
19
|
-
rel="noopener noreferrer"
|
20
|
-
>
|
21
|
-
Discussion on GitHub
|
22
|
-
</a>
|
23
|
-
</p>
|
24
|
-
</div>
|
25
|
-
<PoweredBy />
|
26
|
-
</div>
|
27
|
-
</Fragment>
|
28
|
-
);
|
29
|
-
|
30
|
-
export default SearchFooter;
|
@@ -1,36 +0,0 @@
|
|
1
|
-
import { useEffect, useState } from "react";
|
2
|
-
import { Icon } from '../../components/common-components/Icon'
|
3
|
-
import SearchWrapper from "./searchwrapper";
|
4
|
-
import { SEARCH_INDICES } from "./constants";
|
5
|
-
|
6
|
-
export default function SearchOverlay({showSearch, onCloseSearch}) {
|
7
|
-
|
8
|
-
useEffect(() => {
|
9
|
-
if (showSearch) {
|
10
|
-
document.body.style.overflow = "hidden";
|
11
|
-
}
|
12
|
-
|
13
|
-
return () => {
|
14
|
-
document.body.style.overflow = "unset";
|
15
|
-
};
|
16
|
-
}, [showSearch]);
|
17
|
-
|
18
|
-
if (!showSearch) return null;
|
19
|
-
|
20
|
-
return (
|
21
|
-
<div className="fixed left-0 top-0 w-full h-full z-[10000] bg-neutral-50">
|
22
|
-
<div className="absolute top-4 right-4 cursor-pointer z-[11]" onClick={onCloseSearch}>
|
23
|
-
<Icon height={'w-8 h-8 stroke-[1.5px]'} variant="xclose" strokeClass="stroke-neutral-800" />
|
24
|
-
</div>
|
25
|
-
<div className="py-20 overflow-y-auto h-full w-full">
|
26
|
-
<div className="px-4">
|
27
|
-
<div className="max-w-7xl mx-auto">
|
28
|
-
<div className="w-full">
|
29
|
-
<SearchWrapper indices={SEARCH_INDICES} />
|
30
|
-
</div>
|
31
|
-
</div>
|
32
|
-
</div>
|
33
|
-
</div>
|
34
|
-
</div>
|
35
|
-
);
|
36
|
-
}
|
@@ -1,98 +0,0 @@
|
|
1
|
-
import React, { Fragment } from "react";
|
2
|
-
import { connectStateResults, Highlight, Hits, Index, Snippet } from "react-instantsearch-dom";
|
3
|
-
import { INDEX_TYPES } from "./constants";
|
4
|
-
import SearchFooter from "./searchfooter";
|
5
|
-
import { Typography } from '../../foundation/Typography'
|
6
|
-
|
7
|
-
// import SearchFooter from "./SearchFooter";
|
8
|
-
|
9
|
-
const baseDomain = 'hasura.io';
|
10
|
-
|
11
|
-
|
12
|
-
const HitsHeader = ({ searchResults, indexTitle, showSeparator }) => {
|
13
|
-
const hitCount = searchResults && searchResults.nbHits;
|
14
|
-
return hitCount > 0 ? (
|
15
|
-
<Fragment>
|
16
|
-
{showSeparator && <hr className="my-5 border-t-neutral-200" />}
|
17
|
-
{/* <div className="HitCount">
|
18
|
-
{hitCount} result{hitCount !== 1 ? `s` : ``}
|
19
|
-
</div> */}
|
20
|
-
<Typography textStyle="body2c-medium" className="pb-4">{indexTitle}</Typography>
|
21
|
-
</Fragment>
|
22
|
-
) : null;
|
23
|
-
};
|
24
|
-
|
25
|
-
const CustomHitsHeader = connectStateResults(HitsHeader);
|
26
|
-
|
27
|
-
const PageHit = ({ hit, indexType }) => (
|
28
|
-
<a href={hit.url} className="grid h-full">
|
29
|
-
<div className="self-start">
|
30
|
-
<Typography textStyle="body3c-medium" className="uppercase text-neutral-500">{indexType}</Typography>
|
31
|
-
{indexType === INDEX_TYPES.docs ? (
|
32
|
-
<Fragment>
|
33
|
-
{!!hit.hierarchy && (
|
34
|
-
<Typography textStyle="body1c-bold" className="font-semibold py-3">{`${
|
35
|
-
Object.values(hit.hierarchy)
|
36
|
-
.filter(h => !!h)
|
37
|
-
.reverse()[0]
|
38
|
-
}`}</Typography>
|
39
|
-
)}
|
40
|
-
<Typography textStyle="body2" className="text-neutral-600 break-words">
|
41
|
-
<Snippet attribute="content" hit={hit} tagName="mark" />
|
42
|
-
</Typography>
|
43
|
-
|
44
|
-
</Fragment>
|
45
|
-
) : (
|
46
|
-
<Fragment>
|
47
|
-
<Typography textStyle="body1c-bold" className="font-semibold py-3">
|
48
|
-
<Highlight attribute="title" hit={hit} tagName="mark" />
|
49
|
-
</Typography>
|
50
|
-
<Typography textStyle="body2" className="text-neutral-600 break-words">
|
51
|
-
<Snippet attribute="excerpt" hit={hit} tagName="mark" />
|
52
|
-
</Typography>
|
53
|
-
</Fragment>
|
54
|
-
)}
|
55
|
-
</div>
|
56
|
-
{hit.url ? (
|
57
|
-
<Typography textStyle="body3" className="self-end my-2 pt-3 text-neutral-600">
|
58
|
-
<span className='hit-slug break-words'>{hit.url.replace(`https://${baseDomain}/`, "/")}</span>
|
59
|
-
</Typography>
|
60
|
-
) : null}
|
61
|
-
</a>
|
62
|
-
);
|
63
|
-
|
64
|
-
const HitsByIndexType = ({ indexType }) => {
|
65
|
-
if (INDEX_TYPES[indexType] === undefined) return null;
|
66
|
-
|
67
|
-
return (
|
68
|
-
<Hits
|
69
|
-
className="Hits"
|
70
|
-
hitComponent={hitProps => <PageHit {...hitProps} indexType={indexType} />}
|
71
|
-
/>
|
72
|
-
);
|
73
|
-
};
|
74
|
-
|
75
|
-
const HitsInIndex = ({ index, show }) => (
|
76
|
-
<Index indexName={index.name}>
|
77
|
-
{show && (
|
78
|
-
<Fragment>
|
79
|
-
<CustomHitsHeader
|
80
|
-
indexTitle={index.title}
|
81
|
-
showSeparator={index.type !== INDEX_TYPES.blog}
|
82
|
-
/>
|
83
|
-
<HitsByIndexType indexType={index.type} />
|
84
|
-
</Fragment>
|
85
|
-
)}
|
86
|
-
</Index>
|
87
|
-
);
|
88
|
-
|
89
|
-
const SearchResult = ({ indices, className, id, wrapperRef, activeIndexTypes }) => (
|
90
|
-
<div id={id} className={`${className} search-results z-[2] clear-both`} ref={wrapperRef}>
|
91
|
-
{indices.map(index => (
|
92
|
-
<HitsInIndex index={index} key={index.name} show={activeIndexTypes[index.type]} />
|
93
|
-
))}
|
94
|
-
<SearchFooter />
|
95
|
-
</div>
|
96
|
-
);
|
97
|
-
|
98
|
-
export default SearchResult;
|
@@ -1,126 +0,0 @@
|
|
1
|
-
import algoliasearch from "algoliasearch/lite";
|
2
|
-
import React, { useRef, useState } from "react";
|
3
|
-
import { InstantSearch, connectStateResults, Index } from "react-instantsearch-dom";
|
4
|
-
import SearchBox from "./searchbox";
|
5
|
-
import SearchResults from "./searchresults";
|
6
|
-
import { INDEX_TYPES } from "./constants";
|
7
|
-
import SearchFooter from "./searchfooter";
|
8
|
-
import { Typography } from '../../foundation/Typography'
|
9
|
-
|
10
|
-
|
11
|
-
const algoliaClient = algoliasearch(
|
12
|
-
process.env.ALGOLIA_APP_ID,
|
13
|
-
process.env.ALGOLIA_SEARCH_KEY
|
14
|
-
);
|
15
|
-
|
16
|
-
const searchClient = {
|
17
|
-
...algoliaClient,
|
18
|
-
search(requests) {
|
19
|
-
if (requests.every(({ params }) => !params.query)) {
|
20
|
-
return Promise.resolve({
|
21
|
-
results: requests.map(() => ({
|
22
|
-
hits: [],
|
23
|
-
nbHits: 0,
|
24
|
-
nbPages: 0,
|
25
|
-
processingTimeMS: 0,
|
26
|
-
})),
|
27
|
-
});
|
28
|
-
}
|
29
|
-
|
30
|
-
return algoliaClient.search(requests);
|
31
|
-
},
|
32
|
-
};
|
33
|
-
|
34
|
-
const AllResults = ({ allSearchResults, children, indices, searchState, searching }) => {
|
35
|
-
if (!searchState?.query) return null;
|
36
|
-
|
37
|
-
const hasResults =
|
38
|
-
allSearchResults && Object.values(allSearchResults).some(results => results.nbHits > 0);
|
39
|
-
return !hasResults ? (
|
40
|
-
<div>
|
41
|
-
<div>
|
42
|
-
{searching ? (
|
43
|
-
<span>
|
44
|
-
Searching for "<em>{searchState?.query}</em>"
|
45
|
-
</span>
|
46
|
-
) : (
|
47
|
-
<span>
|
48
|
-
No results for "<em>{searchState?.query}</em>"
|
49
|
-
</span>
|
50
|
-
)}
|
51
|
-
</div>
|
52
|
-
{indices.map(index => (
|
53
|
-
<Index indexName={index.name} key={index.name} />
|
54
|
-
))}
|
55
|
-
<SearchFooter />
|
56
|
-
</div>
|
57
|
-
) : (
|
58
|
-
children
|
59
|
-
);
|
60
|
-
};
|
61
|
-
|
62
|
-
const CustomAllResults = connectStateResults(AllResults);
|
63
|
-
|
64
|
-
const IndexTypeFilter = ({ activeIndexTypes, setActiveIndexTypes }) => {
|
65
|
-
const handleOnChange = indexType => ({ target }) => {
|
66
|
-
setActiveIndexTypes(prevState => ({
|
67
|
-
...prevState,
|
68
|
-
[indexType]: target.checked,
|
69
|
-
}));
|
70
|
-
};
|
71
|
-
|
72
|
-
return (
|
73
|
-
<div className="tb-m:min-w-[150px] static tb-m:sticky top-[96px] self-start">
|
74
|
-
<Typography textStyle="h6" as="h6" className="text-neutral-700 uppercase">Filter</Typography>
|
75
|
-
<ul className="flex tb-m:block">
|
76
|
-
{Object.values(INDEX_TYPES).map(index => (
|
77
|
-
<li key={index} className="flex items-center py-3 mr-4 tb-m:mr-0">
|
78
|
-
<input
|
79
|
-
type="checkbox"
|
80
|
-
id={"algolia_index_type_" + index}
|
81
|
-
name={"algolia_index_type_" + index}
|
82
|
-
value={index}
|
83
|
-
checked={activeIndexTypes[index]}
|
84
|
-
onChange={handleOnChange(index)}
|
85
|
-
className="mr-2 focus:outline-none"
|
86
|
-
/>
|
87
|
-
<label htmlFor={"algolia_index_type_" + index}>{index}</label>
|
88
|
-
</li>
|
89
|
-
))}
|
90
|
-
</ul>
|
91
|
-
</div>
|
92
|
-
);
|
93
|
-
};
|
94
|
-
|
95
|
-
export default function SearchWrapper({ indices }) {
|
96
|
-
const defaultIndexTypesState = Object.values(INDEX_TYPES).reduce((a, c) => {
|
97
|
-
a[c] = true;
|
98
|
-
return a;
|
99
|
-
}, {});
|
100
|
-
const wrapperRef = useRef(null);
|
101
|
-
const [activeIndexTypes, setActiveIndexTypes] = useState(defaultIndexTypesState);
|
102
|
-
return (
|
103
|
-
<InstantSearch
|
104
|
-
searchClient={searchClient}
|
105
|
-
indexName={indices[0].name}
|
106
|
-
onSearchStateChange={() => setActiveIndexTypes(defaultIndexTypesState)}
|
107
|
-
>
|
108
|
-
<SearchBox />
|
109
|
-
<CustomAllResults indices={indices}>
|
110
|
-
<div className="tb-m:flex">
|
111
|
-
<IndexTypeFilter
|
112
|
-
activeIndexTypes={activeIndexTypes}
|
113
|
-
setActiveIndexTypes={setActiveIndexTypes}
|
114
|
-
/>
|
115
|
-
<SearchResults
|
116
|
-
id="search-results"
|
117
|
-
indices={indices}
|
118
|
-
wrapperRef={wrapperRef}
|
119
|
-
activeIndexTypes={activeIndexTypes}
|
120
|
-
className="search-results"
|
121
|
-
/>
|
122
|
-
</div>
|
123
|
-
</CustomAllResults>
|
124
|
-
</InstantSearch>
|
125
|
-
);
|
126
|
-
}
|