import { Dialog, Popover, Transition } from '@headlessui/react' import { Fragment, useEffect } from 'react' import CommandBarArgument from './CommandBarArgument' import CommandComboBox from '../CommandComboBox' import CommandBarReview from './CommandBarReview' import { useLocation } from 'react-router-dom' import useHotkeyWrapper from 'lib/hotkeyWrapper' import { CustomIcon } from 'components/CustomIcon' import Tooltip from 'components/Tooltip' import { commandBarActor, useCommandBarState } from 'machines/commandBarMachine' export const COMMAND_PALETTE_HOTKEY = 'mod+k' export const CommandBar = () => { const { pathname } = useLocation() const commandBarState = useCommandBarState() const { context: { selectedCommand, currentArgument, commands }, } = commandBarState const isSelectionArgument = currentArgument?.inputType === 'selection' const WrapperComponent = isSelectionArgument ? Popover : Dialog // Close the command bar when navigating useEffect(() => { if (commandBarState.matches('Closed')) return commandBarActor.send({ type: 'Close' }) }, [pathname]) // Hook up keyboard shortcuts useHotkeyWrapper([COMMAND_PALETTE_HOTKEY], () => { if (commandBarState.context.commands.length === 0) return if (commandBarState.matches('Closed')) { commandBarActor.send({ type: 'Open' }) } else { commandBarActor.send({ type: 'Close' }) } }) function stepBack() { if (!currentArgument) { if (commandBarState.matches('Review')) { const entries = Object.entries(selectedCommand?.args || {}).filter( ([_, argConfig]) => typeof argConfig.required === 'function' ? argConfig.required(commandBarState.context) : argConfig.required ) const currentArgName = entries[entries.length - 1][0] const currentArg = { name: currentArgName, ...entries[entries.length - 1][1], } commandBarActor.send({ type: 'Edit argument', data: { arg: currentArg, }, }) } else { commandBarActor.send({ type: 'Deselect command' }) } } else { const entries = Object.entries(selectedCommand?.args || {}) const index = entries.findIndex( ([key, _]) => key === currentArgument.name ) if (index === 0) { commandBarActor.send({ type: 'Deselect command' }) } else { commandBarActor.send({ type: 'Change current argument', data: { arg: { name: entries[index - 1][0], ...entries[index - 1][1] }, }, }) } } } return ( { if (selectedCommand?.onCancel) selectedCommand.onCancel() commandBarActor.send({ type: 'Clear' }) }} as={Fragment} > { commandBarActor.send({ type: 'Close' }) }} className={ 'fixed inset-0 z-50 overflow-y-auto pb-4 pt-1 ' + (isSelectionArgument ? 'pointer-events-none' : '') } data-testid="command-bar-wrapper" > {commandBarState.matches('Selecting command') ? ( ) : commandBarState.matches('Gathering arguments') ? ( ) : ( commandBarState.matches('Review') && ( ) )} ) } export default CommandBar