├── .editorconfig ├── .gitignore ├── .prettierrc.json ├── LICENSE ├── dist ├── bind.d.ts ├── bind.js ├── control.d.ts ├── control.js ├── handlers.d.ts ├── handlers.js ├── helpers.d.ts ├── helpers.js ├── index.d.ts ├── index.js ├── input-control.d.ts ├── input-control.js ├── labelling-for.d.ts ├── labelling-for.js ├── state.d.ts ├── state.js ├── types.d.ts ├── types.js ├── validation.d.ts ├── validation.js ├── value.d.ts └── value.js ├── docs ├── build │ ├── app-globals-0f993ce5.js │ ├── css-shim-86c4384d.js │ ├── dom-13b87b71.js │ ├── index-4b905869.js │ ├── index.esm.js │ ├── my-form.entry.js │ ├── shadow-css-3c91b4d2.js │ ├── stencil-forms.esm.js │ └── stencil-forms.js ├── host.config.json └── index.html ├── package-lock.json ├── package.json ├── readme.md ├── scripts └── clean.js ├── src ├── bind.ts ├── control.ts ├── handlers.ts ├── helpers.ts ├── index.ts ├── input-control.ts ├── labelling-for.ts ├── state.ts ├── test │ ├── src │ │ ├── components.d.ts │ │ ├── index.html │ │ ├── my-form.css │ │ └── my-form.tsx │ ├── stencil.config.ts │ └── tsconfig.json ├── types.ts ├── validation.ts └── value.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | www/ 2 | 3 | *~ 4 | *.sw[mnpcod] 5 | *.log 6 | *.lock 7 | *.tmp 8 | *.tmp.* 9 | log.txt 10 | *.sublime-project 11 | *.sublime-workspace 12 | 13 | .stencil/ 14 | .idea/ 15 | .vscode/ 16 | .sass-cache/ 17 | .versions/ 18 | node_modules/ 19 | $RECYCLE.BIN/ 20 | 21 | .DS_Store 22 | Thumbs.db 23 | UserInterfaceState.xcuserstate 24 | .env 25 | src/ionicons -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": true, 4 | "jsxBracketSameLine": false, 5 | "jsxSingleQuote": false, 6 | "quoteProps": "consistent", 7 | "printWidth": 120, 8 | "semi": true, 9 | "singleQuote": true, 10 | "tabWidth": 2, 11 | "trailingComma": "all", 12 | "useTabs": false 13 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dist/bind.d.ts: -------------------------------------------------------------------------------- 1 | import type { ReactiveFormBindOptions } from './types'; 2 | export declare const bind: (instance: T, propName: PropName, bindOpts?: ReactiveFormBindOptions | undefined) => import("./types").ReactiveFormControl; 3 | export declare const bindBoolean: (instance: T, propName: PropName, bindOpts?: ReactiveFormBindOptions | undefined) => import("./types").ReactiveFormControl; 4 | export declare const bindNumber: (instance: T, propName: PropName, bindOpts?: ReactiveFormBindOptions | undefined) => import("./types").ReactiveFormControl; 5 | export declare const bindGroup: (instance: T, propName: PropName, bindOpts?: ReactiveFormBindOptions | undefined) => import("./types").ReactiveFormControlGroup; 6 | -------------------------------------------------------------------------------- /dist/bind.js: -------------------------------------------------------------------------------- 1 | import { inputControl, inputControlGroup } from './input-control'; 2 | import { instanceIds, state } from './state'; 3 | import { toDashCase } from './helpers'; 4 | import { setCastedBindValue } from './value'; 5 | export const bind = (instance, propName, bindOpts) => inputControl(instance[propName], normalizeBindOpts(bindOpts, instance, propName)); 6 | export const bindBoolean = (instance, propName, bindOpts) => inputControl(instance[propName], normalizeBindOpts(bindOpts, instance, propName, 'boolean')); 7 | export const bindNumber = (instance, propName, bindOpts) => inputControl(instance[propName], normalizeBindOpts(bindOpts, instance, propName, 'number')); 8 | export const bindGroup = (instance, propName, bindOpts) => inputControlGroup(instance[propName], normalizeBindOpts(bindOpts, instance, propName)); 9 | const normalizeBindOpts = (bindOpts, instance, propName, valuePropType = 'string') => { 10 | let instanceId = instanceIds.get(instance); 11 | if (instanceId == null) { 12 | instanceIds.set(instance, (instanceId = state.i++)); 13 | } 14 | return { 15 | i: toDashCase(propName) + instanceId, 16 | n: propName, 17 | valuePropType, 18 | ...bindOpts, 19 | onValueChange: ({ value }) => setCastedBindValue(instance, propName, value), 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /dist/control.d.ts: -------------------------------------------------------------------------------- 1 | import type { ReactiveFormControlOptions } from './types'; 2 | export declare const control: (initialValue: any, ctrlOpts: ReactiveFormControlOptions) => import("./types").ReactiveFormControl; 3 | export declare const controlBoolean: (initialValue: any, ctrlOpts: ReactiveFormControlOptions) => import("./types").ReactiveFormControl; 4 | export declare const controlNumber: (initialValue: any, ctrlOpts: ReactiveFormControlOptions) => import("./types").ReactiveFormControl; 5 | export declare const controlGroup: (initialSelectedValue: any, ctrlOpts: ReactiveFormControlOptions) => import("./types").ReactiveFormControlGroup; 6 | -------------------------------------------------------------------------------- /dist/control.js: -------------------------------------------------------------------------------- 1 | import { inputControl, inputControlGroup } from './input-control'; 2 | import { state } from './state'; 3 | export const control = (initialValue, ctrlOpts) => inputControl(initialValue, normalizeControlOpts(ctrlOpts)); 4 | export const controlBoolean = (initialValue, ctrlOpts) => inputControl(initialValue, normalizeControlOpts(ctrlOpts, 'boolean')); 5 | export const controlNumber = (initialValue, ctrlOpts) => inputControl(initialValue, normalizeControlOpts(ctrlOpts, 'number')); 6 | export const controlGroup = (initialSelectedValue, ctrlOpts) => inputControlGroup(initialSelectedValue, normalizeControlOpts(ctrlOpts)); 7 | const normalizeControlOpts = (ctrlOpts, valuePropType = 'string') => { 8 | const propName = 'ctrl' + state.i++; 9 | return { 10 | i: propName, 11 | n: propName, 12 | valuePropType, 13 | ...ctrlOpts, 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /dist/handlers.d.ts: -------------------------------------------------------------------------------- 1 | export declare const sharedEventHandler: (ev: Event) => void; 2 | -------------------------------------------------------------------------------- /dist/handlers.js: -------------------------------------------------------------------------------- 1 | import { checkValidity, catchError } from './validation'; 2 | import { ctrls, ctrlDatas, ctrlStates, getControlState, inputDebounces } from './state'; 3 | import { getValueFromControlElement, setValueToControlElement } from './value'; 4 | import { isFunction, isNumber, showNativeReport } from './helpers'; 5 | export const sharedEventHandler = (ev) => { 6 | const ctrlElm = ev.currentTarget; 7 | const ctrl = ctrls.get(ctrlElm); 8 | const ctrlData = ctrlDatas.get(ctrl); 9 | if (ctrl && ctrlData) { 10 | const ctrlState = getControlState(ctrl); 11 | const type = ev.type; 12 | const key = ev.key; 13 | const rtns = []; 14 | const event = { 15 | value: getValueFromControlElement(ctrlData, ctrlElm), 16 | initialValue: ctrlState.i, 17 | validity: ctrlElm.validity, 18 | key, 19 | type, 20 | ev: ev, 21 | ctrl: ctrlElm, 22 | }; 23 | try { 24 | if (type === 'blur') { 25 | // "blur" event 26 | ctrlState.t = true; 27 | if (isFunction(ctrlData.onBlur)) { 28 | rtns.push(ctrlData.onBlur(event)); 29 | } 30 | } 31 | else if (type === 'focus') { 32 | // "focus" event 33 | // reset "initialValue" state 34 | ctrlState.i = event.initialValue = event.value; 35 | if (!ctrlState.t && isFunction(ctrlData.onTouch)) { 36 | // onTouch should only fire on the first focus 37 | rtns.push(ctrlData.onTouch(event)); 38 | } 39 | if (isFunction(ctrlData.onFocus)) { 40 | rtns.push(ctrlData.onFocus(event)); 41 | } 42 | } 43 | else if (type === 'invalid') { 44 | // "invalid" event 45 | if (!showNativeReport(ctrlElm)) { 46 | ev.preventDefault(); 47 | } 48 | // add a space at the end to ensure we trigger a re-render 49 | ctrlState.e = ctrlElm.validationMessage + ' '; 50 | // a control is automatically "dirty" if it has been invalid at least once. 51 | ctrlState.d = true; 52 | } 53 | else { 54 | // "input" or "change" or keyboard events 55 | ctrlState.d = true; 56 | if (key === 'Escape' && ctrlData.resetOnEscape !== false) { 57 | setValueToControlElement(ctrlData, ctrlElm, ctrlState.i); 58 | if (isFunction(ctrlData.onValueChange)) { 59 | event.value = ctrlState.i; 60 | rtns.push(ctrlData.onValueChange(event)); 61 | } 62 | } 63 | if (key !== 'Enter' && key !== 'Escape' && isNumber(ctrlData.debounce)) { 64 | clearTimeout(inputDebounces.get(ctrlElm)); 65 | inputDebounces.set(ctrlElm, setTimeout(() => checkValidity(ctrlData, ctrlState, ctrlElm, event, setValueChange), ctrlData.debounce)); 66 | } 67 | else if (!(key === 'Enter' && ctrlElm.nodeName === 'TEXTAREA')) { 68 | checkValidity(ctrlData, ctrlState, ctrlElm, event, setValueChange); 69 | } 70 | } 71 | Promise.all(rtns).catch((err) => catchError(ctrlState, event, err)); 72 | } 73 | catch (e) { 74 | catchError(ctrlState, event, e); 75 | } 76 | } 77 | }; 78 | const setValueChange = (ctrlData, event) => { 79 | if (ctrlData && event && event.ctrl && event.ctrl.parentNode) { 80 | const ctrlState = ctrlStates.get(event.ctrl); 81 | const rtns = []; 82 | const eventType = event.type; 83 | if (ctrlState) { 84 | try { 85 | ctrlState.d = true; 86 | if (eventType === 'keydown' && isFunction(ctrlData.onKeyDown)) { 87 | rtns.push(ctrlData.onKeyDown(event)); 88 | } 89 | else if (eventType === 'keyup') { 90 | if (isFunction(ctrlData.onKeyUp)) { 91 | rtns.push(ctrlData.onKeyUp(event)); 92 | } 93 | if (event.key === 'Escape' && isFunction(ctrlData.onEscapeKey)) { 94 | rtns.push(ctrlData.onEscapeKey(event)); 95 | } 96 | else if (event.key === 'Enter') { 97 | ctrlState.i = eventType; 98 | if (isFunction(ctrlData.onEnterKey)) { 99 | rtns.push(ctrlData.onEnterKey(event)); 100 | } 101 | if (ctrlState.n !== event.value && isFunction(ctrlData.onCommit)) { 102 | ctrlState.n = event.value; 103 | rtns.push(ctrlData.onCommit(event)); 104 | } 105 | } 106 | } 107 | else if (ctrlState.g !== event.value && isFunction(ctrlData.onValueChange)) { 108 | ctrlState.g = event.value; 109 | rtns.push(ctrlData.onValueChange(event)); 110 | } 111 | if (eventType === 'change' && ctrlState.n !== event.value && isFunction(ctrlData.onCommit)) { 112 | // onCommit on blur event and Enter key event 113 | ctrlState.n = event.value; 114 | rtns.push(ctrlData.onCommit(event)); 115 | } 116 | Promise.all(rtns).catch((err) => catchError(ctrlState, event, err)); 117 | } 118 | catch (e) { 119 | catchError(ctrlState, event, e); 120 | } 121 | } 122 | } 123 | }; 124 | -------------------------------------------------------------------------------- /dist/helpers.d.ts: -------------------------------------------------------------------------------- 1 | export declare const isBoolean: (v: any) => v is string; 2 | export declare const isFunction: (v: any) => v is Function; 3 | export declare const isNumber: (v: any) => v is number; 4 | export declare const isString: (v: any) => v is string; 5 | export declare const isPromise: (v: any) => v is Promise; 6 | export declare const toDashCase: (str: string) => string; 7 | export declare const setAttribute: (elm: HTMLElement | undefined, attrName: string, attrValue?: string) => string; 8 | export declare const showNativeReport: (elm: HTMLElement | undefined) => boolean; 9 | -------------------------------------------------------------------------------- /dist/helpers.js: -------------------------------------------------------------------------------- 1 | export const isBoolean = (v) => typeof v === 'boolean'; 2 | export const isFunction = (v) => typeof v === 'function'; 3 | export const isNumber = (v) => typeof v === 'number'; 4 | export const isString = (v) => typeof v === 'string'; 5 | export const isPromise = (v) => !!v && (typeof v === 'object' || isFunction(v)) && isFunction(v.then); 6 | export const toDashCase = (str) => str 7 | .toLowerCase() 8 | .replace(/([A-Z0-9])/g, (g) => ' ' + g[0]) 9 | .trim() 10 | .replace(/ /g, '-'); 11 | export const setAttribute = (elm, attrName, attrValue = '') => (elm === null || elm === void 0 ? void 0 : elm.setAttribute(attrName, attrValue), attrValue); 12 | export const showNativeReport = (elm) => { var _a, _b; return !(elm === null || elm === void 0 ? void 0 : elm.hasAttribute('formnovalidate')) && !((_b = (_a = elm) === null || _a === void 0 ? void 0 : _a.form) === null || _b === void 0 ? void 0 : _b.hasAttribute('novalidate')); }; 13 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | export { activelyValidatingMessage, isActivelyValidating, isDirty, isInvalid, isTouched, isValid, validationMessage, submitValidity, } from './validation'; 2 | export { bind, bindBoolean, bindGroup, bindNumber } from './bind'; 3 | export { control, controlBoolean, controlGroup, controlNumber } from './control'; 4 | export { descriptionFor, labelFor, validationFor } from './labelling-for'; 5 | export type { ReactiveFormBindOptions, ReactiveFormControl, ReactiveFormControlGroup, ReactiveFormControlOptions, ReactiveFormEvent, } from './types'; 6 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | export { activelyValidatingMessage, isActivelyValidating, isDirty, isInvalid, isTouched, isValid, validationMessage, submitValidity, } from './validation'; 2 | export { bind, bindBoolean, bindGroup, bindNumber } from './bind'; 3 | export { control, controlBoolean, controlGroup, controlNumber } from './control'; 4 | export { descriptionFor, labelFor, validationFor } from './labelling-for'; 5 | -------------------------------------------------------------------------------- /dist/input-control.d.ts: -------------------------------------------------------------------------------- 1 | import type { ControlData, ReactiveFormControl, ReactiveFormControlGroup } from './types'; 2 | export declare const inputControl: (value: any, ctrlData: ControlData) => ReactiveFormControl; 3 | export declare const inputControlGroup: (selectedValue: any, ctrlData: ControlData) => ReactiveFormControlGroup; 4 | -------------------------------------------------------------------------------- /dist/input-control.js: -------------------------------------------------------------------------------- 1 | import { ctrlChildren, ctrlDatas, ctrlElms, ctrlElmIds, ctrlStates, ctrls, labellingElms, setControlState, state, } from './state'; 2 | import { isFunction, isString, setAttribute } from './helpers'; 3 | import { getGroupChild, setDescribedbyAttributes, setErrormessageAttributes, setLabelledbyAttributes, } from './labelling-for'; 4 | import { checkValidity } from './validation'; 5 | import { sharedEventHandler } from './handlers'; 6 | import { setValueToControlElement } from './value'; 7 | export const inputControl = (value, ctrlData) => { 8 | // create the control arrow fn that'll be used as a weakmap key 9 | // and as a function to return the props for the control element 10 | const ctrlState = setControlState(value, ctrlData); 11 | const ctrl = () => { 12 | state.r = null; 13 | // create the object to be used as a property spread in the render() 14 | const props = { 15 | // get the reference to this form control element 16 | // and remember it so we can look up the form control by the element 17 | ref: (ctrlElm) => { 18 | if (ctrlElm) { 19 | if (ctrlState === null || ctrlState === void 0 ? void 0 : ctrlState.f) { 20 | setValueToControlElement(ctrlData, ctrlElm, value); 21 | } 22 | ctrlElmRef(ctrl, ctrlData, ctrlState, ctrlElm, false); 23 | } 24 | }, 25 | // add the shared event listeners 26 | onInvalid: sharedEventHandler, 27 | onInput: sharedEventHandler, 28 | onChange: sharedEventHandler, 29 | onKeyUp: sharedEventHandler, 30 | onFocus: sharedEventHandler, 31 | onBlur: sharedEventHandler, 32 | }; 33 | if (isFunction(ctrlData.onKeyDown)) { 34 | props.onKeyDown = sharedEventHandler; 35 | } 36 | if (ctrlData.changeEventName) { 37 | props[ctrlData.changeEventName] = sharedEventHandler; 38 | } 39 | return props; 40 | }; 41 | // add to the weakmap the data for this control 42 | ctrlDatas.set(ctrl, ctrlData); 43 | // return the control to be used as a key and what's 44 | // called to get all of the props for the control element 45 | return ctrl; 46 | }; 47 | export const inputControlGroup = (selectedValue, ctrlData) => { 48 | const ctrlState = setControlState(selectedValue, ctrlData); 49 | // create the form control that'll be used as a weakmap key 50 | const ctrl = (groupItemValue) => { 51 | state.r = null; 52 | if (isString(groupItemValue)) { 53 | // group item, like 54 | return inputControlGroupItem(selectedValue, ctrl, ctrlData, ctrlState, groupItemValue); 55 | } 56 | // group container, like
57 | return { 58 | role: 'group', 59 | ref: (ctrlElm) => ctrlElm && ctrlElmRef(ctrl, ctrlData, ctrlState, ctrlElm, true), 60 | }; 61 | }; 62 | ctrlChildren.set(ctrl, new Map()); 63 | // remember the control data 64 | ctrlDatas.set(ctrl, ctrlData); 65 | // return form control is used as a key 66 | // and what's called to get all of the props 67 | return ctrl; 68 | }; 69 | const inputControlGroupItem = (selectedGroupValue, parentCtrl, parentCtrlData, ctrlState, value) => { 70 | getGroupChild(parentCtrl, value); 71 | // grouped control input item, like a group 72 | // only has one "value" and the individual group item that has 73 | // the same "value" as the group value is the "checked" item 74 | const props = { 75 | // group item "value" 76 | // individual radio should each have a unique "value" assigned 77 | value, 78 | // this radio is "checked" if its "value" is the same as the group's "value" 79 | // compare as strings so we can normalize any passed in boolean strings or actual booleans 80 | // however, it's always false if the group's "selectedValue" is null or undefined 81 | checked: selectedGroupValue != null ? String(selectedGroupValue) === value : false, 82 | onFocus: sharedEventHandler, 83 | onBlur: sharedEventHandler, 84 | onInput: sharedEventHandler, 85 | onChange: sharedEventHandler, 86 | // ref for 87 | ref: (childCtrlElm) => childCtrlElm && ctrlGroupItemElmRef(parentCtrl, ctrlState, childCtrlElm, value), 88 | }; 89 | if (parentCtrlData.changeEventName) { 90 | props[parentCtrlData.changeEventName] = sharedEventHandler; 91 | } 92 | return props; 93 | }; 94 | const ctrlElmRef = (ctrl, ctrlData, ctrlState, ctrlElm, isParentGroup) => { 95 | // we just got a reference to the control input element 96 | let ctrlId = ctrlElm.getAttribute('id'); 97 | let ctrlName = ctrlElm.getAttribute('name'); 98 | let labellingElm = labellingElms[0 /* labelledby */].get(ctrl); 99 | if (!ctrlId) { 100 | ctrlId = ctrlData.i; 101 | if (!ctrlId) { 102 | ctrlId = ctrlElmIds.get(ctrlElm); 103 | if (!ctrlId) { 104 | ctrlElmIds.set(ctrlElm, (ctrlId = 'ctrl' + state.i++)); 105 | } 106 | } 107 | } 108 | // since the labelling elements could have already rendered before the control element 109 | // we can now set the attribute information now that we have the "id" for the control element 110 | if (labellingElm) { 111 | // labelledby 112 | setLabelledbyAttributes(ctrlId, ctrlElm, labellingElm); 113 | } 114 | labellingElm = labellingElms[2 /* describedby */].get(ctrl); 115 | if (labellingElm) { 116 | // describedby 117 | setDescribedbyAttributes(ctrlId, ctrlElm, labellingElm); 118 | } 119 | labellingElm = labellingElms[1 /* errormessage */].get(ctrl); 120 | if (labellingElm) { 121 | // errormessage 122 | setErrormessageAttributes(ctrlId, ctrlElm, labellingElm); 123 | } 124 | if ((ctrlState === null || ctrlState === void 0 ? void 0 : ctrlState.e) !== '') { 125 | setAttribute(ctrlElm, 'aria-invalid', 'true'); 126 | } 127 | else { 128 | ctrlElm.removeAttribute('aria-invalid'); 129 | } 130 | ctrlData.i = setAttribute(ctrlElm, 'id', ctrlId); 131 | if (!isParentGroup) { 132 | if (!ctrlName) { 133 | ctrlName = ctrlData.n; 134 | if (!ctrlName) { 135 | ctrlName = ctrlId; 136 | } 137 | } 138 | ctrlData.n = setAttribute(ctrlElm, 'name', ctrlName); 139 | } 140 | ctrls.set(ctrlElm, ctrl); 141 | ctrlElms.set(ctrl, ctrlElm); 142 | ctrlStates.set(ctrlElm, ctrlState); 143 | if (ctrlState === null || ctrlState === void 0 ? void 0 : ctrlState.f) { 144 | checkValidity(ctrlData, ctrlState, ctrlElm, { ctrl: ctrlElm }, null); 145 | ctrlState.f = false; 146 | } 147 | }; 148 | const ctrlGroupItemElmRef = (parentCtrl, ctrlState, childCtrlElm, childValue) => { 149 | const child = getGroupChild(parentCtrl, childValue); 150 | ctrlStates.set(childCtrlElm, ctrlState); 151 | return ctrlElmRef(child === null || child === void 0 ? void 0 : child.ctrl, child === null || child === void 0 ? void 0 : child.data, ctrlState, childCtrlElm, false); 152 | }; 153 | -------------------------------------------------------------------------------- /dist/labelling-for.d.ts: -------------------------------------------------------------------------------- 1 | import type { ReactiveFormControl, ControlElement } from './types'; 2 | export declare const setDescribedbyAttributes: (ctrlId: string, ctrlElm: ControlElement, labellingElm: HTMLElement) => string; 3 | export declare const setErrormessageAttributes: (ctrlId: string, ctrlElm: ControlElement, labellingElm: HTMLElement) => void; 4 | export declare const setLabelledbyAttributes: (ctrlId: string, ctrlElm: ControlElement, labellingElm: HTMLElement) => void; 5 | /** 6 | * The `descriptionFor(ctrl)` method is used to establish a relationship between 7 | * an input control and this text that described it. This is very similar to 8 | * label, but the description provides more information that the user might need. 9 | * When using this method, the element it's attached to will automatically link 10 | * up the description by adding the `aria-describedby` attribute to the control 11 | * element, and a unique id to the description element. 12 | */ 13 | export declare const descriptionFor: (ctrl: ReactiveFormControl, groupItemValue?: string | undefined) => { 14 | ref: (groupItemLabellingElm: HTMLElement) => void; 15 | }; 16 | /** 17 | * The `validationFor(ctrl)` method is used to establish a relationship between 18 | * an input control and it's error message. When using this method, the element 19 | * it's attached to will automatically link up the error by adding the 20 | * `aria-errormessage` attribute to the control element, and a unique id to the 21 | * message element. Additionally, it will add `role="alert"` and `aria-atomic="true"` 22 | * to the message element. 23 | */ 24 | export declare const validationFor: (ctrl: ReactiveFormControl, groupItemValue?: string | undefined) => { 25 | ref: (groupItemLabellingElm: HTMLElement) => void; 26 | }; 27 | /** 28 | * The `labelFor(ctrl)` method is used to establish a relationship between 29 | * an input control and this text that labels it. When the labelling element is 30 | * an actual `