@lyra/form-builder
Version:
Lyra form builder
243 lines (195 loc) • 7.83 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FormBuilderInput = undefined;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _class, _temp2; /* eslint-disable complexity */
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _PatchEvent = require('./PatchEvent');
var _PatchEvent2 = _interopRequireDefault(_PatchEvent);
var _generateHelpUrl = require('@lyra/generate-help-url');
var _generateHelpUrl2 = _interopRequireDefault(_generateHelpUrl);
var _pathUtils = require('./utils/pathUtils');
var PathUtils = _interopRequireWildcard(_pathUtils);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
/*:: import type {Path} from './typedefs/path'*/
/*:: import type {Type} from './typedefs'*/
/*:: type Props = {
value: any,
type: Type,
onChange: PatchEvent => void,
onFocus: Path => void,
onBlur: () => void,
readOnly: boolean,
focusPath: Path,
markers: Array<*>,
level: number,
isRoot: boolean,
path: Array<PathSegment>
}*/
const ENABLE_CONTEXT = () => {};
function getDisplayName(component) {
return component.displayName || component.name || 'Unknown';
}
function trimChildPath(path, childPath) {
return PathUtils.startsWith(path, childPath) ? PathUtils.trimLeft(path, childPath) : [];
}
const FormBuilderInput = (_temp2 = _class = class FormBuilderInput extends _react2.default.PureComponent /*:: <
Props
>*/ {
constructor(...args) {
var _temp;
return _temp = super(...args), this.getValuePath = () => {
return this.context.getValuePath().concat(this.props.path);
}, this.setInput = (component /*: ?FormBuilderInput*/) => {
this._input = component;
}, this.handleChange = patchEvent => {
var _props = this.props;
const type = _props.type,
onChange = _props.onChange;
if (type.readOnly) {
return;
}
onChange(patchEvent);
}, this.handleFocus = nextPath => {
var _props2 = this.props;
const path = _props2.path,
onFocus = _props2.onFocus,
focusPath = _props2.focusPath;
if (!onFocus) {
console.warn(
// eslint-disable-line no-console
'FormBuilderInput was used without passing a required onFocus prop. Read more at %s.', (0, _generateHelpUrl2.default)('form-builder-input-missing-required-prop'));
return;
}
const nextFocusPath = Array.isArray(nextPath) ? [...path, ...nextPath] : path;
if (PathUtils.isEqual(focusPath, nextFocusPath)) {
// no change
return;
}
onFocus(nextFocusPath);
}, this.handleBlur = () => {
const onBlur = this.props.onBlur;
if (!onBlur) {
console.warn(
// eslint-disable-line no-console
'FormBuilderInput was used without passing a required onBlur prop. Read more at %s.', (0, _generateHelpUrl2.default)('form-builder-input-missing-required-prop'));
return;
}
onBlur();
}, this.setElement = (el /*: ?HTMLDivElement*/) => {
this._element = el;
}, _temp;
}
getChildContext() {
return {
getValuePath: this.getValuePath
};
}
componentDidMount() {
var _props3 = this.props;
const focusPath = _props3.focusPath,
path = _props3.path;
if (PathUtils.hasFocus(focusPath, path)) {
this.focus();
}
}
componentWillReceiveProps(nextProps /*: Props*/) {
const willHaveFocus = PathUtils.hasFocus(nextProps.focusPath, nextProps.path);
const hasFocus = PathUtils.hasFocus(this.props.focusPath, this.props.path);
if (willHaveFocus && !hasFocus) {
this.focus();
}
}
componentWillUnmount() {
if (this.scrollTimeout) {
clearTimeout(this.scrollTimeout);
}
}
resolveInputComponent(type /*: Type*/) {
return this.context.formBuilder.resolveInputComponent(type);
}
_withInputDisplayName(cb /*: (str: string) => void*/) {
cb(getDisplayName(this.resolveInputComponent(this.props.type)));
}
focus() {
if (!this._input) {
// should never happen
throw new Error('Attempted to set focus on a missing input component');
}
if (typeof this._input.focus !== 'function') {
this._withInputDisplayName(displayName => console.warn('Missing a required ".focus()" method on input component. Please check the implementation of %s. Read more at %s', displayName, (0, _generateHelpUrl2.default)('input-component-missing-required-method')));
return;
}
this._input.focus();
}
getChildFocusPath() {
var _props4 = this.props;
const path = _props4.path,
focusPath = _props4.focusPath;
return trimChildPath(path, focusPath);
}
render() {
var _props5 = this.props;
const onChange = _props5.onChange,
onFocus = _props5.onFocus,
onBlur = _props5.onBlur,
path = _props5.path,
readOnly = _props5.readOnly,
value = _props5.value,
markers = _props5.markers,
type = _props5.type,
level = _props5.level,
focusPath = _props5.focusPath,
isRoot = _props5.isRoot,
rest = _objectWithoutProperties(_props5, ['onChange', 'onFocus', 'onBlur', 'path', 'readOnly', 'value', 'markers', 'type', 'level', 'focusPath', 'isRoot']);
const InputComponent = this.resolveInputComponent(type);
if (!InputComponent) {
return _react2.default.createElement(
'div',
null,
'No input resolved for type ',
JSON.stringify(type.name)
);
}
const rootProps = isRoot ? { isRoot } : {};
let childMarkers = markers;
if (!isRoot) {
childMarkers = markers.filter(marker => PathUtils.startsWith(path, marker.path)).map(marker => _extends({}, marker, {
path: trimChildPath(path, marker.path)
}));
}
const childFocusPath = this.getChildFocusPath();
const isLeaf = childFocusPath.length === 0 || childFocusPath[0] === PathUtils.FOCUS_TERMINATOR;
const leafProps = isLeaf ? {} : { focusPath: childFocusPath };
return _react2.default.createElement(
'div',
{ ref: this.setElement, 'data-focus-path': PathUtils.toString(path) },
_react2.default.createElement(InputComponent, _extends({}, rest, rootProps, leafProps, {
value: value,
readOnly: readOnly || type.readOnly,
markers: childMarkers,
type: type,
onChange: this.handleChange,
onFocus: this.handleFocus,
onBlur: this.handleBlur,
level: level,
ref: this.setInput
}))
);
}
}, _class.contextTypes = {
formBuilder: ENABLE_CONTEXT,
getValuePath: ENABLE_CONTEXT
}, _class.childContextTypes = {
getValuePath: ENABLE_CONTEXT
}, _class.defaultProps = {
focusPath: [],
path: [],
markers: []
}, _temp2);
exports.FormBuilderInput = FormBuilderInput;