src/components/form-items/text-area.ts (135 lines of code) (raw):

/*! * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ import { Config } from '../../helper/config'; import { DomBuilder, ExtendedHTMLElement } from '../../helper/dom'; import { StyleLoader } from '../../helper/style-loader'; import { checkTextElementValidation } from '../../helper/validator'; import { ValidationPattern } from '../../static'; export interface TextAreaProps { classNames?: string[]; attributes?: Record<string, string>; label?: HTMLElement | ExtendedHTMLElement | string; autoFocus?: boolean; description?: ExtendedHTMLElement; mandatory?: boolean; fireModifierAndEnterKeyPress?: () => void; placeholder?: string; validationPatterns?: { operator?: 'and' | 'or'; patterns: ValidationPattern[]; }; value?: string; onChange?: (value: string) => void; onKeyPress?: (event: KeyboardEvent) => void; testId?: string; } export abstract class TextAreaAbstract { render: ExtendedHTMLElement; setValue = (value: string): void => {}; getValue = (): string => ''; setEnabled = (enabled: boolean): void => {}; checkValidation = (): void => {}; } export class TextAreaInternal extends TextAreaAbstract { private readonly inputElement: ExtendedHTMLElement; private readonly validationErrorBlock: ExtendedHTMLElement; private readonly props: TextAreaProps; private readyToValidate: boolean = false; render: ExtendedHTMLElement; constructor (props: TextAreaProps) { StyleLoader.getInstance().load('components/_form-input.scss'); super(); this.props = props; this.validationErrorBlock = DomBuilder.getInstance().build({ type: 'div', classNames: [ 'mynah-form-input-validation-error-block' ], }); this.inputElement = DomBuilder.getInstance().build({ type: 'textarea', testId: this.props.testId, classNames: [ 'mynah-form-input', ...(this.props.classNames ?? []) ], attributes: { ...(this.props.placeholder !== undefined ? { placeholder: this.props.placeholder } : {}), ...(this.props.autoFocus === true ? { autofocus: 'autofocus' } : {}), }, events: { blur: (e) => { this.readyToValidate = true; this.checkValidation(); }, // TODO: change this to 'input' event? keyup: (e) => { if (this.props.onChange !== undefined) { this.props.onChange((e.currentTarget as HTMLTextAreaElement).value); } this.checkValidation(); }, keydown: (e: KeyboardEvent) => { if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) { this.props.fireModifierAndEnterKeyPress?.(); } }, keypress: (e: KeyboardEvent) => { this.props.onKeyPress?.(e); } }, }); this.inputElement.value = props.value ?? ''; this.render = DomBuilder.getInstance().build({ type: 'div', classNames: [ 'mynah-form-input-wrapper' ], children: [ { type: 'span', classNames: [ 'mynah-form-input-label' ], children: [ ...(props.label !== undefined ? [ props.label ] : []) ] }, { type: 'div', classNames: [ 'mynah-form-input-container' ], ...(props.attributes !== undefined ? { attributes: props.attributes } : {}), children: [ this.inputElement, ] }, ...[ props.description !== undefined ? props.description : '' ], this.validationErrorBlock ] }); if (this.props.autoFocus === true) { setTimeout(() => { this.inputElement.focus(); }, 250); } } setValue = (value: string): void => { this.inputElement.value = value; }; getValue = (): string => { return this.inputElement.value; }; setEnabled = (enabled: boolean): void => { if (enabled) { this.inputElement.removeAttribute('disabled'); } else { this.inputElement.setAttribute('disabled', 'disabled'); } }; checkValidation = (): void => checkTextElementValidation(this.inputElement, this.props.validationPatterns, this.validationErrorBlock, this.readyToValidate, this.props.mandatory); } export class TextArea extends TextAreaAbstract { render: ExtendedHTMLElement; constructor (props: TextAreaProps) { super(); return new (Config.getInstance().config.componentClasses.TextArea ?? TextAreaInternal)(props); } setValue = (value: string): void => {}; getValue = (): string => ''; setEnabled = (enabled: boolean): void => {}; checkValidation = (): void => {}; }