import { FieldPresence, FieldSchema, StructureSchema, ValueType } from '@ephox/boulder'; import { Arr, type Optional, type Result } from '@ephox/katamari'; import type { AlloyComponent } from '../api/component/ComponentApi'; import type { ComponentDetail, SimpleOrSketchSpec, StructDomSchema } from '../api/component/SpecTypes'; import type { AlloyEventRecord } from '../api/events/AlloyEvents'; import * as NativeEvents from '../api/events/NativeEvents'; import * as SystemEvents from '../api/events/SystemEvents'; import type { DomDefinitionDetail } from '../dom/DomDefinition'; import { type DomModification, nu as NuModification } from '../dom/DomModification'; // NB: Tsc requires AlloyEventHandler to be imported here. export interface CustomDetail { 'dom': StructDomSchema; // By this stage, the components are built. 'components': AlloyComponent[]; 'uid': string; 'events': AlloyEventRecord; 'apis': A; 'eventOrder': Record; 'domModification': Optional; 'originalSpec': SimpleOrSketchSpec; 'debug.sketcher': string; } const baseBehaviour = 'alloy.base.behaviour'; const schema = StructureSchema.objOf([ FieldSchema.field('dom', 'dom', FieldPresence.required(), StructureSchema.objOf([ // Note, no children. FieldSchema.required('tag'), FieldSchema.defaulted('styles', {}), FieldSchema.defaulted('classes', []), FieldSchema.defaulted('attributes', {}), FieldSchema.option('value'), FieldSchema.option('innerHtml') ])), FieldSchema.required('components'), FieldSchema.required('uid'), FieldSchema.defaulted('events', {}), FieldSchema.defaulted('apis', {}), // Use mergeWith in the future when pre-built behaviours conflict FieldSchema.field( 'eventOrder', 'eventOrder', FieldPresence.mergeWith({ // Note, not using constant behaviour names to avoid code size of unused behaviours [SystemEvents.execute()]: [ 'disabling', baseBehaviour, 'toggling', 'typeaheadevents' ], [SystemEvents.focus()]: [ baseBehaviour, 'focusing', 'keying' ], [SystemEvents.systemInit()]: [ baseBehaviour, 'disabling', 'toggling', 'representing', 'tooltipping' ], [NativeEvents.input()]: [ baseBehaviour, 'representing', 'streaming', 'invalidating' ], [SystemEvents.detachedFromDom()]: [ baseBehaviour, 'representing', 'item-events', 'toolbar-button-events', 'tooltipping' ], [NativeEvents.mousedown()]: [ 'focusing', baseBehaviour, 'item-type-events' ], [NativeEvents.touchstart()]: [ 'focusing', baseBehaviour, 'item-type-events' ], [NativeEvents.mouseover()]: [ 'item-type-events', 'tooltipping' ], [SystemEvents.receive()]: [ 'receiving', 'reflecting', 'tooltipping' ] }), ValueType.anyValue() ), FieldSchema.option('domModification') ]); const toInfo = (spec: ComponentDetail): Result, any> => StructureSchema.asRaw('custom.definition', schema, spec); const toDefinition = (detail: CustomDetail): DomDefinitionDetail => // EFFICIENCY: Consider not merging here. ({ ...detail.dom, uid: detail.uid, domChildren: Arr.map(detail.components, (comp) => comp.element) }); const toModification = (detail: CustomDetail): DomModification => detail.domModification.fold(() => NuModification({ }), NuModification); const toApis = (info: CustomDetail): A => info.apis; const toEvents = (info: CustomDetail): AlloyEventRecord => info.events; export { toApis, toDefinition, toEvents, toInfo, toModification };