HTML 77.2%
TypeScript 10.5%
Python 9.6%
JavaScript 2.5%
1'use client';2import { createContext, type ReactNode, useCallback, useContext, useEffect, useMemo, useState } from 'react';34const Ctx = createContext<{ open: boolean; setOpen: (v: boolean) => void }>({ open: false, setOpen: () => undefined });56/** Global ⌘K / "/" search dialog state. */7export function SearchProvider({ children }: { children: ReactNode }) {8 const [open, setOpen] = useState(false);9 useEffect(() => {10 const onKey = (e: KeyboardEvent) => {11 const target = e.target as HTMLElement | null;12 const typing = target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable);13 if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {14 e.preventDefault();15 setOpen((o) => !o);16 } else if (e.key === '/' && !typing && !e.metaKey && !e.ctrlKey) {17 e.preventDefault();18 setOpen(true);19 }20 };21 window.addEventListener('keydown', onKey);22 return () => window.removeEventListener('keydown', onKey);23 }, []);24 const value = useMemo(() => ({ open, setOpen }), [open]);25 return <Ctx.Provider value={value}>{children}</Ctx.Provider>;26}2728export function useSearch() {29 return useContext(Ctx);30}31export function useOpenSearch() {32 const { setOpen } = useContext(Ctx);33 return useCallback(() => setOpen(true), [setOpen]);34}35