import * as AlloyParts from '../../parts/AlloyParts'; import * as ExpandableFormSchema from '../../ui/schema/ExpandableFormSchema'; import type { ExpandableFormApis, ExpandableFormDetail, ExpandableFormSketcher, ExpandableFormSpec } from '../../ui/types/ExpandableFormTypes'; import { Representing } from '../behaviour/Representing'; import { Sliding } from '../behaviour/Sliding'; import type { AlloyComponent } from '../component/ComponentApi'; import * as SketchBehaviours from '../component/SketchBehaviours'; import type { SketchSpec } from '../component/SpecTypes'; import { Form } from './Form'; import * as Sketcher from './Sketcher'; import type { CompositeSketchFactory } from './UiSketcher'; const runOnExtra = (detail: ExpandableFormDetail, operation: (comp: AlloyComponent) => void) => (anyComp: AlloyComponent) => { AlloyParts.getPart(anyComp, detail, 'extra').each(operation); }; const factory: CompositeSketchFactory = (detail, components, _spec, _externals): SketchSpec => { const getParts = (form: AlloyComponent) => AlloyParts.getPartsOrDie(form, detail, [ 'minimal', 'extra' ]); return { uid: detail.uid, dom: detail.dom, components, behaviours: SketchBehaviours.augment( detail.expandableBehaviours, [ Representing.config({ store: { mode: 'manual', getValue: (form) => { const parts = getParts(form); const minimalValues = Representing.getValue(parts.minimal()); const extraValues = Representing.getValue(parts.extra()); return { ...minimalValues, ...extraValues }; }, setValue: (form, values) => { const parts = getParts(form); // ASSUMPTION: Form ignore values that it does not have. Representing.setValue(parts.minimal(), values); Representing.setValue(parts.extra(), values); } } }) ] ), apis: { toggleForm: runOnExtra(detail, Sliding.toggleGrow), collapseForm: runOnExtra(detail, Sliding.shrink), collapseFormImmediately: runOnExtra(detail, Sliding.immediateShrink), expandForm: runOnExtra(detail, Sliding.grow), getField: (form: AlloyComponent, key: string) => { return AlloyParts.getPart(form, detail, 'minimal').bind((minimal) => Form.getField(minimal, key)).orThunk(() => AlloyParts.getPart(form, detail, 'extra').bind((extra) => Form.getField(extra, key))); } } }; }; const ExpandableForm: ExpandableFormSketcher = Sketcher.composite({ name: 'ExpandableForm', configFields: ExpandableFormSchema.schema(), partFields: ExpandableFormSchema.parts(), factory, apis: { getField: (apis, component, key) => apis.getField(component, key), toggleForm: (apis, component) => { apis.toggleForm(component); }, collapseForm: (apis, component) => { apis.collapseForm(component); }, collapseFormImmediately: (apis, component) => { apis.collapseFormImmediately(component); }, expandForm: (apis, component) => { apis.expandForm(component); } } }); export { ExpandableForm };