| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 | import BaseFoundation, { DefaultAdapter, noopFunction } from '../base/foundation';import {    noop,    isFunction,    isNumber,    isString} from 'lodash';import calculateNodeHeight from './util/calculateNodeHeight';import getSizingData from './util/getSizingData';import isEnterPress from '../utils/isEnterPress';export interface TextAreaDefaultAdapter {    notifyChange: noopFunction;    setValue: noopFunction;    toggleFocusing: noopFunction;    notifyFocus: noopFunction;    notifyBlur: noopFunction;    notifyKeyDown: noopFunction;    notifyEnterPress: noopFunction;    toggleHovering(hovering: boolean): void;    notifyClear(e: any): void;}export interface TextAreaAdapter extends Partial<DefaultAdapter>, Partial<TextAreaDefaultAdapter> {    setMinLength(length: number): void;    notifyPressEnter(e: any): void;    getRef(): any;    notifyHeightUpdate(e: any): void;}export default class TextAreaFoundation extends BaseFoundation<TextAreaAdapter> {    static get textAreaDefaultAdapter() {        return {            notifyChange: noop,            setValue: noop,            toggleFocusing: noop,            toggleHovering: noop,            notifyFocus: noop,            notifyBlur: noop,            notifyKeyDown: noop,            notifyEnterPress: noop        };    }    constructor(adapter: TextAreaAdapter) {        super({            ...TextAreaFoundation.textAreaDefaultAdapter,            ...adapter        });    }    init() {        this.setInitValue();    }    // eslint-disable-next-line    destroy() { }    setInitValue() {        const {            defaultValue,            value        } = this.getProps();        let v = defaultValue;        if (this._isControlledComponent()) {            v = value;        }        this._adapter.setValue(v);    }    handleValueChange(v: string) {        this._adapter.setValue(v);    }    handleChange(value: string, e: any) {        const { maxLength, minLength, getValueLength } = this._adapter.getProps();        let nextValue = value;        if (maxLength && isFunction(getValueLength)) {            nextValue = this.handleVisibleMaxLength(value);        }        if (minLength && isFunction(getValueLength)) {            this.handleVisibleMinLength(nextValue);        }        if (this._isControlledComponent()) {            this._adapter.notifyChange(nextValue, e);        } else {            this._adapter.setValue(nextValue);            this._adapter.notifyChange(nextValue, e);        }    }    /**     * Modify minLength to trigger browser check for minimum length     * Controlled mode is not checked     * @param {String} value     */    handleVisibleMinLength(value: string) {        const { minLength, getValueLength } = this._adapter.getProps();        const { minLength: stateMinLength } = this._adapter.getStates();        if (isNumber(minLength) && minLength >= 0 && isFunction(getValueLength) && isString(value)) {            const valueLength = getValueLength(value);            if (valueLength < minLength) {                const newMinLength = value.length + (minLength - valueLength);                newMinLength !== stateMinLength && this._adapter.setMinLength(newMinLength);            } else {                stateMinLength !== minLength && this._adapter.setMinLength(minLength);            }        }    }    /**     * Handle input emoji characters beyond maxLength     * Controlled mode is not checked     * @param {String} value     */    handleVisibleMaxLength(value: string) {        const { maxLength, getValueLength } = this._adapter.getProps();        if (isNumber(maxLength) && maxLength >= 0 && isFunction(getValueLength) && isString(value)) {            const valueLength = getValueLength(value);            if (valueLength > maxLength) {                // eslint-disable-next-line max-len                console.warn('[Semi TextArea] The input character is truncated because the input length exceeds the maximum length limit');                const truncatedValue = this.handleTruncateValue(value, maxLength);                return truncatedValue;            } else {                return value;            }        }        return undefined;    }    /**     * Truncate textarea values based on maximum length     * @param {String} value     * @param {Number} maxLength     * @returns {String}     */    handleTruncateValue(value: string, maxLength: number) {        const { getValueLength } = this._adapter.getProps();        if (isFunction(getValueLength)) {            let truncatedValue = '';            for (let i = 1, len = value.length; i <= len; i++) {                const currentValue = value.slice(0, i);                if (getValueLength(currentValue) > maxLength) {                    return truncatedValue;                } else {                    truncatedValue = currentValue;                }            }            return truncatedValue;        } else {            return value.slice(0, maxLength);        }    }    handleFocus(e: any) {        const { value } = this.getStates();        this._adapter.toggleFocusing(true);        this._adapter.notifyFocus(value, e);    }    handleBlur(e: any) {        const { value } = this.getStates();        this._adapter.toggleFocusing(false);        this._adapter.notifyBlur(value, e);    }    handleKeyDown(e: any) {        this._adapter.notifyKeyDown(e);        if (e.keyCode === 13) {            this._adapter.notifyPressEnter(e);        }    }    resizeTextarea = (cb?: any) => {        const { height } = this.getStates();        const { rows } = this.getProps();        const node = this._adapter.getRef().current;        const nodeSizingData = getSizingData(node);        if (!nodeSizingData) {            cb && cb();            return;        }        const newHeight = calculateNodeHeight(            nodeSizingData,            node.value || node.placeholder || 'x',            rows            // maxRows,        );        if (height !== newHeight) {            this._adapter.notifyHeightUpdate(newHeight);            node.style.height = `${newHeight}px`;            return;        }        cb && cb();    };    handleMouseEnter(e) {        this._adapter.toggleHovering(true);    }    handleMouseLeave(e) {        this._adapter.toggleHovering(false);    }    isAllowClear() {        const { value, isFocus, isHover } = this._adapter.getStates();        const { showClear, disabled, readonly } = this._adapter.getProps();        const allowClear = value && showClear && !disabled && (isFocus || isHover) && !readonly;        return allowClear;    }    handleClear(e) {        const { isFocus } = this.getStates();        if (this._isControlledComponent('value')) {            this._adapter.setState({                isFocus: false,            });        } else {            this._adapter.setState({                value: '',                isFocus: false,            });        }        if (isFocus) {            this._adapter.notifyBlur('', e);        }        this._adapter.notifyChange('', e);        this._adapter.notifyClear(e);        this.stopPropagation(e);    }}
 |