SPB Git forge

spb/countryatlas

Public
20commits 1branches 0releases
268.3 MBsize
maindefault branch
12 days agolast push
TypeScript 57% Python 38.6% JavaScript 3.6% CSS 0.6%
1.4 KB · 40 lines tsx
Raw Blame History
1'use client';2import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';34interface Ctx {5  open: boolean;6  setOpen: (v: boolean) => void;7}8const SearchCtx = createContext<Ctx>({ open: false, setOpen: () => {} });910/** Global search state + ⌘K / Ctrl+K / "/" shortcuts. */11export function SearchProvider({ children }: { children: ReactNode }) {12  const [open, setOpen] = useState(false);13  useEffect(() => {14    const onKey = (e: KeyboardEvent) => {15      const target = e.target as HTMLElement | null;16      const typing = target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable);17      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {18        e.preventDefault();19        setOpen((o) => !o);20      } else if (e.key === '/' && !typing && !e.metaKey && !e.ctrlKey && !e.altKey) {21        e.preventDefault();22        setOpen(true);23      }24    };25    window.addEventListener('keydown', onKey);26    return () => window.removeEventListener('keydown', onKey);27  }, []);28  const value = useMemo(() => ({ open, setOpen }), [open]);29  return <SearchCtx.Provider value={value}>{children}</SearchCtx.Provider>;30}3132export function useSearch() {33  return useContext(SearchCtx);34}3536export function useOpenSearch() {37  const { setOpen } = useSearch();38  return useCallback(() => setOpen(true), [setOpen]);39}40