UNPKG

bc-formio-template-extend

Version:

Extension of Formio JS's template for formio components following web accessibility

177 lines (166 loc) 5.69 kB
/** @format */ import { RadioComponentConfig } from '../types/RadioComponentConfig'; export class Radio { private Templates: typeof window.Formio.Templates; constructor() { this.Templates = window.Formio.Templates || {}; } radioStyle(): string { return ` .bc-radios, .bc-radios__item { position: relative; } .bc-radios { border: none !important; padding: 0 !important; } .bc-radios__item { display: flex; flex-wrap: wrap; margin-bottom: 10px; } .bc-radios__input { z-index: 1; width: 44px; height: 44px; margin: 0 !important; opacity: 0; left: 0; top: 0; cursor: pointer; } .bc-radio__label { align-self: center; max-width: calc(100% - 74px); margin-bottom: 0; margin-left: 40px; padding: 7px 15px; cursor: pointer; touch-action: manipulation; } .bc-radio__label > .bc_checkedItem:before { content: ""; box-sizing: border-box; position: absolute; top: 2px; left: 2px; width: 40px; height: 40px; border: 2px solid; border-radius: 50%; background: transparent; } .bc-radio__label > .bc_checkedItem:after { content: ""; position: absolute; top: 12px; left: 12px; width: 0; height: 0; border: 10px solid; border-radius: 50%; opacity: 0; background: #000; } .bc-radios__input:checked + .bc_checkedItem:after { opacity: 1; } .bc-radios__input:checked + .bc_checkedItem:before, .bc-radios__input[type=radio]:focus + .bc_checkedItem:before { outline: 3px solid rgba(0, 0, 0, 0) !important; outline-offset: 1px; box-shadow: 0 0 0 3px #fd0 !important; border-width: 4px; }`; } radio(): { form: (ctx: RadioComponentConfig) => string } { return { form: (ctx: RadioComponentConfig): string => { return ` <fieldset class="govuk-radios bc-radios ${ctx.inline ? 'govuk-radios--inline' : ''}" ref="radioGroup" role="${ctx.component.type === 'selectboxes' ? 'group' : 'radiogroup'}" aria-required="${ctx.component.validate?.required}" aria-labelledby="${ctx.instance.id}-${ctx.component.key}--legend" ${ ctx.component.description ? `aria-describedby="d-${ctx.instance.id}-${ctx.component.key}"` : '' } > <legend hidden id="${ctx.instance.id}-${ctx.component.key}--legend">${ ctx.component.label }</legend> ${ctx.values .map((item, index) => { const inputId = `${ctx.instance?.root?.id}-${ctx.id}-${ctx.row}-${ typeof item.value === 'object' ? item.value + '-' + index : item.value }`; const isChecked = ctx.value && (ctx.value === item.value || (typeof ctx.value === 'object' && Object.prototype.hasOwnProperty.call(ctx.value, item.value) && ctx.value[item.value])); return ` <div class="bc-radios__item ${ctx.input.attr.type} form-check${ ctx.inline ? '-inline' : '' }" ref="wrapper"> <label class="bc-radio__label label-position-${ ctx.component.optionsLabelPosition }" for="${inputId}"> ${ ['left', 'top'].includes(ctx.component.optionsLabelPosition) ? `<span>${ctx.t(item.label, { _userInput: true })}</span>` : '' } <input ref="input" class="bc-radios__input${ctx.input.attr.class ? ' ' + ctx.input.attr.class : ''}" ${Object.entries(ctx.input.attr) .filter(([key]) => key !== 'class') .map(([key, val]) => `${key}="${val}"`) .join(' ')} value="${item.value}" ${isChecked ? 'checked' : ''} ${item.disabled ? 'disabled' : ''} id="${inputId}" role="${ctx.component.type === 'selectboxes' ? 'checkbox' : 'radio'}" /> <span class="bc_checkedItem"></span> ${ !ctx.component.optionsLabelPosition || ['right', 'bottom'].includes(ctx.component.optionsLabelPosition) ? `<span>${ctx.t(item.label, { _userInput: true })}</span>` : '' } </label> </div>`; }) .join('')} </fieldset>`; }, }; } componentStyles(): string[] { return [this.radioStyle()]; } styleTagContent(): string { return this.componentStyles().join('\n'); } injectStyleToHead(): void { if (!document.getElementById('custom-bc-template__style')) { const styleTag = document.createElement('style'); styleTag.id = 'custom-bc-template__style'; styleTag.textContent = this.styleTagContent(); document.head.appendChild(styleTag); } } init(): void { this.Templates.current = { radio: this.radio(), }; this.injectStyleToHead(); } }