import { Id } from '@ephox/katamari'; import { Attribute } from '@ephox/sugar'; import * as AlloyParts from '../../parts/AlloyParts'; import * as FormFieldSchema from '../../ui/schema/FormFieldSchema'; import type { FormFieldApis, FormFieldDetail, FormFieldSketcher, FormFieldSpec } from '../../ui/types/FormFieldTypes'; import { Composing } from '../behaviour/Composing'; import { Representing } from '../behaviour/Representing'; import type { AlloyComponent } from '../component/ComponentApi'; import * as SketchBehaviours from '../component/SketchBehaviours'; import type { SketchSpec } from '../component/SpecTypes'; import * as AlloyEvents from '../events/AlloyEvents'; import * as Sketcher from './Sketcher'; import type { CompositeSketchFactory } from './UiSketcher'; const factory: CompositeSketchFactory = (detail, components, _spec, _externals): SketchSpec => { const behaviours = SketchBehaviours.augment( detail.fieldBehaviours, [ Composing.config({ find: (container) => { return AlloyParts.getPart(container, detail, 'field'); } }), Representing.config({ store: { mode: 'manual', getValue: (field) => { return Composing.getCurrent(field).bind(Representing.getValue); }, setValue: (field, value) => { Composing.getCurrent(field).each((current) => { Representing.setValue(current, value); }); } } }) ] ); const events = AlloyEvents.derive([ // Used to be systemInit AlloyEvents.runOnAttached((component, _simulatedEvent) => { const ps = AlloyParts.getParts(component, detail, [ 'label', 'field', 'aria-descriptor' ]); ps.field().each((field) => { const id = Id.generate(detail.prefix); ps.label().each((label) => { // TODO: Find a nicer way of doing this. Attribute.set(label.element, 'for', id); Attribute.set(field.element, 'id', id); }); ps['aria-descriptor']().each((descriptor) => { const descriptorId = Id.generate(detail.prefix); Attribute.set(descriptor.element, 'id', descriptorId); Attribute.set(field.element, 'aria-describedby', descriptorId); }); }); }) ]); const apis = { getField: (container: AlloyComponent) => AlloyParts.getPart(container, detail, 'field'), getLabel: (container: AlloyComponent) => // TODO: Use constants for part names AlloyParts.getPart(container, detail, 'label') }; return { uid: detail.uid, dom: detail.dom, components, behaviours, events, apis }; }; const FormField: FormFieldSketcher = Sketcher.composite({ name: 'FormField', configFields: FormFieldSchema.schema(), partFields: FormFieldSchema.parts(), factory, apis: { getField: (apis, comp) => apis.getField(comp), getLabel: (apis, comp) => apis.getLabel(comp) } }); export { FormField };