'use client' import { useRouter as useLegacyRouter } from 'next/compat/router' import { type PropsWithChildren, useEffect, useMemo, useCallback } from 'react' import { useConstant } from 'common' import { CommandContext } from '../internal/Context' import { initCommandsState } from '../internal/state/commandsState' import { initPagesState } from '../internal/state/pagesState' import { initQueryState } from '../internal/state/queryState' import { initViewState } from '../internal/state/viewState' import { CrossCompatRouterContext } from './hooks/useCrossCompatRouter' import { useSetCommandMenuOpen, useToggleCommandMenu } from './hooks/viewHooks' const CommandProviderInternal = ({ children }: PropsWithChildren) => { const combinedState = useConstant(() => ({ commandsState: initCommandsState(), pagesState: initPagesState(), queryState: initQueryState(), viewState: initViewState(), })) return {children} } // This is a component not a hook so it can access the wrapping context. const CommandShortcut = ({ openKey }: { openKey: string }) => { const toggleOpen = useToggleCommandMenu() useEffect(() => { const handleKeydown = (evt: KeyboardEvent) => { if (openKey === '') return if (evt.key === openKey && evt.metaKey) { evt.preventDefault() toggleOpen() } } document.addEventListener('keydown', handleKeydown) return () => document.removeEventListener('keydown', handleKeydown) }, [toggleOpen]) return null } function CloseOnNavigation({ children }: PropsWithChildren) { const setIsOpen = useSetCommandMenuOpen() const legacyRouter = useLegacyRouter() const isUsingLegacyRouting = !!legacyRouter const completeNavigation = useCallback(() => { setIsOpen(false) }, [setIsOpen]) const ctx = useMemo( () => ({ onPendingEnd: new Set([completeNavigation]), }), [completeNavigation] ) useEffect(() => { if (!isUsingLegacyRouting) return legacyRouter.events.on('routeChangeComplete', completeNavigation) return () => legacyRouter.events.off('routeChangeComplete', completeNavigation) }, [isUsingLegacyRouting, legacyRouter]) return ( {children} ) } interface CommandProviderProps extends PropsWithChildren { /** * The keyboard shortcut that opens the command menu when used in * combination with the meta key. * * Defaults to `k`. Pass an empty string to disable the keyboard shortcut. */ openKey?: string } const CommandProvider = ({ children, openKey }: CommandProviderProps) => ( {children} ) export { CommandProvider }