Katochimoto/xblocks

View on GitHub
src/blocks/input/controller.jsx

Summary

Maintainability
A
0 mins
Test Coverage
import { PropTypes } from 'react';
import { view } from 'xblocks-core';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import ReactDOM from 'react-dom';

export default view.create({
    displayName: 'xb-input_controller',

    mixins: [ PureRenderMixin ],

    propTypes: {
        'autoFocus': PropTypes.bool,
        'autoComplete': PropTypes.oneOf([ 'on', 'off' ]),
        'autosize': PropTypes.bool,
        'className': PropTypes.string,
        'cols': PropTypes.string,
        'disabled': PropTypes.bool,
        'isPlaceholderHint': PropTypes.bool,
        'multiline': PropTypes.bool,
        'name': PropTypes.string,
        'onChange': PropTypes.func,
        'onHintToggle': PropTypes.func,
        'placeholder': PropTypes.string,
        'readOnly': PropTypes.bool,
        'required': PropTypes.bool,
        'rows': PropTypes.string,
        'tabIndex': PropTypes.string,
        'value': PropTypes.string
    },

    getDefaultProps: function () {
        return {
            'autoFocus': false,
            'autosize': false,
            'disabled': false,
            'isPlaceholderHint': false,
            'multiline': false,
            'readOnly': false,
            'required': false,
            'value': undefined
        };
    },

    componentDidUpdate: function (prevProps) {
        this.recalculateSize();
        this.dispatchEventToggleHint(prevProps.value, this.props.value);
    },

    componentDidMount: function () {
        this.recalculateSize();
    },

    dispatchEventToggleHint: function (prevValue, nextValue) {
        if (this.props.isPlaceholderHint) {
            const hasPrevValue = Boolean(prevValue);
            const hasNestValue = Boolean(nextValue);

            if (hasPrevValue ^ hasNestValue) {
                this.props.onHintToggle(hasPrevValue && !hasNestValue);
            }
        }
    },

    recalculateSize: function () {
        if (!this.props.autosize) {
            return;
        }

        const node = ReactDOM.findDOMNode(this);

        if (this.props.multiline) {
            node.style.height = '0px';
            node.style.height = node.scrollHeight + 'px';

        } else {
            node.style.width = '20px';
            node.style.width = (node.scrollWidth < 20 ? 20 : node.scrollWidth) + 'px';
        }
    },

    render: function () {
        const props = {
            'autoFocus': this.props.autoFocus,
            'autoComplete': this.props.autoComplete,
            'className': this.props.className,
            'disabled': this.props.disabled,
            'name': this.props.name,
            'onChange': this.props.onChange,
            'placeholder': this.props.placeholder || '', // macos inserts placeholder default
            'readOnly': this.props.readOnly,
            'required': this.props.required,
            'tabIndex': this.props.tabIndex,
            'value': this.props.value
        };

        if (this.props.multiline) {
            return (
                <textarea {...props} rows={this.props.rows} cols={this.props.cols} />
            );

        } else {
            return (
                <input {...props} type="text" />
            );
        }
    }
});