import React, { useCallback, useEffect, useState } from "react"; import { createPortal } from "react-dom"; import * as DocSearch from "@docsearch/react"; import { Link, useNavigate } from "@remix-run/react"; import Card from "~/components/Card"; import { MagnifyingGlassIcon } from "@heroicons/react/16/solid"; import { Button } from "../Button"; type HitProps = { hit: { url: string }; children: React.ReactNode; }; const algoliaOptions = { appId: "5I4EPST2WK", apiKey: "4f955170e0f326372dfea6b36f3f8aa7", indexName: "prod_buildjet_gha", }; function Hit({ hit, children }: HitProps) { return {children}; } export interface UseDocSearchKeyboardEventsProps { isOpen: boolean; onOpen: () => void; onClose: () => void; onInput?: (event: KeyboardEvent) => void; searchButtonRef?: React.RefObject; } function isEditingContent(event: KeyboardEvent): boolean { const element = event.target as HTMLElement; const tagName = element.tagName; return ( element.isContentEditable || tagName === "INPUT" || tagName === "SELECT" || tagName === "TEXTAREA" ); } export function useDocSearchKeyboardEvents({ isOpen, onOpen, onClose, onInput, searchButtonRef, }: UseDocSearchKeyboardEventsProps) { React.useEffect(() => { function onKeyDown(event: KeyboardEvent) { 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) || // The `Cmd+K` shortcut both opens and closes the modal. // We need to check for `event.key` because it can be `undefined` with // Chrome's autofill feature. // See https://github.com/paperjs/paper.js/issues/1398 (event.key?.toLowerCase() === "k" && (event.metaKey || event.ctrlKey)) || // The `/` shortcut opens but doesn't close the modal because it's // a character. (!isEditingContent(event) && event.key === "/" && !isOpen) ) { event.preventDefault(); if (isOpen) { onClose(); } else if (!document.body.classList.contains("DocSearch--active")) { open(); } } if ( searchButtonRef && searchButtonRef.current === document.activeElement && onInput ) { if (/[a-zA-Z0-9]/.test(String.fromCharCode(event.keyCode))) { onInput(event); } } } window.addEventListener("keydown", onKeyDown); return () => { window.removeEventListener("keydown", onKeyDown); }; }, [isOpen, onOpen, onClose, onInput, searchButtonRef]); } export function Search() { let [isOpen, setIsOpen] = useState(false); let [modifierKey, setModifierKey] = useState(); const onOpen = useCallback(() => { setIsOpen(true); }, [setIsOpen]); const navigate = useNavigate(); const onClose = useCallback(() => { setIsOpen(false); }, [setIsOpen]); useDocSearchKeyboardEvents({ isOpen, onOpen, onClose }); useEffect(() => { setModifierKey( // @ts-ignore !/(Mac|iPhone|iPod|iPad)/i.test(navigator?.platform) ? "Ctrl " : "⌘", ); }, []); return ( <>
{ setIsOpen(true); }} className="flex h-full items-center justify-center" > Search... {modifierKey && ( {modifierKey} K )}
{isOpen && createPortal( , document.body, )} ); }