import type { Optional } from '@ephox/katamari'; import { Direction, type SugarElement } from '@ephox/sugar'; import type { AlloyComponent } from '../api/component/ComponentApi'; import type { NativeSimulatedEvent } from '../events/SimulatedEvent'; import type { GeneralKeyingConfig, KeyRuleHandler } from '../keying/KeyingModeTypes'; export type ElementMover = (elem: SugarElement, focused: SugarElement, config: C, state: S) => Optional>; // Looks up direction (considering LTR and RTL), finds the focused element, // and tries to move. If it succeeds, triggers focus and kills the event. const useH = (movement: (elem: SugarElement) => ElementMover): KeyRuleHandler => (component, simulatedEvent, config, state) => { const move = movement(component.element); return use(move, component, simulatedEvent, config, state); }; const west = (moveLeft: ElementMover, moveRight: ElementMover): KeyRuleHandler => { const movement = Direction.onDirection(moveLeft, moveRight); return useH(movement); }; const east = (moveLeft: ElementMover, moveRight: ElementMover): KeyRuleHandler => { const movement = Direction.onDirection(moveRight, moveLeft); return useH(movement); }; const useV = (move: ElementMover): KeyRuleHandler => (component, simulatedEvent, config, state) => use(move, component, simulatedEvent, config, state); const use = (move: ElementMover, component: AlloyComponent, simulatedEvent: NativeSimulatedEvent, config: C, state: S): Optional => { const outcome = config.focusManager.get(component).bind((focused) => move(component.element, focused, config, state)); return outcome.map((newFocus): boolean => { config.focusManager.set(component, newFocus); return true; }); }; const north = useV; const south = useV; const move = useV; export { east, west, north, south, move };