import { useSelector } from '@xstate/react' import { Artifact } from 'lang/std/artifactGraph' import { CommandArgument } from 'lib/commandTypes' import { canSubmitSelectionArg, getSelectionCountByType, getSelectionTypeDisplayText, } from 'lib/selections' import { kclManager } from 'lib/singletons' import { reportRejection } from 'lib/trap' import { toSync } from 'lib/utils' import { commandBarActor, useCommandBarState } from 'machines/commandBarMachine' import { modelingMachine } from 'machines/modelingMachine' import { useEffect, useMemo, useRef, useState } from 'react' import { StateFrom } from 'xstate' const semanticEntityNames: { [key: string]: Array } = { face: ['wall', 'cap', 'solid2d'], edge: ['segment', 'sweepEdge', 'edgeCutEdge'], point: [], plane: ['defaultPlane'], } 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 inputRef = useRef(null) const commandBarState = useCommandBarState() const [hasSubmitted, setHasSubmitted] = useState(false) const selection = useSelector(arg.machineActor, selectionSelector) const selectionsByType = useMemo(() => { return getSelectionCountByType(selection) }, [selection]) const canSubmitSelection = useMemo( () => canSubmitSelectionArg(selectionsByType, arg), [selectionsByType] ) useEffect(() => { inputRef.current?.focus() }, [selection, inputRef]) // Show the default planes if the selection type is 'plane' useEffect(() => { if (arg.selectionTypes.includes('plane') && !canSubmitSelection) { toSync(() => { return Promise.all([ kclManager.showPlanes(), kclManager.setSelectionFilter(['plane', 'object']), ]) }, reportRejection)() } return () => { toSync(() => { const promises = [ new Promise(() => kclManager.defaultSelectionFilter(selection)), ] if (!kclManager._isAstEmpty(kclManager.ast)) { promises.push(kclManager.hidePlanes()) } return Promise.all(promises) }, reportRejection)() } }, []) // 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