UNPKG

@lyra/form-builder

Version:
322 lines (260 loc) 11.6 kB
'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: [] };