import { type FieldProcessor, FieldSchema } from '@ephox/boulder'; import { Fun } from '@ephox/katamari'; import { Value } from '@ephox/sugar'; import * as Behaviour from '../../api/behaviour/Behaviour'; import { Focusing } from '../../api/behaviour/Focusing'; import { Representing } from '../../api/behaviour/Representing'; import * as SketchBehaviours from '../../api/component/SketchBehaviours'; import type { RawDomSchema } from '../../api/component/SpecTypes'; import * as Fields from '../../data/Fields'; import type { InputDetail } from '../types/InputTypes'; const schema: () => FieldProcessor[] = Fun.constant([ FieldSchema.defaultedString('type', 'text'), FieldSchema.option('data'), FieldSchema.defaulted('inputAttributes', { }), FieldSchema.defaulted('inputStyles', { }), FieldSchema.defaulted('tag', 'input'), FieldSchema.defaulted('inputClasses', [ ]), Fields.onHandler('onSetValue'), FieldSchema.defaultedFunction('fromInputValue', Fun.identity), FieldSchema.defaultedFunction('toInputValue', Fun.identity), FieldSchema.defaulted('styles', { }), FieldSchema.defaulted('eventOrder', { }), SketchBehaviours.field('inputBehaviours', [ Representing, Focusing ]), FieldSchema.defaulted('selectOnFocus', true) ]); const focusBehaviours = (detail: InputDetail): Behaviour.AlloyBehaviourRecord => Behaviour.derive([ Focusing.config({ onFocus: !detail.selectOnFocus ? Fun.noop : (component) => { const input = component.element; const value = Value.get(input); // TODO: There are probably more types that can't handle setSelectionRange if (detail.type !== 'range') { input.dom.setSelectionRange(0, value.length); } } }) ]); const behaviours = (detail: InputDetail): Behaviour.AlloyBehaviourRecord => ({ ...focusBehaviours(detail), ...SketchBehaviours.augment( detail.inputBehaviours, [ Representing.config({ store: { mode: 'manual', // Propagating its Optional ...detail.data.map((data) => ({ initialValue: data } as { initialValue?: string })).getOr({ }), getValue: (input) => { return detail.fromInputValue(Value.get(input.element)); }, setValue: (input, data) => { const current = Value.get(input.element); // Only set it if it has changed ... otherwise the cursor goes to the end. if (current !== data) { Value.set(input.element, detail.toInputValue(data)); } } }, onSetValue: detail.onSetValue }) ] ) }); const dom = (detail: InputDetail): RawDomSchema => ({ tag: detail.tag, attributes: { type: detail.type, ...detail.inputAttributes }, styles: detail.inputStyles, classes: detail.inputClasses }); export { schema, behaviours, focusBehaviours, dom };