import { useSelector } from '@xstate/react' import { useCommandsContext } from 'hooks/useCommandsContext' import { useKclContext } from 'lang/KclProvider' import { CommandArgument } from 'lib/commandTypes' import { Selection, canSubmitSelectionArg, getSelectionType, getSelectionTypeDisplayText, } from 'lib/selections' import { modelingMachine } from 'machines/modelingMachine' import { useEffect, useMemo, useRef, useState } from 'react' import { StateFrom } from 'xstate' const semanticEntityNames: { [key: string]: Array } = { face: ['extrude-wall', 'start-cap', 'end-cap'], edge: ['edge', 'line', 'arc'], point: ['point', 'line-end', 'line-mid'], } function getSemanticSelectionType(selectionType: Array) { const semanticSelectionType = new Set() selectionType.forEach((type) => { Object.entries(semanticEntityNames).forEach(([entity, entityTypes]) => { if (entityTypes.includes(type)) { semanticSelectionType.add(entity) } }) }) return Array.from(semanticSelectionType) } 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 selectionsByType = useMemo(() => { const selectionRangeEnd = selection?.codeBasedSelections[0]?.range[1] return !selectionRangeEnd || selectionRangeEnd === code.length ? 'none' : getSelectionType(selection) }, [selection, code]) const canSubmitSelection = useMemo( () => canSubmitSelectionArg(selectionsByType, arg), [selectionsByType] ) useEffect(() => { inputRef.current?.focus() }, [selection, inputRef]) // Fast-forward through this arg if it's marked as skippable // and we have a valid selection already useEffect(() => { const argValue = commandBarState.context.argumentsToSubmit[arg.name] if (canSubmitSelection && arg.skip && argValue === undefined) { handleSubmit() } }, [canSubmitSelection]) function handleChange() { inputRef.current?.focus() } function handleSubmit(e?: React.FormEvent) { e?.preventDefault() if (!canSubmitSelection) { setHasSubmitted(true) return } onSubmit(selection) } return (
) } export default CommandBarSelectionInput