import { useSelector } from '@xstate/react' import { useCommandsContext } from 'hooks/useCommandsContext' import { useKclContext } from 'lang/KclProvider' import { CommandArgument } from 'lib/commandTypes' import { canSubmitSelectionArg, getSelectionType, getSelectionTypeDisplayText, } from 'lib/selections' import { kclManager } from 'lib/singletons' import { modelingMachine } from 'machines/modelingMachine' import { useCallback, useEffect, useRef, useState } from 'react' import { useHotkeys } from 'react-hotkeys-hook' import { StateFrom } from 'xstate' const selectionSelector = (snapshot: StateFrom) => snapshot.context.selectionRanges function CommandBarSelectionInput({ arg, stepBack, onSubmit, }: { arg: CommandArgument & { inputType: 'selection'; name: string } stepBack: () => void onSubmit: (data: unknown) => void }) { const { code } = useKclContext() const inputRef = useRef(null) const { commandBarState, commandBarSend } = useCommandsContext() const [hasSubmitted, setHasSubmitted] = useState(false) const selection = useSelector(arg.machineActor, selectionSelector) const initSelectionsByType = useCallback(() => { const selectionRangeEnd = selection.codeBasedSelections[0]?.range[1] return !selectionRangeEnd || selectionRangeEnd === code.length ? 'none' : getSelectionType(selection) }, [selection, code]) const selectionsByType = initSelectionsByType() const [canSubmitSelection, setCanSubmitSelection] = useState( canSubmitSelectionArg(selectionsByType, arg) ) useHotkeys('tab', () => onSubmit(selection), { enableOnFormTags: true, enableOnContentEditable: true, keyup: true, }) useEffect(() => { inputRef.current?.focus() }, [selection, inputRef]) // Exit engine's edit mode when this input step is active, // and re-enter it when it's not. // In future the engine's edit mode will go away and this will be handled differently. useEffect(() => { kclManager.exitEditMode() return () => kclManager.enterEditMode() }, []) // Fast-forward through this arg if it's marked as skippable // and we have a valid selection already useEffect(() => { console.log('selection input effect', { selectionsByType, canSubmitSelection, arg, }) setCanSubmitSelection(canSubmitSelectionArg(selectionsByType, arg)) const argValue = commandBarState.context.argumentsToSubmit[arg.name] if (canSubmitSelection && arg.skip && argValue === undefined) { handleSubmit({ preventDefault: () => {}, } as React.FormEvent) } }, [selectionsByType, arg]) function handleChange() { inputRef.current?.focus() } function handleSubmit(e: React.FormEvent) { e.preventDefault() if (!canSubmitSelection) { setHasSubmitted(true) return } onSubmit(selection) } return (
) } export default CommandBarSelectionInput