import { CustomIconName } from 'components/CustomIcon' import { AllMachines } from 'hooks/useStateMachineCommands' import { AnyStateMachine, ContextFrom, EventFrom, InterpreterFrom, } from 'xstate' import { Selection } from './selections' import { Identifier, Value, VariableDeclaration } from 'lang/wasm' import { commandBarMachine } from 'machines/commandBarMachine' type Icon = CustomIconName const PLATFORMS = ['both', 'web', 'desktop'] as const const INPUT_TYPES = [ 'options', 'string', 'kcl', 'selection', 'boolean', ] as const export interface KclExpression { valueAst: Value valueText: string valueCalculated: string } export interface KclExpressionWithVariable extends KclExpression { variableName: string variableDeclarationAst: VariableDeclaration variableIdentifierAst: Identifier insertIndex: number } export type KclCommandValue = KclExpression | KclExpressionWithVariable export type CommandInputType = (typeof INPUT_TYPES)[number] export type CommandSetSchema = Partial<{ [EventType in EventFrom['type']]: Record }> export type CommandSet< T extends AllMachines, Schema extends CommandSetSchema > = Partial<{ [EventType in EventFrom['type']]: Command< T, EventFrom['type'], Schema[EventType] > }> export type CommandSetConfig< T extends AllMachines, Schema extends CommandSetSchema > = Partial<{ [EventType in EventFrom['type']]: CommandConfig< T, EventFrom['type'], Schema[EventType] > }> export type Command< T extends AnyStateMachine = AnyStateMachine, CommandName extends EventFrom['type'] = EventFrom['type'], CommandSchema extends CommandSetSchema[CommandName] = CommandSetSchema[CommandName] > = { name: CommandName ownerMachine: T['id'] needsReview: boolean onSubmit: (data?: CommandSchema) => void onCancel?: () => void args?: { [ArgName in keyof CommandSchema]: CommandArgument } displayName?: string description?: string icon?: Icon hide?: (typeof PLATFORMS)[number] } export type CommandConfig< T extends AnyStateMachine = AnyStateMachine, CommandName extends EventFrom['type'] = EventFrom['type'], CommandSchema extends CommandSetSchema[CommandName] = CommandSetSchema[CommandName] > = Omit< Command, 'name' | 'ownerMachine' | 'onSubmit' | 'onCancel' | 'args' | 'needsReview' > & { needsReview?: true args?: { [ArgName in keyof CommandSchema]: CommandArgumentConfig< CommandSchema[ArgName], ContextFrom > } } export type CommandArgumentConfig< OutputType, C = ContextFrom > = { description?: string required: | boolean | (( commandBarContext: { argumentsToSubmit: Record }, // Should be the commandbarMachine's context, but it creates a circular dependency machineContext?: C ) => boolean) skip?: boolean } & ( | { inputType: 'options' options: | CommandArgumentOption[] | (( commandBarContext: { argumentsToSubmit: Record }, // Should be the commandbarMachine's context, but it creates a circular dependency machineContext?: C ) => CommandArgumentOption[]) optionsFromContext?: (context: C) => CommandArgumentOption[] defaultValue?: | OutputType | (( commandBarContext: ContextFrom, machineContext?: C ) => OutputType) defaultValueFromContext?: (context: C) => OutputType } | { inputType: 'selection' selectionTypes: Selection['type'][] multiple: boolean } | { inputType: 'kcl'; defaultValue?: string } // KCL expression inputs have simple strings as default values | { inputType: 'string' defaultValue?: | OutputType | (( commandBarContext: ContextFrom, machineContext?: C ) => OutputType) defaultValueFromContext?: (context: C) => OutputType } | { inputType: 'boolean' defaultValue?: | OutputType | (( commandBarContext: ContextFrom, machineContext?: C ) => OutputType) defaultValueFromContext?: (context: C) => OutputType } ) export type CommandArgument< OutputType, T extends AnyStateMachine = AnyStateMachine > = { description?: string required: | boolean | (( commandBarContext: { argumentsToSubmit: Record }, // Should be the commandbarMachine's context, but it creates a circular dependency machineContext?: ContextFrom ) => boolean) skip?: boolean machineActor: InterpreterFrom } & ( | { inputType: Extract options: | CommandArgumentOption[] | (( commandBarContext: { argumentsToSubmit: Record }, // Should be the commandbarMachine's context, but it creates a circular dependency machineContext?: ContextFrom ) => CommandArgumentOption[]) defaultValue?: | OutputType | (( commandBarContext: ContextFrom, machineContext?: ContextFrom ) => OutputType) } | { inputType: 'selection' selectionTypes: Selection['type'][] multiple: boolean } | { inputType: 'kcl'; defaultValue?: string } // KCL expression inputs have simple strings as default value | { inputType: 'string' defaultValue?: | OutputType | (( commandBarContext: ContextFrom, machineContext?: ContextFrom ) => OutputType) } | { inputType: 'boolean' defaultValue?: | OutputType | (( commandBarContext: ContextFrom, machineContext?: ContextFrom ) => OutputType) } ) export type CommandArgumentWithName< OutputType, T extends AnyStateMachine = AnyStateMachine > = CommandArgument & { name: string } export type CommandArgumentOption = { name: string isCurrent?: boolean value: A }