@lyra/form-builder
Version:
Lyra form builder
322 lines (260 loc) • 11.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
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 _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _functions = require('part:@lyra/form-builder/input/array/functions');
var _functions2 = _interopRequireDefault(_functions);
var _operators = require('rxjs/operators');
var _resolveTypeName = require('../../utils/resolveTypeName');
var _pathUtils = require('../../utils/pathUtils');
var _UploadTargetFieldset = require('../../utils/UploadTargetFieldset');
var _UploadTargetFieldset2 = _interopRequireDefault(_UploadTargetFieldset);
var _PatchEvent = require('../../PatchEvent');
var _ArrayInput = require('./styles/ArrayInput.css');
var _ArrayInput2 = _interopRequireDefault(_ArrayInput);
var _resolveListComponents = require('./resolveListComponents');
var _resolveListComponents2 = _interopRequireDefault(_resolveListComponents);
var _ItemValue = require('./ItemValue');
var _ItemValue2 = _interopRequireDefault(_ItemValue);
var _randomKey = require('./randomKey');
var _randomKey2 = _interopRequireDefault(_randomKey);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*:: import type {Uploader} from '../../lyra/uploads/typedefs'*/
/*:: import type {Type, Marker} from '../../typedefs'*/
/*:: import type {Path} from '../../typedefs/path'*/
/*:: import type {Subscription} from '../../typedefs/observable'*/
/*:: import type {ArrayType, ItemValue} from './typedefs'*/
function createProtoValue(type /*: Type*/) /*: ItemValue*/ {
if (type.jsonType !== 'object') {
throw new Error(`Invalid item type: "${type.type}". Default array input can only contain objects (for now)`);
}
const key = (0, _randomKey2.default)(12);
return type.name === 'object' ? { _key: key } : {
_type: type.name,
_key: key
};
}
/*:: type Props = {
type: ArrayType,
value: Array<ItemValue>,
markers: Array<Marker>,
level: number,
onChange: (event: PatchEvent) => void,
onFocus: Path => void,
onBlur: () => void,
focusPath: Path,
readOnly: ?boolean,
resolveUploader?: (type: Type, file: File) => Uploader
}*/
class ArrayInput extends _react2.default.Component /*:: <Props, State>*/ {
constructor(...args) {
var _temp;
return _temp = super(...args), this.uploadSubscriptions = {}, this.state = {
isMoving: false
}, this.insert = (itemValue /*: ItemValue*/, position /*: 'before' | 'after'*/, atIndex /*: number*/) => {
const onChange = this.props.onChange;
onChange(_PatchEvent.PatchEvent.from((0, _PatchEvent.setIfMissing)([]), (0, _PatchEvent.insert)([itemValue], position, [atIndex])));
}, this.handlePrepend = (value /*: ItemValue*/) => {
this.insert(value, 'before', 0);
this.handleFocusItem(value);
}, this.handleAppend = (value /*: ItemValue*/) => {
this.insert(value, 'after', -1);
this.handleFocusItem(value);
}, this.handleRemoveItem = (item /*: ItemValue*/) => {
this.removeItem(item);
}, this.handleFocus = () => {
this.props.onFocus([_pathUtils.FOCUS_TERMINATOR]);
}, this.handleFocusItem = (item /*: ItemValue*/) => {
this.props.onFocus([{ _key: item._key }, _pathUtils.FOCUS_TERMINATOR]);
}, this.handleItemChange = (event /*: PatchEvent*/, item /*: ItemValue*/) => {
var _props = this.props;
const onChange = _props.onChange,
value = _props.value;
const memberType = this.getMemberTypeOfItem(item);
if (!memberType) {
// eslint-disable-next-line no-console
console.log('Could not find member type of item ', item);
return;
}
if (memberType.readOnly) {
return;
}
const key = item._key || (0, _randomKey2.default)(12);
onChange(event.prefixAll({ _key: key }).prepend(item._key ? [] : (0, _PatchEvent.set)(key, [value.indexOf(item), '_key'])));
}, this.handleSortStart = () => {
this.setState({ isMoving: true });
}, this.handleSortEnd = (event /*: {newIndex: number, oldIndex: number}*/) => {
this.setState({ isMoving: false });
var _props2 = this.props;
const value = _props2.value,
onChange = _props2.onChange;
const item = value[event.oldIndex];
const refItem = value[event.newIndex];
// console.log('from %d => %d', event.oldIndex, event.newIndex, event)
if (!item._key || !refItem._key) {
// eslint-disable-next-line no-console
console.error('Neither the item you are moving nor the item you are moving to have a key. Cannot continue.');
return;
}
if (event.oldIndex === event.newIndex || item._key === refItem._key) {
return;
}
onChange(_PatchEvent.PatchEvent.from((0, _PatchEvent.unset)([{ _key: item._key }]), (0, _PatchEvent.insert)([item], event.oldIndex > event.newIndex ? 'before' : 'after', [{ _key: refItem._key }])));
}, this.renderList = () => {
var _props3 = this.props;
const type = _props3.type,
markers = _props3.markers,
readOnly = _props3.readOnly,
value = _props3.value,
focusPath = _props3.focusPath,
onBlur = _props3.onBlur,
onFocus = _props3.onFocus,
level = _props3.level;
const isMoving = this.state.isMoving;
const options = type.options || {};
const isSortable = options.sortable !== false;
const isGrid = options.layout === 'grid';
var _resolveListComponent = (0, _resolveListComponents2.default)(isSortable, isGrid);
const List = _resolveListComponent.List,
Item = _resolveListComponent.Item;
const listProps = isSortable ? {
movingItemClass: _ArrayInput2.default.movingItem,
onSortEnd: this.handleSortEnd,
onSortStart: this.handleSortStart,
lockToContainerEdges: true,
useDragHandle: !isGrid
} : {};
const listItemClassName = isMoving ? _ArrayInput2.default.listItemMute : _ArrayInput2.default.listItem;
return _react2.default.createElement(
List,
_extends({
className: readOnly ? _ArrayInput2.default.listReadOnly : _ArrayInput2.default.list
}, listProps),
value.map((item, index) => {
const isChildMarker = marker => (0, _pathUtils.startsWith)([index], marker.path) || (0, _pathUtils.startsWith)([{ _key: item && item._key }], marker.path);
const itemProps = isSortable ? { index } : {};
return _react2.default.createElement(
Item,
_extends({
key: item._key,
className: isGrid ? _ArrayInput2.default.gridItem : listItemClassName
}, itemProps),
_react2.default.createElement(_ItemValue2.default, {
type: type,
value: item,
level: level,
markers: markers.filter(isChildMarker),
onRemove: this.handleRemoveItem,
onChange: this.handleItemChange,
focusPath: focusPath,
onFocus: onFocus,
readOnly: readOnly,
onBlur: onBlur
})
);
})
);
}, this.setElement = (el /*: ?UploadTargetFieldset*/) => {
this._element = el;
}, this.getUploadOptions = (file /*: File*/) /*: Array<UploadOption>*/ => {
var _props4 = this.props;
const type = _props4.type,
resolveUploader = _props4.resolveUploader;
if (!resolveUploader) {
return [];
}
return type.of.map(memberType => {
const uploader = resolveUploader(memberType, file);
return uploader && {
type: memberType,
uploader
};
}).filter(Boolean);
}, this.handleUpload = ({ file, type, uploader }) => {
const onChange = this.props.onChange;
const item = createProtoValue(type);
const key = item._key;
this.insert(item, 'after', -1);
const events$ = uploader.upload(file, type).pipe((0, _operators.map)(uploadEvent => _PatchEvent.PatchEvent.from(uploadEvent.patches).prefixAll({ _key: key })));
this.uploadSubscriptions = _extends({}, this.uploadSubscriptions, {
[key]: events$.subscribe(onChange)
});
}, _temp;
}
removeItem(item /*: ItemValue*/) {
var _props5 = this.props;
const onChange = _props5.onChange,
onFocus = _props5.onFocus,
value = _props5.value;
onChange(_PatchEvent.PatchEvent.from((0, _PatchEvent.unset)(item._key ? [{ _key: item._key }] : [value.indexOf(item)])));
if (item._key in this.uploadSubscriptions) {
this.uploadSubscriptions[item._key].unsubscribe();
}
const idx = value.indexOf(item);
const nextItem = value[idx + 1] || value[idx - 1];
onFocus([nextItem ? { _key: nextItem._key } : _pathUtils.FOCUS_TERMINATOR]);
}
getExpandedItem() /*: ?ItemValue*/ {
var _props6 = this.props;
const focusPath = _props6.focusPath,
value = _props6.value;
var _ref = focusPath || [],
_ref2 = _slicedToArray(_ref, 1);
const head = _ref2[0];
return head && value.find(item => item._key === head._key);
}
getMemberTypeOfItem(item /*: ItemValue*/) /*: ?Type*/ {
const type = this.props.type;
const itemTypeName = (0, _resolveTypeName.resolveTypeName)(item);
return type.of.find(memberType => memberType.name === itemTypeName);
}
focus() {
if (this._element) {
this._element.focus();
}
}
render() {
var _props7 = this.props;
const type = _props7.type,
level = _props7.level,
markers = _props7.markers,
readOnly = _props7.readOnly,
onChange = _props7.onChange,
value = _props7.value;
return _react2.default.createElement(
_UploadTargetFieldset2.default,
{
markers: markers,
tabIndex: 0,
legend: type.title,
description: type.description,
level: level,
className: _ArrayInput2.default.root,
onUpload: this.handleUpload,
onFocus: this.handleFocus,
type: type,
getUploadOptions: this.getUploadOptions,
ref: this.setElement
},
value && value.length > 0 && this.renderList(),
_react2.default.createElement(_functions2.default, {
type: type,
value: value,
readOnly: readOnly,
onAppendItem: this.handleAppend,
onPrependItem: this.handlePrepend,
onFocusItem: this.handleFocusItem,
onCreateValue: createProtoValue,
onChange: onChange
})
);
}
}
exports.default = ArrayInput;
ArrayInput.defaultProps = {
focusPath: []
};