UNPKG

react-form-with-constraints-tools

Version:
135 lines (134 loc) 5.19 kB
import * as React from 'react'; import { instanceOf } from 'prop-types'; import { Async as _Async, FieldEvent, FieldFeedback as _FieldFeedback, FieldFeedbacks as _FieldFeedbacks, FieldFeedbackType, FormWithConstraints, isHTMLInput } from 'react-form-with-constraints'; function beautifulStringify(obj, space) { let str = JSON.stringify(obj, (_key, value) => (value === undefined ? '__undefined__' : value), space); str = str.replace(/"__undefined__"/g, 'undefined'); str = str.replace(/"([^"]+)":/g, '$1:'); str = str.replace(/: "(.*[\\"].*)",/g, ': $1,'); str = str.replace(/\\"/g, '"'); return str; } function normalizeFieldElementProperty(fields) { return fields.map(field => { const { element, ...otherProps } = field; return element ? { element: isHTMLInput(element) ? element.outerHTML : element.props, ...otherProps } : field; }); } export class DisplayFields extends React.Component { constructor() { super(...arguments); this.reRender = () => { this.forceUpdate(); }; } componentDidMount() { this.context.form.fieldsStore.addListener(FieldEvent.Added, this.reRender); this.context.form.fieldsStore.addListener(FieldEvent.Removed, this.reRender); this.context.form.addFieldDidValidateEventListener(this.reRender); this.context.form.addFieldDidResetEventListener(this.reRender); } componentWillUnmount() { this.context.form.fieldsStore.removeListener(FieldEvent.Added, this.reRender); this.context.form.fieldsStore.removeListener(FieldEvent.Removed, this.reRender); this.context.form.removeFieldDidValidateEventListener(this.reRender); this.context.form.removeFieldDidResetEventListener(this.reRender); } render() { let str = beautifulStringify(normalizeFieldElementProperty(this.context.form.fieldsStore.fields), 2); str = str.replace(/{\s+key: (.*),\s+type: (.*),\s+show: (.*)\s+}/g, '{ key: $1, type: $2, show: $3 }'); return str; } } DisplayFields.contextTypes = { form: instanceOf(FormWithConstraints).isRequired }; export class FieldFeedbacks extends _FieldFeedbacks { render() { const { for: fieldName, stop } = this.props; let attr = ''; if (fieldName) attr += `for="${fieldName}" `; attr += `stop="${stop}"`; return (React.createElement(React.Fragment, null, React.createElement("li", null, "key=\"", this.key, "\" ", attr), React.createElement("ul", null, super.render()))); } } export class FieldFeedback extends _FieldFeedback { constructor() { super(...arguments); this.rootEl = null; } getTextDecoration() { const { show } = this.state.validation; let textDecoration = ''; switch (show) { case false: textDecoration = 'line-through'; break; case undefined: textDecoration = 'line-through dotted'; break; default: textDecoration = ''; } return textDecoration; } render() { const { key, type } = this.state.validation; return (React.createElement("li", { ref: rootEl => (this.rootEl = rootEl) }, React.createElement("span", { style: { textDecoration: this.getTextDecoration() } }, "key=\"", key, "\" type=\"", type, "\""), ' ', super.render())); } componentDidUpdate() { const fieldFeedbackSpans = this.rootEl.querySelectorAll('[data-feedback]'); fieldFeedbackSpans.forEach(fieldFeedbackSpan => { fieldFeedbackSpan.style.display = 'inline'; }); const li = this.rootEl.closest('li.async'); if (li !== null) { const async = li.querySelector('span[style]'); async.style.textDecoration = this.getTextDecoration(); } const { type } = this.state.validation; if (type === FieldFeedbackType.WhenValid) { const span = this.rootEl.querySelector('span[style]'); const whenValid = this.rootEl.querySelector(`span.${this.props.classes.valid}`); span.style.textDecoration = whenValid !== null ? '' : 'line-through'; } } } export class Async extends _Async { constructor() { super(...arguments); this.rootEl = null; } static getTextDecoration() { return 'line-through dotted'; } componentDidUpdate() { const async = this.rootEl.querySelector('span[style]'); async.style.textDecoration = Async.getTextDecoration(); } render() { return (React.createElement("li", { className: "async", ref: rootEl => (this.rootEl = rootEl) }, React.createElement("span", { style: { textDecoration: Async.getTextDecoration() } }, "Async"), React.createElement("ul", null, super.render()))); } }