1import { Component, createRef } from "react";
2import { glossary } from "../lib/glossary";
3import { withRouter } from "next/router";
4import Downshift from "downshift";
6class Search extends Component {
12 this.searchEndpoint = this.searchEndpoint.bind(this);
13 this.onInputValueChange = this.onInputValueChange.bind(this);
14 this.onSelect = this.onSelect.bind(this);
15 this.glossarySearch = this.glossarySearch.bind(this);
18 searchEndpoint(query) {
19 return `/api/search?q=${query}`;
22 glossarySearch(query) {
23 return glossary.filter((entry) => {
24 return query.toLowerCase() === entry.name || entry.symbol === query;
30 this.props.router.push(item.slug);
38 this.props.closeSearch();
41 onInputValueChange(query) {
43 fetch(this.searchEndpoint(query))
44 .then((res) => res.json())
46 // Wrap results in an object which will tell React what component to use to render results.
47 const results = res.results.map((item) => ({
52 const glossaryResults = this.glossarySearch(query).map((item) => ({
53 type: "GLOSSARY_RESULT",
57 const list = [...glossaryResults, ...results];
59 this.setState({ results: list });
62 this.setState({ results: [] });
67 const { state, props } = this;
69 if (props.showSearch) {
72 onSelect={(selection) => this.onSelect(selection)}
73 onInputValueChange={(event) => this.onInputValueChange(event)}
74 itemToString={(item) => (item ? item.slug : "")}
75 defaultHighlightedIndex={0}
89 onClick={(e) => props.closeSearch(e)}
90 className="fixed w-screen h-screen bg-washedWall z-50 flex flex-col items-center p-4"
92 <div className="relative flex flex-col max-w-screen-lg md:my-32 w-full md:w-10/12 lg:w-8/12 xl:w-6/12 rounded-xl bg-white min-h-0 overflow-hidden">
94 style={{ display: "inline-block" }}
95 {...getRootProps({}, { suppressRefError: true })}
99 className="text-lg md:text-xl lg:text-2xl font-medium text-green bg-transparent py-2 px-4 outline-none relative w-full"
100 placeholder="Search..."
102 onClick={(e) => e.stopPropagation()}
104 onKeyDown: (event) => {
105 if (event.key === "Escape") {
106 // Prevent Downshift's default 'Escape' behavior.
107 event.nativeEvent.preventDownshiftDefault = true;
108 this.props.closeSearch(event);
114 <ul {...getMenuProps()} className="overflow-y-scroll">
116 ? state.results.map((item, index) => {
117 const selected = highlightedIndex === index;
118 if (item.type === "GLOSSARY_RESULT") {
121 className={`cursor-pointer flex text-left w-full ${
122 selected ? "bg-green" : ""
125 key: item.content.slug + "-" + index,
128 selected: highlightedIndex === index,
131 <div className="font-semibold p-3">
133 className={`text-base ${
134 selected ? "text-white" : "text-black"
137 {item.content.symbol.length > 0 && (
139 className={`mr-1 rounded px-1 py-0.5 ${
140 selected ? "bg-washedWhite" : "bg-wall"
143 {item.content.symbol}
149 className={`font-normal text-base mt-1 ${
150 selected ? "text-white" : "text-black"
159 if (item.type === "RESULT") {
162 className={`cursor-pointer flex text-left w-full ${
163 selected ? "bg-green" : ""
166 key: item.content.link + "-" + index,
172 <div className="p-3">
174 className={`font-medium text-base ${
175 selected ? "text-white" : "text-black"
178 {item.content.parent !== "Content"
179 ? `${item.content.parent} /`
184 className={`text-base font-regular text-small ${
185 selected ? "text-midWhite" : "text-gray"
188 {item.content.content}
209export default withRouter(Search);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list