import { Obj } from '@ephox/katamari'; import type { Stateless } from '../../behaviour/common/BehaviourState'; import * as KeyboardBranches from '../../behaviour/keyboard/KeyboardBranches'; import * as KeyingState from '../../behaviour/keyboard/KeyingState'; import type { AcylicConfigSpec, CyclicConfigSpec, ExecutingConfigSpec, FlatgridConfigSpec, FlatgridState, FlowConfigSpec, GeneralKeyingConfig, MatrixConfigSpec, MenuConfigSpec, SpecialConfigSpec } from '../../keying/KeyingModeTypes'; import type { AlloyComponent } from '../component/ComponentApi'; import * as Behaviour from './Behaviour'; export interface KeyingBehaviour extends Behaviour.AlloyBehaviour { config: (config: KeyingConfigSpec) => Behaviour.NamedConfiguredBehaviour; focusIn: (component: AlloyComponent) => void; setGridSize: ( component: AlloyComponent, numRows: number, numColumns: number, ) => void; } type KeyingState = Stateless | FlatgridState; export type KeyingConfigSpec = AcylicConfigSpec | CyclicConfigSpec | FlowConfigSpec | FlatgridConfigSpec | MatrixConfigSpec | ExecutingConfigSpec | MenuConfigSpec | SpecialConfigSpec; // TODO: dynamic type, TODO: group these into their KeyingModes export type KeyingModes = 'acyclic' | 'cyclic' | 'flow' | 'flatgrid' | 'matrix' | 'execution' | 'menu' | 'special'; const isFlatgridState = (keyState: KeyingState): keyState is FlatgridState => Obj.hasNonNullableKey(keyState as any, 'setGridSize'); const Keying: KeyingBehaviour = Behaviour.createModes({ branchKey: 'mode', branches: KeyboardBranches, name: 'keying', active: { events: (keyingConfig: GeneralKeyingConfig, keyingState: KeyingState) => { const handler = keyingConfig.handler; return handler.toEvents(keyingConfig, keyingState); } }, apis: { focusIn: (component: AlloyComponent, keyConfig: GeneralKeyingConfig, keyState: KeyingState) => { // If we have a custom sendFocusIn function, use that. // Otherwise, we just trigger focus on the outer element. keyConfig.sendFocusIn(keyConfig).fold( () => { component.getSystem().triggerFocus(component.element, component.element); }, (sendFocusIn) => { sendFocusIn(component, keyConfig, keyState); } ); }, // These APIs are going to be interesting because they are not // available for all keying modes setGridSize: (component: AlloyComponent, keyConfig: GeneralKeyingConfig, keyState: KeyingState, numRows: number, numColumns: number) => { if (!isFlatgridState(keyState)) { // eslint-disable-next-line no-console console.error('Layout does not support setGridSize'); } else { keyState.setGridSize(numRows, numColumns); } } }, state: KeyingState }); export { Keying };